· 7 years ago · Aug 04, 2018, 11:10 AM
1import java.security.SecureRandom
2
3import cats.Monad
4import cats.effect.IO
5import tsec.cipher.symmetric.jca._
6import tsec.cipher.symmetric.{AAD, _}
7import tsec.common._
8
9import scala.util.Random
10
11/*
12 * Setup:
13 *
14 * libraryDependencies ++= Seq(
15 * "io.github.jmcardon" %% "tsec-cipher-jca"
16 * ).map(_ % "0.0.1-M11")
17 *
18 */
19
20object Test {
21
22 private val random = new Random(new SecureRandom())
23 private val crypto = new Crypto()
24
25 def main(args: Array[String]): Unit = {
26 val res = test(100000)
27 if (res.isEmpty) {
28 println("Success")
29 } else {
30 println(s"Failed: ${res.mkString(",")}")
31 }
32 }
33
34 private def test(nrOfTests: Int): Seq[String] = {
35 1.to(nrOfTests).flatMap { _ =>
36 val key = random.alphanumeric.take(32).mkString
37 val string = random.alphanumeric.take(random.nextInt(100000)).mkString
38
39 val encrypted = crypto.encrypt(key, string)
40
41 val decrypted = crypto.decrypt(key, encrypted)
42
43 if (string != decrypted) {
44 Option(string)
45 } else {
46 Option.empty[String]
47 }
48 }
49 }
50
51}
52
53class Crypto(
54 val aad: AAD = AAD("myAdditionalAuthenticationData".utf8Bytes),
55 val algorithm: AESGCM[AES256GCM] = AES256GCM
56)(implicit val strategy: IvGen[IO, AES256GCM] = algorithm.defaultIvStrategy[IO],
57 val cachedAADEncryptor: IO[AADEncryptor[IO, AES256GCM, SecretKey]] =
58 algorithm.genEncryptor[IO]) {
59
60 def encrypt(keyStr: String, value: String): String = {
61 (for {
62 key <- algorithm.buildKey[IO](keyStr.utf8Bytes)
63 cachedAADEncryptor <- cachedAADEncryptor
64 encrypted <- algorithm.encryptWithAAD[IO](
65 PlainText(value.utf8Bytes),
66 key,
67 aad
68 )(implicitly[Monad[IO]], cachedAADEncryptor, strategy)
69 } yield (encrypted.content ++ encrypted.nonce).toB64String)
70 .unsafeRunSync()
71 }
72
73 def decrypt(keyStr: String, value: String): String = {
74 val (string, ivy) = {
75 val stringBytes = value.base64Bytes
76 stringBytes.splitAt(stringBytes.length - 12)
77 }
78 (for {
79 key <- algorithm.buildKey[IO](keyStr.utf8Bytes)
80 cachedAADEncryptor <- cachedAADEncryptor
81 decrypted <- algorithm.decryptWithAAD[IO](
82 CipherText(RawCipherText(string), Iv.apply(ivy)),
83 key,
84 aad
85 )(cachedAADEncryptor)
86 } yield decrypted.toUtf8String).unsafeRunSync()
87 }
88
89}