AES / GCM — Encryption & Decryption using Kotlin

Rohail Ahmad
3 min readAug 20, 2020

What is the Advanced Encryption Standard or AES?
The Advanced Encryption Standard, or AES, is a symmetric block cipher chosen by the U.S. government to protect classified information and is implemented in software and hardware throughout the world to encrypt sensitive data.

How does AES encryption work?
AES comprises three block ciphers: AES-128, AES-192, and AES-256. Each cipher encrypts and decrypts data in blocks of 128 bits using cryptographic keys of 128-, 192- and 256-bits, respectively.

This is my another post after AES/ECB encryption & decryption

In my previous story, I shared AES encryption & decryption using ECB mode and now I will share AES encryption & decryption using GCM mode. Check this out for more information: link

ECB: Electronic Code Book (ECB) is a mode of operation for a block cipher, with the characteristic that each possible block of plaintext has a defined corresponding ciphertext value and vice versa. In other words, the same plaintext value will always result in the same ciphertext value.

GCM: AES with Galois/Counter Mode (GCM) is a mode of operation which provides both authenticated encryption (confidentiality and authentication) and the ability to check the integrity and authentication of additional authenticated data (AAD) that is sent in the clear.

Getting started
I have prepared this tutorial using Intellij IDEA and Kotlin programming language. To start with, you can create a new project using Kotlin or you can just create a Kotlin class in your current project.

Library Dependency
I have used BouncyCastle dependency for this project. You can find maven/gradle dependency e.g:
Maven: bouncycastle:bcprov-jdk16:136

Encryptor

fun encrypt(strToEncrypt: String, secret_key: String): String? {

Security.addProvider(BouncyCastleProvider())

val keyBytes: ByteArray

try {
keyBytes = secret_key.toByteArray(charset("UTF8"))
val secretkey = SecretKeySpec(keyBytes, "AES")
val input = strToEncrypt.toByteArray(charset("UTF8"))

synchronized(Cipher::class.java) {
val cipher = Cipher.getInstance("AES/GCM/NoPadding", "BC")
cipher.init(Cipher.ENCRYPT_MODE, secretkey)

val cipherText = ByteArray(cipher.getOutputSize(input.size))
var ctLength = cipher.update(
input, 0, input.size,
cipherText, 0
)
ctLength += cipher.doFinal(cipherText, ctLength)
return String(
Base64.encode(cipherText)
)
}
} catch (uee: UnsupportedEncodingException) {
uee.printStackTrace()
} catch (ibse: IllegalBlockSizeException) {
ibse.printStackTrace()
} catch (bpe: BadPaddingException) {
bpe.printStackTrace()
} catch (ike: InvalidKeyException) {
ike.printStackTrace()
} catch (nspe: NoSuchPaddingException) {
nspe.printStackTrace()
} catch (nsae: NoSuchAlgorithmException) {
nsae.printStackTrace()
} catch (e: ShortBufferException) {
e.printStackTrace()
}

return null
}

Decryptor

fun decryptWithAES(key: String, strToDecrypt: String?): String? {

Security.addProvider(BouncyCastleProvider())

val keyBytes: ByteArray

try {
keyBytes = key.toByteArray(charset("UTF8"))
val secretkey = SecretKeySpec(keyBytes, "AES")
val input = org.bouncycastle.util.encoders.Base64
.decode(strToDecrypt?.trim { it <= ' ' }?.toByteArray(charset("UTF8")))

synchronized(Cipher::class.java) {
val cipher = Cipher.getInstance("AES/GCM/NoPadding", "BC")
cipher.init(Cipher.DECRYPT_MODE, secretkey)

val plainText = ByteArray(cipher.getOutputSize(input.size))
var ptLength = cipher.update(input, 0, input.size, plainText, 0)
ptLength += cipher.doFinal(plainText, ptLength)
val decryptedString = String(plainText)
return decryptedString.trim { it <= ' ' }
}
} catch (uee: UnsupportedEncodingException) {
uee.printStackTrace()
} catch (ibse: IllegalBlockSizeException) {
ibse.printStackTrace()
} catch (bpe: BadPaddingException) {
bpe.printStackTrace()
} catch (ike: InvalidKeyException) {
ike.printStackTrace()
} catch (nspe: NoSuchPaddingException) {
nspe.printStackTrace()
} catch (nsae: NoSuchAlgorithmException) {
nsae.printStackTrace()
} catch (e: ShortBufferException) {
e.printStackTrace()
}

return null
}

Secret Key example
val secretKey: String = “662ede816988e58fb6d057d9d85605e0”

Enjoy and hit clap 👏 few times.. and below is my Github project sample.

Github

--

--

Rohail Ahmad

Android Engineer with @kivrasweden formerly @Eliq & @Inov8