2012-04-03 54 views
14

目前我們在我們的系統上實現了mcrypt實現,以在我們的PHP應用程序中隱藏一些合理的數據。現在我們有一個新的要求,我們必須將crypt模塊更改爲openssl。另一件重要的事情是知道我們正在使用密碼河豚和模式ecb。所以我開始測試什麼是差異以及如何使用openssl解密mcrypt加密字符串。用OpenSSL替換Mcrypt

我使用了標準的PHP函數:

  • mcrypt_encrypt與openssl_encrypt
  • mcrypt_decrypt與openssl_decrypt

兩種方法都提供不同的結果。第二件事是在兩種類型的給定密碼(河豚)和模式(ecb)中,需要不同的IV長度(openssl = 0和mcrypt = 56)。

是否有人知道如何在不進行大量遷移工作的情況下輕鬆更改模塊?

在此先感謝!

UPDATE:

下面是代碼,這是我測試過它:

<?php 

function say($message){ 
    if(!is_string($message)){ 
     if(!isset($_SERVER["HTTP_USER_AGENT"])) echo "<pre>"; 
     echo var_export($message, true) . ((!isset($_SERVER["HTTP_USER_AGENT"]) ? "\n" : "<br />")); 
     if(!isset($_SERVER["HTTP_USER_AGENT"])) echo "</pre>"; 
    }else{ 
     echo $message . ((!isset($_SERVER["HTTP_USER_AGENT"]) ? "\n" : "<br />")); 
    } 
} 

say("= Begin raw encryption"); 
$key = "anotherpass"; 
$str = "does it work"; 

say(" Params:"); 
say(" - String to encrypt '".$str."'"); 
say(" - Key: ".$key); 
say(""); 


$params = array(
    "openssl" => array(
     "cipher" => "BF", 
     "mode"  => "ECB", 
    ), 
    "mcrypt" => array(
     "cipher" => "blowfish", 
     "mode"  => "ecb", 
    ), 
); 

say("= Mcrypt"); 
$handler = mcrypt_module_open($params['mcrypt']['cipher'], '', $params['mcrypt']['mode'], ''); 
$iv  = mcrypt_create_iv (mcrypt_enc_get_iv_size($handler), MCRYPT_RAND); 
$keysize = mcrypt_enc_get_key_size($handler); 
mcrypt_generic_init($handler,$key,"\0\0\0\0\0\0\0\0"); 
say(" Params:"); 
say(" - InitVector ".bin2hex($iv)." (bin2hex)"); 
say(" - Max keysize ".$keysize); 
say(" - Cipher  ".$params['mcrypt']['cipher']); 
say(" - Mode   ".$params['mcrypt']['mode']); 
say(""); 
say(" Encryption:"); 
$m_encrypted = mcrypt_generic($handler, $str); 
$m_decrypted = mdecrypt_generic($handler, $m_encrypted); 
say(" - Encrypted ".bin2hex($m_encrypted)." (bin2hex)"); 
say(" - Descrypted ".$m_decrypted); 
say(""); 


say("= Openssl"); 
say(" Params:"); 
say(" - InitVector not needed"); 
say(" - Max keysize ".openssl_cipher_iv_length($params['openssl']['cipher']."-".$params['openssl']['mode'])); 
say(" - Cipher  ".$params['openssl']['cipher']); 
say(" - Mode   ".$params['openssl']['mode']); 
say(""); 
say(" Encryption:"); 
$o_encrypted = openssl_encrypt($str,$params['openssl']['cipher']."-".$params['openssl']['mode'],$key,true); 
$o_decrypted = openssl_decrypt($o_encrypted,$params['openssl']['cipher']."-".$params['openssl']['mode'],$key,true); 
say(" - Encrypted ".bin2hex($o_encrypted)." (bin2hex)"); 
say(" - Descrypted ".$o_decrypted); 

這是我的結果:

= Begin raw encryption 
    Params: 
    - String to encrypt 'does it work' 
    - Key: anotherpass 

= Mcrypt 
    Params: 
    - InitVector 06a184909d7bf863 (bin2hex) 
    - Max keysize 56 
    - Cipher  blowfish 
    - Mode   ecb 

    Encryption: 
    - Encrypted 0e93dce9a6a88e343fe5f90d1307684c (bin2hex) 
    - Descrypted does it work 

= Openssl 
    Params: 
    - InitVector not needed 
    - Max keysize 0 
    - Cipher  BF 
    - Mode   ECB 

    Encryption: 
    - Encrypted 213460aade8f9c14d8d51947b8231439 (bin2hex) 
    - Descrypted does it work 
現在

也許什麼想法?

謝謝!

+7

你要麼必須運行使用的mcrypt解密當前數據的遷移腳本,然後再次使用OpenSSL的,否則你」加密您需要實現一種方法,通過該方法您可以知道每個數據項使用哪些加密/解密函數,並在下次訪問使用mcrypt加密的數據時,根據需要將它們從mcrypt更改爲openssl。 – Jon 2012-08-22 14:04:58

+1

據我瞭解,mcrypt和open_ssl使用不同的密鑰派生方法,所以Jon是對的,您需要通過解密進行遷移,然後加密或標記數據,以便在下次訪問時進行遷移。 – 2012-10-31 17:13:55

+0

我想知道爲什麼在ECB模式下需要IB。請參閱http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation上的ECB模式說明。 – doptimusprime 2013-04-06 03:39:42

回答

8

河豚是分組密碼。它要求在加密之前填充數據。 OpenSSL使用PKCS#7,而mcrypt使用PKCS#5。不同的數據填充算法。 最小的PKCS#5填充長度爲0,對於PKCS#7,它是1(wikipedia)。看一看該示例(我已經手動填充的輸入數據。mcrypt_encrypt()在PKCS#7樣式):

<?php 

$key = "anotherpassword1"; 
$str = "does it work 12"; 

$enc = mcrypt_encrypt(MCRYPT_BLOWFISH, $key, $str."\1", MCRYPT_MODE_ECB); 
$dec = mcrypt_decrypt(MCRYPT_BLOWFISH, $key, $enc, MCRYPT_MODE_ECB); 
echo(bin2hex($enc).PHP_EOL); 
var_dump($dec); 

$enc = openssl_encrypt($str, 'bf-ecb', $key, true); 
$dec = openssl_decrypt($enc, 'bf-ecb', $key, true); 
echo(bin2hex($enc).PHP_EOL); 
var_dump($dec); 

?> 

這是不可能的openssl_decrypt()與mcrypt_encrypt(加密數據),除非手動數據填補用製成調用mcrypt_encrypt()之前的PKCS#7。

你的情況只有一種 - 重新獲取數據。

PS:有一個在你的源的錯誤 - ECB模式不會在所有(wikipedia

+1

謝謝,這個提示幫助我使Rijndael-128/AES-128在MCrypt和OpenSSL之間兼容。不幸的是,它不適用於Blowfish - – Narf 2014-01-30 13:08:25

+0

原來它適用於Blowfish,但是密鑰大小必須至少有16個字節(Blowfish的Wikipedia文章稱它支持更少)。 – Narf 2014-02-05 12:14:57

+0

這是因爲在PKCS中填充#7 – clover 2014-02-09 18:41:00

-1

@clover是正確的,對於河豚默認填充是mcrypt的和OpenSSL之間的不同,但其實是錯誤,它無法做到的。如果您使用OPENSSL_ZERO_PADDING選項解密這兩個實際上是兼容的:

openssl_decrypt($data, 'bf-ecb', $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING); 
+0

'OPENSSL_ZERO_PADDING'不添加任何填充,任何非標準填充將需要手動添加加密並在解密時刪除。從文檔[openssl_encrypt](https://secure.php.net/manual/en/function.openssl-encrypt.php),也許你正在使用不同的版本。從doc註釋:因此,OPENSSL_ZERO_PADDING將禁用上下文的填充,這意味着您將不得不手動將自己的填充應用於塊大小。不使用OPENSSL_ZERO_PADDING,您將自動獲得PKCS#7填充。 – zaph 2018-03-09 22:58:02