Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the proper way to perform authenticated encryption in Java?

Authenticated encryption requires that we use some accepted standard for encrypting and authenticating a message. So we both encrypt the message and compute a MAC on the message to verify it has not been tampered with.

This question outlines a way to perform password based key strengthening and encryption:

/* Derive the key, given password and salt. */
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec spec = new PBEKeySpec(password, salt, 65536, 256);
SecretKey tmp = factory.generateSecret(spec);
SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");
/* Encrypt the message. */
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secret);
AlgorithmParameters params = cipher.getParameters();
byte[] iv = params.getParameterSpec(IvParameterSpec.class).getIV();
byte[] ciphertext = cipher.doFinal("Hello, World!".getBytes("UTF-8"));

But as far as I can tell, this does not compute any MAC on the ciphertext and so would be insecure. What is the accepted standard for performing authenticated encryption in Java?

like image 727
Eric Conner Avatar asked Mar 05 '12 17:03

Eric Conner


People also ask

How do you authenticate in Java?

Create a LoginContext with a name that identifies which JAAS configuration entry to use. Perform the authentication. Define the task that the authenticated user is to perform.

How does encryption work in Java?

There are 2 key based encryption algorithms: Symmetric and Asymmetric algorithms. There are various cryptographic parameters which need to be configured correctly for a crypto-system to be secured; these include key size, mode of operation, padding scheme, IV, etc. For symmetric encryption use the AES algorithm.

Which encryption algorithm is best in Java?

The best algorithms are the ones which are shipped with Java. AES is the industry standard as of now as it allows 128 bit encryption. Here is an example of AES Encryption in Java. Apart from that if you're trying to encrypt a password, you should use a hash function to create a hash of the encrypted password string.


1 Answers

I would recommend using GCM mode encryption. It is included in the latest JDK (1.7) by default. It uses a counter mode encryption (a stream cipher, no padding required) and adds an authentication tag. One big advantage is that it requires only a single key, whereas HMAC adds another key to the mix. Bouncy Castle has an implementation as well, which is moslty compatible with one provided by Oracle.

GCM mode encryption is also features in a TLS RFC, and in XML encrypt 1.1 (both not final). GCM mode provides all three security features: confidentiality, integrity and authenticity of the data send. The String would be "AES/GCM/NoPadding" instead of the CBC one you are now deploying. As said, make sure you have the latest JDK from Oracle, or have Bouncy Castle provider installed.

Also check out my answer here, which is mostly about String encoding, but I've succesfully tried GCM mode too - see the comment.

like image 85
Maarten Bodewes Avatar answered Oct 31 '22 06:10

Maarten Bodewes