2012-04-24 16 views
2

PHPとColdFusion9のAES暗号化では異なる結果が生じます。誰かが私を助けてくれますか?PHP ColdFusion9 AES暗号化 - 異なる結果

<cfset thePlainData = "This is a plain string." /> 
<cfset theKey = "12345678123456781234567812345678" /> 
<cfset theAlgorithm = "AES/CBC/PKCS5Padding" /> 
<cfset theEncoding = "base64" /> 
<cfset theIV = "1234567812345678" /> 

<cfset encryptedString = encrypt(thePlainData, theKey, theAlgorithm, theEncoding, theIV) /> 

ColdFusionのコードの下には私KLt55n5/T3ee6xVq9VGFbyCacJznkHEqC/RDRhL + 4NW =

を与えながらPHPコード以下ザ

$key = "12345678123456781234567812345678"; 
$iv = "1234567812345678"; 
$data = "This is a plain string."; 

echo base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_CBC, $iv)); 

は私G + tdEOfQTtVCQGxW3N5uzkqN207OyfIPxS6zf2xrKKY =

を与えます

私はどこが間違っているのか?前もって感謝します。

+0

上記のPHPは私のために実行されますが、上記のCFは「指定されたキーはこの暗号化の有効なキーではありません:不正なキーサイズ」です...本当に正確なCFコードですか?このCF9エンタープライズですか? –

+0

あなたの迅速な対応に感謝します。私はColdFusion9体験版を使用しています。 – user812120

+0

CFは 'theKey'がbase64であることを期待しています。 'theKey'をbase64に変換すると、あなたはもっと近くになりますが、そこまでではありません。だからそれはエンコードの違いかもしれません。 'theKey/iv'の両方を16進またはbase64のどちらかで印刷できますか? – Leigh

答えて

6

残念ながら、ColdFusionとPHPの実装では、使用されるプレーンテキストのパディングスタイルに関して若干の非互換性があります。 AESでは、128で割り切れる平文ブロックサイズが必要です。これを達成するには、適切なブロックサイズを得るためにPHP will pad the plaintext input with NULL charactersを取得します。 ColdFusionはさまざまなpadding techniques that are supported by Javaを使用できます。残念ながら、ColdFusionもJavaも、相互運用性を向上させるためのNULL埋め込みスキーマをサポートしていません。 ColdFusionの文字列処理はNULL文字をサポートしていないため、正しく動作させるにはimplement a PKCS5Padding schema within PHPにする必要があります。

あなたが見えるようにキー設定を必要とするだろうので、また、コメントで述べたように、ColdFusionは、キーはbase64エンコードであることを期待しますが:

<cfset theKey = toBase64("12345678123456781234567812345678") /> 

さらに、デフォルトでのJava(およびColdFusionによって拡張)は最大128ビットのキーサイズしかサポートしません。ここでは、require the Java Unlimited Strength extension(コードをテストし、不正なキーサイズエラーを取得しようとしているもの)の256ビットキーを使用しています。

たPHPコードのようになります。

<cfset thePlainData = "This is a plain string." /> 
<cfset theKey = toBase64("12345678123456781234567812345678") /> 
<cfset theAlgorithm = "AES/CBC/PKCS5Padding" /> 
<cfset theEncoding = "base64" /> 
<cfset theIV = "1234567812345678" /> 

<cfset encryptedString = encrypt(thePlainData, theKey, theAlgorithm, theEncoding, theIV) /> 

<cfoutput>#encryptedString#</cfoutput> 

どちらの出力と同じbase64でエンコードされた文字列:

// Function from http://us3.php.net/manual/en/ref.mcrypt.php#69782 
function pkcs5_pad ($text, $blocksize) 
{ 
    $pad = $blocksize - (strlen($text) % $blocksize); 
    return $text . str_repeat(chr($pad), $pad); 
} 

$key = "12345678123456781234567812345678"; 
$iv = "1234567812345678"; 
// Pad data with PKCS #5 to prevent PHP from using NULL padding. 
$data = pkcs5_pad("This is a plain string.", 16); 

echo base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_CBC, $iv)); 

たColdFusionコードがどのように見える

G+tdEOfQTtVCQGxW3N5uzlu0mGabRKNxuIdAXArQE80= 
+0

ジャスティンの詳細な回答ありがとうございました。それは問題を解決した。 – user812120

+0

MCRYPT_RIJNDAEL_128ではなくMCRYPT_RIJNDAEL_256を使用してPHPでデータを暗号化し、AES復号化を使用してColdFusionまたはRubyで復号化することは可能ですか? – user812120

+0

箱のままではありません。 AESはRijndaelに基づいていますが、ブロックサイズとキーの長さについてはより制限的です。 AESは128ビットの平文ブロックサイズしかサポートしていないので、RijndaelとAESを一緒に使用している場合は、Rijndael側で128ビットブロックサイズを使用して互換性を持たなければなりません。 ( "MCRYPT_RIJNDAEL_128"の "128"はキーの長さではなくブロックサイズを指定していることを思い出してください) –

0

を私はこれを知っています古いスレッドですが、最近同様の質問が出ました。

ネイティブではサポートされていませんが、CFでヌルパディングを生成する方法があります。 This answer by Artjom B.は、PHPでパディングを調整する方が簡単かもしれないが、 "NoPadding"スキームを使用して、0x00のプレーンテキストをalgorithm's block sizeの倍数にパディングすると同じ結果が得られることを指摘します。

CFでヌル文字を生成するのはややこしいですが、using URLDecode("%00")を実行できます。 encrypt()は常に入力をUTF-8でエンコードしているので、charsetEncode()を使用して、単一要素のバイト配列からヌル文字を作成することもできます。つまり、charsetEncode(javacast("byte[]", [0]), "utf-8")です。

は非常にテストされていないが、このようなものがCF10で同じ結果を生成する必要があります

コード:

thePlainData = nullPad("This is a plain string.", 16); 
// NB: JCE unlimited policy files required for 256 bit keys 
theKey = toBase64("12345678123456781234567812345678"); 
theIV = "1234567812345678"; 

encryptedString = encrypt(thePlainData, theKey, "AES/CBC/NoPadding", "base64", theIV); 

結果:

G+tdEOfQTtVCQGxW3N5uzkqN207OyfIPxS6zf2xrKKY= 

機能:

/* 
    Pads a string, with null bytes, to a multiple of the given block size 

    @param plainText - string to pad 
    @param blockSize - pad string so it is a multiple of this size 
    @param encoding - charset encoding of text 
*/ 
string function nullPad(string plainText, numeric blockSize, string encoding="UTF-8") 
{ 
    local.newText = arguments.plainText; 
    local.bytes = charsetDecode(arguments.plainText, arguments.encoding); 
    local.remain = arrayLen(local.bytes) % arguments.blockSize; 

    if (local.remain neq 0) 
    { 
     local.padSize = arguments.blockSize - local.remain; 
     local.newText &= repeatString(urlDecode("%00"), local.padSize); 
    } 

    return local.newText; 
}