Doc #70520 [Ana]: session_regenerate_id() "Failed to create session ID" with custom SessionHandler

From: Date: Fri, 18 Sep 2015 22:41:26 +0000
Subject: Doc #70520 [Ana]: session_regenerate_id() "Failed to create session ID" with custom SessionHandler
References: 1  Groups: php.doc.bugs 
Request: Send a blank email to doc-bugs+get-12766@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=70520&edit=1 ID: 70520 Updated by: yohgaki@php.net Reported by: hpdl at oscommerce dot com Summary: session_regenerate_id() "Failed to create session ID" with custom SessionHandler Status: Analyzed Type: Documentation Problem Package: Session related Operating System: Win10 PHP Version: 7.0.0RC3 Assigned To: yohgaki Block user comment: N Private report: N New Comment: Since mcrypt seems to have problems https://bugs.php.net/bug.php?id=70529 , I've made new example using OpenSSL AES. Any comments on this new sample code? There are too many ini_set() etc, I'll get rid of irrelevant code for the doc later. <?php ob_start(); error_reporting(E_ALL | E_STRICT); ini_set('session.save_path', '/tmp'); ini_set('display_errors', true); /** * decrypt AES 256 * * @param data $edata * @param string $password * @return dencrypted data */ function decrypt($edata, $password) { $data = base64_decode($edata); $salt = substr($data, 0, 16); $ct = substr($data, 16); $rounds = 3; // depends on key length $data00 = $password.$salt; $hash = array(); $hash[0] = hash('sha256', $data00, true); $result = $hash[0]; for ($i = 1; $i < $rounds; $i++) { $hash[$i] = hash('sha256', $hash[$i - 1].$data00, true); $result .= $hash[$i]; } $key = substr($result, 0, 32); $iv = substr($result, 32,16); return openssl_decrypt($ct, 'AES-256-CBC', $key, true, $iv); } /** * crypt AES 256 * * @param data $data * @param string $password * @return base64 encrypted data */ function encrypt($data, $password) { // Set a random salt $salt = openssl_random_pseudo_bytes(16); $salted = ''; $dx = ''; // Salt the key(32) and iv(16) = 48 while (strlen($salted) < 48) { $dx = hash('sha256', $dx.$password.$salt, true); $salted .= $dx; } $key = substr($salted, 0, 32); $iv = substr($salted, 32,16); $encrypted_data = openssl_encrypt($data, 'AES-256-CBC', $key, true, $iv); return base64_encode($salt . $encrypted_data); } class EncryptedSessionHandler extends SessionHandler { private $key; public function __construct($key) { $this->key = $key; } public function read($id) { $data = parent::read($id); if ($data === "") { return ""; } else { return decrypt($data, $this->key); } } public function write($id, $data) { $data = encrypt($data, $this->key); return parent::write($id, $data); } } ini_set('session.save_handler', 'files'); $key = substr(sha1(random_bytes(24)), 0, 24); $handler = new EncryptedSessionHandler($key); session_set_save_handler($handler, true); echo '<pre>'; session_start(); $_SESSION['key'] = 1234; var_dump($_SESSION); echo session_id() . PHP_EOL; session_regenerate_id(true); echo session_id() . PHP_EOL; Previous Comments: ------------------------------------------------------------------------ [2015-09-18 09:47:24] hpdl at oscommerce dot com Thanks for the pointers here. The error occurred with my database session handler read() method returning a bool false instead of a string. This was only caught in RC3 as earlier 7dev releases and previous PHP versions did not produce any kind of error. Thanks for the time spent on this. ------------------------------------------------------------------------ [2015-09-18 09:21:46] yohgaki@php.net I see error for read, but it will fail on both read/write due to wrong key size. ------------------------------------------------------------------------ [2015-09-18 09:19:20] yohgaki@php.net s/write/read/ ------------------------------------------------------------------------ [2015-09-18 09:18:26] yohgaki@php.net Found what's wrong. Current session save handler expects session read function returns STRING type when there is no error. However, the code public function read($id) { $data = parent::read($id); return @mcrypt_decrypt(MCRYPT_3DES, $this->key, $data, MCRYPT_MODE_ECB); } returns non string because $this->key is not valid key length. Apparently, the document has wrong size of key which results mcrypt_decrypt() error. This makes fail to write session data. Making documentation problem. ------------------------------------------------------------------------ [2015-09-18 09:05:41] requinix@php.net I tried it with a session_save_path(".") immediately before the session_start(). CWD was a local directory, and when I ran the code I posted earlier (in the same location) it worked correctly. ------------------------------------------------------------------------ The remainder of the comments for this report are too long. To view the rest of the comments, please view the bug report online at https://bugs.php.net/bug.php?id=70520 -- Edit this bug report at https://bugs.php.net/bug.php?id=70520&edit=1

« previous php.doc.bugs (#12766) next »