来自 mcrypt_decrypt 的额外字符输出
Extra Characters Output From mcrypt_decrypt
我需要一对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 和解码是因为我是 json_encoding 并且在 Post.
中解码令牌
我做错了什么?
那些额外的字符确实是值为零的字节。 PHP 的 mcrypt 使用 0..n - 1
字节的零填充,其中 n
是块大小。换句话说,如果明文已经是块大小的倍数,那么它就不会填充。否则它会填充到块大小。
现在您使用的 MCRYPT_RIJNDAEL_256
不是 AES,而是块大小为 256 位的 Rijndael。所以添加的字节数是 0..31 字节。如果您将它们视为字符串,它们会转换为问号或被删除,具体取决于您查看字符串的方式。在 mcrypt 的 C 库中,可能更有意义,因为零终止了一个以 null 结尾的字符串。
现在的临时标准是 PKCS#7 填充,它增加了 1..blocksize
个填充字节。如果 x
是填充字节数,那么 x
也是添加的字节数。 PKCS#7 填充是确定性的,即无论明文的值如何,您始终可以取消填充。零填充的行为方式大致相同,除非明文末尾包含零字符。然而,对于可打印字符串(ASCII、拉丁文或 UTF-8),情况绝非如此。
最后,要删除填充,只需执行 rtrim(plaintext, "[=16=]")
即可得到原始字符串。
我需要一对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 和解码是因为我是 json_encoding 并且在 Post.
中解码令牌我做错了什么?
那些额外的字符确实是值为零的字节。 PHP 的 mcrypt 使用 0..n - 1
字节的零填充,其中 n
是块大小。换句话说,如果明文已经是块大小的倍数,那么它就不会填充。否则它会填充到块大小。
现在您使用的 MCRYPT_RIJNDAEL_256
不是 AES,而是块大小为 256 位的 Rijndael。所以添加的字节数是 0..31 字节。如果您将它们视为字符串,它们会转换为问号或被删除,具体取决于您查看字符串的方式。在 mcrypt 的 C 库中,可能更有意义,因为零终止了一个以 null 结尾的字符串。
现在的临时标准是 PKCS#7 填充,它增加了 1..blocksize
个填充字节。如果 x
是填充字节数,那么 x
也是添加的字节数。 PKCS#7 填充是确定性的,即无论明文的值如何,您始终可以取消填充。零填充的行为方式大致相同,除非明文末尾包含零字符。然而,对于可打印字符串(ASCII、拉丁文或 UTF-8),情况绝非如此。
最后,要删除填充,只需执行 rtrim(plaintext, "[=16=]")
即可得到原始字符串。