2017-10-19 19 views
1

私は平文をAES-256-CBCで暗号化する簡単なJavaプログラムを作成しようとしています。JavaのAES-256-CBC

import javax.crypto.Cipher; 
import javax.crypto.spec.IvParameterSpec; 
import javax.crypto.spec.SecretKeySpec; 

public class AesCBC { 
    private byte[] key; 
    private byte[] iv; 

    private static final String ALGORITHM="AES"; 

    public AesCBC(byte[] key, byte[] iv) { 
     this.key = key; 
     this.iv = iv; 
    } 

    public byte[] encrypt(byte[] plainText) throws Exception{ 
     SecretKeySpec secretKey=new SecretKeySpec(key,ALGORITHM); 
     IvParameterSpec ivParameterSpec=new IvParameterSpec(iv); 
     Cipher cipher=Cipher.getInstance("AES/CBC/PKCS5Padding"); 
     cipher.init(Cipher.ENCRYPT_MODE,secretKey,ivParameterSpec); 
     return cipher.doFinal(plainText); 
    } 

    public byte[] getKey() { 
     return key; 
    } 

    public void setKey(byte[] key) { 
     this.key = key; 
    } 

    public byte[] getIv() { 
     return iv; 
    } 

    public void setIv(byte[] iv) { 
     this.iv = iv; 
    } 
} 

と可能な使用方法があります:クラスがあり

byte[] test="a".getBytes(); 

byte[] key=DatatypeConverter.parseHexBinary("b38b730d4cc721156e3760d1d58546ce697adc939188e4c6a80f0e24e032b9b7"); 
byte[] iv=DatatypeConverter.parseHexBinary("064df9633d9f5dd0b5614843f6b4b059"); 
AesCBC aes=new AesCBC(key,iv); 
try{ 
    String result=DatatypeConverter.printBase64Binary(aes.encrypt(test)); 
    System.out.println(result); 
}catch(Exception e){ 
    e.printStackTrace(); 
} 

私の出力はVTUOJJp38Tk+P5ikR4YLfw==ですが、私は、このコマンドを実行すると:

/usr/bin/openssl enc -A -aes-256-cbc -base64 -K "b38b730d4cc721156e3760d1d58546ce697adc939188e4c6a80f0e24e032b9b7" -iv "064df9633d9f5dd0b5614843f6b4b059" <<< "a" 

私はJavaでより切り抜いた何かを得ますプログラム(Y65q9DFdR3k1XcWhA2AO2Q==)。悲しいことに、私は同じキーと同じアルゴリズムで同じアルゴリズムを使用するので、なぜ結果が同じでないのか分かりません。私のJavaプログラムが正しく動作しないということですか?どんな助けもありがとう。

+0

Javaおよび/またはOpenSSLを使用してJava出力を復号化しようとしましたか? OpenSSLで再度暗号化すると、同じ出力が得られますか?下のopenssl encヘルプページ(https://wiki.openssl.org/index.php/Enc)によると、「すべての塩析オプションも時代遅れです。」あなたが鍵を使用している場合、OpenSSLは常にあなたの結果を塩にします。 – Jamie

答えて

3

ですが、どちらの方法も正しく動作しますが、異なるものを暗号化しています。

ここの文字列構文(<<<)は、文字列に改行を追加します。したがって、Java出力は "a"を暗号化した結果であり、コマンドライン出力は "a \ n"(つまり、改行が続く文字a)を暗号化した結果です。

は、コマンドラインからこれを試してみてください:

printf "a" | /usr/bin/openssl enc -aes-256-cbc -base64 -K "b38b730d4cc721156e3760d1d58546ce697adc939188e4c6a80f0e24e032b9b7" -iv "064df9633d9f5dd0b5614843f6b4b059" 

結果はVTUOJJp38Tk+P5ikR4YLfw==で、あなたのJava結果に一致します。

0

Javaの結果は正しいです。AES CALCULATORを参照してください。

したがって、opensslコマンドラインの暗号化が正しくないため、マニュアルページを慎重に読んでください。

入力データに手動でPKCS#7パディングを追加しました。
また、VTUOJJp38Tk+P5ikR4YLfw==は16進数で55350E249A77F1393E3F98A447860B7F

関連する問題