第二部分:如何使Ruby AES-256-CBC和PHP MCRYPT_RIJNDAEL_128一
这个问题是我最后一个问题的延续,关于
How to make Ruby AES-256-CBC and PHP MCRYPT_RIJNDAEL_128 play well together.我现在有工作,但我仍然在努力去走另一个方向. PHP生成的密码似乎具有提供的所有信息,但是我无法获取Ruby代码来解密它,没有错误.
以下是我用于生成密码的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=' 那么这里是尝试在Ruby中解密: >> 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? 00 00 00 00 00 00 00 00 00 00 00" >> cleartext << cipher.final OpenSSL::Cipher::CipherError: bad decrypt from (irb):119:in `final' from (irb):119 在我的实际使用情况下,明文是结构化的(一个JSON字符串,因为你问),所以我觉得很舒服,我可以告诉使用这个方案,并检测不好的加密输入,而不执行cipher.final.但是,我不能容忍这种在我的代码中的这种类型,所以我想了解如何使ruby代码优雅地处理最终的块. 解决方法
问题是mcrypt没有填充最后一个块,而Ruby的OpenSSL绑定使用默认的OpenSSL填充方法,即PKCS填充.我从OpenSSL文档中的描述不能真正改进:
在加密之前,您需要手动将适当的填充添加到PHP中的明文末尾.要做到这一点,在加密之前通过PHP侧的pkcs5_pad函数传递$cleartext(通过16作为块大小). function pkcs5_pad ($text,$blocksize) { $pad = $blocksize - (strlen($text) % $blocksize); return $text . str_repeat(chr($pad),$pad); } 如果您还以另一种方式(在Ruby中加密并使用mcrypt进行解密),则必须在解密之后删除填充字节. 旁注:即使明文已经是块大小(整个填充块)的倍数,你必须添加填充的原因是,当您解密时,您知道最后一个块的最后一个字节总是数量的填充.否则,你无法区分明文与单个填充字节和明文之间的差异,没有填充字节刚刚结束的值0x01. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |