Two big commits in one day I know, but redid password storage to use HMAC-SHA1. Consolidated much AES processing to three core methods in session that should handle everything automagically. Installation works; upgrades should. Rebranded as 1.1.6.
authorDan
Sun, 04 Jan 2009 00:55:40 -0500
changeset 801 eb8b23f11744
parent 800 9cdfe82c56cd
child 802 59cce2313f9d
Two big commits in one day I know, but redid password storage to use HMAC-SHA1. Consolidated much AES processing to three core methods in session that should handle everything automagically. Installation works; upgrades should. Rebranded as 1.1.6.
README
ajax.php
cron.php
includes/cache.php
includes/captcha.php
includes/captcha/engine_default.php
includes/captcha/engine_failsafe.php
includes/captcha/engine_potpourri.php
includes/clientside/jscompress.php
includes/clientside/jsres.php
includes/clientside/tinymce/tiny_mce_gzip.php
includes/comment.php
includes/common.php
includes/common_cli.php
includes/constants.php
includes/dbal.php
includes/diff.php
includes/diffiehellman.php
includes/email.php
includes/functions.php
includes/graphs.php
includes/hmac.php
includes/http.php
includes/js-compressor.php
includes/lang.php
includes/math.php
includes/namespaces/admin.php
includes/namespaces/api.php
includes/namespaces/default.php
includes/namespaces/file.php
includes/namespaces/special.php
includes/namespaces/template.php
includes/namespaces/user.php
includes/output.php
includes/pageprocess.php
includes/pageutils.php
includes/paths.php
includes/plugins.php
includes/render.php
includes/rijndael.php
includes/search.php
includes/sessions.php
includes/sql_parse.php
includes/stats.php
includes/tagcloud.php
includes/template.php
includes/wikiengine/Tables.php
includes/wikiformat.php
index.php
install/includes/common.php
install/includes/libenanoinstall.php
install/includes/payload.php
install/includes/stages/confirm.php
install/includes/stages/database.php
install/includes/stages/database_mysql.php
install/includes/stages/database_post.php
install/includes/stages/database_postgresql.php
install/includes/stages/finish.php
install/includes/stages/install.php
install/includes/stages/license.php
install/includes/stages/login.php
install/includes/stages/sysreqs.php
install/includes/stages/website.php
install/includes/ui.php
install/index.php
install/install.php
install/readme.php
install/schemas/mysql_stage2.sql
install/schemas/postgresql_stage2.sql
install/schemas/upgrade/1.1.5-1.1.6-mysql.sql
install/schemas/upgrade/1.1.5-1.1.6-postgresql.sql
install/schemas/upgrade/1.1.5-1.1.6.php
install/upgrade.php
plugins/PrivateMessages.php
plugins/SpecialAdmin.php
plugins/SpecialCSS.php
plugins/SpecialGroups.php
plugins/SpecialPageFuncs.php
plugins/SpecialRecentChanges.php
plugins/SpecialSearch.php
plugins/SpecialUpdownload.php
plugins/SpecialUserFuncs.php
plugins/SpecialUserPrefs.php
plugins/admin/CacheManager.php
plugins/admin/GroupManager.php
plugins/admin/LangManager.php
plugins/admin/PageEditor.php
plugins/admin/PageGroups.php
plugins/admin/PageManager.php
plugins/admin/PluginManager.php
plugins/admin/SecurityLog.php
plugins/admin/ThemeManager.php
plugins/admin/UserManager.php
plugins/admin/UserRanks.php
--- a/README	Sat Jan 03 18:11:18 2009 -0500
+++ b/README	Sun Jan 04 00:55:40 2009 -0500
@@ -1,5 +1,5 @@
 Enano CMS
-Version 1.1.5
+Version 1.1.6
 -----------------------------
 
 Thanks for downloading Enano! If you're looking for an installation guide,
@@ -9,7 +9,7 @@
 -----------------------------
 
 Enano CMS
-Copyright (C) 2006-2008 Dan Fuhry. All rights except those explicitly granted
+Copyright (C) 2006-2009 Dan Fuhry. All rights except those explicitly granted
 by the included license agreement reserved.
 
 PHILOSOPHY
--- a/ajax.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/ajax.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
--- a/cron.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/cron.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
--- a/includes/cache.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/includes/cache.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
--- a/includes/captcha.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/includes/captcha.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  * captcha.php - visual confirmation system used during registration
  *
--- a/includes/captcha/engine_default.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/includes/captcha/engine_default.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  * captcha.php - visual confirmation system used during registration
  *
--- a/includes/captcha/engine_failsafe.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/includes/captcha/engine_failsafe.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  * captcha.php - visual confirmation system used during registration
  *
--- a/includes/captcha/engine_potpourri.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/includes/captcha/engine_potpourri.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  * captcha.php - visual confirmation system used during registration
  *
--- a/includes/clientside/jscompress.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/includes/clientside/jscompress.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  * jsres.php - the Enano client-side runtime, a.k.a. AJAX on steroids
  *
--- a/includes/clientside/jsres.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/includes/clientside/jsres.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  * jsres.php - the Enano client-side runtime, a.k.a. AJAX on steroids
  *
--- a/includes/clientside/tinymce/tiny_mce_gzip.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/includes/clientside/tinymce/tiny_mce_gzip.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  * tiny_mce_gzip.php - TinyMCE gzip and caching script, stock from MoxieCode with one modification
  *
--- a/includes/comment.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/includes/comment.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
--- a/includes/common.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/includes/common.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
@@ -44,7 +44,7 @@
 // be the expected output of enano_version(), which will always be in the
 // format of 1.0.2, 1.0.2a1, 1.0.2b1, 1.0.2RC1
 // You'll want to change this for custom distributions.
-$version = '1.1.5';
+$version = '1.1.6';
 
 /**
  * Returns a floating-point number with the current UNIX timestamp in microseconds. Defined very early because we gotta call it
@@ -147,6 +147,7 @@
 require_once(ENANO_ROOT.'/includes/pageprocess.php');
 require_once(ENANO_ROOT.'/includes/namespaces/default.php');
 require_once(ENANO_ROOT.'/includes/tagcloud.php');
+require_once(ENANO_ROOT.'/includes/hmac.php');
 
 strip_magic_quotes_gpc();
 
--- a/includes/common_cli.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/includes/common_cli.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
--- a/includes/constants.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/includes/constants.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  * constants.php - important defines used Enano-wide
  *
--- a/includes/dbal.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/includes/dbal.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
--- a/includes/diff.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/includes/diff.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
--- a/includes/diffiehellman.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/includes/diffiehellman.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  * diffiehellman.php - Diffie Hellman key exchange and supporting functions
  *
--- a/includes/email.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/includes/email.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
--- a/includes/functions.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/includes/functions.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
@@ -1259,6 +1259,7 @@
       '1.1.3'  => 'Caoineag alpha 3',
       '1.1.4'  => 'Caoineag alpha 4',
       '1.1.5'  => 'Caoineag alpha 5',
+      '1.1.6'  => 'Caoineag beta 1'
     );
   $version = enano_version();
   if ( isset($names[$version]) )
--- a/includes/graphs.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/includes/graphs.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/hmac.php	Sun Jan 04 00:55:40 2009 -0500
@@ -0,0 +1,89 @@
+<?php
+
+/*
+ * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
+ * Version 1.1.6 (Caoineag beta 1)
+ * Copyright (C) 2006-2008 Dan Fuhry
+ * hmac.php - HMAC cryptographic functions
+ *
+ * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
+ */
+
+function hmac_gen_padding($val, $len = 32)
+{
+  $ret = array();
+  for ( $i = 0; $i < $len; $i++ )
+  {
+    $ret[] = $val;
+  }
+  return $ret;
+}
+
+function hmac_core($message, $key, $hashfunc)
+{
+  static $block_sizes = array();
+  if ( !isset($block_sizes[$hashfunc]) )
+  {
+    $block_sizes[$hashfunc] = strlen($hashfunc(''))/2;
+  }
+  $blocksize = $block_sizes[$hashfunc];
+  $ipad = hmac_gen_padding(0x5c, $blocksize);
+  $opad = hmac_gen_padding(0x36, $blocksize);
+  if ( strlen($key) != ( $blocksize * 2 ) )
+    $key = $hashfunc($key);
+  $key = hmac_hexbytearray($key);
+  for ( $i = 0; $i < count($key); $i++ )
+  {
+    $ipad[$i] = $ipad[$i] ^ $key[$i];
+    $opad[$i] = $opad[$i] ^ $key[$i];
+  }
+  return $hashfunc(hmac_bytearraytostring($opad) . $hashfunc(hmac_bytearraytostring($ipad) . $message));
+}
+
+function hmac_hexbytearray($val)
+{
+  $val = hexdecode($val);
+  return hmac_bytearray($val);
+}
+
+function hmac_bytearray($val)
+{
+  $val = str_split($val, 1);
+  foreach ( $val as &$char )
+  {
+    $char = ord($char);
+  }
+  return $val;
+}
+
+function hmac_bytearraytostring($val)
+{
+  foreach ( $val as &$char )
+  {
+    $char = chr($char);
+  }
+  return implode('', $val);
+}
+
+function hmac_md5($message, $key)
+{
+  return hmac_core($message, $key, 'md5');
+}
+
+function hmac_sha1($message, $key)
+{
+  return hmac_core($message, $key, 'sha1');
+}
+
+function hmac_sha256($message, $key)
+{
+  require_once(ENANO_ROOT . '/includes/math.php');
+  require_once(ENANO_ROOT . '/includes/diffiehellman.php');
+  return hmac_core($message, $key, 'sha256');
+}
+
+?>
--- a/includes/http.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/includes/http.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  * class_http.php - Pure PHP HTTP client library
  *
--- a/includes/js-compressor.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/includes/js-compressor.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  * Javascript compression library - used to compact the client-side Javascript code (all 72KB of it!) to save some bandwidth
  *
--- a/includes/lang.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/includes/lang.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
--- a/includes/math.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/includes/math.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  * diffiehellman.php - Diffie Hellman key exchange and supporting functions
  *
--- a/includes/namespaces/admin.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/includes/namespaces/admin.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
--- a/includes/namespaces/api.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/includes/namespaces/api.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
--- a/includes/namespaces/default.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/includes/namespaces/default.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
--- a/includes/namespaces/file.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/includes/namespaces/file.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
--- a/includes/namespaces/special.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/includes/namespaces/special.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
--- a/includes/namespaces/template.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/includes/namespaces/template.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
--- a/includes/namespaces/user.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/includes/namespaces/user.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
--- a/includes/output.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/includes/output.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * output.php - Controls output format, messages of death, that kind of stuff
  * Copyright (C) 2006-2008 Dan Fuhry
  *
--- a/includes/pageprocess.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/includes/pageprocess.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * pageprocess.php - intelligent retrieval of pages
  * Copyright (C) 2006-2008 Dan Fuhry
  *
--- a/includes/pageutils.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/includes/pageutils.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  * pageutils.php - a class that handles raw page manipulations, used mostly by AJAX requests or their old-fashioned form-based counterparts
  *
--- a/includes/paths.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/includes/paths.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /**
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  * paths.php - The part of Enano that actually manages content. Everything related to page handling and namespaces is in here.
  *
--- a/includes/plugins.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/includes/plugins.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
--- a/includes/render.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/includes/render.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  * render.php - handles fetching pages and parsing them into HTML
  *
--- a/includes/rijndael.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/includes/rijndael.php	Sun Jan 04 00:55:40 2009 -0500
@@ -1658,25 +1658,30 @@
    * @return string a BINARY key
    */
   
-  function randkey($len = 32)
+  static function randkey($len = 32)
+  {
+    if ( @file_exists('/dev/urandom') && @is_readable('/dev/urandom') )
+    {
+      // Let's use something a little more secure
+      $ur = @fopen('/dev/urandom', 'r');
+      if ( !$ur )
+        return self::randkey_safe($len);
+      $ukey = @fread($ur, $len);
+      fclose($ur);
+      if ( strlen($ukey) != $len )
+        return self::randkey_safe($len);
+      return $ukey;
+    }
+    return self::randkey_safe($len);
+  }
+  
+  static function randkey_safe($len = 32)
   {
     $key = '';
     for($i=0;$i<$len;$i++)
     {
       $key .= chr(mt_rand(0, 255));
     }
-    if ( @file_exists('/dev/urandom') && @is_readable('/dev/urandom') )
-    {
-      // Let's use something a little more secure
-      $ur = @fopen('/dev/urandom', 'r');
-      if ( !$ur )
-        return $key;
-      $ukey = @fread($ur, $len);
-      fclose($ur);
-      if ( strlen($ukey) != $len )
-        return $key;
-      return $ukey;
-    }
     return $key;
   }
   
--- a/includes/search.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/includes/search.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  * search.php - algorithm used to search pages
  *
--- a/includes/sessions.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/includes/sessions.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  * sessions.php - everything related to security and user management
  *
@@ -501,7 +501,7 @@
           }
           else
           {
-            $key = strrev($_REQUEST['auth']);
+            $key = $_REQUEST['auth'];
             if ( !empty($key) && ( strlen($key) / 2 ) % 4 == 0 )
             {
               $super = $this->validate_session($key);
@@ -645,7 +645,14 @@
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
     
-    $pass_hashed = ( $already_md5ed ) ? $password : md5($password);
+    if ( $already_md5ed )
+    {
+      // No longer supported
+      return array(
+          'mode' => 'error',
+          'error' => '$already_md5ed is no longer supported (set this parameter to false and make sure the password you send to $session->login_without_crypto() is not hashed)'
+        );
+    }
     
     // Replace underscores with spaces in username
     // (Added in 1.0.2)
@@ -654,7 +661,7 @@
     // Perhaps we're upgrading Enano?
     if($this->compat)
     {
-      return $this->login_compat($username, $pass_hashed, $level);
+      return $this->login_compat($username, md5($password), $level);
     }
     
     if ( !defined('IN_ENANO_INSTALL') )
@@ -710,7 +717,13 @@
     $success = false;
     
     // Retrieve the real password from the database
-    $this->sql('SELECT password,old_encryption,user_id,user_level,temp_password,temp_password_time FROM '.table_prefix.'users WHERE ' . ENANO_SQLFUNC_LOWERCASE . '(username)=\''.$this->prepare_text(strtolower($username)).'\';');
+    $username_db = $db->escape(strtolower($username));
+    if ( !$db->sql_query('SELECT password,password_salt,old_encryption,user_id,user_level,temp_password,temp_password_time FROM '.table_prefix."users\n"
+                       . "  WHERE " . ENANO_SQLFUNC_LOWERCASE . "(username) = '$username_db';") )
+    {
+      $this->sql('SELECT password,\'\' AS password_salt,old_encryption,user_id,user_level,temp_password,temp_password_time FROM '.table_prefix."users\n"
+               . "  WHERE " . ENANO_SQLFUNC_LOWERCASE . "(username) = '$username_db';");
+    }
     if($db->numrows() < 1)
     {
       // This wasn't logged in <1.0.2, dunno how it slipped through
@@ -747,8 +760,8 @@
     
     if((intval($row['temp_password_time']) + 3600*24) > time() )
     {
-      $temp_pass = $aes->decrypt( $row['temp_password'], $this->private_key, ENC_HEX );
-      if( md5($temp_pass) == $pass_hashed )
+      $temp_pass = hmac_sha1($password, $row['password_salt']);
+      if( $temp_pass === $row['temp_password'] )
       {
         $code = $plugins->setHook('login_password_reset');
         foreach ( $code as $cmd )
@@ -759,31 +772,41 @@
         return array(
             'success' => false,
             'error' => 'valid_reset',
-            'redirect_url' => makeUrlComplete('Special', 'PasswordReset/stage2/' . $row['user_id'] . '/' . $row['temp_password'])
+            'redirect_url' => makeUrlComplete('Special', 'PasswordReset/stage2/' . $row['user_id'] . '/' . $this->pk_encrypt($password))
           );
       }
     }
     
-    if($row['old_encryption'] == 1)
+    if ( $row['old_encryption'] == 1 )
     {
       // The user's password is stored using the obsolete and insecure MD5 algorithm - we'll update the field with the new password
-      if($pass_hashed == $row['password'] && !$already_md5ed)
+      if(md5($password) === $row['password'])
       {
-        $pass_stashed = $aes->encrypt($password, $this->private_key, ENC_HEX);
-        $this->sql('UPDATE '.table_prefix.'users SET password=\''.$pass_stashed.'\',old_encryption=0 WHERE user_id='.$row['user_id'].';');
+        $hmac_secret = AESCrypt::randkey(20);
+        $password_hmac = hmac_sha1($password, $hmac_secret);
+        $this->sql('UPDATE '.table_prefix."users SET password = '$password_hmac', password_salt = '$hmac_secret', old_encryption = 0 WHERE user_id={$row['user_id']};");
         $success = true;
       }
-      elseif($pass_hashed == $row['password'] && $already_md5ed)
+    }
+    else if ( $row['old_encryption'] == 2 )
+    {
+      // Our password field uses the 1.0RC1-1.1.5 encryption format
+      $real_pass = $aes->decrypt($row['password'], $this->private_key);
+      if($password === $real_pass)
       {
-        // We don't have the real password so don't bother with encrypting it, just call it success and get out of here
+        $success = true;
+        $hmac_secret = AESCrypt::randkey(20);
+        $password_hmac = hmac_sha1($password, $hmac_secret);
+        $this->sql('UPDATE '.table_prefix."users SET password = '$password_hmac', password_salt = '$hmac_secret', old_encryption = 0 WHERE user_id={$row['user_id']};");
         $success = true;
       }
     }
     else
     {
-      // Our password field is up-to-date with the >=1.0RC1 encryption standards, so decrypt the password in the table and see if we have a match
-      $real_pass = $aes->decrypt($row['password'], $this->private_key);
-      if($pass_hashed == md5($real_pass))
+      // Password uses HMAC-SHA1
+      $user_challenge = hmac_sha1($password, $row['password_salt']);
+      $password_hmac =& $row['password'];
+      if ( $user_challenge === $password_hmac )
       {
         $success = true;
       }
@@ -795,7 +818,7 @@
           'success' => false,
           'error' => 'too_big_for_britches'
         );
-      $sess = $this->register_session(intval($row['user_id']), $username, $real_pass, $level, $remember);
+      $sess = $this->register_session($row['user_id'], $username, $password_hmac, $level, $remember);
       if($sess)
       {
         if($level > USER_LEVEL_MEMBER)
@@ -886,37 +909,34 @@
    * Basically the session key is a hex-encoded cookie (encrypted with the site's private key) that says "u=[username];p=[sha1 of password];s=[unique key id]"
    * @param int $user_id
    * @param string $username
-   * @param string $password
+   * @param string $password_hmac The HMAC of the user's password, right from the database
    * @param int $level The level of access to grant, defaults to USER_LEVEL_MEMBER
    * @param bool $remember Whether the session should be long-term (true) or not (false). Defaults to short-term.
    * @return bool
    */
    
-  function register_session($user_id, $username, $password, $level = USER_LEVEL_MEMBER, $remember = false)
+  function register_session($user_id, $username, $password_hmac, $level = USER_LEVEL_MEMBER, $remember = false)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
     
     // Random key identifier
-    $salt = md5(microtime() . mt_rand());
+    $salt = '';
+    for ( $i = 0; $i < 32; $i++ )
+    {
+      $salt .= chr(mt_rand(32, 127));
+    }
     
-    // SHA1 hash of password, stored in the key
-    $passha1 = sha1($password);
-    
-    // Unencrypted session key
-    $session_key = "u=$username;p=$passha1;s=$salt";
+    // Session key
+    $session_key = hmac_sha1($password_hmac, $salt);
     
     // Type of key
     $key_type = ( $level > USER_LEVEL_MEMBER ) ? SK_ELEV : ( $remember ? SK_LONG : SK_SHORT );
     
-    // Encrypt the key
-    $aes = AESCrypt::singleton(AES_BITS, AES_BLOCKSIZE);
-    $session_key = $aes->encrypt($session_key, $this->private_key, ENC_HEX);
-    
     // If we're registering an elevated-privilege key, it needs to be on GET
     if($level > USER_LEVEL_MEMBER)
     {
       // Reverse it - cosmetic only ;-)
-      $hexkey = strrev($session_key);
+      $hexkey = $session_key;
       $this->sid_super = $hexkey;
       $_GET['auth'] = $hexkey;
     }
@@ -943,10 +963,10 @@
       die('Somehow an SQL injection attempt crawled into our session registrar! (2)');
     
     // All done!
-    $query = $db->sql_query('INSERT INTO '.table_prefix.'session_keys(session_key, salt, user_id, auth_level, source_ip, time, key_type) VALUES(\''.$keyhash.'\', \''.$salt.'\', '.$user_id.', '.$level.', \''.$ip.'\', '.$time.', ' . $key_type . ');');
+    $query = $db->sql_query('INSERT INTO '.table_prefix.'session_keys(session_key, salt, user_id, auth_level, source_ip, time, key_type) VALUES(\''.$keyhash.'\', \''.$db->escape($salt).'\', '.$user_id.', '.$level.', \''.$ip.'\', '.$time.', ' . $key_type . ');');
     if ( !$query && defined('IN_ENANO_UPGRADE') )
       // we're trying to upgrade so the key_type column is probably missing - try it again without specifying the key type
-      $this->sql('INSERT INTO '.table_prefix.'session_keys(session_key, salt, user_id, auth_level, source_ip, time) VALUES(\''.$keyhash.'\', \''.$salt.'\', '.$user_id.', '.$level.', \''.$ip.'\', '.$time.');');
+      $this->sql('INSERT INTO '.table_prefix.'session_keys(session_key, salt, user_id, auth_level, source_ip, time) VALUES(\''.$keyhash.'\', \''.$db->escape($salt).'\', '.$user_id.', '.$level.', \''.$ip.'\', '.$time.');');
       
     return true;
   }
@@ -1025,9 +1045,33 @@
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
     profiler_log("SessionManager: checking session: " . sha1($key));
+    
+    if ( strlen($key) > 48 )
+    {
+      return $this->validate_aes_session($key);
+    }
+    
+    profiler_log("SessionManager: checking session: " . $key);
+    
+    return $this->validate_session_shared($key, '');
+  }
+  
+  /**
+   * Validates an old-format AES session key. DO NOT USE THIS. Will return false if called outside of an upgrade.
+   * @param string Session key
+   * @return array
+   */
+  
+  protected function validate_aes_session($key)
+  {
+    global $db, $session, $paths, $template, $plugins; // Common objects
+    
+    // No valid use except during upgrades
+    if ( !preg_match('/^upg-/', enano_version()) || !defined('IN_ENANO_UPGRADE') )
+      return false;
+    
     $aes = AESCrypt::singleton(AES_BITS, AES_BLOCKSIZE);
     $decrypted_key = $aes->decrypt($key, $this->private_key, ENC_HEX);
-    
     if ( !$decrypted_key )
     {
       // die_semicritical('AES encryption error', '<p>Something went wrong during the AES decryption process.</p><pre>'.print_r($decrypted_key, true).'</pre>');
@@ -1042,24 +1086,59 @@
     }
     $keyhash = md5($key);
     $salt = $db->escape($keydata[3]);
-    profiler_log("SessionManager: checking session: " . sha1($key) . ": decrypted session key to $decrypted_key");
+    
+    return $this->validate_session_shared($keyhash, $salt, true);
+  }
+  
+  /**
+   * Shared portion of session validation. Do not try to call this.
+   * @return array
+   * @access private
+   */
+  
+  protected function validate_session_shared($key, $salt, $loose_call = false)
+  {
+    global $db, $session, $paths, $template, $plugins; // Common objects
+    
     // using a normal call to $db->sql_query to avoid failing on errors here
-    $query = $db->sql_query('SELECT u.user_id AS uid,u.username,u.password,u.email,u.real_name,u.user_level,u.theme,u.style,u.signature,' . "\n"
-                             . '    u.reg_time,u.account_active,u.activation_key,u.user_lang,u.user_title,k.source_ip,k.time,k.auth_level,k.key_type,COUNT(p.message_id) AS num_pms,' . "\n"
-                             . '    u.user_timezone, u.user_dst, x.* FROM '.table_prefix.'session_keys AS k' . "\n"
-                             . '  LEFT JOIN '.table_prefix.'users AS u' . "\n"
-                             . '    ON ( u.user_id=k.user_id )' . "\n"
-                             . '  LEFT JOIN '.table_prefix.'users_extra AS x' . "\n"
-                             . '    ON ( u.user_id=x.user_id OR x.user_id IS NULL )' . "\n"
-                             . '  LEFT JOIN '.table_prefix.'privmsgs AS p' . "\n"
-                             . '    ON ( p.message_to=u.username AND p.message_read=0 )' . "\n"
-                             . '  WHERE k.session_key=\''.$keyhash.'\'' . "\n"
-                             . '    AND k.salt=\''.$salt.'\'' . "\n"
-                             . '  GROUP BY u.user_id,u.username,u.password,u.email,u.real_name,u.user_level,u.theme,u.style,u.signature,u.reg_time,u.account_active,u.activation_key,u.user_lang,u.user_timezone,u.user_title,u.user_dst,k.source_ip,k.time,k.auth_level,k.key_type,x.user_id, x.user_aim, x.user_yahoo, x.user_msn, x.user_xmpp, x.user_homepage, x.user_location, x.user_job, x.user_hobbies, x.email_public, x.disable_js_fx;');
+    $columns_select  = "u.user_id AS uid, u.username, u.password, u.password_salt, u.email, u.real_name, u.user_level, u.theme,\n"
+                      . "  u.style,u.signature, u.reg_time, u.account_active, u.activation_key, u.user_lang, u.user_title, k.salt, k.source_ip,\n"
+                      . "  k.time, k.auth_level, k.key_type, COUNT(p.message_id) AS num_pms, u.user_timezone, u.user_dst, x.*";
+    
+    $columns_groupby = "u.user_id, u.username, u.password, u.email, u.real_name, u.user_level, u.theme, u.style, u.signature,\n"
+                      . "           u.reg_time, u.account_active, u.activation_key, u.user_lang, u.user_timezone, u.user_title, u.user_dst,\n"
+                      . "           k.salt, k.source_ip, k.time, k.auth_level, k.key_type, x.user_id, x.user_aim, x.user_yahoo, x.user_msn,\n"
+                      . "           x.user_xmpp, x.user_homepage, x.user_location, x.user_job, x.user_hobbies, x.email_public,\n"
+                      . "           x.disable_js_fx";
+    
+    $joins = "  LEFT JOIN " . table_prefix . "users AS u\n"
+            . "    ON ( u.user_id=k.user_id )\n"
+            . "  LEFT JOIN " . table_prefix . "users_extra AS x\n"
+            . "    ON ( u.user_id=x.user_id OR x.user_id IS NULL )\n"
+            . "  LEFT JOIN " . table_prefix . "privmsgs AS p\n"
+            . "    ON ( p.message_to=u.username AND p.message_read=0 )\n";
+    if ( !$loose_call )
+    {
+      $key_md5 = md5($key);
+      $query = $db->sql_query("SELECT $columns_select\n"
+                            . "FROM " . table_prefix . "session_keys AS k\n"
+                            . $joins
+                            . "  WHERE k.session_key='$key_md5'\n"
+                            . "  GROUP BY $columns_groupby;");
+    }
+    else
+    {
+      $query = $db->sql_query("SELECT $columns_select\n"
+                            . "FROM " . table_prefix . "session_keys AS k\n"
+                            . $joins
+                            . "  WHERE k.session_key='$key'\n"
+                            . "    AND k.salt='$salt'\n"
+                            . "  GROUP BY $columns_groupby;");
+    }
     
     if ( !$query && ( defined('IN_ENANO_INSTALL') or defined('IN_ENANO_UPGRADE') ) )
     {
-      $query = $this->sql('SELECT u.user_id AS uid,u.username,u.password,u.email,u.real_name,u.user_level,u.theme,u.style,u.signature,u.reg_time,u.account_active,u.activation_key,k.source_ip,k.time,k.auth_level,COUNT(p.message_id) AS num_pms, 1440 AS user_timezone, \'0;0;0;0;60\' AS user_dst, ' . SK_SHORT . ' AS key_type FROM '.table_prefix.'session_keys AS k
+      $query = $this->sql('SELECT u.user_id AS uid,u.username,u.password,\'\' AS password_salt,u.email,u.real_name,u.user_level,u.theme,u.style,u.signature,u.reg_time,u.account_active,u.activation_key,k.source_ip,k.time,k.auth_level,COUNT(p.message_id) AS num_pms, 1440 AS user_timezone, \'0;0;0;0;60\' AS user_dst, ' . SK_SHORT . ' AS key_type FROM '.table_prefix.'session_keys AS k
                              LEFT JOIN '.table_prefix.'users AS u
                                ON ( u.user_id=k.user_id )
                              LEFT JOIN '.table_prefix.'privmsgs AS p
@@ -1078,7 +1157,8 @@
       return false;
     }
     $row = $db->fetchrow();
-    profiler_log("SessionManager: checking session: " . sha1($key) . ": selected and fetched results");
+    profiler_log("SessionManager: session check: selected and fetched results");
+    
     $row['user_id'] =& $row['uid'];
     $ip = $_SERVER['REMOTE_ADDR'];
     if($row['auth_level'] > $row['user_level'])
@@ -1103,15 +1183,21 @@
         return false;
     }
     
-    // Do the password validation
-    $real_pass = $aes->decrypt($row['password'], $this->private_key, ENC_HEX);
-    
-    //die('<pre>'.print_r($keydata, true).'</pre>');
-    if(sha1($real_pass) != $keydata[2])
+    // $loose_call is turned on only from validate_aes_session
+    if ( !$loose_call )
     {
-      // Failed password check
-      // echo '(debug) $session->validate_session: encrypted password is wrong<br />Real password: '.$real_pass.'<br />Real hash: '.sha1($real_pass).'<br />User hash: '.$keydata[2];
-      return false;
+      $correct_key = hexdecode(hmac_sha1($row['password'], $row['salt']));
+      $user_key = hexdecode($key);
+      if ( $correct_key !== $user_key || !is_string($user_key) )
+      {
+        return false;
+      }
+    }
+    else
+    {
+      // if this is a "loose call", this only works once (during the final upgrade stage). Destroy the contents of session_keys.
+      if ( $row['auth_level'] == USER_LEVEL_ADMIN )
+        $this->sql('DELETE FROM ' . table_prefix . "session_keys;");
     }
     
     // timestamp check
@@ -1156,7 +1242,7 @@
     // If this is an elevated-access or short-term session key, update the time
     if( $row['key_type'] == SK_ELEV || $row['key_type'] == SK_SHORT )
     {
-      $this->sql('UPDATE '.table_prefix.'session_keys SET time='.time().' WHERE session_key=\''.$keyhash.'\';');
+      $this->sql('UPDATE '.table_prefix.'session_keys SET time='.time().' WHERE session_key=\''.md5($key).'\';');
     }
     
     $user_extra = array();
@@ -1169,7 +1255,7 @@
     $this->user_extra = $user_extra;
     // Leave the rest to PHP's automatic garbage collector ;-)
     
-    $row['password'] = md5($real_pass);
+    $row['password'] = '';
     $row['user_timezone'] = intval($row['user_timezone']) - 1440;
     
     profiler_log("SessionManager: finished session check");
@@ -1256,12 +1342,8 @@
       {
         return 'success';
       }
-      // See if we can get rid of the cached decrypted session key
-      $key_bin = hex2bin(strrev($this->sid_super));
-      $key_hash = sha1($key_bin . '::' . $this->private_key);
-      aes_decrypt_cache_destroy($key_hash);
       // Destroy elevated privileges
-      $keyhash = md5(strrev($this->sid_super));
+      $keyhash = md5($this->sid_super);
       $this->sql('DELETE FROM '.table_prefix.'session_keys WHERE session_key=\''.$keyhash.'\' AND user_id=\'' . $this->user_id . '\';');
       $this->sid_super = false;
       $this->auth_level = USER_LEVEL_MEMBER;
@@ -1996,8 +2078,18 @@
    
   function register_temp_password($user_id, $password)
   {
-    $aes = AESCrypt::singleton(AES_BITS, AES_BLOCKSIZE);
-    $temp_pass = $aes->encrypt($password, $this->private_key, ENC_HEX);
+    global $db;
+    if ( !is_int($user_id) )
+      return false;
+    
+    $this->sql('SELECT password_salt FROM ' . table_prefix . "users WHERE user_id = $user_id;");
+    if ( $db->numrows() < 1 )
+      return false;
+    
+    list($salt) = $db->fetchrow_num();
+    $db->free_result();
+    
+    $temp_pass = hmac_sha1($password, $salt);
     $this->sql('UPDATE '.table_prefix.'users SET temp_password=\'' . $temp_pass . '\',temp_password_time='.time().' WHERE user_id='.intval($user_id).';');
   }
   
@@ -2285,6 +2377,27 @@
   }
   
   /**
+   * Sets a user's password.
+   * @param int|string User ID or username
+   * @param string New password
+   */
+  
+  function set_password($user, $password)
+  {
+    // Generate new password and salt
+    $hmac_secret = hexencode(AESCrypt::randkey(20), '', '');
+    $password_hmac = hmac_sha1($password, $hmac_secret);
+    
+    // Figure out how we want to specify the user
+    $uidcol = is_int($user) ? "user_id = $user" : ENANO_SQLFUNC_LOWERCASE . "(username) = '" . strtolower($this->prepare_text($user)) . "'";
+    
+    // Perform update
+    $this->sql('UPDATE ' . table_prefix . "users SET old_encryption = 0, password = '$password_hmac', password_salt = '$hmac_secret' WHERE $uidcol;");
+    
+    return true;
+  }
+  
+  /**
    * Encrypts a string using the site's private key.
    * @param string
    * @param int Return type - one of ENC_BINARY, ENC_HEX, ENC_BASE64
@@ -3389,7 +3502,7 @@
   }
   
   /**
-   * Generates some Javascript that calls the AES encryption library.
+   * Generates some Javascript that calls the AES encryption library. Put this after your </form>.
    * @param string The name of the form
    * @param string The name of the password field
    * @param string The name of the field that switches encryption on or off
@@ -3402,15 +3515,16 @@
    * @return string
    */
    
-  function aes_javascript($form_name, $pw_field, $use_crypt, $crypt_key, $crypt_data, $challenge, $dh_supported = false, $dh_pubkey = false, $dh_client_pubkey = false)
+  function aes_javascript($form_name, $pw_field, $use_crypt = 'use_crypt', $crypt_key = 'crypt_key', $crypt_data = 'crypt_data', $challenge = 'challenge_data', $dh_supported = 'dh_supported', $dh_pubkey = 'dh_public_key', $dh_client_pubkey = 'dh_client_public_key')
   {
     $code = '
       <script type="text/javascript">
           
-          function runEncryption()
+          function runEncryption(nowhiteout)
           {
             var frm = document.forms.'.$form_name.';
-            whiteOutForm(frm);
+            if ( !nowhiteout )
+              whiteOutForm(frm);
             
             load_component(\'crypto\');
             var testpassed = ' . ( ( isset($_GET['use_crypt']) && $_GET['use_crypt']=='0') ? 'false; // CRYPTO-AUTH DISABLED ON USER REQUEST // ' : '' ) . '( aes_self_test() && md5_vm_test() );
@@ -3429,6 +3543,25 @@
               frm[\'' . $dh_supported . '\'].value = ( use_diffiehellman ) ? "true" : "false";
             }
             
+            if ( frm["' . $pw_field . '_confirm"] )
+            {
+              pass1 = frm.' . $pw_field . '.value;
+              pass2 = frm.' . $pw_field . '_confirm.value;
+              if ( pass1 != pass2 )
+              {
+                load_component("l10n");
+                alert($lang.get("userfuncs_passreset_err_no_match"));
+                return false;
+              }
+              if ( pass1.length < 6 )
+              {
+                load_component("l10n");
+                alert($lang.get("userfuncs_passreset_err_too_short"));
+                return false;
+              }
+              frm.' . $pw_field . '_confirm.value = "";
+            }
+            
             if ( testpassed && use_diffiehellman )
             {
               // try to blank out the table to prevent double submits and what have you
@@ -3506,7 +3639,6 @@
               frm.'.$crypt_data.'.value = cryptstring;
               frm.'.$pw_field.'.value = \'\';
             }
-            return false;
           }
         </script>
         ';
@@ -3514,6 +3646,125 @@
   }
   
   /**
+   * Generates the HTML form elements required for an encrypted logon experience.
+   * @return string
+   */
+  
+  function generate_aes_form()
+  {
+    $return = '<input type="hidden" name="use_crypt" value="no" />';
+    $return .= '<input type="hidden" name="crypt_key" value="' . $this->rijndael_genkey() . '" />';
+    $return .= '<input type="hidden" name="crypt_data" value="" />';
+    $return .= '<input type="hidden" name="challenge_data" value="' . $this->dss_rand() . '" />';
+    
+    require_once(ENANO_ROOT . '/includes/math.php');
+    require_once(ENANO_ROOT . '/includes/diffiehellman.php');
+    
+    global $dh_supported, $_math;
+    if ( $dh_supported )
+    {
+      $dh_key_priv = dh_gen_private();
+      $dh_key_pub = dh_gen_public($dh_key_priv);
+      $dh_key_priv = $_math->str($dh_key_priv);
+      $dh_key_pub = $_math->str($dh_key_pub);
+      // store the keys in the DB
+      $this->sql('INSERT INTO ' . table_prefix . "diffiehellman( public_key, private_key ) VALUES ( '$dh_key_pub', '$dh_key_priv' );");
+      
+      $return .=  "<input type=\"hidden\" name=\"dh_supported\" value=\"true\" />
+            <input type=\"hidden\" name=\"dh_public_key\" value=\"$dh_key_pub\" />
+            <input type=\"hidden\" name=\"dh_client_public_key\" value=\"\" />";
+    }
+    else
+    {
+      $return .=  "<input type=\"hidden\" name=\"dh_supported\" value=\"false\" />";
+    }
+    return $return;
+  }
+  
+  /**
+   * If you used all the same form fields as the normal login interface, this will take care of DiffieHellman for you and return the key.
+   * @param string Password field name (defaults to "password")
+   * @return string
+   */
+  
+  function get_aes_post($fieldname = 'password')
+  {
+    global $db, $session, $paths, $template, $plugins; // Common objects
+    
+    $aes = AESCrypt::singleton(AES_BITS, AES_BLOCKSIZE);
+    if ( $_POST['use_crypt'] == 'yes' )
+    {
+      $crypt_key = $this->fetch_public_key($_POST['crypt_key']);
+      if ( !$crypt_key )
+      {
+        throw new Exception($lang->get('user_err_key_not_found'));
+      }
+      $crypt_key = hexdecode($crypt_key);
+      $data = $aes->decrypt($_POST['crypt_data'], $crypt_key, ENC_HEX);
+    }
+    else if ( $_POST['use_crypt'] == 'yes_dh' )
+    {
+      require_once(ENANO_ROOT . '/includes/math.php');
+      require_once(ENANO_ROOT . '/includes/diffiehellman.php');
+      
+      global $dh_supported, $_math;
+        
+      if ( !$dh_supported )
+      {
+        throw new Exception('Server does not support DiffieHellman, denying request');
+      }
+      
+      // Fetch private key
+      $dh_public = $_POST['dh_public_key'];
+      if ( !preg_match('/^[0-9]+$/', $dh_public) )
+      {
+        throw new Exception('ERR_DH_KEY_NOT_INTEGER');
+      }
+      $q = $db->sql_query('SELECT private_key, key_id FROM ' . table_prefix . "diffiehellman WHERE public_key = '$dh_public';");
+      if ( !$q )
+        $db->die_json();
+      
+      if ( $db->numrows() < 1 )
+      {
+        throw new Exception('ERR_DH_KEY_NOT_FOUND');
+      }
+      
+      list($dh_private, $dh_key_id) = $db->fetchrow_num();
+      $db->free_result();
+      
+      // We have the private key, now delete the key pair, we no longer need it
+      $q = $db->sql_query('DELETE FROM ' . table_prefix . "diffiehellman WHERE key_id = $dh_key_id;");
+      if ( !$q )
+        $db->die_json();
+      
+      // Generate the shared secret
+      $dh_secret = dh_gen_shared_secret($dh_private, $_POST['dh_client_public_key']);
+      $dh_secret = $_math->str($dh_secret);
+      
+      // Did we get all our math right?
+      $dh_secret_check = sha1($dh_secret);
+      $dh_hash = $_POST['crypt_key'];
+      if ( $dh_secret_check !== $dh_hash )
+      {
+        throw new Exception('ERR_DH_HASH_NO_MATCH');
+      }
+      
+      // All good! Generate the AES key
+      $aes_key = substr(sha256($dh_secret), 0, ( AES_BITS / 4 ));
+      
+      // decrypt user info
+      $aes_key = hexdecode($aes_key);
+      $aes = AESCrypt::singleton(AES_BITS, AES_BLOCKSIZE);
+      $data = $aes->decrypt($_POST['crypt_data'], $aes_key, ENC_HEX);
+    }
+    else
+    {
+      $data = $_POST[$fieldname];
+    }
+    return $data;
+  }
+  
+  /**
    * Backend code for the JSON login interface. Basically a frontend to the session API that takes all parameters in one huge array.
    * @param array LoginAPI request
    * @return array LoginAPI response
@@ -3736,7 +3987,7 @@
         
         // If we're logging in with a temp password, attach to the login_password_reset hook to send our JSON response
         // A bit hackish since it just dies with the response :-(
-        $plugins->attachHook('login_password_reset', '$this->process_login_request(array(\'mode\' => \'respond_password_reset\', \'user_id\' => $row[\'user_id\'], \'temp_password\' => $row[\'temp_password\']));');
+        $plugins->attachHook('login_password_reset', '$this->process_login_request(array(\'mode\' => \'respond_password_reset\', \'user_id\' => $row[\'user_id\'], \'temp_password\' => $this->pk_encrypt($password)));');
         
         // attempt the login
         // function login_without_crypto($username, $password, $already_md5ed = false, $level = USER_LEVEL_MEMBER, $captcha_hash = false, $captcha_code = false)
--- a/includes/sql_parse.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/includes/sql_parse.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  * Installation package
  * sql_parse.php - SQL query splitter and templater
--- a/includes/stats.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/includes/stats.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  * stats.php - handles statistics for pages (disablable in the admin CP)
  *
--- a/includes/tagcloud.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/includes/tagcloud.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
--- a/includes/template.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/includes/template.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
--- a/includes/wikiengine/Tables.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/includes/wikiengine/Tables.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
--- a/includes/wikiformat.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/includes/wikiformat.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
--- a/index.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/index.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
--- a/install/includes/common.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/install/includes/common.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  * Installation package
  * common.php - Installer common functions
@@ -16,8 +16,8 @@
 
 // Our version number. This needs to be changed for any custom releases.
 $installer_version = array(
-  'version' => '1.1.5',
-  'type' => 'alpha'
+  'version' => '1.1.6',
+  'type' => 'beta'
   // If type is set to "rc", "beta", or "alpha", optionally another version number can be issued with the key 'sub':
   // 'sub' => '3' will produce Enano 1.1.1a3 / Enano 1.1.1 alpha 3
 );
@@ -105,6 +105,7 @@
 require_once(ENANO_ROOT . '/includes/json.php');
 require_once(ENANO_ROOT . '/includes/constants.php');
 require_once(ENANO_ROOT . '/includes/rijndael.php');
+require_once(ENANO_ROOT . '/includes/hmac.php');
 
 // If we have at least PHP 5, load json2
 if ( version_compare(PHP_VERSION, '5.0.0', '>=') )
--- a/install/includes/libenanoinstall.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/install/includes/libenanoinstall.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  * Installation package
  * libenanoinstall.php - Installation payload backend
--- a/install/includes/payload.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/install/includes/payload.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  * Installation package
  * payload.php - Installer payload (the installation logic)
@@ -96,11 +96,12 @@
     return $sql_parser->parse();
   
   $aes = AESCrypt::singleton(AES_BITS, AES_BLOCKSIZE);
+  $hmac_secret = hexencode(AESCrypt::randkey(20), '', '');
   
   $site_key = stg_make_private_key();
   $site_key = hexdecode($site_key);
   $admin_pass_clean = stg_password_decode();
-  $admin_pass = $aes->encrypt($admin_pass_clean, $site_key, ENC_HEX);
+  $admin_pass = hmac_sha1($admin_pass_clean, $hmac_secret);
   
   unset($admin_pass_clean); // Security
   
@@ -137,6 +138,7 @@
       'VERSION'              => $installer_version['version'],
       'ADMIN_USER'           => $db->escape($_POST['username']),
       'ADMIN_PASS'           => $admin_pass,
+      'ADMIN_PASS_SALT'      => $hmac_secret,
       'ADMIN_EMAIL'          => $db->escape($_POST['email']),
       'REAL_NAME'            => '', // This has always been stubbed.
       'ADMIN_EMBED_PHP'      => strval(AUTH_DISALLOW),
--- a/install/includes/stages/confirm.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/install/includes/stages/confirm.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  * Installation package
  * confirm.php - Installer installation summary/confirmation stage
--- a/install/includes/stages/database.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/install/includes/stages/database.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  * Installation package
  * database.php - Installer database driver selection stage
--- a/install/includes/stages/database_mysql.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/install/includes/stages/database_mysql.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  * Installation package
  * database_mysql.php - Installer database info page, MySQL
--- a/install/includes/stages/database_post.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/install/includes/stages/database_post.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  * Installation package
  * database_post.php - Database installation, stage 1
--- a/install/includes/stages/database_postgresql.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/install/includes/stages/database_postgresql.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  * Installation package
  * database_postgresql.php - Installer database info page, PostgreSQL
--- a/install/includes/stages/finish.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/install/includes/stages/finish.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  * Installation package
  * finish.php - Installer finalization stage
--- a/install/includes/stages/install.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/install/includes/stages/install.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  * Installation package
  * install.php - Installer payload stage
--- a/install/includes/stages/license.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/install/includes/stages/license.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  * Installation package
  * license.php - Installer license-agreement stage
--- a/install/includes/stages/login.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/install/includes/stages/login.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  * Installation package
  * login.php - Installer login information stage
--- a/install/includes/stages/sysreqs.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/install/includes/stages/sysreqs.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  * Installation package
  * sysreqs.php - Installer system-requirements page
--- a/install/includes/stages/website.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/install/includes/stages/website.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  * Installation package
  * website.php - Installer website-settings stage
--- a/install/includes/ui.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/install/includes/ui.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  * Installation package
  * ui.php - User interface for installations and upgrades
--- a/install/index.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/install/index.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  * Installation package
  * welcome.php - Portal to upgrade, readme, and install pages
--- a/install/install.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/install/install.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  * Installation package
  * install.php - Main installation interface
--- a/install/readme.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/install/readme.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  * Installation package
  * install.php - Main installation interface
--- a/install/schemas/mysql_stage2.sql	Sat Jan 03 18:11:18 2009 -0500
+++ b/install/schemas/mysql_stage2.sql	Sun Jan 04 00:55:40 2009 -0500
@@ -93,7 +93,8 @@
 CREATE TABLE {{TABLE_PREFIX}}users(
   user_id mediumint(8) NOT NULL auto_increment,
   username text,
-  password varchar(255),
+  password varchar(40),
+  password_salt varchar(40) NOT NULL DEFAULT '',
   email text,
   real_name text,
   user_level tinyint(1) NOT NULL DEFAULT 2,
@@ -373,9 +374,9 @@
   ('oxygen', 'Oxygen', 1, 'bleu.css', 1),
   ('stpatty', 'St. Patty', 2, 'shamrock.css', 1);
 
-INSERT INTO {{TABLE_PREFIX}}users(user_id, username, password, email, real_name, user_level, theme, style, signature, reg_time, account_active, user_registration_ip) VALUES
-  (1, 'Anonymous', 'invalid-pass-hash', 'anonspam@enanocms.org', 'None', 1, 'oxygen', 'bleu', '', 0, 0, '{{IP_ADDRESS}}'),
-  (2, '{{ADMIN_USER}}', '{{ADMIN_PASS}}', '{{ADMIN_EMAIL}}', '{{REAL_NAME}}', 9, 'oxygen', 'bleu', '', UNIX_TIMESTAMP(), 1, '{{IP_ADDRESS}}');
+INSERT INTO {{TABLE_PREFIX}}users(user_id, username, password, password_salt, email, real_name, user_level, theme, style, signature, reg_time, account_active, user_registration_ip) VALUES
+  (1, 'Anonymous', 'invalid-pass-hash', '', 'anonspam@enanocms.org', 'None', 1, 'oxygen', 'bleu', '', 0, 0, '{{IP_ADDRESS}}'),
+  (2, '{{ADMIN_USER}}', '{{ADMIN_PASS}}', '{{ADMIN_PASS_SALT}}', '{{ADMIN_EMAIL}}', '{{REAL_NAME}}', 9, 'oxygen', 'bleu', '', UNIX_TIMESTAMP(), 1, '{{IP_ADDRESS}}');
   
 INSERT INTO {{TABLE_PREFIX}}users_extra(user_id) VALUES
   (2);
--- a/install/schemas/postgresql_stage2.sql	Sat Jan 03 18:11:18 2009 -0500
+++ b/install/schemas/postgresql_stage2.sql	Sun Jan 04 00:55:40 2009 -0500
@@ -94,6 +94,7 @@
   user_id SERIAL,
   username text,
   password varchar(255),
+  password_salt varchar(40) NOT NULL DEFAULT '',
   email text,
   real_name text,
   user_level smallint NOT NULL DEFAULT 2,
@@ -390,9 +391,9 @@
   ('oxygen', 'Oxygen', 1, 'bleu.css', 1),
   ('stpatty', 'St. Patty', 2, 'shamrock.css', 1);
 
-INSERT INTO {{TABLE_PREFIX}}users(user_id, username, password, email, real_name, user_level, theme, style, signature, reg_time, account_active, user_registration_ip, user_lang, user_has_avatar, avatar_type) VALUES
-  (1, 'Anonymous', 'invalid-pass-hash', 'anonspam@enanocms.org', 'None', 1, 'oxygen', 'bleu', '', 0, 0, '', 0, 0, 'png'),
-  (2, '{{ADMIN_USER}}', '{{ADMIN_PASS}}', '{{ADMIN_EMAIL}}', '{{REAL_NAME}}', 9, 'oxygen', 'bleu', '', {{UNIX_TIME}}, 1, '{{IP_ADDRESS}}', 0, 0, 'png');
+INSERT INTO {{TABLE_PREFIX}}users(user_id, username, password, password_salt, email, real_name, user_level, theme, style, signature, reg_time, account_active, user_registration_ip, user_lang, user_has_avatar, avatar_type) VALUES
+  (1, 'Anonymous', 'invalid-pass-hash', '', 'anonspam@enanocms.org', 'None', 1, 'oxygen', 'bleu', '', 0, 0, '', 0, 0, 'png'),
+  (2, '{{ADMIN_USER}}', '{{ADMIN_PASS}}', '{{ADMIN_PASS_SALT}}', '{{ADMIN_EMAIL}}', '{{REAL_NAME}}', 9, 'oxygen', 'bleu', '', {{UNIX_TIME}}, 1, '{{IP_ADDRESS}}', 0, 0, 'png');
   
 INSERT INTO {{TABLE_PREFIX}}users_extra(user_id) VALUES
   (2);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/install/schemas/upgrade/1.1.5-1.1.6-mysql.sql	Sun Jan 04 00:55:40 2009 -0500
@@ -0,0 +1,2 @@
+ALTER TABLE users ADD COLUMN password_salt varchar(40) NOT NULL DEFAULT '';
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/install/schemas/upgrade/1.1.5-1.1.6-postgresql.sql	Sun Jan 04 00:55:40 2009 -0500
@@ -0,0 +1,2 @@
+ALTER TABLE users ADD COLUMN password_salt varchar(40) NOT NULL DEFAULT '';
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/install/schemas/upgrade/1.1.5-1.1.6.php	Sun Jan 04 00:55:40 2009 -0500
@@ -0,0 +1,35 @@
+<?php
+
+// Migrate passwords to the new encryption scheme
+
+global $db, $session, $paths, $template, $plugins; // Common objects
+require_once(ENANO_ROOT . '/includes/hmac.php');
+
+@set_time_limit(0);
+
+$q = $db->sql_query('UPDATE ' . table_prefix . "users SET old_encryption = 2 WHERE user_id > 1 AND old_encryption = 0;");
+if ( !$q )
+  $db->_die();
+
+$q = $db->sql_query('SELECT user_id, password FROM ' . table_prefix . "users WHERE user_id > 1 AND old_encryption = 2;");
+if ( !$q )
+  $db->_die();
+
+while ( $row = $db->fetchrow($q) )
+{
+  $password = $session->pk_decrypt($row['password']);
+  if ( empty($password) )
+  {
+    global $ui;
+    echo '<p>1.1.5-1.1.6 migration script: ERROR: bad password returned from $session->pk_decrypt()</p>';
+    $ui->show_footer();
+    exit;
+  }
+  $hmac_secret = hexencode(AESCrypt::randkey(20), '', '');
+  $password = hmac_sha1($password, $hmac_secret);
+  $e = $db->sql_query('UPDATE ' . table_prefix . "users SET password = '{$password}', password_salt = '{$hmac_secret}', old_encryption = 0 WHERE user_id = {$row['user_id']};");
+  if ( !$e )
+    $db->_die();
+}
+
+
--- a/install/upgrade.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/install/upgrade.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  * Installation package
  * upgrade.php - Upgrade interface
@@ -19,7 +19,7 @@
 // The list of versions in THIS AND PREVIOUS branches, in chronological order.
 $enano_versions = array();
 $enano_versions['1.0'] = array('1.0', '1.0.1', '1.0.2b1', '1.0.2', '1.0.3', '1.0.4', '1.0.5');
-$enano_versions['1.1'] = array('1.1.1', '1.1.2', '1.1.3', '1.1.4', '1.1.5');
+$enano_versions['1.1'] = array('1.1.1', '1.1.2', '1.1.3', '1.1.4', '1.1.5', '1.1.6');
 
 // Turn on every imaginable API hack to make common load on older databases
 define('IN_ENANO_UPGRADE', 1);
--- a/plugins/PrivateMessages.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/plugins/PrivateMessages.php	Sun Jan 04 00:55:40 2009 -0500
@@ -12,7 +12,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
--- a/plugins/SpecialAdmin.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/plugins/SpecialAdmin.php	Sun Jan 04 00:55:40 2009 -0500
@@ -12,7 +12,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
--- a/plugins/SpecialCSS.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/plugins/SpecialCSS.php	Sun Jan 04 00:55:40 2009 -0500
@@ -12,7 +12,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
--- a/plugins/SpecialGroups.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/plugins/SpecialGroups.php	Sun Jan 04 00:55:40 2009 -0500
@@ -12,7 +12,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2007 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
--- a/plugins/SpecialPageFuncs.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/plugins/SpecialPageFuncs.php	Sun Jan 04 00:55:40 2009 -0500
@@ -12,7 +12,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
--- a/plugins/SpecialRecentChanges.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/plugins/SpecialRecentChanges.php	Sun Jan 04 00:55:40 2009 -0500
@@ -12,7 +12,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
--- a/plugins/SpecialSearch.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/plugins/SpecialSearch.php	Sun Jan 04 00:55:40 2009 -0500
@@ -12,7 +12,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
--- a/plugins/SpecialUpdownload.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/plugins/SpecialUpdownload.php	Sun Jan 04 00:55:40 2009 -0500
@@ -12,7 +12,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  * SpecialUpdownload.php - handles uploading and downloading of user-uploaded files - possibly the most rigorously security-enforcing script in all of Enano, although sessions.php comes in a close second
  *
--- a/plugins/SpecialUserFuncs.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/plugins/SpecialUserFuncs.php	Sun Jan 04 00:55:40 2009 -0500
@@ -12,7 +12,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
@@ -121,12 +121,6 @@
   global $__login_status;
   global $lang;
   
-  require_once( ENANO_ROOT . '/includes/diffiehellman.php' );
-  global $dh_supported, $_math;
-  
-  $pubkey = $session->rijndael_genkey();
-  $challenge = $session->dss_rand();
-  
   $locked_out = false;
   // are we locked out?
   $threshold = ( $_ = getConfig('lockout_threshold') ) ? intval($_) : 5;
@@ -436,10 +430,6 @@
          </tr>
       </table>
     </div>
-      <input type="hidden" name="challenge_data" value="<?php echo $challenge; ?>" />
-      <input type="hidden" name="use_crypt" value="no" />
-      <input type="hidden" name="crypt_key" value="<?php echo $pubkey; ?>" />
-      <input type="hidden" name="crypt_data" value="" />
       <input type="hidden" name="auth_level" value="<?php echo (string)$level; ?>" />
       <?php if ( $level <= USER_LEVEL_MEMBER ): ?>
       <script type="text/javascript">
@@ -451,34 +441,11 @@
       </script>
       <?php endif; ?>
       <?php
-      // 1.1.4
-      
-      require_once( ENANO_ROOT . '/includes/diffiehellman.php' );
-      
-      global $dh_supported, $_math;
-      if ( $dh_supported )
-      {
-        $dh_key_priv = dh_gen_private();
-        $dh_key_pub = dh_gen_public($dh_key_priv);
-        $dh_key_priv = $_math->str($dh_key_priv);
-        $dh_key_pub = $_math->str($dh_key_pub);
-        // store the keys in the DB
-        $q = $db->sql_query('INSERT INTO ' . table_prefix . "diffiehellman( public_key, private_key ) VALUES ( '$dh_key_pub', '$dh_key_priv' );");
-        if ( !$q )
-          $db->_die();
-        
-        echo "<input type=\"hidden\" name=\"dh_supported\" value=\"true\" />
-              <input type=\"hidden\" name=\"dh_public_key\" value=\"$dh_key_pub\" />
-              <input type=\"hidden\" name=\"dh_client_public_key\" value=\"\" />";
-      }
-      else
-      {
-        echo "<input type=\"hidden\" name=\"dh_supported\" value=\"false\" />";
-      }
+      echo $session->generate_aes_form();
       ?>
     </form>
     <?php
-      echo $session->aes_javascript('loginform', 'pass', 'use_crypt', 'crypt_key', 'crypt_data', 'challenge_data', 'dh_supported', 'dh_public_key', 'dh_client_public_key');
+      echo $session->aes_javascript('loginform', 'pass');
     ?>
   <?php
   $template->footer();
@@ -516,93 +483,28 @@
   }
   if ( isset($_GET['act']) && $_GET['act'] == 'ajaxlogin' )
   {
-    echo 'This version of the Enano LoginAPI is deprecated. Please use the action.json method instead.';
+    echo 'This version of the Enano LoginAPI is deprecated. Please clear your browser\'s cache and try your login again. Developers, please use the action.json method instead.';
     return true;
   }
   if(isset($_POST['login']))
   {
     $captcha_hash = ( isset($_POST['captcha_hash']) ) ? $_POST['captcha_hash'] : false;
     $captcha_code = ( isset($_POST['captcha_code']) ) ? $_POST['captcha_code'] : false;
-    if ( $_POST['use_crypt'] == 'yes' )
+    
+    try
     {
-      $result = $session->login_with_crypto($_POST['username'], $_POST['crypt_data'], $_POST['crypt_key'], $_POST['challenge_data'], intval($_POST['auth_level']), $captcha_hash, $captcha_code, isset($_POST['remember']));
+      $password = $session->get_aes_post('pass');
     }
-    else if ( $_POST['use_crypt'] == 'yes_dh' )
+    catch ( Exception $e )
     {
-      // retrieve and decrypt the password using DiffieHellman
-      
-      require_once( ENANO_ROOT . '/includes/diffiehellman.php' );
-      global $dh_supported, $_math;
-      
-      if ( !$dh_supported )
-      {
-        die_semicritical('DiffieHellman error', 'Server does not support DiffieHellman, denying logon request');
-      }
-      
-      // Fetch private key
-      $dh_public = $_POST['dh_public_key'];
-      if ( !preg_match('/^[0-9]+$/', $dh_public) )
-      {
-        $__login_status = array(
-          'success' => false,
-          'error' => 'ERR_DH_KEY_NOT_INTEGER',
-          'debug' => "public key: $dh_public"
-        );
-        return false;
-      }
-      $q = $db->sql_query('SELECT private_key, key_id FROM ' . table_prefix . "diffiehellman WHERE public_key = '$dh_public';");
-      if ( !$q )
-        $db->die_json();
-      
-      if ( $db->numrows() < 1 )
-      {
-        $__login_status = array(
-          'success' => false,
-          'error' => 'ERR_DH_KEY_NOT_FOUND',
-          'debug' => "public key: $dh_public"
-        );
-        return false;
-      }
-      
-      list($dh_private, $dh_key_id) = $db->fetchrow_num();
-      $db->free_result();
-      
-      // We have the private key, now delete the key pair, we no longer need it
-      $q = $db->sql_query('DELETE FROM ' . table_prefix . "diffiehellman WHERE key_id = $dh_key_id;");
-      if ( !$q )
-        $db->die_json();
-      
-      // Generate the shared secret
-      $dh_secret = dh_gen_shared_secret($dh_private, $_POST['dh_client_public_key']);
-      $dh_secret = $_math->str($dh_secret);
-      
-      // Did we get all our math right?
-      $dh_secret_check = sha1($dh_secret);
-      $dh_hash = $_POST['crypt_key'];
-      if ( $dh_secret_check !== $dh_hash )
-      {
-        $__login_status = array(
-          'success' => false,
-          'error' => 'ERR_DH_HASH_NO_MATCH',
-          'debug' => "dh_secret_check = $dh_secret_check\ndh_hash_input = $dh_hash"
-        );
-        return false;
-      }
-      
-      // All good! Generate the AES key
-      $aes_key = substr(sha256($dh_secret), 0, ( AES_BITS / 4 ));
-      
-      // decrypt user info
-      $aes_key = hexdecode($aes_key);
-      $aes = AESCrypt::singleton(AES_BITS, AES_BLOCKSIZE);
-      $password = $aes->decrypt($_POST['crypt_data'], $aes_key, ENC_HEX);
-      
-      $result = $session->login_without_crypto($_POST['username'], $password, false, intval($_POST['auth_level']), $captcha_hash, $captcha_code, isset($_POST['remember']));
+      $__login_status = array(
+        'mode' => 'error',
+        'error' => $e->getMessage()
+      );
+      return false;
     }
-    else
-    {
-      $result = $session->login_without_crypto($_POST['username'], $_POST['pass'], false, intval($_POST['auth_level']), $captcha_hash, $captcha_code, isset($_POST['remember']));
-    }
+    
+    $result = $session->login_without_crypto($_POST['username'], $password, false, intval($_POST['auth_level']), $captcha_hash, $captcha_code, isset($_POST['remember']));
    
     if($result['success'])
     {
@@ -1598,6 +1500,9 @@
   $template->header();
   if($paths->getParam(0) == 'stage2')
   {
+    require_once(ENANO_ROOT . '/includes/math.php');
+    require_once(ENANO_ROOT . '/includes/diffiehellman.php');
+    
     $user_id = intval($paths->getParam(1));
     $encpass = $paths->getParam(2);
     if ( $user_id < 2 )
@@ -1613,7 +1518,7 @@
       return false;
     }
     
-    $q = $db->sql_query('SELECT username,temp_password_time FROM '.table_prefix.'users WHERE user_id='.$user_id.' AND temp_password=\'' . $encpass . '\';');
+    $q = $db->sql_query('SELECT username,temp_password_time,temp_password,password_salt FROM '.table_prefix.'users WHERE user_id='.$user_id.';');
     if($db->numrows() < 1)
     {
       echo '<p>Invalid credentials</p>';
@@ -1623,6 +1528,16 @@
     $row = $db->fetchrow();
     $db->free_result();
     
+    $temp_pass = $session->pk_decrypt($encpass);
+    $temp_hmac = hmac_sha1($temp_pass, $row['password_salt']);
+    
+    if ( $temp_hmac !== $row['temp_password'] )
+    {
+      echo '<p>Invalid credentials</p>';
+      $template->footer();
+      return false;
+    }
+    
     if ( ( intval($row['temp_password_time']) + ( 3600 * 24 ) ) < time() )
     {
       echo '<p>' . $lang->get('userfuncs_passreset_err_pass_expired', array('reset_url' => makeUrlNS('Special', 'PasswordReset'))) . '</p>';
@@ -1632,48 +1547,29 @@
     
     if ( isset($_POST['do_stage2']) )
     {
-      $aes = AESCrypt::singleton(AES_BITS, AES_BLOCKSIZE);
-      if($_POST['use_crypt'] == 'yes')
-      {
-        $crypt_key = $session->fetch_public_key($_POST['crypt_key']);
-        if(!$crypt_key)
-        {
-          echo $lang->get('user_err_key_not_found');
-          $template->footer();
-          return false;
-        }
-        $crypt_key = hexdecode($crypt_key);
-        $data = $aes->decrypt($_POST['crypt_data'], $crypt_key, ENC_HEX);
-        if(strlen($data) < 6)
-        {
-          echo $lang->get('userfuncs_passreset_err_too_short');
-          $template->footer();
-          return false;
-        }
-      }
-      else
-      {
-        $data = $_POST['pass'];
-        $conf = $_POST['pass_confirm'];
-        if($data != $conf)
-        {
-          echo $lang->get('userfuncs_passreset_err_no_match');
-          $template->footer();
-          return false;
-        }
-        if(strlen($data) < 6)
-        {
-          echo $lang->get('userfuncs_passreset_err_too_short');
-          $template->footer();
-          return false;
-        }
-      }
+      $data = $session->get_aes_post('pass');
+      
       if(empty($data))
       {
         echo 'ERROR: Sanity check failed!';
         $template->footer();
         return false;
       }
+      if ( strlen($data) < 6 )
+      {
+        echo '<p>' . $lang->get('userfuncs_passreset_err_too_short') . '</p>';
+        $template->footer();
+        return false;
+      }
+      if ( $_POST['use_crypt'] == 'no' )
+      {
+        if ( $_POST['pass'] !== $_POST['pass_confirm'] )
+        {
+          echo '<p>' . $lang->get('userfuncs_passreset_err_no_match') . '</p>';
+          $template->footer();
+          return false;
+        }
+      }
       if ( getConfig('pw_strength_enable') == '1' )
       {
         $min_score = intval(getConfig('pw_strength_minimum'));
@@ -1686,8 +1582,10 @@
           return false;
         }
       }
-      $encpass = $session->pk_encrypt($data, ENC_HEX);
-      $q = $db->sql_query('UPDATE '.table_prefix.'users SET password=\'' . $encpass . '\',temp_password=\'\',temp_password_time=0 WHERE user_id='.$user_id.';');
+      
+      $session->set_password($user_id, $data);
+      
+      $q = $db->sql_query('UPDATE '.table_prefix.'users SET temp_password=\'\',temp_password_time=0 WHERE user_id = '.$user_id.';');
       
       if($q)
       {
@@ -1704,10 +1602,8 @@
     }
     
     // Password reset form
-    $pubkey = $session->rijndael_genkey();
-    
     $evt_get_score = ( getConfig('pw_strength_enable') == '1' ) ? 'onkeyup="password_score_field(this);" ' : '';
-    $pw_meter =      ( getConfig('pw_strength_enable') == '1' ) ? '<tr><td class="row1">' . $lang->get('userfuncs_passreset_stage2_lbl_strength') . '</td><td class="row1"><div id="pwmeter"></div><script type="text/javascript">password_score_field(document.forms.resetform.pass);</script></td></tr>' : '';
+    $pw_meter =      ( getConfig('pw_strength_enable') == '1' ) ? '<tr><td class="row1">' . $lang->get('userfuncs_passreset_stage2_lbl_strength') . '</td><td class="row1"><div id="pwmeter"></div></td></tr>' : '';
     $pw_blurb =      ( getConfig('pw_strength_enable') == '1' && intval(getConfig('pw_strength_minimum')) > -10 ) ? '<br /><small>' . $lang->get('userfuncs_passreset_stage2_blurb_strength') . '</small>' : '';
     
     ?>
@@ -1721,86 +1617,23 @@
           <?php echo $pw_meter; ?>
           <tr>
             <td colspan="2" class="row3" style="text-align: center;">
-              <input type="hidden" name="use_crypt" value="no" />
-              <input type="hidden" name="crypt_key" value="<?php echo $pubkey; ?>" />
-              <input type="hidden" name="crypt_data" value="" />
+              
               <input type="submit" name="do_stage2" value="<?php echo $lang->get('userfuncs_passreset_stage2_btn_submit'); ?>" />
             </td>
           </tr>
         </table>
       </div>
+      <?php echo $session->generate_aes_form(); ?>
     </form>
     <script type="text/javascript">
-    if ( !KILL_SWITCH )
-    {
-      disableJSONExts();
-      str = '';
-      for(i=0;i<keySizeInBits/4;i++) str+='0';
-      var key = hexToByteArray(str);
-      var pt = hexToByteArray(str);
-      var ct = rijndaelEncrypt(pt, key, "ECB");
-      var ct = byteArrayToHex(ct);
-      switch(keySizeInBits)
-      {
-        case 128:
-          v = '66e94bd4ef8a2c3b884cfa59ca342b2e';
-          break;
-        case 192:
-          v = 'aae06992acbf52a3e8f4a96ec9300bd7aae06992acbf52a3e8f4a96ec9300bd7';
-          break;
-        case 256:
-          v = 'dc95c078a2408989ad48a21492842087dc95c078a2408989ad48a21492842087';
-          break;
-      }
-      var testpassed = ( ct == v && md5_vm_test() );
-      var frm = document.forms.resetform;
-      if(testpassed)
+    addOnloadHook(function()
       {
-        frm.use_crypt.value = 'yes';
-        var cryptkey = frm.crypt_key.value;
-        frm.crypt_key.value = hex_md5(cryptkey);
-        cryptkey = hexToByteArray(cryptkey);
-        if(!cryptkey || ( ( typeof cryptkey == 'string' || typeof cryptkey == 'object' ) ) && cryptkey.length != keySizeInBits / 8 )
-        {
-          frm._login.disabled = true;
-          len = ( typeof cryptkey == 'string' || typeof cryptkey == 'object' ) ? '\nLen: '+cryptkey.length : '';
-          alert('The key is messed up\nType: '+typeof(cryptkey)+len);
-        }
-      }
-      function runEncryption()
-      {
-        var frm = document.forms.resetform;
-        pass1 = frm.pass.value;
-        pass2 = frm.pass_confirm.value;
-        if ( pass1 != pass2 )
-        {
-          alert($lang.get('userfuncs_passreset_err_no_match'));
-          return false;
-        }
-        if ( pass1.length < 6 )
-        {
-          alert($lang.get('userfuncs_passreset_err_too_short'));
-          return false;
-        }
-        if(testpassed)
-        {
-          pass = frm.pass.value;
-          pass = stringToByteArray(pass);
-          cryptstring = rijndaelEncrypt(pass, cryptkey, 'ECB');
-          if(!cryptstring)
-          {
-            return false;
-          }
-          cryptstring = byteArrayToHex(cryptstring);
-          frm.crypt_data.value = cryptstring;
-          frm.pass.value = "";
-          frm.pass_confirm.value = "";
-        }
-        return true;
-      }
-    }
+        load_component('pwstrength');
+        password_score_field(document.forms.resetform.pass);
+      });
     </script>
     <?php
+    echo $session->aes_javascript('resetform', 'pass', 'use_crypt', 'crypt_key', 'crypt_data', 'challenge_data', 'dh_supported', 'dh_public_key', 'dh_client_public_key');
     $template->footer();
     return true;
   }
--- a/plugins/SpecialUserPrefs.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/plugins/SpecialUserPrefs.php	Sun Jan 04 00:55:40 2009 -0500
@@ -12,7 +12,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  *
  * This program is Free Software; you can redistribute it and/or modify it under the terms of the GNU General Public License
@@ -226,13 +226,9 @@
           $email_changed = true;
         }
         // Obtain password
-        if ( $_POST['use_crypt'] == 'yes' && !empty($_POST['crypt_data']) )
+        if ( !empty($_POST['crypt_data']) || !empty($_POST['newpass']) )
         {
-          $key = $session->fetch_public_key($_POST['crypt_key']);
-          if ( !$key )
-            die('Can\'t lookup key');
-          $key = hexdecode($key);
-          $newpass = $aes->decrypt($_POST['crypt_data'], $key, ENC_HEX);
+          $newpass = $session->get_aes_post('newpass');
           // At this point we know if we _want_ to change the password...
           
           // We can't check the password to see if it matches the confirmation
@@ -255,14 +251,15 @@
               if ( $score_inp < $score_min )
                 $errors .= '<div class="error-box" style="margin: 0 0 10px 0;">' . $lang->get('usercp_emailpassword_err_password_too_weak', array('score' => $score_inp)) . '</div>';
             }
+            if ( $_POST['use_crypt'] == 'no' && $newpass != $_POST['newpass_confirm'] )
+            {
+              $errors .= '<div class="error-box">' . $lang->get('usercp_emailpassword_err_password_no_match') . '</div>';
+            }
             // Encrypt new password
             if ( empty($errors) )
             {
-              $newpass_enc = $session->pk_encrypt($newpass, ENC_HEX);
               // Perform the swap
-              $q = $db->sql_query('UPDATE '.table_prefix.'users SET password=\'' . $newpass_enc . '\' WHERE user_id=' . $session->user_id . ';');
-              if ( !$q )
-                $db->_die();
+              $session->set_password($session->username, $newpass);
               // Log out and back in
               $username = $session->username;
               $session->logout();
@@ -282,39 +279,6 @@
             }
           }
         }
-        else
-        {
-          switch('foo') // allow breaking out of our section...i can't wait until PHP6 (goto support!)
-          {
-            case 'foo':
-              $pass = $_POST['newpass'];
-              if ( $pass != $_POST['newpass_conf'] )
-              {
-                $errors .= '<div class="error-box">' . $lang->get('usercp_emailpassword_err_password_no_match') . '</div>';
-                break;
-              }
-              
-              $session->logout();
-              if ( $email_changed )
-              {
-                if ( getConfig('account_activation') == 'user' )
-                {
-                  redirect(makeUrl(get_main_page()), $lang->get('usercp_emailpassword_msg_profile_success'), $lang->get('usercp_emailpassword_msg_need_activ_user'), 20);
-                }
-                else if ( getConfig('account_activation') == 'admin' )
-                {
-                  redirect(makeUrl(get_main_page()), $lang->get('usercp_emailpassword_msg_profile_success'), $lang->get('usercp_emailpassword_msg_need_activ_admin'), 20);
-                }
-              }
-              else
-              {
-                $session->login_without_crypto($session->username, $newpass);
-                redirect(makeUrlNS('Special', 'Preferences'), $lang->get('usercp_emailpassword_msg_pass_success'), $lang->get('usercp_emailpassword_msg_password_changed'), 5);
-              }
-              
-              return;
-          }
-        }
       }
       $template->tpl_strings['PAGE_NAME'] = $lang->get('usercp_emailpassword_title');
       break;
@@ -359,8 +323,6 @@
       echo '<form action="' . makeUrlNS('Special', 'Preferences/EmailPassword') . '" method="post" onsubmit="return runEncryption();" name="empwform" >';
       
       // Password change form
-      $pubkey = $session->rijndael_genkey();
-      
       echo '<fieldset>
         <legend>' . $lang->get('usercp_emailpassword_grp_chpasswd') . '</legend>
         ' . $lang->get('usercp_emailpassword_field_newpass') . '<br />
@@ -368,7 +330,7 @@
         <br />
         <br />
         ' . $lang->get('usercp_emailpassword_field_newpass_confirm') . '<br />
-        <input type="password" name="newpass_conf" size="30" tabindex="2" />
+        <input type="password" name="newpass_confirm" size="30" tabindex="2" />
         ' . ( getConfig('pw_strength_enable') == '1' ? '<br /><br /><div id="pwmeter"></div>
         <small>' . $lang->get('usercp_emailpassword_msg_password_min_score') . '</small>' : '' ) . '
       </fieldset><br />
@@ -381,75 +343,24 @@
         ' . $lang->get('usercp_emailpassword_field_newemail_confirm') . '<br />
           <input type="text" value="' . ( isset($_POST['newemail']) ? htmlspecialchars($_POST['newemail']) : '' ) . '" name="newemail_conf" size="30" tabindex="4" />
       </fieldset>
-      <input type="hidden" name="use_crypt" value="no" />
-      <input type="hidden" name="crypt_key" value="' . $pubkey . '" />
-      <input type="hidden" name="crypt_data" value="" />
       <br />
       <div style="text-align: right;"><input type="submit" name="submit" value="' . $lang->get('etc_save_changes') . '" tabindex="5" /></div>';
       
+      echo $session->generate_aes_form();
       echo '</form>';
       
       // ENCRYPTION CODE
       ?>
+      <?php if ( getConfig('pw_strength_enable') == '1' ): ?>
       <script type="text/javascript">
-      <?php if ( getConfig('pw_strength_enable') == '1' ): ?>
       addOnloadHook(function()
         {
           password_score_field(document.forms.empwform.newpass);
         });
+      </script>
       <?php endif; ?>
-        
-        function runEncryption()
-        {
-          load_component('crypto');
-          var aes_testpassed = aes_self_test();
-          
-          var frm = document.forms.empwform;
-          if ( frm.newpass.value.length < 1 )
-            return true;
-          
-          pass1 = frm.newpass.value;
-          pass2 = frm.newpass_conf.value;
-          if ( pass1 != pass2 )
-          {
-            alert($lang.get('usercp_emailpassword_err_password_no_match'));
-            return false;
-          }
-          if ( pass1.length < 6 && pass1.length > 0 )
-          {
-            alert($lang.get('usercp_emailpassword_err_password_too_short'));
-            return false;
-          }
-          
-          if(aes_testpassed)
-          {
-            frm.use_crypt.value = 'yes';
-            var cryptkey = frm.crypt_key.value;
-            frm.crypt_key.value = hex_md5(cryptkey);
-            cryptkey = hexToByteArray(cryptkey);
-            if(!cryptkey || ( ( typeof cryptkey == 'string' || typeof cryptkey == 'object' ) ) && cryptkey.length != keySizeInBits / 8 )
-            {
-              frm.submit.disabled = true;
-              len = ( typeof cryptkey == 'string' || typeof cryptkey == 'object' ) ? '\nLen: '+cryptkey.length : '';
-              alert('The key is messed up\nType: '+typeof(cryptkey)+len);
-            }
-            pass = frm.newpass.value;
-            pass = stringToByteArray(pass);
-            cryptstring = rijndaelEncrypt(pass, cryptkey, 'ECB');
-            if(!cryptstring)
-            {
-              return false;
-            }
-            cryptstring = byteArrayToHex(cryptstring);
-            frm.crypt_data.value = cryptstring;
-            frm.newpass.value = "";
-            frm.newpass_conf.value = "";
-          }
-          return true;
-        }
-      </script>
       <?php
-      
+      echo $session->aes_javascript('empwform', 'newpass');
       break;
     case 'Signature':
       if ( isset($_POST['new_sig']) )
--- a/plugins/admin/CacheManager.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/plugins/admin/CacheManager.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
--- a/plugins/admin/GroupManager.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/plugins/admin/GroupManager.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
--- a/plugins/admin/LangManager.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/plugins/admin/LangManager.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
--- a/plugins/admin/PageEditor.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/plugins/admin/PageEditor.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
--- a/plugins/admin/PageGroups.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/plugins/admin/PageGroups.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
--- a/plugins/admin/PageManager.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/plugins/admin/PageManager.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
--- a/plugins/admin/PluginManager.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/plugins/admin/PluginManager.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
--- a/plugins/admin/SecurityLog.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/plugins/admin/SecurityLog.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
--- a/plugins/admin/ThemeManager.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/plugins/admin/ThemeManager.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
--- a/plugins/admin/UserManager.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/plugins/admin/UserManager.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
@@ -76,72 +76,7 @@
         $password = false;
         if ( $_POST['changing_pw'] == 'yes' )
         {
-          $aes = AESCrypt::singleton(AES_BITS, AES_BLOCKSIZE);
-          if ( $_POST['dh_supported'] === 'true' )
-          {
-            $my_public = $_POST['dh_public'];
-            $remote_public = $_POST['dh_mypublic'];
-            
-            // Check the key
-            if ( !preg_match('/^[0-9]+$/', $my_public) || !preg_match('/^[0-9]+$/', $remote_public) )
-            {
-              $errors[] = $lang->get('user_err_dh_key_not_numeric');
-            }
-            else
-            {
-              // We have our own public key - cross reference it with the private key in the database
-              $q = $db->sql_query('SELECT private_key, key_id FROM ' . table_prefix . "diffiehellman WHERE public_key = '$my_public';");
-              if ( !$q )
-                $db->_die();
-              
-              if ( $db->numrows() < 1 )
-              {
-                $errors[] = $lang->get('user_err_dh_key_not_found');
-              }
-              else
-              {
-                list($my_private, $key_id) = $db->fetchrow_num($q);
-                $db->free_result();
-                // now that we have this key it can be disposed of
-                $q = $db->sql_query("DELETE FROM " . table_prefix . "diffiehellman WHERE key_id = $key_id;");
-                if ( !$q )
-                  $db->_die();
-                // get the shared secret
-                $dh_secret = dh_gen_shared_secret($my_private, $remote_public);
-                global $_math;
-                $dh_secret = $_math->str($dh_secret);
-                
-                // make sure we calculated everything right
-                $secret_check = sha1($dh_secret);
-                if ( $secret_check !== $_POST['crypt_key'] )
-                {
-                  // uh-oh.
-                  $errors[] = $lang->get('user_err_dh_key_not_found');
-                }
-                else
-                {
-                  $aes_key = substr(sha256($dh_secret), 0, ( AES_BITS / 4 ));
-                  $aes_key = hexdecode($aes_key);
-                  $password = $aes->decrypt($_POST['crypt_data'], $aes_key, ENC_HEX);
-                }
-              }
-            }
-          }
-          else if ( $_POST['dh_supported'] === 'false' )
-          {
-            $key_hex_md5 = $_POST['crypt_key'];
-            $key_hex = $session->fetch_public_key($key_hex_md5);
-            if ( $key_hex )
-            {
-              $key_bin = hexdecode($key_hex);
-              $data_hex = $_POST['crypt_data'];
-              $password = $aes->decrypt($data_hex, $key_bin, ENC_HEX);
-            }
-          }
-          else
-          {
-            $errors[] = $lang->get('acpum_err_no_aes_key');
-          }
+          $password = $session->get_aes_post('new_password');
         }
         
         $email = $_POST['email'];
@@ -939,13 +874,7 @@
             <!-- BEGINNOT same_user -->
             if ( form.changing_pw.value == 'yes' )
             {
-              if ( form.new_password.value != form.new_password_confirm.value )
-              {
-                alert(\$lang.get('user_reg_err_alert_password_nomatch'));
-                return false;
-              }
-              form.new_password_confirm.value = '';
-              runEncryption();
+              return runEncryption(true);
             }
             <!-- END same_user -->
             return true;
@@ -1003,13 +932,7 @@
                         {lang:acpum_msg_same_user_password} <a href="#" onclick="userform_{UUID}_chpasswd_cancel(); return false;">{lang:etc_cancel}</a>
                       <!-- BEGINELSE same_user -->
                       <input type="hidden" name="changing_pw" value="no" />
-                      <input type="hidden" name="challenge_data" value="{MD5_CHALLENGE}" />
-                      <input type="hidden" name="use_crypt" value="no" />
-                      <input type="hidden" name="crypt_key" value="{PUBLIC_KEY}" />
-                      <input type="hidden" name="crypt_data" value="" />
-                      <input type="hidden" name="dh_supported" value="{DH_SUPPORTED}" />
-                      <input type="hidden" name="dh_public" value="{DH_PUBLIC}" />
-                      <input type="hidden" name="dh_mypublic" value="" />
+                      {AES_FORM}
                       <table border="0" style="background-color: transparent;" cellspacing="0" cellpadding="0">
                         <tr>
                           <td colspan="2">
@@ -1346,26 +1269,7 @@
     }
     
     $form_action = makeUrlNS('Special', 'Administration', 'module=' . $paths->cpage['module'], true);
-    $aes_javascript = $session->aes_javascript("useredit_$this->uuid", 'new_password', 'use_crypt', 'crypt_key', 'crypt_data', 'challenge_data', 'dh_supported', 'dh_public', 'dh_mypublic');
-    
-    // FIXME should this be in logic rather than presentation code?
-    if ( $dh_supported )
-    {
-      global $_math;
-      
-      $dh_key_priv = dh_gen_private();
-      $dh_key_pub = dh_gen_public($dh_key_priv);
-      $dh_key_priv = $_math->str($dh_key_priv);
-      $dh_key_pub = $_math->str($dh_key_pub);
-      // store the keys in the DB for later fetching
-      $q = $db->sql_query('INSERT INTO ' . table_prefix . "diffiehellman( public_key, private_key ) VALUES ( '$dh_key_pub', '$dh_key_priv' );");
-      if ( !$q )
-        $db->_die();
-    }
-    else
-    {
-      $dh_key_pub = '';
-    }
+    $aes_javascript = $session->aes_javascript("useredit_$this->uuid", 'new_password');
     
     // build rank list
     $q = $db->sql_query('SELECT rank_id, rank_title FROM ' . table_prefix . 'ranks');
@@ -1382,10 +1286,7 @@
         'USERNAME' => $this->username,
         'EMAIL' => $this->email,
         'USER_ID' => $this->user_id,
-        'MD5_CHALLENGE' => $session->dss_rand(),
-        'PUBLIC_KEY' => $session->rijndael_genkey(),
-        'DH_SUPPORTED' => ( $dh_supported ? 'true' : 'false' ),
-        'DH_PUBLIC' => $dh_key_pub,
+        'AES_FORM' => $session->generate_aes_form(),
         'REAL_NAME' => $this->real_name,
         'SIGNATURE_FIELD' => $template->tinymce_textarea('signature', $this->signature, 10, 50),
         'USER_TITLE' => $this->user_title,
--- a/plugins/admin/UserRanks.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/plugins/admin/UserRanks.php	Sun Jan 04 00:55:40 2009 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License