Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I properly use the "PBEWithHmacSHA512AndAES_256" algorithm?

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);
    }
}
like image 612
jwd Avatar asked Mar 23 '15 16:03

jwd


People also ask

What is PBEWITHHMACSHA512ANDAES_256?

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.

What is PBEWithMD5AndDES algorithm?

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.

What is Jasypt encryption?

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.

Does Javascript have built in 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.


1 Answers

// 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.

like image 60
user207421 Avatar answered Nov 15 '22 19:11

user207421