2017-01-10 25 views
3

PHPスクリプトからJavaクライアントに情報を送るシンプルで安全な方法を実装したかったのです。私はすでにここでいくつかの実装を見てきましたが、これまでには何も働いていなかったので、今や不満を感じています。PHPで単純なAESを暗号化し、Javaで解読する

PHP:

function enc3($plaintext) { 

$length = 16; 
$key = openssl_random_pseudo_bytes($length); 

$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC); 
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND); 

$ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, 
          $plaintext, MCRYPT_MODE_CBC, $iv); 

echo base64_encode($ciphertext); 
echo "\n".base64_encode($iv); 
echo "\n".base64_encode($key); 
} 
enc3("test"); 

のJava:私は編集のビットを使用し、最後の一つは、この一つです

public static byte[] decrypt(byte[] key, byte[] initVector, byte[] encryptedValue) { 

    try { 

     IvParameterSpec iv = new IvParameterSpec(initVector); 
     SecretKeySpec skeySpec = new SecretKeySpec(key, "AES"); 

     Cipher cipher = Cipher.getInstance("AES/CBC/NOPADDING"); 
     cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv); 

     byte[] original = cipher.doFinal(encryptedValue); 

     return original; 
    } catch (Exception ex) { 
     Logger.getLogger(MainGUI.class.getName()).log(Level.SEVERE, null, ex); 
    } 

    return null; 
} 
... 
byte[] encpryted = Base64.getDecoder().decode(rd.readLine()); 
byte[] iv = Base64.getDecoder().decode(rd.readLine()); 
byte[] key = Base64.getDecoder().decode(rd.readLine()); 

byte[] output = decrypt(key, iv, encpryted); 

そして私が手:

javax.crypto.IllegalBlockSizeException: Input length not multiple of 16 bytes 

キーもちろん、そこではデバッグ用です。もちろん、動作しているときには削除してクライアントに格納します。何が最善の方法であるかわからない、どういうわけか、私は隠れた方法でそれを隠すことを考えていた。サーバーはそれをどのように作り出すかも知っている。しかし、私はそれがメモリに読み込み可能になると思います。

+0

PHP 7.1.0を使用している場合、 'mcrypt_encrypt()'は廃止されました。 –

+0

いいえ私はPHP7を使用していません。PHP5.6.22-2です。 –

+0

'encryptedValue'の長さを確認しましたか? – SubOptimal

答えて

3

AESはブロック暗号であり、16バイトのブロックでのみ正常に動作します。暗号文の長さが16で割り切れない場合は、その後にIllegalBlockSizeExceptionが発生します。

あなたは簡単に基本的にはどのようにパッドあなたの平文入力をし、ブロックサイズの倍数であることを標準的な方法であるPHPでのAES/CBC暗号用のPKCS5パディングを実装することができます

function pkcs5_pad($text) { 
    $size = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC); 
    $pad = $size - (strlen($text) % $size); 
    return $text . str_repeat(chr($pad), $pad); 
} 

その後、あなたを更新します暗号化機能は、パディングを使用します

$ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, 
pkcs5_pad($plaintext), MCRYPT_MODE_CBC, $iv); 

JavaはすでにちょうどAES暗号初期を更新し、PKCS5のサポートを実装しています

Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING"); 
+0

それは今働いています、ありがとう!しかし、私は別の問題を抱えています。私はこのようなものをエンコードします: "sha1、sha2"、そしてそれをJavaで分割します。デコードは正常に機能しますが、split [1]の長さはsplit [0]と同じではありません。次の15個の "目に見えない"文字があり、バイト= 0と思われます。 [1] .toString()を分割すると "sha2"が表示されますが、split1.length()を作成すると、4ではなく19が表示されます。私はsplit [1] .equal(sha2)が動作しなかった理由は分かりませんでしたので、何時間も狂ってしまいました。 –

+0

それでも、私は推測すると、まだjavax.crypto.IllegalBlockSizeExceptionを取得していると思います:あなたのトリム実装、任意のアイデア理由、またはこれをどのように修正するにせよ、ランダムに16バイトの倍数ではありませんか?常に起こっているわけではありませんが、暗号化されたテキストでさえ変わらないことさえあります。 –

+1

@ M.H。あなたは正しい、以前のソリューションに問題があったので、デコードされたテキストには隠れた文字が残っていた。私は暗号化されたテキストを適切にパッドする方法を標準化した方法で私の答えを更新しました。 – sider

関連する問題