I'm using AES-GCM mode in my project and I have some doubts.
public String encrypt(String plainText, String authenticationTag) throws GeneralSecurityException, IOException {
Cipher cipher = Cipher.getInstance(ALGORITHM_MODE_PADDING);
final int blockSize = cipher.getBlockSize();
SecretKey secretKey = readKeyFile(...);
byte[] plainTextByte = plainText.trim().getBytes(Charset.forName("UTF-8"));
byte[] ivBytes = generateIV();
cipher.init(Cipher.ENCRYPT_MODE, secretKey, new GCMParameterSpec(GCM_TAG_LENGTH, ivBytes));
cipher.updateAAD(authenticationTag.getBytes(Charset.forName("UTF-8")));
byte[] encryptedMessage = cipher.doFinal(plainTextByte);
byte iv_and_encryptedMessage[] = concatIvAndCipher(ivBytes, encryptedMessage, blockSize);
Base64.Encoder encoder = Base64.getEncoder().withoutPadding();
String iv_and_encryptedText = encoder.encodeToString(iv_and_encryptedMessage);
return iv_and_encryptedText;
}
public String decrypt(String iv_and_encryptedTextBase64, String authenticationTag)
throws GeneralSecurityException, IOException {
Cipher cipher = Cipher.getInstance(ALGORITHM_MODE_PADDING);
final int blockSize = cipher.getBlockSize();
Base64.Decoder decoder = Base64.getDecoder();
byte[] iv_and_encryptedMessage = decoder.decode(iv_and_encryptedTextBase64.trim());
byte[] ivBytes = extractIvFrom(iv_and_encryptedMessage, blockSize);
byte[] encryptedTextBytes = extractEncryptedMessageFrom(iv_and_encryptedMessage, blockSize);
SecretKey secretKey = readKeyFile(...);
cipher.init(Cipher.DECRYPT_MODE, secretKey, new GCMParameterSpec(GCM_TAG_LENGTH, ivBytes));
cipher.updateAAD(authenticationTag.getBytes(Charset.forName("UTF-8")));
byte[] decryptedByte = cipher.doFinal(encryptedTextBytes);
String decryptedMessage = new String(decryptedByte, Charset.forName("UTF-8"));
return decryptedMessage;
}
Questions:
I'm using a GUID as authentication tag which is binding to a user to whom the sensitive information belongs. The encrypted text and tag is stored in separate databases at separate locations. Is this OK?
From what I've read AES-GCM takes in (plain text, IV, key, associated data) and outputs (cipher text, authentication tag). Are associated data and authentication tag the same thing, because my implementation of encrypt and decrypt work when I pass same value in
cipher.updateAAD(...)
? How to obtain the authentication tag after encrypting?Should I use Bouncy Castle instead of using default Java implementation?
If the data to encrypt is 16 bytes, when should I generate a new DEK for enc/dec?
One master KEK for all DEK's? For encrypting DEK's should I use same AES implementation? If not, then what to use?
blockSize
as the size of the IV added to and later removed from the ciphertext, but yourgenerateIV()
call doesn't use it. Moreover, unlike several other modes, the IV for GCM is not fixed at the size of the cipher block; in fact AES' blocksize is 16 octets but the preferred GCM IV size is 12 octets (although it does handle 16). $\endgroup$