使用 MCRYPT 在 PHP 中加密/解密...结果不一致
Posted
技术标签:
【中文标题】使用 MCRYPT 在 PHP 中加密/解密...结果不一致【英文标题】:Encrypting/Decrypting in PHP with MCRYPT...Inconsistent Results 【发布时间】:2014-03-25 17:32:27 【问题描述】:长期以来,我一直在使用您的网站来帮助我解决各种编程问题,但我终于遇到了一个在其他任何地方都找不到解决的问题。
我正在尝试在 php 中使用 mcrypt 来加密和解密存储在我客户网站上的密码。这些密码用于外部网站,因此必须加密/解密而不是散列。我目前正在将他们的旧框架 Legato 更新为更新的 Yii 框架。密码使用类文件中概述的加密方案存储在当前数据库中。方案如下:
<?php
//--------------------------------------------------------------------------
// Name: Legato_Encryption
// Desc: An encryption engine. Contains functions to encrypt and decrypt
// text.
//--------------------------------------------------------------------------
class Legato_Encryption
//------------------------------------------------------------------------
// Public Variables
//------------------------------------------------------------------------
private $_cypher; // The cypher algorithm.
private $_mode; // The encryption mode.
private $_td; // The TD for mcrypt.
private $_private_key; // The private key.
//------------------------------------------------------------------------
// Public Member Functions
//------------------------------------------------------------------------
//------------------------------------------------------------------------
// Name: __construct()
// Desc: Class constructor.
//------------------------------------------------------------------------
public function __construct( $private_key, $cypher = 'blowfish', $mode = 'cfb' )
// Make sure everything was filled in.
if ( $private_key == "" || $cypher == "" || $mode == "" )
Legato_Debug_Debugger::add_item( 'Invalid parameters for encryption. NULL passed in.' );
return false;
// Assign the class variables to those passed in.
$this->_cypher = $cypher;
$this->_mode = $mode;
// Get the TD.
$this->_td = mcrypt_module_open( $this->_cypher, '', $this->_mode, '' );
// Get the expected key size based on mode and cipher .
$expected_key_size = mcrypt_enc_get_key_size( $this->_td );
// We dont need to know the real key, we just need to be able to confirm a hashed version.
$this->_private_key = substr( md5($private_key), 0, $expected_key_size );
//------------------------------------------------------------------------
// Name: encrypt()
// Desc: Encrypts the plaint text passed in.
//------------------------------------------------------------------------
public function encrypt( $plaintext )
// Create the IV.
$iv = mcrypt_create_iv( mcrypt_enc_get_iv_size($this->_td), MCRYPT_RAND );
// Initialize the mcrypt engine.
mcrypt_generic_init( $this->_td, $this->_private_key, $iv );
// Encode/encrypt the text.
$crypttext = base64_encode( mcrypt_generic($this->_td, $plaintext) );
// Shut down mcrypt.
mcrypt_generic_deinit( $this->_td );
// Return the iv prefixed to the encrypted text.
return $iv . $crypttext;
//------------------------------------------------------------------------
// Name: decrypt()
// Desc: Decrypts the encrypted text passed in.
//------------------------------------------------------------------------
public function decrypt( $crypttext )
// Get the iv from the beginning of the encrypted text.
$iv_size = mcrypt_enc_get_iv_size( $this->_td );
$iv = substr( $crypttext, 0, $iv_size );
// Get the encrypted text.
$crypttext = substr( $crypttext, $iv_size );
$plaintext = '';
// Attempt to decrypt the text.
if ( $iv )
// Initialize the mcrypt engine.
mcrypt_generic_init( $this->_td, $this->_private_key, $iv );
// Decode the crypted text, then decrypt it, then trim it of whitespaces.
$plaintext = trim( mdecrypt_generic($this->_td, base64_decode($crypttext)) );
// Shut down mcrypt.
mcrypt_generic_deinit( $this->_td );
// End if $iv true.
// Return the plain text.
return $plaintext;
我的问题是在实时服务器上使用该类,它可以准确地加密和解密密码。如果我采用该代码,将其粘贴到一个新文件中并以完全相同的方式使用相同的输入,它会返回一个不同的字符串,通常带有“?”字符(不是问号字符,而是网络浏览器无法解释的字符)。
例如,Legato_Encryption('hello', 'twofish').encrypt('hello') 将返回完全不同于我在 say Yii_Encryption('hello', 'twofish').encrypt('hello ')。这是相同的代码和相同的过程,具有相同的参数......它怎么能返回不同的值?我相信 encrypt() 函数似乎每次执行时都会生成随机值,但 decrypt() 应该返回正确的字符串。
有没有人发现这段代码可能会变得喜怒无常或产生不一致的结果?我在这个问题上花费了太多时间,因为这里关于类似问题的许多其他帖子都没有产生成功的结果。
【问题讨论】:
或许相关:***.com/questions/2283937/… 另见 Openwall 的Portable PHP password hashing framework。它强化了对用户密码的一些常见攻击。 【参考方案1】:听起来您遇到了由不同操作系统/PHP 版本引起的“便携式哈希”问题。可能需要以编程方式升级哈希(我建议使用 phpNode 的 Yii 密码行为扩展),然后使用更新的哈希系统...
【讨论】:
以上是关于使用 MCRYPT 在 PHP 中加密/解密...结果不一致的主要内容,如果未能解决你的问题,请参考以下文章
解密在 PHP 中使用 MCRYPT_RIJNDAEL_256 加密的 Python 字符串
使用 PHP mcrypt 加密后使用 Javascript CryptoJS 解密 AES
在 Javascript 中使用 Crypto-js 加密,在 PHP 中使用 mcrypt 解密?