Java PBEWithHMACSHA512和AES模式,如GCM

Java PBEWithHMACSHA512和AES模式,如GCM,java,cryptography,passwords,aes,Java,Cryptography,Passwords,Aes,首先,我已经成功地使用Java(JDK 8)编写了使用pbewithhmacsha512andaes128进行加密和解密的代码 但我想知道它是否是AES,那么如何使用GCM这样的模式来检查完整性 另一方面,我能够将AES/GCM/NoPadding与PBKDF2WithHmacSHA256结合使用。表示密钥是使用带HMACSHA256的PBKDF2生成的,并在AES/GCM中使用 但我正在努力寻找使用PBEWithHmacSHA512AndAES_128和使用AES/GCM生成密钥的源代码 或者

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

但我想知道它是否是AES,那么如何使用GCM这样的模式来检查完整性

另一方面,我能够将
AES/GCM/NoPadding
PBKDF2WithHmacSHA256
结合使用。表示密钥是使用带HMACSHA256的PBKDF2生成的,并在AES/GCM中使用

  • 但我正在努力寻找使用
    PBEWithHmacSHA512AndAES_128
    和使用AES/GCM生成密钥的源代码 或者即使这是可能的或者是有意义的

  • 其次,使用
    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);
        }
    }
    
    private byte[]getRandomNumber(最终整数大小)抛出NoSuchAlgorithmException{
    SecureRandom SecureRandom=SecureRandom.getInstanceStrong();
    字节[]随机字节=新字节[大小];
    secureRandom.nextBytes(随机字节);
    返回随机字节;
    }
    私有SecretKey getPBE_AES_密钥(最终字符串密码,最终字节[]salt){
    试一试{
    char[]passwdData=password.toCharArray();
    PBEKeySpec PBEKeySpec=新的PBEKeySpec(passwdData,salt,4096128);
    SecretKeyFactory keyFactory=SecretKeyFactory.getInstance(“PBEWithHmacSHA256AndAES_128”);
    SecretKey pbeKey=keyFactory.generateSecret(pbeKeySpec);
    返回pbeKey;//
    另一方面,我能够将
    AES/GCM/NoPadding
    PBKDF2WithHmacSHA256
    结合使用

    很好。您似乎希望默认为AES-128。正确实现后,上面的操作几乎没有错误,更改为SHA-512在安全方面不会有多大帮助(如果有的话)

    但我正在努力寻找使用pbewithhmacsha512andaes128生成密钥并使用AES/GCM的源代码,或者即使这是可能的或者是有意义的

    AES_128已经表明该模式不使用完整性。这是一种默认为CBC的“全有或全无”方案。如上所述,我只保留您所拥有的

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


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

    显然,在我对第二个问题做出更准确的评论之前,您需要显示您的代码。谢谢您的回复nding@maarten bodewes…我已经添加了代码块并重新表述了2个问题…其次,你是说在Java中使用
    PBewithhmacsha512andaes128
    时,我们没有任何机制使用GCM?如果是这样的话,那么我将不得不求助于HMAC,以便在使用
    PBEWithHmacSHA51时仔细检查IV+盐2AndAES_128
    …有意义吗?欢迎使用stackoverflow。您知道可以使用反勾号字符格式化内联代码吗?
    `code`