Ruby AES-256-CBC ve PHP MCRYPT_RIJNDAEL_128 birlikte iyi bir oyun yapmak için nasıl

3 Cevap php

Ben bir PHP yığınına bir Ruby yığından göndermek için veri üreten ediyorum. Ben Ruby yan ve PHP 'mcrypt' kütüphane üzerinde OpenSSL :: Şifreleme kitaplığı kullanıyorum. Ben Ruby 'aes-256-CBC' (256-bit blok boyutu) ile şifrelemek ben bunu şifresini PHP MCRYPT_RIJNDAEL_128 (128-bit blok boyutu) kullanmanız gerekir. Ben cipher.iv_len 16, çünkü kırık Ruby kodu şüpheli; Ben 32 olması gerektiğine inanıyoruz:

>> 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

Yani burada benim test. Ruby tarafta, ilk önce anahtarı ve iv oluşturmak:

>> 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="

Sonra şifreleme yapmak için bu tuşları kullanın:

>> 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="

Burada PHP çözme bulunuyor:

$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.'

Ben uzun blok boyutunu kullanmayı tercih ediyorum. Açıkçası ben API'lerini yanlış anlama var. Yardım?

3 Cevap

Ben PHP bilmiyorum, ama kenar çubuğunda ilgili sorular aracılığıyla okuma, ben Converting Ruby AES256 decrypt function to PHP bkz. Bu 128 MCRYPT_RIJNDAEL_128 şifreleme blok boyutu, değil anahtar boyutu ifade ettiğini işaret ederek, this page için bir başvuru içerir. Eğer yakut ve PHP arasındaki ilettik anahtar boyutu her iki durumda da 256 bit olduğunu fark edeceksiniz. Diğer bir deyişle, bu beklenen davranış gibi görünüyor ve zaten büyük tuşunu kullanıyorsunuz.

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

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

HTH

Ben başkası yukarıdaki tartışmanın açıklayıcı olabilecek bir örnek yazdı:

$ Cat 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('Bu benim metin')
crypt << cipher.final()

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

$ Cat 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";

Komut satırı denemede, bunu test etmek için:

$ Ruby publisher.rb | php consumer.php

Bu benim metin

PHP 8 karakterden daha küçük bir parola kullanarak çünkü ben sorunları vardı. Bu durumda biri PHP ile uyumlu hale getirmek için, 0 eklemek gerekiyor:

mcrypt-encrypt manual page "key

The key with which the data will be encrypted. If it's smaller than the required keysize, it is padded with '\0'. It is better not to use ASCII strings for keys. http://php.net/manual/en/function.mcrypt-encrypt.php It is recommended to use the mhash functions to create a key from a string."

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()