4

これは、ミッションクリティカルというよりも、私が間違っていることの練習になりましたが、それでも、私が犯している(おそらく単純な)間違いを確認したいと思います。

文字列を暗号化するためにmysql(5.1.x)AES_ENCRYPTを使用しています。CFのgenerateSecretKey('AES')を使用してキーを作成しています(デフォルトで128ビットと256ビットの長さで試しました)。

それで、私のコードが次のようになっているとしましょう:

    <cfset key = 'qLHVTZL9zF81kiTnNnK0Vg=='/>
    <cfset strToEncrypt = '4111111111111111'/>
    <cfquery name="i" datasource="#dsn#">
        INSERT INTO table(str) 
            VALUES AES_ENCRYPT(strToEncrypt,'#key#');
    </cfquery>

これは期待どおりに正常に機能し、SELECT AES_DECRYPT(str、'#key#')AS...を使用して問題なく選択できます。

私ができないように見えるのは、CFに次のようなものを使用して復号化させることです。

    <cfquery name="s" datasource="#dsn#">
        SELECT str
          FROM table
    </cfquery>
    <cfoutput>#Decrypt(s.str,key,'AES')#</cfoutput>

また

    <cfoutput>#Decrypt(toString(s.str),key,'AES')#</cfoutput>

「入力と出力のエンコーディングが同じではありません」(toString()を含む-それがないと、バイナリデータエラーが発生します)が発生し続けます。db内の暗号化された文字列のフィールドタイプはblobです。

4

1 に答える 1

5

このエントリは、mySQLがAES-128キーを予想とは少し異なる方法で処理することを説明しています。

.. MySQLアルゴリズムは、パスワードが16文字より長い場合は、指定されたパスフレーズのバイトを前のバイトと比較し、パスワードが16文字より短い場合は0のままにします。

高度なテストは行われていませんが、これで同じ結果が得られるようです(16進数)。

<cfscript>
    function getMySQLAES128Key( key ) {
        var keyBytes   = charsetDecode( arguments.key, "utf-8" );
        var finalBytes = listToArray( repeatString("0,", 16) );

        for (var i = 1; i <= arrayLen(keyBytes); i++) {
            // adjust for base 0 vs 1 index
            var pos = ((i-1) % 16) + 1;
            finalBytes[ pos ] = bitXOR(finalBytes[ pos ], keyBytes[ i ]);
        }

        return binaryEncode( javacast("byte[]", finalBytes ), "base64" );
    }

    key     = "qLHVTZL9zF81kiTnNnK0Vg==";
    input   = "4111111111111111";

    encrypted = encrypt(input, getMySQLAES128Key(key), "AES", "hex");
    WriteDump("encrypted="& encrypted);

    // note: assumes input is in "hex". either convert the bytes 
    // to hex in mySQL first or use binaryEncode
    decrypted = decrypt(encrypted, getMySQLAES128Key(key), "AES", "hex");
    WriteDump("decrypted="& decrypted);
</cfscript>

注:暗号化にmySQLを使用している場合は、プレーンテキストがさまざまなログ (レプリケーション、履歴、その他)に記録され、「その情報への読み取りアクセス権を持つ人なら誰でも読むことができる」と記載されているドキュメントを必ず参照してください。


更新:状況は変更された可能性がありますが、この2004年のバグレポートによると、.mysql_historyファイルはUnix上にのみあります。(他のログファイルがある可能性があることに注意してください).mysql_historyをクリアするための詳細な手順は、マニュアルに記載されていますが、要約すると次のようになります。

  • MYSQL_HISTFILE変数を/dev/ nullに設定します(ログインごとに)
  • / dev / nullへのシンボリックリンクとして.mysql_historyを作成します(1回のみ)
于 2012-06-07T06:10:01.957 に答える