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

tsec.signature.libsodium.Ed25519Sig.scala Maven / Gradle / Ivy

package tsec.signature.libsodium

import cats.effect.Sync
import tsec.cipher.asymmetric.libsodium.SodiumSignatureError
import tsec.keygen.asymmetric.{AsymmetricKeyGen, AsymmetricKeyGenAPI}
import tsec.libsodium.ScalaSodium
import tsec.libsodium.ScalaSodium._
import tsec.signature._

sealed trait Ed25519Sig

//Todo: Streaming sigs
object Ed25519Sig
    extends SignatureAPI[Ed25519Sig, PublicKey, PrivateKey]
    with AsymmetricKeyGenAPI[Ed25519Sig, PublicKey, PrivateKey, SodiumKeyPair] {

  val pubKLen  = ScalaSodium.crypto_sign_PUBLICKEYBYTES
  val privKLen = ScalaSodium.crypto_sign_SECRETKEYBYTES
  val sigLen   = ScalaSodium.crypto_sign_BYTES

  implicit def genSigner[F[_]](implicit F: Sync[F], S: ScalaSodium): Signer[F, Ed25519Sig, PublicKey, PrivateKey] =
    new Signer[F, Ed25519Sig, PublicKey, PrivateKey] {
      def sign(unsigned: Array[Byte], secretKey: PrivateKey[Ed25519Sig]): F[CryptoSignature[Ed25519Sig]] =
        F.delay(impl.sign(unsigned, secretKey))

      def verifyBool(
          raw: Array[Byte],
          signature: CryptoSignature[Ed25519Sig],
          publicKey: PublicKey[Ed25519Sig]
      ): F[Boolean] =
        F.delay(impl.verify(raw, signature, publicKey))
    }

  implicit def keyGen[F[_]](
      implicit F: Sync[F],
      S: ScalaSodium
  ): AsymmetricKeyGen[F, Ed25519Sig, PublicKey, PrivateKey, SodiumKeyPair] =
    new AsymmetricKeyGen[F, Ed25519Sig, PublicKey, PrivateKey, SodiumKeyPair] {
      def generateKeyPair: F[SodiumKeyPair[Ed25519Sig]] =
        F.delay(impl.generateKeyPair)

      def buildPrivateKey(rawPk: Array[Byte]): F[PrivateKey[Ed25519Sig]] =
        F.delay(impl.buildPrivateKey(rawPk))

      def buildPublicKey(rawPk: Array[Byte]): F[PublicKey[Ed25519Sig]] =
        F.delay(impl.buildPublicKey(rawPk))
    }

  object impl {
    def generateKeyPair(implicit S: ScalaSodium): SodiumKeyPair[Ed25519Sig] = {
      val pubk  = PublicKey[Ed25519Sig](new Array[Byte](pubKLen))
      val privK = PrivateKey[Ed25519Sig](new Array[Byte](privKLen))
      S.crypto_sign_keypair(pubk, privK)
      SodiumKeyPair(pubk, privK)
    }

    def sign(
        unsigned: Array[Byte],
        secretKey: PrivateKey[Ed25519Sig]
    )(implicit S: ScalaSodium): CryptoSignature[Ed25519Sig] = {
      val out = new Array[Byte](sigLen)
      S.crypto_sign_detached(out, NullPtrInt, unsigned, unsigned.length, secretKey)
      CryptoSignature[Ed25519Sig](out)
    }

    def verify(
        raw: Array[Byte],
        signature: CryptoSignature[Ed25519Sig],
        publicKey: PublicKey[Ed25519Sig]
    )(implicit S: ScalaSodium): Boolean =
      S.crypto_sign_verify_detached(signature, raw, raw.length, publicKey) == 0

    def buildPrivateKey(rawPk: Array[Byte]): PrivateKey[Ed25519Sig] =
      if (rawPk.length != privKLen)
        throw SodiumSignatureError("Invalid Private Key")
      else
        PrivateKey[Ed25519Sig](rawPk)

    def buildPublicKey(rawPk: Array[Byte]): PublicKey[Ed25519Sig] =
      if (rawPk.length != pubKLen)
        throw SodiumSignatureError("Invalid Private Key")
      else
        PublicKey[Ed25519Sig](rawPk)
  }

  def signCombined[F[_]](
      unsigned: RawMessage[Ed25519Sig],
      secretKey: PrivateKey[Ed25519Sig]
  )(implicit F: Sync[F], S: ScalaSodium): F[SignedMessage[Ed25519Sig]] =
    F.delay {
      val out = new Array[Byte](unsigned.length + sigLen)
      S.crypto_sign(out, NullPtrInt, unsigned, unsigned.length, secretKey)
      SignedMessage[Ed25519Sig](out)
    }

  def verifyCombined[F[_]](
      signedMessage: SignedMessage[Ed25519Sig],
      publicKey: PublicKey[Ed25519Sig]
  )(implicit F: Sync[F], S: ScalaSodium): F[RawMessage[Ed25519Sig]] = F.delay {
    val msgLen = signedMessage.length - sigLen
    if (msgLen < 0)
      throw SodiumSignatureError("Invalid message length")

    val out = RawMessage[Ed25519Sig](new Array[Byte](msgLen))
    if (S.crypto_sign_open(out, NullPtrInt, signedMessage, signedMessage.length, publicKey) != 0)
      throw SodiumSignatureError("Invalid Signature")
    RawMessage[Ed25519Sig](out)
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy