PBEWithHmacSHA512AndAES_128和AES模式如GCM

时间:2017-04-05 13:55:44

标签: java cryptography passwords aes

首先,我使用Java(JDK 8)成功编写了使用PBEWithHmacSHA512AndAES_128进行加密和解密的代码。

但我想知道它的AES是否可以使用像GCM这样的模式来检查完整性。

另一方面 - 我可以将AES/GCM/NoPaddingPBKDF2WithHmacSHA256结合使用。表示密钥是使用PBKDF2WithHmacSHA256生成的,并在AES / GCM中使用。

  1. 但我很难找到使用PBEWithHmacSHA512AndAES_128生成密钥并使用AES / GCM的源代码 或者即使它有可能或者它是否有意义?

  2. 其次,使用PBEWithHmacSHA512AndAES_128生成的密钥总是9个字节 - 如果是这种情况,那么我想知道AES 128需要大小为16字节的密钥以及如何将密钥生成为9个字节

  3. 对此方面的任何帮助/澄清表示高度赞赏......

    使用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);
        }
    }
    

    如您所见,有两个问题......

    a)在我的代码中,我使用密文保持IV和salt。我想使用AES / GCM来检查整个IV +盐的完整性。

    b)为什么key的byte []是9个字节? (当我输入Pree@2017时,生成的密钥是9个字节 - 我检查了pbeKey.getEncoded()及其9的长度。

    非常感谢

    更新 - 下面回答第一个问题。然而,第二个问题在https://crypto.stackexchange.com/questions/46849/pbewithhmacsha512andaes-128-and-aes-modes-like-gcm

    得到了解答

    谢谢大家!

1 个答案:

答案 0 :(得分:2)

  

另一方面 - 我可以将AES/GCM/NoPaddingPBKDF2WithHmacSHA256结合使用。

完美。您似乎想要默认为AES-128。如果正确实现,上面几乎没有错,改为SHA-512不会对安全性有所帮助(如果有的话)。

  

但是我很难找到使用PBEWithHmacSHA512AndAES_128生成密钥的来源并使用AES / GCM或即使它可能或有意义吗?

AES_128已经表明该模式没有使用完整性。它是一种默认为CBC的全有或全无的方案。如上所示,我只是保留你拥有的东西。

  

其次,使用PBEWithHmacSHA512AndAES_128生成的密钥总是9个字节 - 如果是这样的话,那么我想知道AES 128需要大小为16字节的密钥以及如何将密钥生成为9个字节?

这不可能是正确的。毫无疑问,密钥是128位/ 16字节,但您只是得到了错误的信息,例如通过尝试直接打印出底层字节数组而不是先将其转换为十六进制数。