Skip to content

Instantly share code, notes, and snippets.

@rtfpessoa
Created August 4, 2018 11:00
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 rtfpessoa/92d8b1a63a97ce000e222c7ae3a9b978 to your computer and use it in GitHub Desktop.
Save rtfpessoa/92d8b1a63a97ce000e222c7ae3a9b978 to your computer and use it in GitHub Desktop.
Scala Crypto AES GCM
import java.security.SecureRandom
import cats.Monad
import cats.effect.IO
import tsec.cipher.symmetric.jca._
import tsec.cipher.symmetric.{AAD, _}
import tsec.common._
import scala.util.Random
/*
* Setup:
*
* libraryDependencies ++= Seq(
* "io.github.jmcardon" %% "tsec-cipher-jca"
* ).map(_ % "0.0.1-M11")
*
*/
object Test {
private val random = new Random(new SecureRandom())
private val crypto = new Crypto()
def main(args: Array[String]): Unit = {
val res = test(100000)
if (res.isEmpty) {
println("Success")
} else {
println(s"Failed: ${res.mkString(",")}")
}
}
private def test(nrOfTests: Int): Seq[String] = {
1.to(nrOfTests).flatMap { _ =>
val key = random.alphanumeric.take(32).mkString
val string = random.alphanumeric.take(random.nextInt(100000)).mkString
val encrypted = crypto.encrypt(key, string)
val decrypted = crypto.decrypt(key, encrypted)
if (string != decrypted) {
Option(string)
} else {
Option.empty[String]
}
}
}
}
class Crypto(
val aad: AAD = AAD("myAdditionalAuthenticationData".utf8Bytes),
val algorithm: AESGCM[AES256GCM] = AES256GCM
)(implicit val strategy: IvGen[IO, AES256GCM] = algorithm.defaultIvStrategy[IO],
val cachedAADEncryptor: IO[AADEncryptor[IO, AES256GCM, SecretKey]] =
algorithm.genEncryptor[IO]) {
def encrypt(keyStr: String, value: String): String = {
(for {
key <- algorithm.buildKey[IO](keyStr.utf8Bytes)
cachedAADEncryptor <- cachedAADEncryptor
encrypted <- algorithm.encryptWithAAD[IO](
PlainText(value.utf8Bytes),
key,
aad
)(implicitly[Monad[IO]], cachedAADEncryptor, strategy)
} yield (encrypted.content ++ encrypted.nonce).toB64String)
.unsafeRunSync()
}
def decrypt(keyStr: String, value: String): String = {
val (string, ivy) = {
val stringBytes = value.base64Bytes
stringBytes.splitAt(stringBytes.length - 12)
}
(for {
key <- algorithm.buildKey[IO](keyStr.utf8Bytes)
cachedAADEncryptor <- cachedAADEncryptor
decrypted <- algorithm.decryptWithAAD[IO](
CipherText(RawCipherText(string), Iv.apply(ivy)),
key,
aad
)(cachedAADEncryptor)
} yield decrypted.toUtf8String).unsafeRunSync()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment