Skip to content

Instantly share code, notes, and snippets.

@marko-asplund
Created November 27, 2018 08:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save marko-asplund/bf84e9d3acbddf151d5405cb53a6afe2 to your computer and use it in GitHub Desktop.
Save marko-asplund/bf84e9d3acbddf151d5405cb53a6afe2 to your computer and use it in GitHub Desktop.
Implement AEAD with AES + GCM
package com.practicingtechie
// implement AEAD with AES + GCM
object AeadHelper {
import javax.crypto._
import javax.crypto.spec.{GCMParameterSpec, SecretKeySpec}
import java.security._
import java.util.Base64
val AesKeySize = 256
val IvSize = 96
val TagBitLength = 128
val AlgoTransformationString = "AES/GCM/PKCS5Padding"
val SecretKeyString = "<base64 encoded key here>"
val SecretKey = new SecretKeySpec(Base64.getDecoder.decode(SecretKeyString), "AES")
val secRandom = new SecureRandom
def generateKey = {
val keygen = KeyGenerator.getInstance("AES")
keygen.init(AesKeySize)
val key = keygen.generateKey
println(s"key: ${Base64.getEncoder.encodeToString(key.getEncoded)}")
key
}
def encrypt(plainText: Array[Byte], aad: Array[Byte]) = {
def aesEncrypt(plainText: Array[Byte], aesKey: SecretKey, gcmParamSpec: GCMParameterSpec, aadData: Array[Byte]) = {
val c = Cipher.getInstance(AlgoTransformationString)
c.init(Cipher.ENCRYPT_MODE, aesKey, gcmParamSpec, new SecureRandom)
c.updateAAD(aadData)
c.doFinal(plainText)
}
val iv = new Array[Byte](IvSize)
secRandom.nextBytes(iv)
val gcmParamSpec = new GCMParameterSpec(TagBitLength, iv)
val cipherText = aesEncrypt(plainText, SecretKey, gcmParamSpec, aad)
val buf = new Array[Byte](IvSize + cipherText.size)
System.arraycopy(iv, 0, buf, 0, IvSize)
System.arraycopy(cipherText, 0, buf, IvSize, cipherText.size)
buf
}
def decrypt(message: Array[Byte], aad: Array[Byte]) = {
def aesDecrypt(cipherText: Array[Byte], aesKey: SecretKey, gcmParamSpec: GCMParameterSpec, aadData: Array[Byte]): Array[Byte] = {
val c = Cipher.getInstance(AlgoTransformationString)
c.init(Cipher.DECRYPT_MODE, aesKey, gcmParamSpec, new SecureRandom)
c.updateAAD(aadData)
c.doFinal(cipherText)
}
val cipherTextLen = message.size - IvSize
val gcmParamSpec = new GCMParameterSpec(TagBitLength, message, 0, IvSize)
val cipherText = new Array[Byte](cipherTextLen)
System.arraycopy(message, IvSize, cipherText, 0, cipherTextLen)
aesDecrypt(cipherText, SecretKey, gcmParamSpec, aad)
}
def runEncryptDecrypt(plainText: String, aad: String) = {
val cipherText = encrypt(plainText.getBytes, aad.getBytes)
println(s"cipher text: '${Base64.getEncoder.encodeToString(cipherText)}'")
val decryptedText = decrypt(cipherText, aad.getBytes)
println(s"decrypted text '${new String(decryptedText)}'")
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment