RubyのAES-256-CBCおよびPHP MCRYPT_RIJNDAEL_128が一緒によく遊ぶようにする方法

StackOverflow https://stackoverflow.com/questions/1862710

質問

私はRubyはPHPスタックにスタックから送信するデータを生成しています。私は、Ruby側とPHPの「mcryptの」ライブラリにOpenSSLの::暗号ライブラリを使用しています。 I 'は、AES-256-CBC' 私はそれを復号化するためにPHPでMCRYPT_RIJNDAEL_128(128ビットのブロックサイズ)を使用する必要がRubyで(256ビットのブロックサイズ)を使用して暗号化します。 cipher.iv_lenが16であるので、私は、壊れているRubyのコードを疑います。私はそれが32であるべきと考えています:

>> cipher = OpenSSL::Cipher::Cipher.new('aes-128-cbc')
=> #<OpenSSL::Cipher::Cipher:0x3067c5c>
>> cipher.key_len
=> 16
>> cipher.iv_len
=> 16
>> cipher = OpenSSL::Cipher::Cipher.new('aes-256-cbc')
=> #<OpenSSL::Cipher::Cipher:0x306de18>
>> cipher.key_len
=> 32
>> cipher.iv_len
=> 16

だからここに私のテストです。 Rubyの側では、最初に私は、キーとIVを生成します:

>> cipher = OpenSSL::Cipher::Cipher.new('aes-256-cbc')
>> cipher.encrypt
>> iv = cipher.random_iv
>> iv64 = [iv].pack("m").strip
=> "vCkaypm5tPmtP3TF7aWrug=="
>> key = cipher.random_key
>> key64 = [key].pack("m").strip
=> "RIvFgoi9xZaHS/0Bp0J9WDRyND6Z7jrd3btiAfcQ8Y0="

それから私は、暗号化を行うためにこれらのキーを使用します:

>> plain_data = "Hi, Don, this is a string."
>> cipher = OpenSSL::Cipher::Cipher.new('aes-256-cbc')
>> cipher.encrypt
>> cipher.key = Base64.decode64(key64)
>> cipher.iv = Base64.decode64(iv64)
>> encrypted_data = cipher.update(plain_data)
>> encrypted_data << cipher.final
>> crypt64 = [encrypted_data].pack("m").strip
=> "5gfC/kJcnAV2fJI0haxnLcdraIKWgtu54UoznVxf8K0="

ここではPHPの解読です。

$ruby_crypt = "5gfC/kJcnAV2fJI0haxnLcdraIKWgtu54UoznVxf8K0=";
$encrypted_data = base64_decode($ruby_crypt);
$key = base64_decode("RIvFgoi9xZaHS/0Bp0J9WDRyND6Z7jrd3btiAfcQ8Y0=");
$iv = base64_decode("vCkaypm5tPmtP3TF7aWrug==");
$result = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $encrypted_data, MCRYPT_MODE_CBC, $iv);
$unencrypt = rtrim($result, "\x00..\x1F");
print "\nUnencrypted token:\n'$unencrypt'\n";

RESULT:
Unencrypted token:
'Hi, Don, this is a string.'

私は長いブロックサイズを使用することを好むだろう。明らかに私は、APIを誤解しています。ヘルプ?

役に立ちましたか?

解決

私はPHPを知らないが、サイドバーに関連する質問を通読、私は<のhref = "https://stackoverflow.com/questions/1628488/converting-ruby-aes256-decrypt-function-to-を参照してくださいPHP のにルビーAES256暗号化解除機能を変換するPHP ">。これはMCRYPT_RIJNDAEL_128 128を指すことを指摘、このページへの言及を含みます暗号のブロックサイズではなく、キーのサイズ。あなたはルビーとPHPとの間を通過してきたキーサイズは両方のケースでは256ビットであることがわかります。言い換えれば、これは正常な動作であると思われる、とあなたはすでに大きなキーを使用しています。

#!/usr/bin/ruby
require 'base64'

puts((Base64.decode64("RIvFgoi9xZaHS/0Bp0J9WDRyND6Z7jrd3btiAfcQ8Y0=").length * 8).to_s)

HTH

他のヒント

私は他の誰かが上記の議論の説明を見つけることの例を書きました

$猫publisher.rb

#!/usr/bin/env ruby

require 'openssl'
require 'base64'

key = '7fc4d85e2e4193b842bb0541de51a497'

cipher = OpenSSL::Cipher::Cipher.new('aes-128-cbc')
cipher.encrypt()
iv = cipher.random_iv

cipher = OpenSSL::Cipher::Cipher.new('aes-256-cbc')
cipher.encrypt()
cipher.key = key
cipher.iv = iv
crypt = cipher.update('This is my text')
crypt << cipher.final()

puts [Base64.encode64(crypt).strip(), Base64.encode64(iv).strip()].join('|')

$猫consumer.php

$key256 = '7fc4d85e2e4193b842bb0541de51a497';

$fd = fopen("php://stdin", "r");
$tokens = '';
while (!feof($fd))
  $tokens .= fread($fd, 1024);
fclose($fd);

$tokens = explode('|', trim($tokens));
$crypt = $tokens[0];
$iv = $tokens[1];

$crypttext = base64_decode($crypt);
$iv = base64_decode($iv);
$decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key256, $crypttext, MCRYPT_MODE_CBC, $iv);

print $decrypted ."\n";

コマンドライン試してから、それをテストするには:

  

$ルビーpublisher.rb | PHPのconsumer.php

     

これは私のテキストです。

PHPは、8文字未満のパスワードを使用していたので、

私は悩みを持っていました。この場合、1は、PHPと互換性を持たせるために、0を追加する必要があります:

mcryptの暗号化マニュアルページ 「キー

データを暗号化する際のキー。それは必要なキーサイズよりも小さいなら、それは「\ 0」で埋められています。キーのASCII文字列を使用しない方が良いです。 http://php.net/manual/en/function.mcrypt-encrypt.php の 文字列からキーを生成するにはmhash関数を使用することをお勧めします。 "

require 'openssl'
cipher = OpenSSL::Cipher.new('DES-ECB')
cipher.encrypt
key =  'passwrd'[0...7].ljust(8, 0.chr)  #Pad the key smaller than 8 chars
cipher.key = key
encrypted = cipher.update('33')
encrypted << cipher.final
dec = Base64.encode64(encrypted).strip()

私はあなたにいくつかのコードをお見せしましょう。

PHPコード:

$privateKey = "1234567890123456"; # the size is 16.
$data = "hello";
$iv = "0123456789012345";

$result = mcrypt_encrypt(
  MCRYPT_RIJNDAEL_128, $privateKey, $data, MCRYPT_MODE_CBC, $iv
)

$base64str = base64_encode($result);
$base64str = str_replace("+", "-",  $base64str);
$base64str = str_replace("/","_",  $base64str);

# => f-WffBXnf122NcVBUZ6Rlg==

Rubyコード:

require 'base64'
require 'openssl'

private_key = "1234567890123456"
data = "hello"
iv = "0123456789012345"

cipher = OpenSSL::Cipher::AES.new(128, :CBC) 
cipher.encrypt

cipher.padding = 0 # we must disable padding in ruby.
cipher.key = private_key
cipher.iv = iv
block_size = cipher.block_size

# Add padding by yourself.
data = data + "\0" * (block_size - data.bytesize % block_size)
result = cipher.update(data) + cipher.final

Base64.urlsafe_encode64(result)
# ==> f-WffBXnf122NcVBUZ6Rlg==

あなたはprivate_keyのサイズは16であるので、私はルビーでAES-128を使用しています見ることができるように。 つまり、あなたのprivate_keyのサイズが32である場合には、AES-256を使用する必要があります。

式:size_of_private_key * 8

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top