patternjavaMinor
AES Encryption/Decryption
Viewed 0 times
encryptiondecryptionaes
Problem
Where I currently work I'm tasked with writing a good encryption and decryption code which will have DEK as well as KEK. Haven't started on KEK yet. I have already told them, that we need expert help, but I don't think I am going to get any. Any tips on KEK how to generate them and where to store them? (HSM ?) would be appreciated.
After researching over the week I've written this code below.
Looking for feedback on what is wrong in the code below and how it can be fixed.
Also, I'm using a GUID as authentication tag which is binding to a user to whom the information belongs. The encrypted text and tag is stored in separate database at separate location. Am I on the right path? if not please show me.
```
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.security.GeneralSecurityException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public enum AES {
INSTANCE;
private static final String CIPHER_ALGORITHM = "AES";
private static final String ALGORITHM_MODE_PADDING = "AES/GCM/NoPadding";
private static final int IV_LENGTH_BYTES = 16;
private static final int AES_KEY_SIZE = 128;
private static final int GCM_TAG_LENGTH = 128;
public String encrypt(String plainText, String authenticationTag) throws GeneralSecurityException, IOException {
createKeyFile(authenticationTag);
Cipher cipher = Cipher.getInstance(ALGORITHM_MODE_PADDING);
final int blockSize = cipher.getBlockSize();
SecretKey secretKey = readKeyFile(authenticationTag);
byte[] plainTextByte = plainText.trim().getBytes(Charset.forName("UTF-8"));
byte[] ivBytes = generateIV();
cipher.in
After researching over the week I've written this code below.
Looking for feedback on what is wrong in the code below and how it can be fixed.
Also, I'm using a GUID as authentication tag which is binding to a user to whom the information belongs. The encrypted text and tag is stored in separate database at separate location. Am I on the right path? if not please show me.
```
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.security.GeneralSecurityException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public enum AES {
INSTANCE;
private static final String CIPHER_ALGORITHM = "AES";
private static final String ALGORITHM_MODE_PADDING = "AES/GCM/NoPadding";
private static final int IV_LENGTH_BYTES = 16;
private static final int AES_KEY_SIZE = 128;
private static final int GCM_TAG_LENGTH = 128;
public String encrypt(String plainText, String authenticationTag) throws GeneralSecurityException, IOException {
createKeyFile(authenticationTag);
Cipher cipher = Cipher.getInstance(ALGORITHM_MODE_PADDING);
final int blockSize = cipher.getBlockSize();
SecretKey secretKey = readKeyFile(authenticationTag);
byte[] plainTextByte = plainText.trim().getBytes(Charset.forName("UTF-8"));
byte[] ivBytes = generateIV();
cipher.in
Solution
I won't say anything about the cryptographic aspects (as in, what I see
looks okay to me (but I too am not an expert, take it to IT Security
please, or actually pay someone for it), but there's no indication
except for the HSM bit what this is going to be used for).
aren't necessary, take a look at the other constructors for
specifying the offset and length of the part of the array to use.
Concatenating things is also a bit wasteful, but I guess punting on
precalculating the necessary buffer size is fine for the moment.
the
instead.
plain text as that's quite limiting in what can be passed in, but if
that's the use case, sure.
the fact that nothing else is marked
though I find that it will probably not help too much with testing if
everything refers to a single instance of this. At least it's
thread-safe, so that's something, but that could've been achieved with
static methods too.
looks okay to me (but I too am not an expert, take it to IT Security
please, or actually pay someone for it), but there's no indication
except for the HSM bit what this is going to be used for).
- I guess
readKeyFileandcreateKeyFilewere left out as irrelevant.
- At least the
extractIvFromandextractEncryptedMessageFrommethods
aren't necessary, take a look at the other constructors for
GCMParameterSpec and the other methods for doFinal which allowspecifying the offset and length of the part of the array to use.
Concatenating things is also a bit wasteful, but I guess punting on
precalculating the necessary buffer size is fine for the moment.
- Some values are repeatedly used, just move them into constants, like
the
Charset value, or, even better, usejava.nio.charset.StandardCharsets.UTF_8instead.
- In terms of API I probably wouldn't use an actual
Stringfor the
plain text as that's quite limiting in what can be passed in, but if
that's the use case, sure.
- There are random
finals in the methods that are inconsistent with
the fact that nothing else is marked
final.- Finally, you'll probably hear different advice about singletons,
though I find that it will probably not help too much with testing if
everything refers to a single instance of this. At least it's
thread-safe, so that's something, but that could've been achieved with
static methods too.
Context
StackExchange Code Review Q#143073, answer score: 2
Revisions (0)
No revisions yet.