...
This compliant solution uses the Advanced Encryption Standard (AES) algorithm in Galois/Counter Mode (GCM) to perform the encryption. GCM has the benefit of providing authenticity (integrity) in addition to confidentiality. The same secret key can be used to encrypt multiple messages in GCM mode, but it is very important that a different initialization vector (IV) be used for each message. The below encrypt_gcm
method uses SecureRandom to generate a unique (with very high probability) IV for each message encrypted. Logically, the encrypt_gcm
method produces a pair of (IV, ciphertext), which the decrypt_gcm
method consumes. However, at the Java level, the encrypt
_gcm method returns a single byte array that consists of the IV followed by the ciphertext, since in practice this is often easier to handle than a pair of byte arrays.
...
This compliant solution uses the Advanced Encryption Standard (AES) algorithm in Cipher Block Chaining (CBC) mode to perform the encryption. It uses the "AES/CBC/PKCS5Padding" transformation, which the Java documentation guarantees to be available on all conforming implementations of the Java platform. However, CBC mode does not incorporate any authentication checks. Therefore, a separate message authentication code (MAC) should be generated by the sender after encryption and verified by the receiver before decryption. (Note that verifying the MAC after decryption, rather than before decryption, can introduce a "padding oracle" vulnerability.)
Code Block | ||
---|---|---|
| ||
import java.util.Arrays; import javax.crypto.*; import javax.crypto.spec.*; import java.security.SecureRandom; import java.security.GeneralSecurityException; class Msc61 { public static SecretKey generateKey() throws GeneralSecurityException { KeyGenerator kgen = KeyGenerator.getInstance("AES"); kgen.init(128); return kgen.generateKey(); } public static byte[] encrypt_cbc(SecretKey skey, String plaintext) throws GeneralSecurityException { byte[] ciphertext = null; Cipher cipher = Cipher.getInstance("AES/CBC/ISO10126PaddingPKCS5Padding"); final int blockSize = cipher.getBlockSize(); byte[] initVector = new byte[blockSize]; (new SecureRandom()).nextBytes(initVector); IvParameterSpec ivSpec = new IvParameterSpec(initVector); cipher.init(Cipher.ENCRYPT_MODE, skey, ivSpec); byte[] encoded = plaintext.getBytes(java.nio.charset.StandardCharsets.UTF_8); ciphertext = new byte[initVector.length + ((encoded.length / blockSize) + 1) * blockSize]; for (int i=0; i < initVector.length; i++) { ciphertext[i] = initVector[i]; } // Perform encryption cipher.doFinal(encoded, 0, encoded.length, ciphertext, initVector.length); return ciphertext; } public static String decrypt_cbc(SecretKey skey, byte[] ciphertext) throws GeneralSecurityException { Cipher cipher = Cipher.getInstance("AES/CBC/ISO10126PaddingPKCS5Padding"); final int blockSize = cipher.getBlockSize(); byte[] initVector = Arrays.copyOfRange(ciphertext, 0, blockSize); IvParameterSpec ivSpec = new IvParameterSpec(initVector); cipher.init(Cipher.DECRYPT_MODE, skey, ivSpec); byte[] plaintext = cipher.doFinal(ciphertext, blockSize, ciphertext.length - blockSize); return new String(plaintext); } } |
The Both of the above compliant solutions use 128-bit AES keys. Longer keys (192-bit and 256-bit) may be available if the "Unlimited Strength Jurisdiction Policy" files are installed and available to the Java runtime environment. A brute-force attack against 128-bit AES keys would take billions of years with current computational resources, so absent a cryptographic weakness in AES, 128-bit keys are likely suitable for secure encryption.
...