11

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?

Community
  • 1
  • 1
Eric Conner
  • 10,422
  • 6
  • 51
  • 67
  • If you encrypt/decrypt the full message you know it hasn't been tampered with no!? Isn't HMAC used when you want to send a message (or data) in "plain text" and then send the HMAC along to authenticate the plain text? – TacticalCoder Mar 05 '12 at 17:24
  • There is no accepted standard for doing authenticated encryption, it might be (asymmetric) signatures, MAC (e.g. AESCMAC), HMAC or authenticated modes. There are a few unsafe ones though (default AES-MAC is not very safe for example). See below for a good answer which should fit your use case. – Maarten Bodewes Mar 05 '12 at 21:51
  • Any problem with the answers Eric? – Maarten Bodewes Mar 06 '12 at 12:16
  • 1
    @TacticalCoder The reason you need both is because confidentiality-only modes of encryption are vulnerable to chosen-ciphertext attacks. The idea is basically that an attacker can generate ciphertexts and submit them for decryption until they find one that's valid. They can then send that as the message. – Eric Conner Feb 16 '17 at 19:19

2 Answers2

12

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.

Community
  • 1
  • 1
Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263
  • As with any stream cipher, be carefull how you use the NONCE/IV, as reapeating the same value will lead to insecurities. – Maarten Bodewes Mar 05 '12 at 21:52
  • Yea I think this is the best answer all things considered. I'm constricted to using JDK 1.6 so I went with a solution that performs password based key strengthening to generate a 256 bit key. I take the first 128 bits of the key and use it to encrypt using AES CBC and then use the last 128 bits to MAC the ciphertext. – Eric Conner Mar 07 '12 at 07:19
  • @EricConner don't forget to also MAC the initialization vector! – MauganRa Feb 16 '17 at 08:14
3

When transferring files from one server to another through secure ftp, I use private/public key pairs with the private key residing on the "from" server and the public key residing on the "to" server.

Using private/public key pairs is a secure standard when transferring files.

I believe it would also be a secure means in the context of a Java application.

Check out Generating and Verifying Signatures and Generate Public and Private Keys for more details on using a private/public key pair setup for digital signatures in Java.

Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263
Zack Macomber
  • 6,682
  • 14
  • 57
  • 104
  • OK, that's a whole new use case but I was a bit harsh. Signatures and PKI *are* a valid method of integrity control and authentication, but it's rather heavy way of calculating a MAC. – Maarten Bodewes Mar 06 '12 at 00:20
  • 2
    @owlstead - I briefly recall your original comment but can't see it now cause it looks like it's been deleted. No worries either way. I've had several folks downvote my answers and I understand why in several cases. I'm hoping that more folks downvote for the reason that is seen when hovering over the downvote - "This answer is not useful". In this case, I really do believe my answer could help the OP and that's why I posted it. God forbid that any of us would just throw something up there for points. We should all be striving to help one another ultimately... – Zack Macomber Mar 06 '12 at 13:48
  • Precisely, that's why I thought it was rather harsh, I've got to stop myself from being too negative sometimes. I'm not sure if FTP and RSA is what Eric was looking for, but it's not incorrect, so the answer should be left fighting for its own... – Maarten Bodewes Mar 06 '12 at 15:30