All Downloads are FREE. Search and download functionalities are using the official Maven repository.

tsec.cipher.symmetric.jca.AESGCM.scala Maven / Gradle / Ivy

The newest version!
package tsec.cipher.symmetric.jca

import java.util.concurrent.atomic.AtomicInteger

import cats.effect.Sync
import tsec.cipher.common.padding.NoPadding
import tsec.cipher.symmetric._
import tsec.cipher.symmetric.jca.primitive.JCAAEADPrimitive

sealed abstract class AESGCM[A] extends JCAAEAD[A, GCM, NoPadding] with AES[A] with JCAKeyGen[A] {
  implicit val ae: AESGCM[A] = this

  implicit def genEncryptor[F[_]: Sync](implicit c: AES[A]): AADEncryptor[F, A, SecretKey] =
    JCAAEADPrimitive.sync[F, A, GCM, NoPadding]

  /** Our default Iv strategy for GCM mode
    * produces randomized IVs
    *
    */
  def defaultIvStrategy[F[_]: Sync](implicit c: AES[A]): IvGen[F, A] = GCM.randomIVStrategy[F, A]

  /** An incremental iv strategy, as referenced in the
    * nist recommendations for the GCM mode of operation
    * http://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf
    * where:
    *
    * The fixed field(nonce) is the leftmost 4 bytes of the IV
    * The invocation field starts as a zeroed out array as the rightmost 8 bytes
    *
    */
  def incrementalIvStrategy[F[_]](implicit F: Sync[F]): CounterIvGen[F, A] =
    new CounterIvGen[F, A] {
      private val delta                      = 1000000
      private val maxVal: Int                = Int.MaxValue - delta
      private val fixedCounter: Array[Byte]  = Array.fill[Byte](8)(0.toByte)
      private val atomicNonce: AtomicInteger = new AtomicInteger(Int.MinValue)

      def refresh: F[Unit] = F.delay(atomicNonce.set(Int.MinValue))

      def counterState: F[Long] = F.delay(unsafeCounterState)

      def unsafeCounterState: Long = atomicNonce.get().toLong

      def genIv: F[Iv[A]] =
        F.delay(genIvUnsafe)

      def genIvUnsafe: Iv[A] =
        if (atomicNonce.get() >= maxVal)
          throw IvError("Maximum safe nonce number reached")
        else {
          val nonce = atomicNonce.incrementAndGet()
          val iv    = new Array[Byte](12) //GCM optimal iv len
          iv(0) = (nonce >> 24).toByte
          iv(1) = (nonce >> 16).toByte
          iv(2) = (nonce >> 8).toByte
          iv(3) = nonce.toByte
          System.arraycopy(fixedCounter, 0, iv, 4, 8)
          Iv[A](iv)
        }
    }

  def ciphertextFromConcat(rawCT: Array[Byte]): Either[CipherTextError, CipherText[A]] =
    CTOPS.ciphertextFromArray[A, GCM, NoPadding](rawCT)
}

sealed trait AES128GCM

object AES128GCM extends AESGCM[AES128GCM] with AES128[AES128GCM]

sealed trait AES192GCM

object AES192GCM extends AESGCM[AES192GCM] with AES192[AES192GCM]

sealed trait AES256GCM

object AES256GCM extends AESGCM[AES256GCM] with AES256[AES256GCM]




© 2015 - 2024 Weber Informatics LLC | Privacy Policy