更新 5
質問を Security StackExchange に切り替えました - 回答を得ました。 https://security.stackexchange.com/questions/30168/aes-cfb-128-decryption-encryption-problem-between-erlang-and-php
更新 4
問題を解決したか、そう思ったので、実装を進めようとしました。十分ではないことが判明しました。
実際の単語データを入れ始めると、すべてが地獄に落ちました。例として、プレーン テキストを から1234567812345678
に増やします。12345678123456781234567812345678
この場合、cypertext の最初の 128 ビット ブロックは同じでしたが、2 番目のブロックは異なっていました。
PHP:
139 182 94 68 208 173 127 90 14 236 33 230 41 29 210 121 153 57 173 191 237 169 242 222 217 104 116 144 240 175 39 33
アーラン:
<<139,182,94,68,208,173,127,90,14,236,33,230,41,29,210,121,147,172,
114,74,61,11,162,5,112,104,102,63,24,78,34,179>>
更新 3 - (私はそうでしたが) 解決済み (しかし私は間違っていました)
この回答は最終的な手がかりを提供しました: Crypto++ AES暗号化をPHPのmcryptに移植するときのキーサイズが正しくありません
問題は、'cfb'
モード がmycrypt
エミュレートするのに適切なフィードバック ブロックサイズを使用していないことです。aes cfb
モードを使用する必要がありますnofb
。
更新 2
AES-CFB-128 を両方で機能させようとしています。そのため、ブロック サイズとタイプが 128mycrypt
のモードを使用することは、Erlangでの PHP と同等であることがわかりました。RINJDAEL_128
'cfb'
crypto:aes_cfb_128/3
そこで、これを証明するために、両方の言語でルーチンを書き始めました。
PHP のバージョン:
<?php
// fugly because I don't know enough PHP to write it better
// big apologies to any PHP code poets out there, my bad :(
function dump($String, $Bin) {
echo $String . " is " . ord($Bin[0]) . " " . ord($Bin[1]) . " " . ord($Bin[2]) . " " . ord($Bin[3]) . " " . ord($Bin[4]) . " " . ord($Bin[5]) . " " . ord($Bin[6]) . " " . ord($Bin[7]) . " " . ord($Bin[8]) . " " . ord($Bin[9]) . " " . ord($Bin[10]) . " " . ord($Bin[11]) . " " . ord($Bin[12]) . " " . ord($Bin[13]) . " " . ord($Bin[14]) . " " . ord($Bin[15]) . "\n";
}
$Key = "abcdefghabcdefgh";
$IV = "12345678abcdefgh";
$Text = "1234567812345678";
$KeySize = strlen($Key) * 8;
$IVSize = strlen($IV) * 8;
$TextSize = strlen($Text) * 8;
$Size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CFB);
echo "Block size is " . $Size . " bytes or " . $Size * 8 . " bits\n";
$Crypt = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $Key, $Text, MCRYPT_MODE_CFB, $IV);
$Decrypt = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $Key, $Crypt, MCRYPT_MODE_CFB, $IV);
echo "Key is " . $Key . " with size " . $KeySize . "\n";
echo "IV is " . $IV . " with size " . $IVSize . "\n";
echo "Text is " . $Text . " with size " . $TextSize . "\n";
echo "Crypt is " . $Crypt . "\n";
dump("Crypt", $Crypt);
echo "Decrypt is " . $Decrypt . "\n";
dump("Decrypt", $Decrypt);
?>
実行すると、次の PHP 出力が得られます。
Block size is 16 bytes or 128 bits
Key is abcdefghabcdefgh with size 128
IV is 12345678abcdefgh with size 128
Text is 1234567812345678 with size 128
Crypt is ��*�b�ls�M��
Crypt is 139 0 188 42 175 98 18 177 108 27 115 189 77 144 127 176
Decrypt is 1234567812345678
Decrypt is 49 50 51 52 53 54 55 56 49 50 51 52 53 54 55 56
Erlang のバージョンは次のとおりです。
-module(test_crypto).
-export([
test/0
]).
test() ->
Key = <<"abcdefghabcdefgh">>,
IV = <<"12345678abcdefgh">>,
Text = <<"1234567812345678">> ,
KeySize = bit_size(Key),
IVSize = bit_size(IV),
TextSize = bit_size(Text),
io:format("Key is ~p with size ~p~n", [Key, KeySize]),
io:format("IV is ~p with size ~p~n", [IV, IVSize]),
io:format("Text is ~p with size ~p~n", [Text, TextSize]),
Crypt = crypto:aes_cfb_128_encrypt(Key, IV, Text),
io:format("Crypt is ~p~n", [Crypt]),
Decrypt = crypto:aes_cfb_128_decrypt(Key, IV, Crypt),
io:format("Decrypt is ~p~n", [Decrypt]),
ok.
実行すると、Erlang の出力が得られます。
Key is <<"abcdefghabcdefgh">> with size 128
IV is <<"12345678abcdefgh">> with size 128
Text is <<"1234567812345678">> with size 128
Crypt is <<139,182,94,68,208,173,127,90,14,236,33,230,41,29,210,121>>
Decrypt is <<"1234567812345678">>
したがって、それぞれが暗号化/復号化サイクルを正しく実行しますが、暗号形式は異なります。Erlang と PHP の間で使用することはできません。
簡単な説明があると確信していますが、理解するのに途方に暮れています。
PHP は文字列を入力として受け取り、Erlang はバイナリを受け取りますが、PHP ascii 文字列はバイナリとして格納されているようです。そうですか、何か不足していますか?
更新 1
crypto:md5_mac/2
関数はphp関数で複製できることがわかりました:
function encrypt_term_hex($Key, $Msg) {
return hash_hmac("md5", $Msg, $Key);
}
元の質問
Erlang で作成されたシステムと PHP で作成されたシステムの 2 つのシステム間で情報を共有したいと考えています。
計画では、Erlang システム間で共有される秘密鍵を使用して Erlang 用語に署名することを含む、複数の Erlang システム間で既に実行されているシステムを使用する予定です。
Erlang 側は関数crypto:md5_mac/2
を使用し、Erlang 側はcrypto:aes_cfb_128_encrypt/3
基礎となる OpenSSL 暗号化ライブラリを使用します。
暗号化側 (Erlang で) は次のとおりです。
encrypt_bin(Key0, PlainT0) ->
PlainT = extend(PlainT0),
Key = crypto:md5_mac(get_server_salt(), Key0),
crypto:aes_cfb_128_encrypt(Key, get_salt(), PlainT).
この関数が行うことは、キーと値のペアを取ることです。次に、用語のサイズを固定サイズに拡張し、md5_mac と固定 (共有) ソルトを使用してキーを生成し、最後に暗号化を行います - 別のソルト ベクトルで初期化します。
ここまでは順調ですね。私の仕事は、この fn を PHP で複製することです (もちろん、その復号化ツインも)。
Erlang のドキュメントは優れています。
http://erlang.org/doc/man/crypto.html
Erlang が基礎となる Crypto ライブラリをどのように呼び出すかを正確に理解しようとするのは少し難しいです - ソースコードが不明瞭な NIF マクロを示すからです。
PHP は OpenSSL の周りにライブラリ ラッパーを実装しているように見えるので、簡単なはずです。残念ながら、私はそれの頭も尻尾も作ることができません。たとえば、私は openssl-encrypt を見て、それが文書化されていないと述べています:
http://php.net/manual/en/function.openssl-encrypt.php
OpenSSL が PHP にどのように実装されているかの良い例/ドキュメントを入手できる場所はありますか? または、Erlang NIF ローダーはどのように機能しますか? または両方?