2014-12-19 221 views
2

java的加密我有在Java中以下代碼:解密的AES-GCM使用的OpenSSL

public static void deriveKeyAndIV(String password) 
      throws Exception 
    { 
     SecureRandom random = new SecureRandom(); 
     if (salt == null) 
     { 
      salt = new byte[HASH_BYTE_SIZE/8]; // use salt size at least as long as hash 
      random.nextBytes(salt); 
     } 
     if (ivBytes == null) 
     { 
      ivBytes = new byte[HASH_BYTE_SIZE/8]; 
      random.nextBytes(ivBytes); 
     } 

     PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), salt, PBKDF2_ITERATIONS, HASH_BYTE_SIZE); 
     SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256"); 
     keyBytes = skf.generateSecret(spec).getEncoded(); 
    } 
public static byte[] encrypt(byte[] message) 
      throws Exception 
    { 
     // wrap key data in Key/IV specs to pass to cipher 
     SecretKeySpec key = new SecretKeySpec(keyBytes, "AES"); 
     //IvParameterSpec ivSpec = new IvParameterSpec(ivBytes); 
     // create the cipher with the algorithm you choose 
     // see javadoc for Cipher class for more info, e.g. 
     Cipher cipher = Cipher.getInstance("AES/GCM/PKCS5Padding"); 

     GCMParameterSpec gps = new GCMParameterSpec(128, ivBytes); 

     cipher.init(Cipher.ENCRYPT_MODE, key, gps); 
     byte[] encrypted = new byte[cipher.getOutputSize(message.length)]; 
     int enc_len = cipher.update(message, 0, message.length, encrypted, 0); 
     enc_len += cipher.doFinal(encrypted, enc_len); 
     return encrypted; 
    } 
public static byte[] decrypt(byte[] cipher_text) 
      throws Exception 
    { 
     // wrap key data in Key/IV specs to pass to cipher 
     SecretKeySpec key = new SecretKeySpec(keyBytes, "AES"); 
     // create the cipher with the algorithm you choose 
     // see javadoc for Cipher class for more info, e.g. 
     Cipher cipher = Cipher.getInstance("AES/GCM/PKCS5Padding"); 

     GCMParameterSpec gps = new GCMParameterSpec(128, ivBytes); 

     cipher.init(Cipher.DECRYPT_MODE, key, gps); 
     byte[] decrypted = new byte[cipher.getOutputSize(cipher_text.length)]; 
     int dec_len = cipher.update(cipher_text, 0, cipher_text.length, decrypted, 0); 
     dec_len += cipher.doFinal(decrypted, dec_len); 
     return decrypted; 
    } 
public static void main(String[] args) { 
     String pass = "hello"; 
     try { 
      deriveKeyAndIV(pass); 
      byte[] tmp = encrypt("world!".getBytes()); 
      System.out.println(new String(Base64.getEncoder().encode(tmp))); 
      System.out.println(new String(tmp)); 
      System.out.println("encrypted:\t" + bytesToHex(tmp)); 
      System.out.println("key:\t" + bytesToHex(keyBytes)); 
      System.out.println("iv:\t" + bytesToHex(ivBytes)); 
      tmp = decrypt(tmp); 

      System.out.println("decrypted:\t" + bytesToHex(tmp)); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 

    } 

示例輸出:

5xwfm037nXfGS06V5OKgW/oo6WDuow== 
��M��w�KN���[�(�`� 
encrypted: E71C1F9B4DFB9D77C64B4E95E4E2A05BFA28E960EEA3 
key: 6D525D38BFF7F70AD25205E97368C197 
iv: 060374643557ED8E2F6A215F1B6DBD0E 
decrypted: 776F726C6421 

我複製的Base64輸出到一個文件(測試中) ,並試圖使用下面的命令解密它:

openssl enc -d -base64 -id-aes128-GCM -K 6D525D38BFF7F70AD25205E97368C197 -in ~/Desktop/test-in -out ~/Desktop/test-out -iv 060374643557ED8E2F6A215F1B6DBD0E 

我得到bad decrypt錯誤消息(退出代碼:1)。嘗試不同的模式(id-aes192-GCM和id-aes256-GCM)的結果相同。

我在做什麼錯了?

+0

以下是[EVP認證加密和解密](http://wiki.openssl.org/index.php/EVP_Authenticated_Encryption_and_Decryption)上的OpenSSL wiki頁面。 OpenSSL將解密Java數據,但你必須編寫一個C程序來完成它。您不能使用命令行工具。 – jww 2014-12-21 21:15:30

回答

1

我複製的Base64輸出到一個文件(測試中),並使用試圖解密它以下命令...

經過身份驗證的加密模式不能在命令行工具中使用。從openssl enc man page

該enc程序不支持認證的加密模式,如 CCM和GCM。該實用程序不會存儲或檢索認證 標記。

我知道該文檔最近更新(大約在2014年5月或6月)與上述聲明。觸發它的郵件列表消息是v1.0.1g command line gcm error

我不知道的工具更新的版本(如openssl enc在1.0.2或1.1.0)提供有意義的錯誤信息,或者如果你只是得到壞解密


我做錯了什麼?

什麼都沒有。