Rijndael AES-128 encryption decryption in Ruby

岁酱吖の 提交于 2019-12-05 08:04:41

问题


I want to use rijndael aes128 for encryption in ruby. I have this code:

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

which is not working. But using this PHP function:

<?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/>";
  ?>

I got my desired output:

0D5835AFEBEE04C6DC2421538DB7C38A1283970EB31F21A47D2E3CC623D29EF0461279C7ACF93B031BE2B69CE45C9339554957F29EF609F019EEC975983A03B537622D7E0F196BE148F1C7CBB88E602A

How can I get my Ruby code to produce the same output?


回答1:


The problem is that mcrypt isn't padding the last block, whereas Ruby's OpenSSL binding uses the default OpenSSL padding method, which is PKCS padding. I can't really improve on the description from the OpenSSL documentation:

PKCS padding works by adding n padding bytes of value n to make the total length of the data a multiple of the block size. Padding is always added so if the data is already a multiple of the block size n will equal the block size. For example if the block size is 8 and 11 bytes are to be encrypted then 5 padding bytes of value 5 will be added. You'll need to manually add proper padding to the end of the cleartext in PHP before encrypting. To do that, pass your $cleartext through this pkcs5_pad function on the PHP side before you encrypt it (passing 16 as the blocksize).

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

If you also go the other way (encrypt in Ruby and decrypt with mcrypt), you'll have to strip off the padding bytes after decrypting.

Side note: The reason you have to add padding even if the cleartext is already a multiple of the blocksize (a whole block of padding), is so that when you are decrypting you know that the last byte of the last block is always the amount of padding added. Otherwise, you couldn't tell the difference between cleartext with a single padding byte and a cleartext with no padding bytes that just happened to end in the value 0x01.




回答2:


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

Output:

0D5835AFEBEE04C6DC2421538DB7C38A1283970EB31F21A47D2E3CC623D29EF0461279C7ACF93B031BE2B69CE45C9339554957F29EF609F019EEC975983A03B537622D7E0F196BE148F1C7CBB88E602A


来源:https://stackoverflow.com/questions/18374550/rijndael-aes-128-encryption-decryption-in-ruby

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!