-
-
Save divukman/93baa12714903d6862ff15c584f22158 to your computer and use it in GitHub Desktop.
Java Authenticated Encryption with AES and GCM
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package at.favre.lib.bytes.otherPackage; | |
| import org.junit.Test; | |
| import javax.crypto.Cipher; | |
| import javax.crypto.SecretKey; | |
| import javax.crypto.spec.GCMParameterSpec; | |
| import javax.crypto.spec.SecretKeySpec; | |
| import java.nio.ByteBuffer; | |
| import java.nio.charset.StandardCharsets; | |
| import java.security.SecureRandom; | |
| import java.security.spec.AlgorithmParameterSpec; | |
| import static org.junit.Assert.assertEquals; | |
| /** | |
| * A simple showcase for encryption and decryption with AES + GCM in Java | |
| */ | |
| public class AesGcmTest { | |
| private final SecureRandom secureRandom = new SecureRandom(); | |
| private final static int GCM_IV_LENGTH = 12; | |
| @Test | |
| public void testEncryption() throws Exception { | |
| //create new random key | |
| byte[] key = new byte[16]; | |
| secureRandom.nextBytes(key); | |
| SecretKey secretKey = new SecretKeySpec(key, "AES"); | |
| byte[] associatedData = "ProtocolVersion1".getBytes(StandardCharsets.UTF_8); //meta data you want to verify with the secret message | |
| String message = "the secret message"; | |
| byte[] cipherText = encrypt(message, secretKey, associatedData); | |
| String decrypted = decrypt(cipherText, secretKey, associatedData); | |
| assertEquals(message, decrypted); | |
| } | |
| /** | |
| * Encrypt a plaintext with given key. | |
| * | |
| * @param plaintext to encrypt (utf-8 encoding will be used) | |
| * @param secretKey to encrypt, must be AES type, see {@link SecretKeySpec} | |
| * @param associatedData optional, additional (public) data to verify on decryption with GCM auth tag | |
| * @return encrypted message | |
| * @throws Exception if anything goes wrong | |
| */ | |
| private byte[] encrypt(String plaintext, SecretKey secretKey, byte[] associatedData) throws Exception { | |
| byte[] iv = new byte[GCM_IV_LENGTH]; //NEVER REUSE THIS IV WITH SAME KEY | |
| secureRandom.nextBytes(iv); | |
| final Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); | |
| GCMParameterSpec parameterSpec = new GCMParameterSpec(128, iv); //128 bit auth tag length | |
| cipher.init(Cipher.ENCRYPT_MODE, secretKey, parameterSpec); | |
| if (associatedData != null) { | |
| cipher.updateAAD(associatedData); | |
| } | |
| byte[] cipherText = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8)); | |
| ByteBuffer byteBuffer = ByteBuffer.allocate(iv.length + cipherText.length); | |
| byteBuffer.put(iv); | |
| byteBuffer.put(cipherText); | |
| return byteBuffer.array(); | |
| } | |
| /** | |
| * Decrypts encrypted message (see {@link #encrypt(String, SecretKey, byte[])}). | |
| * | |
| * @param cipherMessage iv with ciphertext | |
| * @param secretKey used to decrypt | |
| * @param associatedData optional, additional (public) data to verify on decryption with GCM auth tag | |
| * @return original plaintext | |
| * @throws Exception if anything goes wrong | |
| */ | |
| private String decrypt(byte[] cipherMessage, SecretKey secretKey, byte[] associatedData) throws Exception { | |
| final Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); | |
| //use first 12 bytes for iv | |
| AlgorithmParameterSpec gcmIv = new GCMParameterSpec(128, cipherMessage, 0, GCM_IV_LENGTH); | |
| cipher.init(Cipher.DECRYPT_MODE, secretKey, gcmIv); | |
| if (associatedData != null) { | |
| cipher.updateAAD(associatedData); | |
| } | |
| //use everything from 12 bytes on as ciphertext | |
| byte[] plainText = cipher.doFinal(cipherMessage, GCM_IV_LENGTH, cipherMessage.length - GCM_IV_LENGTH); | |
| return new String(plainText, StandardCharsets.UTF_8); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment