【问题标题】:Rijndael AES-128 encryption decryption in RubyRuby 中的 Rijndael AES-128 加密解密
【发布时间】:2013-08-24 20:03:33
【问题描述】:

我想在 ruby​​ 中使用 rijndael aes128 进行加密。我有这个代码:

cipher = OpenSSL::Cipher::Cipher.new("aes-128-cbc")
cipher.encrypt
cipher.key = 'abcdef0123456789abcdef0123456789'
cipher.iv = '0000000000000000'
encrypted =   cipher.update('2~1~000024~0910~20130723092446~T~00002000~USD~F~375019001012120~0~0~00000000000~')
encrypted << cipher.final

这不起作用。但是使用这个 PHP 函数:

<?php 
 function hex2bin($hex_string) 
  {
     return pack('H*', $hex_string);
  } 
 $data_to_encrypt = '2~1~000024~0910~20130723092446~T~00002000~USD~F~375019001012120~0~0~00000000000~';
  $key = 'abcdef0123456789abcdef0123456789'; 
  $iv = '0000000000000000'; 
  $key = hex2bin($key);
  $iv = hex2bin($iv); 
  $data_encrypted = bin2hex(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $data_to_encrypt, MCRYPT_MODE_CBC, $iv));
  echo "Data encrypted: ".strtoupper($data_encrypted)."<br/>"; echo "Length: ".strlen($data_encrypted)."<br/>";
  ?>

我得到了我想要的输出:

0D5835AFEBEE04C6DC2421538DB7C38A1283970EB31F21A47D2E3CC623D29EF0461279C7ACF93B031BE2B69CE45C9339554957F29EF609F019EEC975983A03B537622D7E0F196BE148F1C7CBB88E602A

如何让我的 Ruby 代码产生相同的输出?

【问题讨论】:

  • 有很多事情会出错,而且由于 PHP 和 Ruby 是敌人,您希望人们如何检查您的问题?尝试浏览两本手册或检查一些关于 SO(在右侧栏)的问题,也许this 可以让您了解可能出现的问题...

标签: php ruby openssl aes rijndael


【解决方案1】:
require 'openssl'

cleartext = '2~1~000024~0910~20130723092446~T~00002000~USD~F~375019001012120~0~0~00000000000~'
key = 'abcdef0123456789abcdef0123456789'
iv = '0000000000000000'

cipher = OpenSSL::Cipher::Cipher.new("aes-128-cbc")
cipher.encrypt
cipher.padding = 0
cipher.key = [key].pack('H*')
cipher.iv = [iv].pack('H*')
encrypted = cipher.update(cleartext)
encrypted << cipher.final
puts encrypted.unpack('H*').first.upcase

输出:

0D5835AFEBEE04C6DC2421538DB7C38A1283970EB31F21A47D2E3CC623D29EF0461279C7ACF93B031BE2B69CE45C9339554957F29EF609F019EEC975983A03B537622D7E0F196BE148F1C7CBB88E602A

【讨论】:

  • 这是我的完整代码,它给出了与我上面写的相同的 o/p 检查这个。"; echo "长度:".strlen($data_encrypted)."
    "; ?>
  • 这段代码和你上面贴的很不一样!我们应该如何猜测所有周围的代码?当您发布大量代码时,请直接编辑您的答案,而不是将其放入评论中。
  • 您的代码会引发警告:mcrypt_encrypt(): The IV parameter must be as long as the blocksize。密钥和 IV 都必须是两倍长!
  • 我知道 PHP 代码会发出警告,但这不是问题。如果您知道如何在 ruby​​ 中转换该代码,或者您可以更正上述 ruby​​ 代码,或者您可以检测到我在 ruby​​ 代码中出错的区域,请回答
  • 您不能使用快捷键将该代码转换为 ruby​​,因为 ruby​​ 会抛出错误并退出!
【解决方案2】:

问题在于 mcrypt 没有填充最后一个块,而 Ruby 的 OpenSSL 绑定使用默认的 OpenSSL 填充方法,即 PKCS 填充。我无法真正改进 OpenSSL 文档中的描述:

PKCS 填充通过添加 n 个值为 n 的填充字节来使数据的总长度成为块大小的倍数。始终添加填充,因此如果数据已经是块大小的倍数,则 n 将等于块大小。例如,如果块大小为 8,并且要加密 11 个字节,则将添加 5 个填充字节,值为 5。 在加密之前,您需要在 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 结尾的没有填充字节的明文。

【讨论】:

    猜你喜欢
    • 2016-05-26
    • 1970-01-01
    • 2014-12-10
    • 1970-01-01
    • 2012-07-20
    • 1970-01-01
    • 1970-01-01
    • 2013-04-08
    • 2014-12-07
    相关资源
    最近更新 更多