私の必要条件は次のとおりです:PHPで暗号化されたものが、Rubyで暗号化された同じ文字列と一致しないのはなぜですか?
AES暗号化(ランダムivを含む)を使用してPHPで文字列を暗号化し、Base64でエンコードし、URLパラメータとして渡すことができるようにURLエンコードする必要があります。
私はPHPとRubyの両方で同じ結果を得ようとしていますが、動作させることはできません。ここで
function encryptData($data,$iv){
$cipher = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
$iv_size = mcrypt_enc_get_iv_size($cipher);
if (mcrypt_generic_init($cipher, 'g6zys8dlvvut6b1omxc5w15gnfad3jhb', $iv) != -1){
$cipherText = mcrypt_generic($cipher,$data);
mcrypt_generic_deinit($cipher);
return $cipherText;
}
else {
return false;
}
}
$data = 'Mary had a little lamb';
$iv = '96b88a5f0b9efb43';
$crypted_base64 = base64_encode(encryptData($data, $iv));
私のRubyのコードは次のとおりです:
は、ここに私のPHPコードである
module AESCrypt
def AESCrypt.encrypt(data, key, iv)
aes = OpenSSL::Cipher::Cipher.new("aes-256-cbc")
aes.encrypt
aes.key = key
aes.iv = iv
aes.update(data) + aes.final
end
end
plaintext = "Mary had a little lamb"
iv = "96b88a5f0b9efb43"
@crypted = AESCrypt::encrypt(plaintext, "g6zys8dlvvut6b1omxc5w15gnfad3jhb", iv)
@crypted_base64 = Base64.encode64(@crypted)
@crypted_base64_url = CGI.escape(@crypted_base64)
腹立たしいものは、両方のコードサンプルは似てではなく、同一のハッシュを生成することです。例えば、上記のコードは、(Base64エンコード、URLエンコードされていない)を生成:
PHP:/aRCGgLBMOOAarjjtfTW2Qg2OtbPDLhx3KmgfgMzDJU=
をルビー:/aRCGgLBMOOAarjjtfTW2XIZhZ9VjBx8PdozxSL8IE0=
誰も私が間違ってここにやっているかを説明することはできますか?また、PHPコードではなくRubyコードを修正する方が簡単です(私はRubyの人でPHPではなく)。だから、もしあなたがRubyでPHPとよく似たソリューションを提供したいのであれば、私は最も感謝しています。
ああ、また、実際にはivは本当にランダムですが、この例では出力を比較できるように永久に同じに設定しています。
EDIT:オイゲン・Rieckの答えに
おかげで、私は解決策に到着しました。 Rubyはブロックを埋めますが、PHPはそうではありません。手動で行う必要があります。以下にPHPコードを変更し、あなたが上記のRubyコードを簡単に解読できる暗号化された文字列を取得:
$iv = '96b88a5f0b9efb43';
$data = 'Mary had a little lamb';
function encryptData($data,$iv){
$key = 'g6zys8dlvvut6b1omxc5w15gnfad3jhb';
$padded_data = pkcs5_pad($data);
$cryptogram = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $padded_data, MCRYPT_MODE_CBC, $iv);
return $cryptogram;
}
function pkcs5_pad ($text, $blocksize){
$pad = $blocksize - (strlen($text) % $blocksize);
return $text . str_repeat(chr($pad), $pad);
}
解決策には役に立ちませんが、これはブロックパディングと関係があります(出力文字列は最初のn文字で同じなので)。ブロックサイズに基づいてプレーンテキストに手動でパディングを追加することをお勧めします。 – Mikk
RubyコードがAES-256を呼び出しています。 PHPコードがAES-128を呼び出しています。これが正しいと確信していますか?あなたのIVは明らかに128です。 – Charles
@Charles私はこれも理解していません。しかし、これは物事が働く唯一の方法です。AES-256を呼び出すようにPHPを切り替えると、RubyはOpenSSLから「不正な復号化」エラーを引き起こします。 (以下の答えに私のコメントに記載されたスレッドを参照してください。) また、[this](http://www.chilkatsoft.com/p/php_aes.asp)は、PHPの暗号の奇妙なことを詳しく説明しています。私はそれがあなたの質問をクリアすると思う。 – John