我需要在一对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中解码令牌。
我做错了什么?
答案 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")
即可获得原始字符串。