2017-04-05 92 views
1

首先,我已經成功地使用Java(JDK 8)編寫代碼進行加密和解密,使用PBEWithHmacSHA512AndAES_128PBEWithHmacSHA512AndAES_128和AES模式像GCM

但我想知道如果它是AES,那麼如何使用GCM模式來檢查完整性。

另一方面 - 我可以使用AES/GCM/NoPaddingPBKDF2WithHmacSHA256一起使用。意思密鑰是使用PBKDF2WithHmacSHA256生成的,並在AES/GCM中使用。

  1. 但我在努力尋找生成密鑰使用PBEWithHmacSHA512AndAES_128來源和使用AES/GCM 或者,即使有可能,或者如果它是有道理的?

  2. 其次,使用PBEWithHmacSHA512AndAES_128生成的密鑰始終是9個字節 - 如果是這種情況,那麼我想知道AES 128需要16個字節的密鑰以及密鑰如何生成爲9個字節?

任何幫助/澄清在這點上是高度讚賞...

代碼中使用PBEWithHmacSHA512AndAES_128

private byte[] getRandomNumber(final int size) throws NoSuchAlgorithmException { 
    SecureRandom secureRandom = SecureRandom.getInstanceStrong(); 
    byte[] randomBytes = new byte[size]; 
    secureRandom.nextBytes(randomBytes); 
    return randomBytes; 
} 


private SecretKey getPBE_AES_Key(final String password, final byte[] salt) { 
    try { 
     char[] passwdData = password.toCharArray(); 

     PBEKeySpec pbeKeySpec = new PBEKeySpec(passwdData, salt, 4096, 128); 
     SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithHmacSHA256AndAES_128"); 
     SecretKey pbeKey = keyFactory.generateSecret(pbeKeySpec); 
     return pbeKey; // <-- size of this byte array is 9 - I thought it should be 16 since its AES 
    } catch (NoSuchAlgorithmException | InvalidKeySpecException ex) { 
     throw new OperationFailedException(ex.getMessage(), ex); 
    } 
} 


public String encrypt_PBE_AES(final String plaintext, final String password) { 
    try { 
     byte[] ivBytes = getRandomNumber(16); 
     byte[] saltBytes = getRandomNumber(16); 
     byte[] dataToEncrypt = plaintext.getBytes("UTF-8"); 

     Cipher cipher = Cipher.getInstance("PBEWithHmacSHA256AndAES_128"); 
     IvParameterSpec ivParameterSpec = new IvParameterSpec(ivBytes); 
     PBEParameterSpec pbeParameterSpec = new PBEParameterSpec(saltBytes, 4096, ivParameterSpec); 

     cipher.init(Cipher.ENCRYPT_MODE, getPBE_AES_Key(password, saltBytes), pbeParameterSpec); 
     byte[] encryptedData = cipher.doFinal(dataToEncrypt); 

     byte[] ivWithSalt = ArrayUtils.addAll(ivBytes, saltBytes); 
     byte[] encryptedDataWithIVAndSalt = ArrayUtils.addAll(ivWithSalt, encryptedData); 
     String encodedData = Base64.getUrlEncoder().encodeToString(encryptedDataWithIVAndSalt); 
     return encodedData; 
    } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException 
     | BadPaddingException | IOException | InvalidAlgorithmParameterException ex) { 
     throw new OperationFailedException(ex.getMessage(), ex); 
    } 
} 

public String decrypt_PBE_AES(final String ciphertext, final String password) { 
    try { 
     byte[] encryptedDataWithIVAndSalt = Base64.getUrlDecoder().decode(ciphertext); 
     byte[] ivBytes = ArrayUtils.subarray(encryptedDataWithIVAndSalt, 0, 16); 
     byte[] saltBytes = ArrayUtils.subarray(encryptedDataWithIVAndSalt, 16, 
      16 + 16); 
     byte[] dataToDecrypt = ArrayUtils.subarray(encryptedDataWithIVAndSalt, 
      16 + 16, encryptedDataWithIVAndSalt.length); 

     Cipher cipher = Cipher.getInstance("PBEWithHmacSHA256AndAES_128"); 
     IvParameterSpec ivParameterSpec = new IvParameterSpec(ivBytes); 
     PBEParameterSpec pbeParameterSpec = new PBEParameterSpec(saltBytes, 4096, ivParameterSpec); 

     cipher.init(Cipher.DECRYPT_MODE, getPBE_AES_Key(password, saltBytes), pbeParameterSpec); 
     byte[] decryptedData = cipher.doFinal(dataToDecrypt); 

     return new String(decryptedData, "UTF-8"); 
    } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | UnsupportedEncodingException 
     | IllegalBlockSizeException | BadPaddingException | InvalidAlgorithmParameterException ex) { 
     throw new OperationFailedException(ex.getMessage(), ex); 
    } 
} 

正如你可以看到有2個問題...

a)在我的代碼中,我使用密文保持IV和salt。我想用AES/GCM來檢查整個IV +鹽的完整性。

b)爲什麼密鑰的byte []是9個字節? (當我給輸入作爲[email protected]生成的密鑰是9個字節 - 我有檢查pbeKey.getEncoded()長度和其9.

非常感謝

更新 - 。第一個問題是以下回答然而第二個問題得到回答在https://crypto.stackexchange.com/questions/46849/pbewithhmacsha512andaes-128-and-aes-modes-like-gcm

謝謝大家

+0

歡迎計算器。你知道你可以使用反碼字符來格式化你的內聯代碼嗎?代碼\''< - 這些 –

回答

2

在另一方面 - !我可以結合使用AES/GCM/NoPaddingPBKDF2WithHmacSHA256

完美。您似乎想要默認使用AES-128。如果正確實施,以上幾乎沒有什麼問題,並且轉換爲SHA-512不會對您有很大的幫助(如果有的話)的安全性。

但我在努力尋找生成密鑰使用PBEWithHmacSHA512AndAES_128來源和使用AES/GCM或者,即使有可能,或者如果它是有道理的?

AES_128已經表明該模式不使用完整性。這是一種默認爲CBC的全有或全無的方案。正如上面所指出的那樣,我只需要保持你擁有的東西。

其次使用PBEWithHmacSHA512AndAES_128始終是9個字節產生的關鍵 - 如果是的話,那麼我想知道的大小爲16個字節的AES 128需求的關鍵,如何關鍵是讓爲9個字節產生的?

這不可能是正確的。毫無疑問,關鍵是128位/ 16字節,但你只是得到錯誤的信息,例如通過嘗試直接打印出底層字節數組而不是先將其轉換爲十六進制數。

+0

顯然你需要顯示你的代碼,然後才能對第二個問題做出更精確的評論。 –

+0

感謝您迴應@馬騰 - bodewes ...我添加的代碼塊,並改寫了2個問題。其次,你說,在Java中使用''PBEWithHmacSHA512AndAES_128時,我們沒有任何機制來使用GCM?如果是這樣的話,那麼我就只能使用'PBEWithHmacSHA512AndAES_128' ...有意義時回落到HMAC爲itegrity檢查IV +鹽? –