2014-02-24 54 views
1

我一直使用您的網站來幫助我解決各種編程問題,並且終於遇到了一個我在其他地方找不到的問題。使用MCRYPT加密/解密PHP ...結果不一致

我試圖在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; 

    } 

} 

我的問題是,使用實時服務器上的類,它準確地進行加密和解密的密碼。如果我把這段代碼粘貼到一個新文件中,並以相同的輸入方式使用它,它會返回一個不同的字符串,通常使用「?」字符(不是問號字符,而是Web瀏覽器無法解釋的字符)。例如,Legato_Encryption('hello','twofish')。encrypt('hello')將返回與Yii_Encryption('hello','twofish')中使用它完全不同的東西。encrypt('你好')。這是相同的代碼和相同的過程與相同的參數...它怎麼能返回不同的值?我相信encrypt()函數似乎在每次執行時都會生成隨機值,但decrypt()應該返回正確的字符串。

有沒有人看到一個可能的區域,在這個代碼可能是脾氣暴躁或產生不一致的結果?我在這個問題上花費了太多時間,因爲許多其他關於類似問題的帖子都沒有取得成功。

+0

也許相關:http://stackoverflow.com/questions/2283937/how -hould-I-ethically-approach-user-password-storage-for-later-plaintext-retrieve – ntoskrnl

+0

另請參閱Openwall的[便攜式PHP密碼哈希框架](http://www.openwall.com/phpass/)。它強化了對用戶密碼的一些常見攻擊。 – jww

回答

0

聽起來就像您遇到由不同OS/PHP版本引起的「便攜式散列」問題。可能需要一次編程升級哈希(我建議phpNode的Yii密碼行爲擴展),然後使用更新的哈希系統...