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

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

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

import java.util.concurrent.atomic.AtomicLong

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

sealed abstract class AESCTR[A] extends JCACipherAPI[A, CTR, NoPadding] with AES[A] with JCAKeyGen[A] {
  implicit val ae: AESCTR[A] = this

  implicit def genEncryptor[F[_]: Sync](implicit c: BlockCipher[A]): JCAPrimitiveCipher[F, A, CTR, NoPadding] =
    JCAPrimitiveCipher.sync[F, A, CTR, NoPadding]

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

  /** An incremental iv generator, intended for use
    * with a single key.
    *
    * See: https://crypto.stanford.edu/~dabo/cs255/lectures/PRP-PRF.pdf,
    * courtesy of dan boneh
    *
    * For a 128 bit iv, we use a 64 bit leftmost bits as a nonce,
    * and the rightmost 64 bits (zeroed out) as the counter.
    *
    * This means, using the incremental strategy, you can safely generate
    * generate 2^^64 - 10^^6 different nonces maximum, each of which can safely increment
    * a maximum of 2^^64 blocks.
    *
    * 2^^64 - 10^^6 is a safe limit to possibly avoid overflowing the safe number of nonces you can
    * generate with one key.
    *
    */
  def incrementalIvStrategy[F[_]](implicit F: Sync[F]): CounterIvGen[F, A] =
    new CounterIvGen[F, A] {
      private val delta                     = 1000000L
      private val maxVal: Long              = Long.MaxValue - delta
      private val fixedCounter: Array[Byte] = Array.fill[Byte](8)(0.toByte)
      private val atomicNonce: AtomicLong   = new AtomicLong(Long.MinValue)

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

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

      def unsafeCounterState: Long = atomicNonce.get()

      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](16) //AES block size
          iv(0) = (nonce >> 56).toByte
          iv(1) = (nonce >> 48).toByte
          iv(2) = (nonce >> 40).toByte
          iv(3) = (nonce >> 32).toByte
          iv(4) = (nonce >> 24).toByte
          iv(5) = (nonce >> 16).toByte
          iv(6) = (nonce >> 8).toByte
          iv(7) = nonce.toByte
          System.arraycopy(fixedCounter, 0, iv, 8, 8)
          Iv[A](iv)
        }
    }

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

sealed trait AES128CTR

object AES128CTR extends AESCTR[AES128CTR] with AES128[AES128CTR]

sealed trait AES192CTR

object AES192CTR extends AESCTR[AES192CTR] with AES192[AES192CTR]

sealed trait AES256CTR

object AES256CTR extends AESCTR[AES256CTR] with AES256[AES256CTR]




© 2015 - 2025 Weber Informatics LLC | Privacy Policy