1

したがって、node.jsには、aes128を使用し、IVを渡さない暗号化スキームがあります。例は次のとおりです

 var cipher = require('crypto').createCipher('aes128','password');
 cipher.update('test','utf8','base64')+cipher.final('base64');

を出力しますCjZ3R/tW8jiyLvg+/TE6bA==。問題は、多くの実装とバリエーションを試したにもかかわらず、PHP でこれを再現できないことです。

次に、openssl を介してこれを実行しようとすると、次のように実行します。

 echo "test" | openssl enc -e -aes128 -a -k password

どちらも一致しない U2FsdGVkX19Ccfv3SWvuzuZWeov9GDuwx1RMK2HWa/s= を出力します。また、可能なすべてのオプションで を使用しようとしました-mdが、どちらも一致しませんでした (同じブロックサイズでさえありません)。PHPで実行しているときに、パディングを使用して、パディングを使用して、キーをハッシュする/ハッシュしないで、入力に計算されたパディングを使用しようとしました。そして、IVをパスワードとnullバイトに設定しようとしましたが、それでも一致しません。

ここに提案/アイデアはありますか?

編集:

そのため、php で関数 openssl_encrypt を発見し、それを使用して同じテストを試みたところ、まったく異なる出力が得られました (これは node.js とまったく同じ引数を取り、両方とも openssl を使用していると思われます):

 openssl_encrypt ( "test" , 'aes128' , "password")

JleA91MvYHdEdnj3KYHmog==少なくとも現在はブロック数が一致しているが、同じ暗号文ではない出力 (既に base64 で) 。

また、IVをnodejsに渡すことはオプションであり、不一致を解決する可能性があることにも言及する必要がありますが、phpのこのスキームは、すでに稼働しているnodejsの古いスキームを置き換えるため、すでに作成された暗号文を復号化できる必要があります

4

1 に答える 1

5

だから私は解決策を考え出しました。node.js の C++ ソース コードを調べたところ、openssl 関数 EVP_BytesToKey を使用してキーと iv が生成されていることがわかりました。この関数の実装を検索した後、この関数のバージョンを含むこのスタックオーバーフローポストを見つけました。それを変更し、opensslバージョンがパディングに必要なバイト数に等しいASCII文字でデータをパディングするという事実を追加して、nodejs暗号化スキームに完全に一致する次の関数を思いつきました:

function aes128Encrypt($key, $data) {
    $padding = 16 - (strlen($data) % 16);
    $data .= str_repeat(chr($padding), $padding);

    $keySize   = 16;
    $ivSize    = 16;

    $rawKey = $key;
    $genKeyData = '';
    do
    {
        $genKeyData = $genKeyData.md5( $genKeyData.$rawKey, true );
    } while( strlen( $genKeyData ) < ($keySize + $ivSize) );

    $generatedKey = substr( $genKeyData, 0, $keySize );
    $generatedIV  = substr( $genKeyData, $keySize, $ivSize );

    print($generatedIV);
    print($generatedKey);

    return mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $generatedKey, $data, MCRYPT_MODE_CBC, $generatedIV);
}

これは、node.js 関数と正確に一致します。

 function aes128Encrypt(key,data) {
      var cipher = require('crypto').createCipher('aes128',key);
      return cipher.update(data,'utf8','binary')+cipher.final('binary');
 }
于 2012-11-15T20:08:47.233 に答える