这个问题是继续我的最后一个,有关 如何让红宝石AES-256-CBC and PHP MCRYPT_RIJNDAEL_128发挥好一起.我已经有了,现在的工作,但我仍然要走另一个方向。PHP产生的密码显示的所有信息提供,但我不能让红宝石的代码解密就没有错误。

这里的代码,我在使用的生成密:

$cleartext = "Who's the clever boy?";
$key = base64_decode("6sEwMG/aKdBk5Fa2rR6vVw==\n");
$iv = base64_decode("vCkaypm5tPmtP3TF7aWrug==");
$cryptogram = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $cleartext, MCRYPT_MODE_CBC, $iv);
$result = base64_encode($cryptogram);
print "\n'$result'\n";

RESULT
'JM0OxMINPTnF1vwXdI3XdKI0KlVx210CvpJllFja+GM='

然后这是试图解在红宝石:

>> cipher = OpenSSL::Cipher::Cipher.new('aes-128-cbc')
>> cipher.key = Base64.decode64("6sEwMG/aKdBk5Fa2rR6vVw==\n")
>> cipher.iv = Base64.decode64("vCkaypm5tPmtP3TF7aWrug==")
>> cryptogram = Base64.decode64('JM0OxMINPTnF1vwXdI3XdKI0KlVx210CvpJllFja+GM=')
>> cleartext = cipher.update(cryptogram)
=> "Who's the clever"
>> cleartext << cipher.final
OpenSSL::Cipher::CipherError: bad decrypt
 from (irb):100:in `final'
 from (irb):100

什么是真正令人沮丧的是,它能够获得完整的明文出了加密的串。重复上述的,但加入一个无稽之谈垫密:

  >> cleartext = cipher.update(cryptogram + 'pad')
  => "Who's the clever boy?\000\000\000\000\000\000\000\000\000\000\000"
  >> cleartext << cipher.final
  OpenSSL::Cipher::CipherError: bad decrypt
   from (irb):119:in `final'
   from (irb):119

在我的实际使用情况的明文结构(JSON串,由于你要求),所以我觉得舒适这一点,我可以告诉使用这种方案和检测不加密的输入不需要执行 cipher.final.然而,我不能容忍这种暂且在我的代码,因此我想了解如何使红宝石的代码处理的最后一块优雅。

有帮助吗?

解决方案

的问题是,mcrypt未填充最后的块,而Ruby的绑定的OpenSSL使用默认OpenSSL的填补方法,其是PKCS填充。我无法真正改善来自OpenSSL文档的描述:

  

PKCS填充作品通过加入正填充   值n的字节,使总   的数据的长度   块大小的倍数。填充是   总是添加因此,如果数据已经   块大小n的倍数将   等于块大小。例如,如果   的块大小为8首11个字节是   要被加密然后5填充字节   的值5将被添加。

您需要手动适当填充在PHP加密前增加了明文的结束。要做到这一点,通过你的$cleartext通过在PHP端这pkcs5_pad功能,您加密的(通过16的块大小)之前。

function pkcs5_pad ($text, $blocksize)
{
    $pad = $blocksize - (strlen($text) % $blocksize);
    return $text . str_repeat(chr($pad), $pad);
}

如果你也去的其他方式(加密在Ruby和与mcrypt的解密),你将有解密后剥去填充字节。

边注:的,你必须添加填充即使明文已经是块大小(填充整个块)的倍数的原因,就是这样,当你解密你知道最后一个块的最后一个字节是总是添加的填充量。否则,你不能告诉明文之间有一个填充字节,并明文与刚刚发生在价值0x01结束无填充字节的区别。

其他提示

它的出现PHP \0 垫明文之前对它进行加密。你可以设定红宝石禁用的填充。

http://www.ruby-doc.org/stdlib-1.9.3/libdoc/openssl/rdoc/OpenSSL/Cipher.html#method-i-padding-3D

这将工作,但然后你必须带填充掉手动。

1.9.3p125 :008 > cipher = OpenSSL::Cipher::Cipher.new('aes-128-cbc')
 => #<OpenSSL::Cipher::Cipher:0x0000000561ee78>
1.9.3p125 :009 > cipher.decrypt
 => #<OpenSSL::Cipher::Cipher:0x0000000561ee78>
1.9.3p125 :010 > cipher.padding = 0
 => 0
1.9.3p125 :011 > cipher.key = Base64.decode64("6sEwMG/aKdBk5Fa2rR6vVw==\n")
 => "\xEA\xC100o\xDA)\xD0d\xE4V\xB6\xAD\x1E\xAFW"
1.9.3p125 :012 > cipher.iv = Base64.decode64("vCkaypm5tPmtP3TF7aWrug==")
 => "\xBC)\x1A\xCA\x99\xB9\xB4\xF9\xAD?t\xC5\xED\xA5\xAB\xBA"
1.9.3p125 :013 > cryptogram =  Base64.decode64('JM0OxMINPTnF1vwXdI3XdI2j8NJ8kr+Du0fnkxorNl0=')
 => "$\xCD\x0E\xC4\xC2\r=9\xC5\xD6\xFC\x17t\x8D\xD7t\x8D\xA3\xF0\xD2|\x92\xBF\x83\xBBG\xE7\x93\x1A+6]"
1.9.3p125 :014 > cleartext = cipher.update(cryptogram)
 => "Who's the clever girl?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
1.9.3p125 :015 > cleartext << cipher.final
 => "Who's the clever girl?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"



1.9.3p125 :042 > cleartext.strip
 => "Who's the clever girl?"
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top