サーバー側で中程度から強力な暗号化が必要なので、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;
}
関数の何が問題になっていますか? データにそのようなプレフィックスを付ける必要があるのはなぜですか (私はそれを汚い回避策と考えているので、修正したいと考えています)。
暗号化されたデータを保存することは問題ではありません。データベースに保存せずに暗号化の直後に復号化すると、同じエラーが発生します。