从mcrypt_decrypt输出额外字符

时间:2015-01-13 22:03:43

标签: php encryption mcrypt

我需要在一对PHP脚本中进行对称加密和解密。我正在使用mcrypt_encrypt和crypt_decrypt。为了测试这个,我有以下代码:

$encrypted_token = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $ENCRYPTION_SECRET, $refresh_token, MCRYPT_MODE_ECB);

$encrypted_encoded_token=base64_encode($encrypted_token);
echo "\nEncrypted Token: " . $encrypted_encoded_token . "\n";

为了测试这一点,我在同一个PHP脚本中执行以下操作:

$decoded_refresh_token = base64_decode($encrypted_encoded_token);

$decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $ENCRYPTION_SECRET, $decoded_refresh_token, MCRYPT_MODE_ECB);
echo "\nDecrypted Token After decrypt: " . $decrypted . "\n";

我的输入$ refresh_token是一长串字符,看起来像这样(只有更长):

AQCNKTZhaWTmUl3WvHOtlkv2Vc-Ybkl24D5Zp1lZPLBraTxrr-YQhErXrI2IWWEIWk5lnBc1k

解密后的令牌解密后看起来像这样:

AQCNKTZhaWTmUl3WvHOtlkv2Vc-Ybkl24D5Zp1lZPLBraTxrr-YQhErXrI2IWWEIWk5lnBc1k�������������������

我的$ ENCRYPTION_SECRET长度为32个字符。 base64_encode和decode是因为我是json_encoding并在Post中解码令牌。

我做错了什么?

1 个答案:

答案 0 :(得分:8)

这些额外的字符确实是零值的字节。 PHP的mcrypt使用0..n - 1字节的零填充,其中n是块大小。换句话说,如果明文已经是块大小的倍数,那么它就不会填充。否则它会填充块大小。

现在您使用的是不是AES的MCRYPT_RIJNDAEL_256,而是使用块大小为256位的Rijndael。所以添加的字节数是0..31个字节。如果您将它们视为字符串,它们会转换为问号或删除,具体取决于您查看字符串的内容。在mcrypt的C库中,可能更有意义,因为零终止了一个以null结尾的字符串。

现在ad-hoc标准是PKCS#7填充,它增加了1..blocksize个填充字节。如果x是填充字节数,则x也是添加的字节的值。 PKCS#7填充是确定性的,即无论明文的值如何,您都可以始终取消填充。除非明文在末尾包含零个字符,否则零填充的行为大致相同。但是,对于可打印的字符串(ASCII,拉丁语或UTF-8),情况绝非如此。

最后,要删除填充,只需执行rtrim(plaintext, "\0")即可获得原始字符串。