如何正确使用“PBEWithHmacSHA512AndAES_256”算法?

我正在做一些Java加密,并且无法找到正确使用PBEWithHmacSHA512AndAES_256算法的方法。

加密似乎工作正常,但我无法正确初始化解密密码。

以下是一个演示该问题的简短程序。 特别是,请参阅“问题”评论。

注意:我已经看到了这个非常有用的答案 ,我可以使用该方案让事情发挥作用,但我很想知道我在这里做错了什么。

import java.nio.charset.StandardCharsets; import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.PBEParameterSpec; public final class CryptQuestion { private static final String ALGORITHM = "PBEWithHmacSHA512AndAES_256"; private static final int ITERATIONS = 1000; // Aside: not sure what is a good number, here. public static void main(final String[] args) throws Exception { final String message = "This is the secret message... BOO!"; System.out.println("Original : " + message); final byte[] messageBytes = message.getBytes(StandardCharsets.US_ASCII); final String password = "some password"; final byte[] salt = "would be random".getBytes(StandardCharsets.US_ASCII); // Create the Key final SecretKeyFactory factory = SecretKeyFactory.getInstance(ALGORITHM); final PBEKeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt, ITERATIONS); SecretKey key = factory.generateSecret(keySpec); // Build the encryption cipher. final Cipher cipherEncrypt = Cipher.getInstance(ALGORITHM); cipherEncrypt.init(Cipher.ENCRYPT_MODE, key); // Encrypt! final byte[] ciphertext = cipherEncrypt.doFinal(messageBytes); final byte[] iv = cipherEncrypt.getIV(); // Now for decryption... The receiving end will have as input: // * ciphertext // * IV // * password // * salt // We just re-use 'key' from above, since it will be identical. final PBEParameterSpec pbeParamSpec = new PBEParameterSpec(salt, ITERATIONS); final IvParameterSpec ivParamSpec = new IvParameterSpec(iv); // Build the decryption cipher. final Cipher cipherDecrypt = Cipher.getInstance(ALGORITHM); // PROBLEM: If I pass "ivParamSpec", I get "java.security.InvalidAlgorithmParameterException: Wrong parameter type: PBE expected" // Whereas if I pass pbeParamSpec, I get "java.security.InvalidAlgorithmParameterException: Missing parameter type: IV expected" // What to do? cipherDecrypt.init( Cipher.DECRYPT_MODE, key, ivParamSpec //pbeParamSpec ); final String decrypted = new String( cipherDecrypt.doFinal(ciphertext), StandardCharsets.US_ASCII); System.out.println("Decrypted: " + decrypted); } } 

 // PROBLEM: If I pass "ivParamSpec", I get "java.security.InvalidAlgorithmParameterException: Wrong parameter type: PBE expected" // Whereas if I pass pbeParamSpec, I get "java.security.InvalidAlgorithmParameterException: Missing parameter type: IV expected" // What to do? cipherDecrypt.init( Cipher.DECRYPT_MODE, key, ivParamSpec //pbeParamSpec ); 

使用加密CipherAlgorithmParameters

 cipherDecrypt.init( Cipher.DECRYPT_MODE, key, cipherEncrypt.getParameters() ); 

如果您想要一个在解密站点上不涉及cipherEncrypt的更cipherEncrypt的方法,请将算法参数保存为一个字节并将其与密钥数据一起传输:

 byte[] algorithmParametersEncoded = cipherEncrypt.getParameters().getEncoded(); 

并在解密站点重建它们:

 AlgorithmParameters algorithmParameters = AlgorithmParameters.getInstance(ALGORITHM); algorithmParameters.init(algorithmParametersEncoded); 

并使用algorithmParameters作为上面Cipher.init()parameters参数。

我已经从teh jasyptto增强了StandardPBEByteEncryptor,支持“PBEWithHmacSHA512AndAES_256”算法。 看这里的代码

请参阅PBEEncryptorTest中的unit testing