· 7 years ago · Nov 27, 2018, 08:08 AM
1package com.practicingtechie
2
3// implement AEAD with AES + GCM
4object AeadHelper {
5 import javax.crypto._
6 import javax.crypto.spec.{GCMParameterSpec, SecretKeySpec}
7 import java.security._
8 import java.util.Base64
9
10 val AesKeySize = 256
11 val IvSize = 96
12 val TagBitLength = 128
13 val AlgoTransformationString = "AES/GCM/PKCS5Padding"
14
15 val SecretKeyString = "<base64 encoded key here>"
16 val SecretKey = new SecretKeySpec(Base64.getDecoder.decode(SecretKeyString), "AES")
17 val secRandom = new SecureRandom
18
19
20 def generateKey = {
21 val keygen = KeyGenerator.getInstance("AES")
22 keygen.init(AesKeySize)
23 val key = keygen.generateKey
24 println(s"key: ${Base64.getEncoder.encodeToString(key.getEncoded)}")
25 key
26 }
27
28 def encrypt(plainText: Array[Byte], aad: Array[Byte]) = {
29 def aesEncrypt(plainText: Array[Byte], aesKey: SecretKey, gcmParamSpec: GCMParameterSpec, aadData: Array[Byte]) = {
30 val c = Cipher.getInstance(AlgoTransformationString)
31 c.init(Cipher.ENCRYPT_MODE, aesKey, gcmParamSpec, new SecureRandom)
32 c.updateAAD(aadData)
33 c.doFinal(plainText)
34 }
35 val iv = new Array[Byte](IvSize)
36 secRandom.nextBytes(iv)
37 val gcmParamSpec = new GCMParameterSpec(TagBitLength, iv)
38 val cipherText = aesEncrypt(plainText, SecretKey, gcmParamSpec, aad)
39 val buf = new Array[Byte](IvSize + cipherText.size)
40 System.arraycopy(iv, 0, buf, 0, IvSize)
41 System.arraycopy(cipherText, 0, buf, IvSize, cipherText.size)
42 buf
43 }
44
45 def decrypt(message: Array[Byte], aad: Array[Byte]) = {
46 def aesDecrypt(cipherText: Array[Byte], aesKey: SecretKey, gcmParamSpec: GCMParameterSpec, aadData: Array[Byte]): Array[Byte] = {
47 val c = Cipher.getInstance(AlgoTransformationString)
48 c.init(Cipher.DECRYPT_MODE, aesKey, gcmParamSpec, new SecureRandom)
49 c.updateAAD(aadData)
50 c.doFinal(cipherText)
51 }
52 val cipherTextLen = message.size - IvSize
53 val gcmParamSpec = new GCMParameterSpec(TagBitLength, message, 0, IvSize)
54 val cipherText = new Array[Byte](cipherTextLen)
55 System.arraycopy(message, IvSize, cipherText, 0, cipherTextLen)
56 aesDecrypt(cipherText, SecretKey, gcmParamSpec, aad)
57 }
58
59 def runEncryptDecrypt(plainText: String, aad: String) = {
60 val cipherText = encrypt(plainText.getBytes, aad.getBytes)
61
62 println(s"cipher text: '${Base64.getEncoder.encodeToString(cipherText)}'")
63
64 val decryptedText = decrypt(cipherText, aad.getBytes)
65 println(s"decrypted text '${new String(decryptedText)}'")
66 }
67
68}