mcrypt 加密添加一堆“%00”到字符串末尾
使用 OAuth 并使用以下函数和字符串加密密钥,我们将其称为“foo”(实际上是 OAuth 令牌)。
public function encrypt( $text )
{
// add end of text delimiter
$data = mcrypt_encrypt( MCRYPT_RIJNDAEL_128, $this->key, $text, MCRYPT_MODE_ECB, $this->iv );
return base64_encode( $data );
}
当我使用反函数解密它时,我最终得到:
函数:
public function decrypt( $text )
{
$text = base64_decode( $text );
return mcrypt_decrypt( MCRYPT_RIJNDAEL_128, $this->key, $text, MCRYPT_MODE_ECB, $this->iv );
}
结果:
foo%00%00%00%00%00%00%00%00%00%00%00%00%00%00
编辑:
再看一下,我意识到它实际上是 URL 编码为 %00,这意味着我的字符串以某种方式被空字符填充?所以我目前正在使用trim()来摆脱它们,但我想了解为什么会发生这种情况。
Working with OAuth and encrypting the keys with the following function with a string which we'll call 'foo' (actually an OAuth token)
public function encrypt( $text )
{
// add end of text delimiter
$data = mcrypt_encrypt( MCRYPT_RIJNDAEL_128, $this->key, $text, MCRYPT_MODE_ECB, $this->iv );
return base64_encode( $data );
}
When I decrypt it using the inverse function, I end up with:
Function:
public function decrypt( $text )
{
$text = base64_decode( $text );
return mcrypt_decrypt( MCRYPT_RIJNDAEL_128, $this->key, $text, MCRYPT_MODE_ECB, $this->iv );
}
Result:
foo%00%00%00%00%00%00%00%00%00%00%00%00%00%00
Edit:
Looking at it a little more, I realized that it is actually URL encoding to %00, which means that my strings are somehow being padded by null characters? So I am currently using trim() to get rid of them, but I would like to understand why this is happening.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
Rijndael 是一种分组密码,这意味着它对特定长度的数据块(本例中为 128 位)进行操作。这意味着如果输入文本的长度不是块大小的倍数,则必须对其进行填充以适应。在这种情况下,填充为零;还有许多其他可能的填充方案可以使用,但如果您希望它们与 PHP 的 mcrypt 一起使用您必须手动应用它们。
Rijndael is a block cypher, which means that it operates on chunks of data of a particular length (128 bits in this case). This means that if the length of the input text is not a multiple of the block size, it must be padded out to fit. In this case, the padding is zeros; there are a number of other possible padding schemes that could be used, but if you want them with PHP's mcrypt you'll have to apply them manually.
您可以使用此方法修复它以摆脱填充字符:在我们的例子中,我们使用的是 Zend。
You can Fix it with this method to get rid of padding characters: In our case we are using Zend.
MCRYPT_MODE_ECB
表示您正在使用 ECB,这是一种分组密码操作模式。分组密码可以针对分组密码操作模式或流密码操作模式来处理。常见的分组密码模式是 ECB 和 CBC,常见的流密码模式是 CTR,即计数器模式操作。MCRYPT_RIJNDAEL_128
是 AES 的实现。 AES 是 Rijndael 密码,块大小为 128 位,并且具有三种可能的密钥大小:128、192 和 256 位。因此,如果您使用分组密码模式的加密,那么您需要将纯文本划分为每个 128 位 - 16 字节的大小。当然,这给您带来了当最后一个块不是 16 字节时该怎么办的问题。PHP 的
mcrypt_encrypt
或多或少将其留给用户。如果块未满到块大小,它将用00
值字符填充。如果输入是字符串,这没问题;您可以简单地trim
关闭 <返回字符串中的 code>00 个字符。但是,如果输入是以00
字符结尾的二进制数据,则该字符将丢失(当然还有从字符串开头和结尾获取的任何其他字符)。当然,您也可以将加密的字符串长度与明文一起发送。为了获得更好的方案,您只需查看 PKCS#7 填充。可以在评论部分找到用于实现填充的多个代码片段
mcrypt_encrypt
。mcrypt_encrypt
目前似乎不支持 AES 的流模式,因此如果您想保留 PHP mcrypt 库,则该选项不适用。MCRYPT_MODE_ECB
means that you are using ECB, a block cipher mode of operation. Block ciphers can be handled either for block cipher modes of operation or for stream cipher modes of operation. Common block cipher modes are ECB and CBC, a common stream cipher mode is CTR, better known as counter mode operation.MCRYPT_RIJNDAEL_128
is an implementation of AES. AES is the Rijndael cipher with a block size of 128 bits, and three possible key sizes, 128, 192 and 256 bits. So if you use a block cipher mode of encryption then you need to divide up the plain text is sizes of 128 bits - 16 bytes - each. Of course this leaves you with the question what to do when the last block is not 16 bytes.PHP's
mcrypt_encrypt
more or less leaves this up to the user. It pads with00
valued characters if the block is not full up to the block size. This is fine if the input is a string; you can simplytrim
off the00
characters from the returned string. If the input is however binary data that ends with a00
character than that character is lost (+ any other character that is taken from the start and end of the string of course). You can also send the length of the string encrypted together with the plaintext of course.For a better scheme you only have to look at PKCS#7 padding. Multiple code snippets for implementing the padding can be found in the comments section of
mcrypt_encrypt
.mcrypt_encrypt
currently does not seem to support stream modes for AES, so that option is out if you want to keep with the PHP mcrypt library.