So sorgen Sie dafür, dass Ruby AES-256-CBC und PHP MCRYPT_RIJNDAEL_128 gut zusammenspielen
Frage
Ich erstelle Daten, die von einem Ruby-Stack an einen PHP-Stack gesendet werden sollen.Ich verwende die OpenSSL::Cipher-Bibliothek auf der Ruby-Seite und die „mcrypt“-Bibliothek in PHP.Wenn ich in Ruby mit „aes-256-cbc“ (256-Bit-Blockgröße) verschlüssele, muss ich zum Entschlüsseln MCRYPT_RIJNDAEL_128 (128-Bit-Blockgröße) in PHP verwenden.Ich vermute, dass der Ruby-Code kaputt ist, weil cipher.iv_len 16 ist;Ich glaube, es sollte 32 sein:
>> 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
Hier ist also mein Test.Auf der Ruby-Seite generiere ich zuerst den Schlüssel und 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="
Dann verwende ich diese Schlüssel, um die Verschlüsselung durchzuführen:
>> 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="
Hier ist die PHP-Entschlüsselung:
$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.'
Ich würde lieber die längere Blockgröße verwenden.Offensichtlich verstehe ich die APIs falsch.Helfen?
Lösung
Ich weiß, PHP nicht, aber auf der Sidebar durch Fragen zu lesen, ich sehe Konvertieren von Ruby-AES256 decrypt Funktion PHP . Dies beinhaltet eine Referenz href="http://www.chilkatsoft.com/p/php_aes.asp" rel="nofollow noreferrer"> dieser Seite MCRYPT_RIJNDAEL_128 auf die verweist Blockgröße der Verschlüsselung nicht die Schlüsselgröße. Sie werden bemerken, dass die Schlüsselgröße, die Sie zwischen Ruby und PHP ist 256 Bits in beiden Fällen bestanden haben. Mit anderen Worten, scheint dies das erwartete Verhalten zu sein, und Sie werden mit dem größeren Schlüssel bereits.
#!/usr/bin/ruby
require 'base64'
puts((Base64.decode64("RIvFgoi9xZaHS/0Bp0J9WDRyND6Z7jrd3btiAfcQ8Y0=").length * 8).to_s)
HTH
Andere Tipps
Ich habe ein Beispiel geschrieben, das jemand anderes als Erklärung für die obige Diskussion finden könnte:
$ cat editor.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('|')
$ 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";
Um es zu testen, versuchen Sie es über die Befehlszeile:
$ Ruby Publisher.RB | PHP Consumer.php
Das ist mein Text
Ich hatte Probleme, weil die PHP war ein Passwort kleiner als 8 Zeichen. In diesem Fall muss man die 0 hinzufügen, um es mit PHP kompatibel zu machen:
mcrypt-encrypt Manpage „Taste
Der Schlüssel, mit dem die Daten werden verschlüsselt. Wenn es kleiner als die erforderlichen keysize, ist es mit ‚\ 0‘ aufgefüllt. Es ist besser, nicht ASCII-Zeichenkette für Schlüssel zu verwenden. http://php.net/manual/en/function.mcrypt-encrypt.php Es wird empfohlen, die mhash Funktionen zu verwenden, um einen Schlüssel aus einem String zu erstellen. "
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()
Lassen Sie mich Ihnen etwas Code zeigen.
PHP-Code:
$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-Code:
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==
Wie Sie sehen Ich bin mit AES-128 in Ruby, da die Größe private_key
16 ist.
So haben Sie AES-256 zu verwenden, wenn die Größe Ihres private_key
32 ist.
Formel:. size_of_private_key
* 8