Created
August 4, 2018 11:00
-
-
Save rtfpessoa/92d8b1a63a97ce000e222c7ae3a9b978 to your computer and use it in GitHub Desktop.
Scala Crypto AES GCM
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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