2

サーバー側で中程度から強力な暗号化が必要なので、PHP で mcrypt を使用すると考えました。以下の関数を使用すると、元の文字列の先頭が復号化後にバイナリ ガベージに変わります。(これは追加のガベージが追加されるという通常の問題ではなく、代わりに文字列が変更されます。) ドキュメントによると、mcrypt_encrypt() は、選択したアルゴリズムのブロック サイズに一致するように十分な文字をパディングする必要がありますが、機能しないと思われます。

ただし、Rijndael の 128 ビット (16 バイト) のブロック サイズに手動でパディングしても、うまくいきません。これを機能させる唯一の方法は、ガベージブロックをカバーするのに十分な長さの文字列を先頭に追加し、その文字列とデータの間に「DATA#」などの既知のプレフィックスを追加することです。復号化後、そのブロックは部分的に壊れていますが、私のプレフィックスとその後のすべてのデータは正しく復号化されています.

$GLOBALS['encryptionmarker'] = 'DATA#';

function encrypt($plain, $key) {
    /*
    // workaround because beginning of decrypted string is being mangled
    // so we simply prefix with some text plus marker
    $prefix = str_pad('', 128, '#', STR_PAD_RIGHT).$GLOBALS['encryptionmarker'];
    $plain = $prefix.$plain;
    */

    $encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $plain, MCRYPT_MODE_CFB,
        mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CFB),
        MCRYPT_DEV_URANDOM));

    return $encrypted;
}

function decrypt($encrypted, $key) {
    $decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $encrypted, MCRYPT_MODE_CFB,
        mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CFB),
        MCRYPT_DEV_URANDOM));

    /*
    // workaround: remove garbage
    $pos = strpos($decrypted, $GLOBALS['encryptionmarker']);
    $decrypted = trim(substr($decrypted, $pos + strlen($GLOBALS['encryptionmarker'])));
    */

    return $decrypted;
}

関数の何が問題になっていますか? データにそのようなプレフィックスを付ける必要があるのはなぜですか (私はそれを汚い回避策と考えているので、修正したいと考えています)。

暗号化されたデータを保存することは問題ではありません。データベースに保存せずに暗号化の直後に復号化すると、同じエラーが発生します。

4

2 に答える 2

5

あなたの問題は、受信側で新しい、異なる、ランダムな IV を生成していることです。ご覧のとおり、これは機能しません。

受信者は、送信者が使用した IV を知る必要があります。そのため、暗号化されたデータと一緒に送信して、 に渡す必要がありmcrypt_decrypt()ます。

mhash()また、キー (暗号化キーとは別のキー) を使用してメッセージに対して HMAC を生成し、受信側で確認する必要があることに注意してください。そうしないと、中間者がメッセージの一部をあなたが気付かないうちに簡単に変更する可能性があります。

于 2009-08-24T13:36:05.943 に答える
2

暗号化と復号化で同じ IV を使用します。IV は共有シークレットではありませんが、共有する必要があります。ウィキペディアを参照してください: IV

$IV = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CFB),
      MCRYPT_DEV_URANDOM));

IV は 1 回転送する必要があります。パケットごとに IV の値を増やしたい場合があります。ただし、これは両側で個別に行うことができます。

于 2009-08-24T13:42:08.820 に答える