-
Notifications
You must be signed in to change notification settings - Fork 0
Kotlin
alex [dot] kramer [at] g_m_a_i_l [dot] com edited this page Oct 12, 2018
·
6 revisions
Use ECB
for short payloads. Use CBC
with an IV (initialization vector) for longer payloads.
import com.google.gson.Gson
import org.junit.Assert.assertEquals
import org.junit.Test
import java.util.*
import javax.crypto.*
import javax.crypto.spec.SecretKeySpec
class EncryptionService {
companion object {
private val KEY_ALGORITHM = "AES"
private val CIPHER_ALGORITHM = "AES/ECB/PKCS5PADDING"
private val base64Encoder = Base64.getEncoder()
private val base64Decoder = Base64.getDecoder()
fun generateAesKey(): SecretKey {
val keyGen = KeyGenerator.getInstance(KEY_ALGORITHM)
keyGen.init(256)
val secretKey = keyGen.generateKey()
return secretKey
}
fun encodeAesKeyBase64(key: SecretKey): String {
return base64Encoder.encodeToString(key.encoded)
}
fun decodeAesKeyBase64(keyEncodedAsBase64: String): SecretKey {
val keyData = base64Decoder.decode(keyEncodedAsBase64)
return SecretKeySpec(keyData, 0, keyData.size, KEY_ALGORITHM)
}
fun encryptToBase64Ciphertext(key: SecretKey, stringToEncrypt: String): String {
val aesCipher = Cipher.getInstance(CIPHER_ALGORITHM)
aesCipher.init(Cipher.ENCRYPT_MODE, key)
val stringToEncryptBytes = stringToEncrypt.toByteArray()
val ciphertextBytes = aesCipher.doFinal(stringToEncryptBytes)
return base64Encoder.encodeToString(ciphertextBytes)
}
fun decrypt(key: SecretKey, base64Ciphertext: String): String {
val cipher = Cipher.getInstance(CIPHER_ALGORITHM)
cipher.init(Cipher.DECRYPT_MODE, key)
val ciphertext = base64Decoder.decode(base64Ciphertext)
val decryptedBytes = cipher.doFinal(ciphertext)
return String(decryptedBytes)
}
}
}
class EncryptionTest {
data class Thingy(
val field1: String,
val field2: Double,
val field3: Long
)
@Test
fun `encrypt all the things`() {
val key = EncryptionService.generateAesKey()
// Thingy to serialize and encrypt
val thingy = Thingy("eleventeen", 3.14159, 42)
// Serialize thingy
val thingyJson = Gson().toJson(thingy)
// Encrypt serialized thingy
val thingyJsonCiphertextBase64 = EncryptionService.encryptToBase64Ciphertext(key, thingyJson)
// Encode key (for distribution/storage)
val encodedKeyBase64 = EncryptionService.encodeAesKeyBase64(key)
// Decode key
val decodedKey = EncryptionService.decodeAesKeyBase64(encodedKeyBase64)
// Decrypt thingy
val decryptedThingyJson = EncryptionService.decrypt(decodedKey, userDataJsonCiphertextBase64)
// Deserialize thingy
val deserializedThingy = Gson().fromJson(decryptedThingyJson, Thingy::class.java)
// Sanity checks
assertEquals(key, decodedKey)
assertEquals(decryptedThingyJson, thingyJson)
assertEquals(thingy, deserializedThingy)
println(deserializedThingy)
}
}