I'm doing some Java encryption, and cannot figure out a way to properly use the the PBEWithHmacSHA512AndAES_256 algorithm.
Encryption seems to work fine, but I am unable to properly initialize a decryption cipher.
Below is a short program that demonstrates the issue. In particular, see the "PROBLEM" comment.
Note: I have seen this very helpful answer, and I can get things to work using that scheme, but I'm curious to know what I'm doing wrong here.
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);
}
}
PBEWITHHMACSHA512ANDAES_256 applies PBKDF2 to generate the key. Encryption is performed with AES-256, CBC. The (originally) posted Jasypt test function used RandomIvGenerator , which creates a random IV. For the salt, ZeroSaltGenerator is applied, which generates a salt consisting of 16 zero bytes.
PBEWithMD5AndDES: The PBES1 password-based encryption algorithm as defined in PKCS #5: Password-Based Cryptography Specification, Version 2.1. Note that this algorithm implies CBC as the cipher mode and PKCS5Padding as the padding scheme and cannot be used with any other cipher modes or padding schemes.
Jasypt is a java library which allows the developer to add basic encryption capabilities to his/her projects with minimum effort, and without the need of having deep knowledge on how cryptography works. High-security, standards-based encryption techniques, both for unidirectional and bidirectional encryption.
js has a built-in library called crypto for data encryption and decryption. Encryption and decryption aim to enhance safety. This article will help you learn how to use the Node. js crypto module to encrypt and decrypt data in your applications.
// 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
);
Use the AlgorithmParameters
from the encrypting Cipher
:
cipherDecrypt.init(
Cipher.DECRYPT_MODE,
key,
cipherEncrypt.getParameters()
);
If you want a cleaner way that doesn't involve cipherEncrypt
at the decrypting site, save the algorithm parameters as a byte and transmit them along with the key data:
byte[] algorithmParametersEncoded = cipherEncrypt.getParameters().getEncoded();
and reconstruct them at the decrypting site thus:
AlgorithmParameters algorithmParameters = AlgorithmParameters.getInstance(ALGORITHM);
algorithmParameters.init(algorithmParametersEncoded);
and use algorithmParameters
as the parameters
argument for Cipher.init()
above.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With