2016-12-16 168 views
8

我有这个mcrypt_encrypt呼吁,对于给定的$键,$消息,$ IV:PHP:mcrypt_encrypt到openssl_encrypt,并OPENSSL_ZERO_PADDING问题

$string = mcrypt_encrypt(MCRYPT_3DES, $key, $message, MCRYPT_MODE_CBC, $iv); 

我想给mcrypt_encrypt呼叫更改为openssl_encrypt一个,以防万一。

通过有$mode = 'des-ede3-cbc'$mode = '3DES';$options = true我得到更相似的响应,但不完全相同。有没有其他的方式叫它获得完美的比赛?

我得到这个(Base64编码)的LOREM-存有$message + $key组合,所以我开始相信一个函数或其它被加密之前有所填充的消息...

为mcrypt的

“Y + JgMBdfI7ZYY3M9lJXCtb5Vgu + rWvLBfjug2GLX7uo =”

用于OpenSSL的

“Y + JgMBdfI7ZYY3M9lJXCtb5Vgu + rWvLBvte4swdttHY =”

在一个空字符串使用$选项传递OPENSSL_ZERO_PADDING,但传送什么,但(OPENSSL_RAW_DATA,或)结果试过...

既不使用也不OPENSSL_ZERO_PADDING工作OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING ... :(

还有其他线索吗?我正在使用“OpenSSL 1.0.2g 2016年3月1日”。

已读取this q & a,但它不帮助我。不是onlyone与填充麻烦,但迄今没有解决方案。 (二答案谈论添加填充到mcrypt的电话,我真的想移除的OpenSSL加密通话填充...

+0

你永远不应该得到一个完美的匹配,永远。这就是初始化矢量的用途。每次您使用** same **算法和** same **键加密** same **有效内容时,如果您想要安全,应该得到完全不同的输出。如果对于相同的输入获得相同的输出,则加密功能很弱。这就是加密的第四点。一旦加密,您就可以将IV加密的有效载荷传送到另一端。 – Mjh

+1

如果我使用相同的有效载荷,相同的算法,相同的IV;我想我应该得到相同的输出。不要紧,我应该为每个调用使用不同的IV:对于两个调用(mcrypt和openssl)使用相同的IV,我想我应该得到相同的输出,对吧? 我开始相信与消息填充有关,因为输出的乞求是相同的。 – yivi

+0

如果一切都一样,那么你应该得到相同的输出,是正确的。 'openssl_encrypt'的第四个参数控制着填充。你可以用'$ encrypted = openssl_encrypt($ data,$ alg,$ key,OPENSSL_ZERO_PADDING,$ iv)加密;'并检查你是否得到相同的输出。在[www.php.net/openssl_encrypt](http://www.php.net/openssl_encrypt)中,您可以阅读注释以了解如何使用第4个参数。 – Mjh

回答

13

mcrypt_encrypt零垫输入数据如果它不是块大小的倍数,这会导致如果数据本身具有尾随零,则结果不明确。显然OpenSSL不允许你在这种情况下使用零填充,这就解释了错误的返回值。

你可以通过手动添加填充来避开这种情况。

$message = "Lorem ipsum"; 
$key = "123456789"; 
$iv = "12345678"; 

$message_padded = $message; 
if (strlen($message_padded) % 8) { 
    $message_padded = str_pad($message_padded, 
     strlen($message_padded) + 8 - strlen($message_padded) % 8, "\0"); 
} 
$encrypted_mcrypt = mcrypt_encrypt(MCRYPT_3DES, $key, 
    $message, MCRYPT_MODE_CBC, $iv); 
$encrypted_openssl = openssl_encrypt($message_padded, "DES-EDE3-CBC", 
    $key, OPENSSL_RAW_DATA | OPENSSL_NO_PADDING, $iv); 

printf("%s => %s\n", bin2hex($message), bin2hex($encrypted_mcrypt)); 
printf("%s => %s\n", bin2hex($message_padded), bin2hex($encrypted_openssl)); 

这打印出两者相等。

4c6f72656d20697073756d => c6fed0af15d494e485af3597ad628cec 
4c6f72656d20697073756d0000000000 => c6fed0af15d494e485af3597ad628cec 
+0

是的,但是这涉及修改消息(我不能这么做),并且改变'mcrypt_'响应,以便它匹配'openssl_'(这与我想要的相反,我需要'openssl_'响应匹配mcrypt) – yivi

+0

mcrypt在内部添加填充。您只需填充OpenSSL的字符串。我会修改我的答案来澄清这一点。 – Joe

+0

看起来不错。在通电话。我会在几个小时内对它进行测试。 – yivi

-2

mcrypt_encrypt使用零来填充消息块的大小。所以,你可以添加到零原始数据的尾部,然后加密块。

使用OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING应该工作。如果没有,那么你可以自己删除解密的数据填充。

+2

10k代表,来吧请使用适当的格式x_x – DanFromGermany

+0

为什么我应该花时间呢? –

+0

'OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING'不起作用。可能是phps openssl实现中的一个错误?从未加密的数据中删除多余的字符不适用于我。该字符串用作验证签名:我提供了一个和一些数据,创建此加密数据以匹配收到的签名。我不控制另一边的系统。修改mcrypt_调用,使其匹配openssl_不会帮助我,我需要openssl_来匹配mcrypt_ :) – yivi