2010-12-27 4 views
11

私の問題は次のとおりです:Javaで暗号化するもの私は完全にJavaで解読できますが、mcryptは解読できません。 mcryptで暗号化するものmcryptで復号化できますが、Javaではできません。JavaとPHPの間でAES-256で暗号化されたデータを交換できません

Javaアプリケーションから暗号化されたデータをPHPページに送受信したいので、互換性が必要です。

ここ

JAVA ...私が持っているものだ...

public static String crypt(String input, String key){ 
    byte[] crypted = null; 
    try{ 
     SecretKeySpec skey = new SecretKeySpec(Base64.decodeBase64(key), "AES"); 
     Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); 
     cipher.init(Cipher.ENCRYPT_MODE, skey); 
     crypted = cipher.doFinal(input.getBytes()); 
    }catch(Exception e){ 
    } 
    return Base64.encodeBase64String(crypted); 
} 

public static String decrypt(String input, String key){ 
    byte[] output = null; 
    try{ 
     SecretKeySpec skey = new SecretKeySpec(Base64.decodeBase64(key), "AES"); 
     Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); 
     cipher.init(Cipher.DECRYPT_MODE, skey); 
     output = cipher.doFinal(Base64.decodeBase64(input)); 
    }catch(Exception e){ 
    } 
    return new String(output); 
} 

実行:

public static void main(String[] args) { 
    String key = "Zvzpv8/PXbezPCZpxzQKzL/FeoPw68jIb+NONX/LIi8="; 
    String data = "example"; 
    System.out.println(Cpt.decrypt(Cpt.crypt(data, key), key)); 
} 

出力:

example 

PHP ...

function getEncrypt($sStr, $sKey) { 
    return base64_encode(
     mcrypt_encrypt(
      MCRYPT_RIJNDAEL_256, 
      $sKey, 
      $sStr, 
      MCRYPT_MODE_ECB 
     ) 
    ); 
} 

function getDecrypt($sStr, $sKey) { 
    return mcrypt_decrypt(
     MCRYPT_RIJNDAEL_256, 
     $sKey, 
     base64_decode($sStr), 
     MCRYPT_MODE_ECB 
    ); 
} 

実行:

$crypt = getDecrypt(getEncrypt($str, $key), $key); 
echo "<p>Crypt: $crypt</p>"; 

出力:

Crypt: example������������������������� 

キーで "例" 陰窩するPHPを使用した "Zvzpv8/PXbezPCZpxzQKzL/FeoPw68jIb + NONX/LIi8 =" 私は「YTYhgp4zC +を取得しますw5IsViTR5PUkHMX4i7JzvA6NJT1FqhoGY = "。 Javaを使用して同じキーで同じものを暗号化すると、 "+ tdAZq7WAVPXhB3Tp5 + g =="と表示されます。

私は正しい順序でbase64をエンコードしてデコードしています。私はJavaとPHPの間でbase64エンコードとデコードの互換性をテストしています。

答えて

14

バグ#1

MCRYPT_RIJNDAEL_256 AESではありません。その定数の256は、鍵のサイズではなく、ブロックのサイズを指します。 MCRYPT_RIJNDAEL_128を使用して、AESと同じアルゴリズムを取得します。 keysizeは、指定したキー引数のバイト数だけ設定されます。したがって、32バイトを供給すると、256ビットのAESが得られます。

バグ#2

これらの2行は、Javaで正しいことはありませんし、暗号変換によって生成任意のバイナリデータの性質の根本的な誤解を示している:何も悪いことは

output = cipher.doFinal(Base64.decodeBase64(input)); 
return new String(output); 

ありませんbyte[]を直接送信して保存することができますが、印刷可能な文字列を使用する必要がある場合は、base64エンコード/デコードを行う必要があります。既にbase64を広範囲に使用しているので、それはやり方のように思えるでしょう。

output = cipher.doFinal(Base64.decodeBase64(input)); 
return new String(Base64.encodeBase64(output), "UTF-8"); 

EDIT:

ちょうどバグ#2についての冗談、私は正しい2行だろうと推測します。本当に、私は間違っていた、私はそれが解読の方向であることに気付かなかった。もちろん、解読されたbyte[]が有効な文字列であることが分かっている場合、コードが行うことを行うのは完全に正しいです。

+0

私はちょっとそれを発見しましたが、私はAES-128を使っていました。だからそれは確かに256です。これらの行については、暗号化されたデータには常に文字列のみが含まれ、バイナリデータは含まれないと確信しています。 – LZZ

1

文字列と同じエンコードを使用することに注意してください。例えば、UTF-8に両方の言語で文字列を変換しようとすると、エンコードされたバイナリデータに変換より:

PHP(S utf8_encode()機能。):

$strAndBlob = utf8_encode("My string"); 

のJava:

String str = "My string"; 
byte[] blob = str.getBytes("utf-8"); 

PHPは、たとえば、デフォルトではUTF-8を使用しないでください。

+1

ええ、それは重要ですが、それは問題ではありません。 – LZZ

3

はこちらをご覧ください:

あなたが直面している問題は、パディング、問題です。私はJavaを知らないが、AES/ECB/PKCS5PaddingはPKCS#5(それは本質的にはPKCS#7と同じ)パディングを使用しているのに対し、PHPはネイティブにNULL-パディングをサポートしているようです。それは、PKCS#5月7日に何だ:

パッド 全長8 バイトの倍数を作る 1〜8バイトのパディング列と入力。 パディング文字列の各バイトの値は、 0x08の8バイト、0x07の値の7バイト、...、2 バイトの値、または の1バイトが追加された、 バイトの数に設定されます0x01。

ので、パディングを行うにはPHPコードは右簡単です:

$blockSize = mcrypt_get_block_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB); 
$padding = $blockSize - (strlen($data) % $blockSize); 
$data  .= str_repeat(chr($padding), $padding); 
+0

まあ、あなたが言ったことはまったく行いましたが、問題は修正されませんでしたが、私は128bitを使用するとPHPがJavaの暗号化されたテキストを解読できることに気付きました。私のJavaアプリケーションはAES-128で暗号化されていると思いますが、32バイトのキーでも暗号化されています。 – LZZ

9

これは古いトピックですが、実際の解決方法を追加します。あなたの鍵は、Base64でエンコードされているので、あなたがBASE64_DECODEすべき

function getEncrypt($sStr, $sKey) { 
    return base64_encode(
    mcrypt_encrypt(
     MCRYPT_RIJNDAEL_128, 
     base64_decode($sKey), 
     $sStr, 
     MCRYPT_MODE_ECB 
    ) 
); 
} 

function getDecrypt($sStr, $sKey) { 
    return mcrypt_decrypt(
    MCRYPT_RIJNDAEL_128, 
    base64_decode($sKey), 
    base64_decode($sStr), 
    MCRYPT_MODE_ECB 
); 
} 

($のsKey):

あなたは、スクリプトのPHP側を書き換える必要があります。

$key = "Zvzpv8/PXbezPCZpxzQKzL/FeoPw68jIb+NONX/LIi8="; 

その後、あなたは(クレジットがhttp://www.php.net/manual/en/function.mcrypt-decrypt.phpからbeltrachiに行く)この関数を作成する必要があります。

function pkcs5_pad ($text, $blocksize) { 
    $pad = $blocksize - (strlen($text) % $blocksize); 
    return $text . str_repeat(chr($pad), $pad); 
} 

は、このコードを使用すると、エンコード/デコードを行います。

$decrypt = getDecrypt("6XremNEs1jv/Nnf/fRlQob6oG1jkge+5Ut3PL489oIo=", $key); 
echo $decrypt; 
echo "\n\n"; 
echo getEncrypt(pkcs5_pad("My very secret text:)", 16), $key); 

私はこの意志を願っています誰かのために役立つ! :)

+0

pkcs5_padはたくさんの苦痛から私たちを救った! – kouton

関連する問題