2012-03-20 4 views
8

は、暗号化したデータを復号化PHPのデモスクリプトです:mcrypt_encrypt()が文字列の最後にバイナリ文字を置くのはなぜですか?ここ

<? 

$encryptionkey = 'h8y2p9d1'; 

$card_nbr = "1234"; 
echo "original card_nbr: $card_nbr <br>\n"; 

$card_nbr_encrypted=encrypt_data($card_nbr); 
echo "card_nbr_encrypted: $card_nbr_encrypted <br>\n"; 

$card_nbr_decrypted=decrypt_data($card_nbr_encrypted); 
echo "card_nbr_decrypted: $card_nbr_decrypted <br>\n"; 

$len=strlen($card_nbr_decrypted); 
echo "length: $len <br>\n"; 



function encrypt_data($text){ 
    global $encryptionkey; 
    $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB); 
    $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND); 
    $encrypted_text = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $encryptionkey, $text, MCRYPT_MODE_ECB, $iv); 
    return $encrypted_text; 
} 

function decrypt_data($text){ 
    global $encryptionkey; 
    $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB); 
    $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND); 
    $decrypted_text = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $encryptionkey, $text, MCRYPT_MODE_ECB, $iv); 
    return $decrypted_text; 
} 

?> 


出力は次のとおりです。

original card_nbr: 1234 
card_nbr_encrypted: vY¨(Z$<§G3-žÃ-Éù3Ý2Ê×rz¨VÛ 
card_nbr_decrypted: 1234 (and 28 binary characters) 
length: 32 


出力が正常に復号化されているが、28進文字が追加されています終わり。これは、HTMLソースを表示しているときにFirefoxで最も簡単に見ることができます。 文字列の長さが32であることもこれを実証しています。何か案は?

enter image description here

+0

これは助けになるかどうかを確認してください。http://php.net/manual/en/function.base64-encode.php –

+0

@Mian_Khurram_Ijazなぜそれが役に立たないのかわかりません。 – Ben

+0

出力は実際にバイナリ形式です暗号化と復号化が正常に動作しているので、バイナリ文字が問題の場合はbase64を使用すると考えました。 –

答えて

8

返される文字列は、ヌル文字\0を使用してn * blocksizeバイトを埋めて埋め尽くされているため、余分なデータが表示されます。

$card_nbr_decrypted= rtrim($card_nbr_decrypted, "\0");を実行すると、実際のデータが返されます。

+0

あなたが望むならば、 'rtrim'を使った解決策はもちろん壊れています実際にいくつかのヌル数で終了する可能性のある任意のバイナリデータを暗号化します。その場合、文字列の長さをout-of-bandと 'substr'をその長さに戻すか(簡単ですが、文字列の長さが漏れます)、暗号化する前にパディングを行う必要があります。理解しやすいPKCS#7パディングメソッド。 – hobbs

+0

PKCS#7の問題は、mcryptを書いて保守していたbozosがそれをサポートしていたことです。 – zaph

3

known problemのようです。過剰なNULを取り除くために復号化した後にrtrim()を使用してください。

2

あなたがブロックサイズに合わせて平文の終わりをパッド電子コードブロック(ECB)あなたのblock cipher mode of operationためを、使用しているので、あなたはNULLバイトを受信して​​います。あなたの場合、MCRYPT_RIJNDAEL_256を使用しているため、ブロックサイズは256ビットです。 MCRYPT_MODE_CFB - - なしNULLバイト、トリミングする必要はありませんあなたは暗号フィードバック(CFB)モードを使用する場合

あなたはすべて一緒にこのパディングの問題を回避することができます。しかし、CFBの場合、(see "Mallet")で改ざんされていないことを確認するために、暗号化されたデータをHMACに送信する必要があります。作業実装の例はCryptography For The Average Developerにあります。

また、ECBモードは、reveal data patternsとすることができるため、安全性が低いとみなされます。プラス、ECB(そしてCBCもパッドなので)はpadding oracle attackに脆弱です。あなたが使用する平文のためBASE64_ENCODE($テキスト)を使用することができます与えられたパラメータ

でプレーンテキストを暗号化する -

MCRYPT_ENCRYPTは:

-1

は、私はこの問題は、ときにバイナリデータを使用していることだと思います。

+0

エンコーディングは暗号化と同じではありません。 –

+0

私は知っています。しかし、あなたがmcrypt_encryptを使うなら、$ textをbase64の平文として送ることは、エンコーディングの問題を避けるのに便利です。 ユーザーが提案するものと同じように、base64_encode($ text)またはrtrim()を使用できます。 – bLuEdDy

関連する問題