2012-03-20 37 views
8

这里是一个PHP演示脚本,加密和解密数据:为什么mcrypt_encrypt()将二进制字符放在我的字符串末尾?

<? 

$encryptionkey = 'h8y2p9d1'; 

$card_nbr = "1234"; 
echo "original card_nbr: $card_nbr <br>\n"; 

$card_nbr_encrypted=encrypt_data($card_nbr); 
echo "card_nbr_encrypted: $card_nbr_encrypted <br>\n"; 

$card_nbr_decrypted=decrypt_data($card_nbr_encrypted); 
echo "card_nbr_decrypted: $card_nbr_decrypted <br>\n"; 

$len=strlen($card_nbr_decrypted); 
echo "length: $len <br>\n"; 



function encrypt_data($text){ 
    global $encryptionkey; 
    $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB); 
    $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND); 
    $encrypted_text = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $encryptionkey, $text, MCRYPT_MODE_ECB, $iv); 
    return $encrypted_text; 
} 

function decrypt_data($text){ 
    global $encryptionkey; 
    $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB); 
    $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND); 
    $decrypted_text = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $encryptionkey, $text, MCRYPT_MODE_ECB, $iv); 
    return $decrypted_text; 
} 

?> 


的输出是:

original card_nbr: 1234 
card_nbr_encrypted: vY¨(Z$<§G3-žÃ-Éù3Ý2Ê×rz¨VÛ 
card_nbr_decrypted: 1234 (and 28 binary characters) 
length: 32 


输出被成功地解密,但28个二进制字符被添加到结束。在查看HTML源代码时,这在Firefox中很容易看到。 32的字符串长度也说明了这一点。有任何想法吗?

enter image description here

+0

看看是否可以有任何帮助http://php.net/manual/en/function.base64-encode.php – 2012-03-20 05:33:34

+0

@Mian_Khurram_Ijaz我不明白为什么会有所帮助 – Ben 2012-03-20 05:38:41

+0

输出实际上是二进制格式所以为了使它安全跨网络base64_encode是有益的加密和解密工作正常,所以我想如果二进制字符是问题,然后使用base64 .. – 2012-03-20 05:41:20

回答

8

使用空字符\0填充返回的字符串以填充n * blocksize字节,这就是您看到额外数据的原因。

如果您运行$card_nbr_decrypted= rtrim($card_nbr_decrypted, "\0");它应该返回实际数据。

+0

如果你想要的话,使用'rtrim'的解决方案当然会被破坏来加密任意二进制数据,这些数据可能实际上以一些空值结束。在这种情况下,你应该将带外字符串的长度和substr的长度传回给那个长度(容易,但是会泄漏字符串的长度),或者在加密前自己填充 - 我推荐使用PKCS#7填充方法,因为它很容易理解。 – hobbs 2012-03-20 05:49:14

+0

PKCS#7的问题是编写和维护mcrypt的bozos确实为它提供了支持。 – zaph 2016-01-16 21:37:24

3

这似乎是一个known problem。解码后使用rtrim()删除多余的NUL。

2

由于您使用电子代码块(ECB)为您的block cipher mode of operation填充了明文末尾以符合块大小,因此您正在接收空字节。在你的情况下,块大小是256位,因为你使用的是MCRYPT_RIJNDAEL_256

如果您使用密码反馈(CFB)模式 - MCRYPT_MODE_CFB - 无空字节,无需修剪,则可以避免使用此填充问题。但是,对于CFB,您应该使用加密数据HMAC,以验证它是否已被篡改(see "Mallet")。你可以在Cryptography For The Average Developer找到一个工作实现的例子。

另外值得注意的是,ECB模式被认为不太安全,因为它可以reveal data patterns。此外,ECB(和CBC,因为它也垫)可能容易受到padding oracle attack

-1

我认为这个问题是您正在使用二进制数据时:

mcrypt_encrypt - 加密与给定参数

您可以使用使用明文BASE64_ENCODE($文本)明文。

+0

编码与加密不同。 – 2016-06-22 15:51:23

+0

我知道。但是,如果您使用mcrypt_encrypt将$ text作为base64明文发送以避免编码问题很有用。 您可以使用base64_encode($ text)或rtrim()作为其他用户的建议。 – bLuEdDy 2016-06-28 09:37:10

相关问题