PHP AES 暗号化…何をしているのかわかりません
-
26-09-2019 - |
質問
暗号化についてはあまり詳しくありませんが、PHP で AES を動作させることができました。幾分。私が使用している関数をいくつか示します。
function aes_decrypt($val,$ky)
{
$key="\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
for($a=0;$a<strlen($ky);$a++)
$key[$a%16]=chr(ord($key[$a%16]) ^ ord($ky[$a]));
$mode = MCRYPT_MODE_ECB;
$enc = MCRYPT_RIJNDAEL_128;
$dec = @mcrypt_decrypt($enc, $key, $val, $mode, @mcrypt_create_iv( @mcrypt_get_iv_size($enc, $mode), MCRYPT_RAND) );
return rtrim($dec,(( ord(substr($dec,strlen($dec)-1,1))>=0 and ord(substr($dec, strlen($dec)-1,1))<=16)? chr(ord( substr($dec,strlen($dec)-1,1))):null));
}
function aes_encrypt($val,$ky)
{
$key="\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
for($a=0;$a<strlen($ky);$a++)
$key[$a%16]=chr(ord($key[$a%16]) ^ ord($ky[$a]));
$mode=MCRYPT_MODE_ECB;
$enc=MCRYPT_RIJNDAEL_128;
$val=str_pad($val, (16*(floor(strlen($val) / 16)+(strlen($val) % 16==0?2:1))), chr(16-(strlen($val) % 16)));
return mcrypt_encrypt($enc, $key, $val, $mode, mcrypt_create_iv( mcrypt_get_iv_size($enc, $mode), MCRYPT_RAND));
}
これらは、 mcrypt の PHP ドキュメント ページのコメント. 。(Windows 環境では dev_urandom が利用できないため、dev_urandom から rand に変更しました。)
とにかく、この関数で使用するキーは次のように定義されています。
define("PSK", pack("H*", "abcd7b5ca46e12345678a8161fdacee9"));
次のように関数を呼び出します。
echo bin2hex(aes_encrypt("wootwootwootwootwootwootwoo", PSK));
これで、結果の 16 進数文字列の最初の 16 バイト (32 桁) は正常になります。次の 16 バイトは予期されたものと一致しません。
このデータを外部 Web サービスに投稿し、そこで復号化されます。(残念ながら) 暗号化キーとデータを渡さずに、私が持っている 1 つのテスト ケースを提供することはできません。大変申し訳ありませんが、mcrypt に詳しい方がこれを見て、何が間違っているのか教えていただければ幸いです。
繰り返しになりますが、しっかりとしたテストケースが不足していて申し訳ありませんが、ご協力いただければ幸いです。
編集: 投稿先のプロバイダーが null IV を使用しているようです。Rook さんのアドバイスに従い、CBC モードに切り替え、キーに関連する不要なコードを削除しました。私の新しい関数は次のとおりです。
function aes_decrypt($val,$key)
{
$mode = MCRYPT_MODE_CBC;
$enc = MCRYPT_RIJNDAEL_128;
$dec = @mcrypt_decrypt($enc, $key, $val, $mode, null);
return rtrim($dec,(( ord(substr($dec,strlen($dec)-1,1))>=0 and ord(substr($dec, strlen($dec)-1,1))<=16)? chr(ord( substr($dec,strlen($dec)-1,1))):null));
}
function aes_encrypt($val,$key)
{
$mode = MCRYPT_MODE_CBC;
$enc=MCRYPT_RIJNDAEL_128;
$val=str_pad($val, (16*(floor(strlen($val) / 16)+(strlen($val) % 16==0?2:1))), chr(16-(strlen($val) % 16)));
return mcrypt_encrypt($enc, $key, $val, $mode, null);
}
解決
これは、この暗号化サービスは、CBCのような操作の異なるブロック暗号モードを使用している可能性があります。ヌルIVはCBCモードで使用されている場合、ECBとCBCの最初のブロックは、(この場合は16バイト)は、同じ暗号文を生成します。 ECBモードは、何らかの理由で誰でも使用してはいけません。
はここでは例のECBモード暗号化されたメッセージであります
他のヒント
MeおよびiPhoneアプリをコーディングし、ここで、暗号化と復号化データに上記方法を使用して私の大学。私は彼のiPhoneから読み込まれるデータを暗号化されたとき、しかし、我々は問題を発見しました。 iPhoneはPKCS7パディングを使用しました。上記のコードは、これはiPhoneの解読方法が失敗する原因となる余分なパディングを追加しました。私たちは、現在の問題を解決するためにコードを修正します:
public static function aes128Encrypt($key,$val)
{
$mode = MCRYPT_MODE_CBC;
$enc=MCRYPT_RIJNDAEL_128;
$blocksize= mcrypt_get_block_size($enc,$mode);
$stringLength = strlen($val);
$paddingLength =$blocksize-($stringLength%$blocksize);
$val=str_pad($val,$paddingLength+$stringLength,chr($paddingLength));
return base64_encode(mcrypt_encrypt($enc, $key, $val, $mode, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"));
}