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

com.dwolla.security.crypto.BouncyCastleResource.scala Maven / Gradle / Ivy

package com.dwolla.security.crypto

import java.security.Security
import cats.effect._
import cats.syntax.all._
import org.bouncycastle.jce.provider.BouncyCastleProvider

import java.util.concurrent.atomic.AtomicInteger

sealed trait BouncyCastleResource
object BouncyCastleResource {
  private val timesBouncyCastleHasBeenRegistered: AtomicInteger = new AtomicInteger(0)

  private def register(provider: BouncyCastleProvider): Unit =
    synchronized {
      val previousCount = timesBouncyCastleHasBeenRegistered.getAndIncrement()
      val position = Security.addProvider(provider)

      /*
       * If BouncyCastle was already registered (as indicated by the returned
       * position being -1) but we didn't register it (as indicated
       * by the previous count being 0, then increment the counter so we
       * don't end up removing it when all these BouncyCastleResources
       * go out of scope.
       */
      if (position == -1 && previousCount == 0)
        timesBouncyCastleHasBeenRegistered.incrementAndGet()

      ()
    }

  private def deregister(name: String): Unit =
    synchronized {
      val remaining = timesBouncyCastleHasBeenRegistered.decrementAndGet()

      if (0 == remaining)
        Security.removeProvider(name)
    }

  def apply[F[_] : Sync]: Resource[F, BouncyCastleResource] = {
    def registerBouncyCastle: F[String] =
      for {
        provider <- Sync[F].blocking(new BouncyCastleProvider)
        _ <- Sync[F].blocking(register(provider))
      } yield provider.getName

    def removeBouncyCastle(name: String): F[Unit] =
      Sync[F].blocking(deregister(name))

    Resource.make(registerBouncyCastle)(removeBouncyCastle).as(new BouncyCastleResource {})
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy