// Generate 96bit Initialization Vector final byte[] iv = new byte[12]; final SecureRandom rand = new SecureRandom(); rand.nextBytes(iv); // Init AES-GCM final Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); cipher.init(Cipher.ENCRYPT_MODE, key, new GCMParameterSpec(128, iv)); try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) { // add the IV baos.write(iv); // encrypt the 'message' baos.write(cipher.doFinal(message)); // Get the full cipherText: IV + Encrypted-Message + Auth-Tag final byte[] cipherText = baos.toByteArray(); return cipherText; } } byte[] decrypt(final SecretKey key, final byte[] cipherText) throws Exception { // Init AES-GCM, IV is in the first 12bytes of the ciphertext final Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); final GCMParameterSpec gcmSpec = new GCMParameterSpec(128, cipherText, 0, 12); cipher.init(Cipher.DECRYPT_MODE, key, gcmSpec); // Decrypt the message (exclude the IV) final byte[] plainText = cipher.doFinal(cipherText, 12, cipherText.length - 12); return plainText; } Java async function aesEncrypt(key: CryptoKey, message: ArrayBuffer) { // Generate 96bit Initialization Vector const iv = new Uint8Array(12); crypto.getRandomValues(iv); // Encrypt the 'message' const aesData = await crypto.subtle.encrypt( { name: "AES-GCM", iv: iv }, key, message, ); // Compose the ciphertext: IV + Encrypted-Message + Auth-Tag const ciphertext = new Uint8Array(iv.length + aesData.byteLength); ciphertext.set(iv, 0); ciphertext.set(new Uint8Array(aesData), iv.length); return ciphertext; } async function aesDecrypt(key: CryptoKey, ciphertext: Uint8Array) { // IV is in the first 12bytes of the ciphertext const iv = ciphertext.slice(0, 12); // AES encrypted data + GCM auth-tag const aesData = ciphertext.slice(12); // decrypt data const plaintext = await crypto.subtle.decrypt( { name: "AES-GCM", iv: iv }, key, aesData ); return plaintext; } Javascript from cryptography.hazmat.primitives.ciphers import * import os def aes_encrypt(key: bytes, message: bytes) -> bytes: # Generate 96bit Initialization Vector iv = os.urandom(12) # Init AES-GCM cipher = Cipher(algorithms.AES(key), modes.GCM(iv)) encryptor = cipher.encryptor() # Encrypt 'message' aes_data = encryptor.update(message) + encryptor.finalize() # Get the full cipherText: IV + Encrypted-Message + Auth-Tag ciphertext = iv + aes_data + encryptor.tag return ciphertext def aes_decrypt(key: bytes, ciphertext: bytes) -> bytes: iv = ciphertext[0:12] aes_data = ciphertext[12:-16] tag = ciphertext[-16:] cipher = Cipher(algorithms.AES(key), modes.GCM(iv, tag)) decryptor = cipher.decryptor() text = decryptor.update(aes_data) + decryptor.finalize() return text Python pip install cryptography AES Encrypt/Decrypt symmetric cryptography AES-GCM IV (12bytes) AES Encrypted Data Auth Tag (16bytes) Secure Random Data GCM “Integrity Check” The Encrypted Message // Encrypt a message with AES-GCM iv = generate_secure_random(12); aes_gcm = new_aes_gcm(key, iv) ciphertext = aes_gcm.encrypt(message) send(iv, ciphertext, aes_gcm.auth_tag) // Decrypt a message with AES-GCM iv, ciphertext, gcm_auth_tag = recv() aes_gcm = new_aes_gcm(key, iv, gcm_auth_tag) message = aes_gcm.decrypt(ciphertext) GCM (Galois/Counter Mode): Counter mode with authentication. (Encryption and integrity) CTR (Counter): Encrypts blocks using a counter. (Parallel encryption, random access) XTS (XEX-based Tweaked Codebook Mode): For Disk encryption with manipulation protection. EAX (Encrypt-then-authenticate-then-translate): Provides encryption and integrity. CCM (Counter with CBC-MAC): Authenticated encryption with associated data SIV (Synthetic Initialization Vector): Deterministic encryption with unique authenticity. AES Modes