mirror of
https://github.com/fluencelabs/crypto
synced 2025-05-17 09:41:20 +00:00
refactor sign classes (#34)
* refactor sign classes store in private key only S, in public key only Q point without wrappers * refactor, class ...[F[_]] to method ...[F[_]] * remove redundant
This commit is contained in:
parent
fdae5eaf8f
commit
79738aa2c7
@ -17,17 +17,18 @@
|
|||||||
|
|
||||||
package fluence.crypto.algorithm
|
package fluence.crypto.algorithm
|
||||||
|
|
||||||
|
import java.math.BigInteger
|
||||||
import java.security._
|
import java.security._
|
||||||
import java.security.spec.{ PKCS8EncodedKeySpec, X509EncodedKeySpec }
|
import java.security.interfaces.ECPrivateKey
|
||||||
|
|
||||||
import cats.MonadError
|
import cats.MonadError
|
||||||
import cats.syntax.flatMap._
|
import cats.syntax.flatMap._
|
||||||
import cats.syntax.functor._
|
import cats.syntax.functor._
|
||||||
import fluence.crypto.keypair.KeyPair
|
import fluence.crypto.keypair.KeyPair
|
||||||
import fluence.crypto.signature.SignatureChecker
|
|
||||||
import org.bouncycastle.jce.ECNamedCurveTable
|
import org.bouncycastle.jce.ECNamedCurveTable
|
||||||
|
import org.bouncycastle.jce.interfaces.ECPublicKey
|
||||||
import org.bouncycastle.jce.provider.BouncyCastleProvider
|
import org.bouncycastle.jce.provider.BouncyCastleProvider
|
||||||
import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec
|
import org.bouncycastle.jce.spec.{ ECNamedCurveParameterSpec, ECParameterSpec, ECPrivateKeySpec, ECPublicKeySpec }
|
||||||
import scodec.bits.ByteVector
|
import scodec.bits.ByteVector
|
||||||
|
|
||||||
import scala.language.higherKinds
|
import scala.language.higherKinds
|
||||||
@ -38,18 +39,17 @@ import scala.util.control.NonFatal
|
|||||||
* @param curveType http://www.bouncycastle.org/wiki/display/JA1/Supported+Curves+%28ECDSA+and+ECGOST%29
|
* @param curveType http://www.bouncycastle.org/wiki/display/JA1/Supported+Curves+%28ECDSA+and+ECGOST%29
|
||||||
* @param scheme https://bouncycastle.org/specifications.html
|
* @param scheme https://bouncycastle.org/specifications.html
|
||||||
*/
|
*/
|
||||||
class Ecdsa[F[_]](curveType: String, scheme: String)(implicit F: MonadError[F, Throwable]) extends JavaAlgorithm
|
class Ecdsa(curveType: String, scheme: String) extends JavaAlgorithm
|
||||||
with SignatureFunctions[F] with KeyGenerator[F] {
|
with SignatureFunctions with KeyGenerator {
|
||||||
import Ecdsa._
|
import Ecdsa._
|
||||||
private def nonFatalHandling[A](a: ⇒ A)(errorText: String): F[A] = {
|
private def nonFatalHandling[F[_], A](a: ⇒ A)(errorText: String)(implicit F: MonadError[F, Throwable]): F[A] = {
|
||||||
try F.pure(a)
|
try F.pure(a)
|
||||||
catch {
|
catch {
|
||||||
case NonFatal(e) ⇒ F.raiseError(CryptoErr(errorText + " " + e.getLocalizedMessage))
|
case NonFatal(e) ⇒ F.raiseError(CryptoErr(errorText + " " + e.getLocalizedMessage))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override def generateKeyPair(random: SecureRandom): F[KeyPair] = {
|
override def generateKeyPair[F[_]](random: SecureRandom)(implicit F: MonadError[F, Throwable]): F[KeyPair] = {
|
||||||
import JavaAlgorithm._
|
|
||||||
for {
|
for {
|
||||||
ecSpecOp ← F.pure(Option(ECNamedCurveTable.getParameterSpec(curveType)))
|
ecSpecOp ← F.pure(Option(ECNamedCurveTable.getParameterSpec(curveType)))
|
||||||
ecSpec ← ecSpecOp match {
|
ecSpec ← ecSpecOp match {
|
||||||
@ -59,28 +59,33 @@ class Ecdsa[F[_]](curveType: String, scheme: String)(implicit F: MonadError[F, T
|
|||||||
g ← getKeyPairGenerator
|
g ← getKeyPairGenerator
|
||||||
_ ← nonFatalHandling(g.initialize(ecSpec, random))("Could not initialize KeyPairGenerator.")
|
_ ← nonFatalHandling(g.initialize(ecSpec, random))("Could not initialize KeyPairGenerator.")
|
||||||
keyPair ← Option(g.generateKeyPair()) match {
|
keyPair ← Option(g.generateKeyPair()) match {
|
||||||
case Some(p) ⇒ F.pure(p)
|
case Some(p) ⇒
|
||||||
case None ⇒ F.raiseError[java.security.KeyPair](CryptoErr("Could not generate KeyPair. Unexpected."))
|
//store S number for private key and compressed Q point on curve for public key
|
||||||
|
val pk = p.getPublic.asInstanceOf[ECPublicKey].getQ.getEncoded(true)
|
||||||
|
val sk = p.getPrivate.asInstanceOf[ECPrivateKey].getS.toByteArray
|
||||||
|
F.pure(KeyPair.fromBytes(pk, sk))
|
||||||
|
case None ⇒ F.raiseError[KeyPair](CryptoErr("Could not generate KeyPair. Unexpected."))
|
||||||
}
|
}
|
||||||
} yield keyPair
|
} yield keyPair
|
||||||
}
|
}
|
||||||
|
|
||||||
override def generateKeyPair(): F[KeyPair] = {
|
override def generateKeyPair[F[_]]()(implicit F: MonadError[F, Throwable]): F[KeyPair] = {
|
||||||
generateKeyPair(new SecureRandom())
|
generateKeyPair(new SecureRandom())
|
||||||
}
|
}
|
||||||
|
|
||||||
override def sign(keyPair: KeyPair, message: ByteVector): F[fluence.crypto.signature.Signature] = {
|
override def sign[F[_]](keyPair: KeyPair, message: ByteVector)(implicit F: MonadError[F, Throwable]): F[fluence.crypto.signature.Signature] = {
|
||||||
signMessage(keyPair.secretKey.value.toArray, message.toArray)
|
signMessage(keyPair.secretKey.value.toArray, message.toArray)
|
||||||
.map(bb ⇒ fluence.crypto.signature.Signature(keyPair.publicKey, ByteVector(bb)))
|
.map(bb ⇒ fluence.crypto.signature.Signature(keyPair.publicKey, ByteVector(bb)))
|
||||||
}
|
}
|
||||||
|
|
||||||
override def verify(signature: fluence.crypto.signature.Signature, message: ByteVector): F[Boolean] = {
|
override def verify[F[_]](signature: fluence.crypto.signature.Signature, message: ByteVector)(implicit F: MonadError[F, Throwable]): F[Boolean] = {
|
||||||
verifySign(signature.publicKey.value.toArray, message.toArray, signature.sign.toArray)
|
verifySign(signature.publicKey.value.toArray, message.toArray, signature.sign.toArray)
|
||||||
}
|
}
|
||||||
|
|
||||||
private def signMessage(privateKey: Array[Byte], message: Array[Byte]): F[Array[Byte]] = {
|
private def signMessage[F[_]](privateKey: Array[Byte], message: Array[Byte])(implicit F: MonadError[F, Throwable]): F[Array[Byte]] = {
|
||||||
val keySpec = new PKCS8EncodedKeySpec(privateKey)
|
|
||||||
for {
|
for {
|
||||||
|
ec ← curveSpec
|
||||||
|
keySpec ← nonFatalHandling(new ECPrivateKeySpec(new BigInteger(privateKey), ec))("Cannot read private key.")
|
||||||
keyFactory ← getKeyFactory
|
keyFactory ← getKeyFactory
|
||||||
signProvider ← getSignatureProvider
|
signProvider ← getSignatureProvider
|
||||||
sign ← {
|
sign ← {
|
||||||
@ -93,9 +98,10 @@ class Ecdsa[F[_]](curveType: String, scheme: String)(implicit F: MonadError[F, T
|
|||||||
} yield sign
|
} yield sign
|
||||||
}
|
}
|
||||||
|
|
||||||
private def verifySign(publicKey: Array[Byte], message: Array[Byte], signature: Array[Byte]): F[Boolean] = {
|
private def verifySign[F[_]](publicKey: Array[Byte], message: Array[Byte], signature: Array[Byte])(implicit F: MonadError[F, Throwable]): F[Boolean] = {
|
||||||
val keySpec = new X509EncodedKeySpec(publicKey)
|
|
||||||
for {
|
for {
|
||||||
|
ec ← curveSpec
|
||||||
|
keySpec ← nonFatalHandling(new ECPublicKeySpec(ec.getCurve.decodePoint(publicKey), ec))("Cannot read public key.")
|
||||||
keyFactory ← getKeyFactory
|
keyFactory ← getKeyFactory
|
||||||
signProvider ← getSignatureProvider
|
signProvider ← getSignatureProvider
|
||||||
verify ← {
|
verify ← {
|
||||||
@ -108,13 +114,16 @@ class Ecdsa[F[_]](curveType: String, scheme: String)(implicit F: MonadError[F, T
|
|||||||
} yield verify
|
} yield verify
|
||||||
}
|
}
|
||||||
|
|
||||||
private lazy val getKeyPairGenerator =
|
private def curveSpec[F[_]](implicit F: MonadError[F, Throwable]) =
|
||||||
|
nonFatalHandling(ECNamedCurveTable.getParameterSpec(curveType).asInstanceOf[ECParameterSpec])("Cannot get curve parameters.")
|
||||||
|
|
||||||
|
private def getKeyPairGenerator[F[_]](implicit F: MonadError[F, Throwable]) =
|
||||||
nonFatalHandling(KeyPairGenerator.getInstance(ECDSA, BouncyCastleProvider.PROVIDER_NAME))("Cannot get key pair generator.")
|
nonFatalHandling(KeyPairGenerator.getInstance(ECDSA, BouncyCastleProvider.PROVIDER_NAME))("Cannot get key pair generator.")
|
||||||
|
|
||||||
private lazy val getKeyFactory =
|
private def getKeyFactory[F[_]](implicit F: MonadError[F, Throwable]) =
|
||||||
nonFatalHandling(KeyFactory.getInstance(ECDSA, BouncyCastleProvider.PROVIDER_NAME))("Cannot get key factory instance.")
|
nonFatalHandling(KeyFactory.getInstance(ECDSA, BouncyCastleProvider.PROVIDER_NAME))("Cannot get key factory instance.")
|
||||||
|
|
||||||
private lazy val getSignatureProvider =
|
private def getSignatureProvider[F[_]](implicit F: MonadError[F, Throwable]) =
|
||||||
nonFatalHandling(Signature.getInstance(scheme, BouncyCastleProvider.PROVIDER_NAME))("Cannot get signature instance.")
|
nonFatalHandling(Signature.getInstance(scheme, BouncyCastleProvider.PROVIDER_NAME))("Cannot get signature instance.")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,16 +137,4 @@ object Ecdsa {
|
|||||||
* `SHA256withECDSA` Preferably the size of the key is greater than or equal to the digest algorithm
|
* `SHA256withECDSA` Preferably the size of the key is greater than or equal to the digest algorithm
|
||||||
*/
|
*/
|
||||||
def ecdsa_secp256k1_sha256[F[_]](implicit F: MonadError[F, Throwable]) = new Ecdsa("secp256k1", "SHA256withECDSA")
|
def ecdsa_secp256k1_sha256[F[_]](implicit F: MonadError[F, Throwable]) = new Ecdsa("secp256k1", "SHA256withECDSA")
|
||||||
|
|
||||||
class Signer(keyPair: KeyPair) extends fluence.crypto.signature.Signer {
|
|
||||||
override def publicKey: KeyPair.Public = keyPair.publicKey
|
|
||||||
|
|
||||||
override def sign[F[_]](plain: ByteVector)(implicit F: MonadError[F, Throwable]): F[fluence.crypto.signature.Signature] =
|
|
||||||
Ecdsa.ecdsa_secp256k1_sha256.sign(keyPair, plain)
|
|
||||||
}
|
|
||||||
|
|
||||||
case object Checker extends SignatureChecker {
|
|
||||||
override def check[F[_]](signature: fluence.crypto.signature.Signature, plain: ByteVector)(implicit F: MonadError[F, Throwable]): F[Boolean] =
|
|
||||||
Ecdsa.ecdsa_secp256k1_sha256.verify(signature, plain)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -19,9 +19,7 @@ package fluence.crypto.algorithm
|
|||||||
|
|
||||||
import java.security.Security
|
import java.security.Security
|
||||||
|
|
||||||
import fluence.crypto.keypair.KeyPair
|
|
||||||
import org.bouncycastle.jce.provider.BouncyCastleProvider
|
import org.bouncycastle.jce.provider.BouncyCastleProvider
|
||||||
import scodec.bits.ByteVector
|
|
||||||
|
|
||||||
import scala.language.{ higherKinds, implicitConversions }
|
import scala.language.{ higherKinds, implicitConversions }
|
||||||
|
|
||||||
@ -33,15 +31,6 @@ private[crypto] trait JavaAlgorithm extends Algorithm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
object JavaAlgorithm {
|
object JavaAlgorithm {
|
||||||
/**
|
|
||||||
* getEncoded methods return ASN.1 encoding in PKCS#8 standard for secret key and X.509 standard for public
|
|
||||||
* ASN.1 serialization standard defined by ISO. https://en.wikipedia.org/wiki/Abstract_Syntax_Notation_One
|
|
||||||
* PKCS #8 is a standard syntax for storing private key information. https://en.wikipedia.org/wiki/PKCS_8
|
|
||||||
* X.509 is a standard that defines the format of public key certificates. https://en.wikipedia.org/wiki/X.509
|
|
||||||
*/
|
|
||||||
implicit def jKeyPairToKeyPair(jKeyPair: java.security.KeyPair): KeyPair =
|
|
||||||
KeyPair(KeyPair.Public(ByteVector(jKeyPair.getPublic.getEncoded)), KeyPair.Secret(ByteVector(jKeyPair.getPrivate.getEncoded)))
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* add JVM-specific security provider in class loader
|
* add JVM-specific security provider in class loader
|
||||||
*/
|
*/
|
||||||
|
@ -52,37 +52,34 @@ class SignatureSpec extends WordSpec with Matchers with BeforeAndAfterAll {
|
|||||||
}
|
}
|
||||||
|
|
||||||
"correctly work with signer and checker" in {
|
"correctly work with signer and checker" in {
|
||||||
val keys = Ecdsa.ecdsa_secp256k1_sha256.generateKeyPair().get
|
val algo = new SignAlgo(Ecdsa.ecdsa_secp256k1_sha256)
|
||||||
val signer = new Ecdsa.Signer(keys)
|
val keys = algo.generateKeyPair().get
|
||||||
|
val signer = algo.signer(keys)
|
||||||
|
|
||||||
val data = rndByteVector(10)
|
val data = rndByteVector(10)
|
||||||
val sign = signer.sign(data).get
|
val sign = signer.sign(data).get
|
||||||
|
|
||||||
Ecdsa.Checker.check(sign, data).get shouldBe true
|
algo.checker.check(sign, data).get shouldBe true
|
||||||
|
|
||||||
val randomSign = signer.sign(rndByteVector(10)).get
|
val randomSign = signer.sign(rndByteVector(10)).get
|
||||||
Ecdsa.Checker.check(randomSign, data).get shouldBe false
|
algo.checker.check(randomSign, data).get shouldBe false
|
||||||
}
|
}
|
||||||
|
|
||||||
"throw an errors on invalid data" in {
|
"throw an errors on invalid data" in {
|
||||||
val keys = Ecdsa.ecdsa_secp256k1_sha256.generateKeyPair().get
|
val algo = new SignAlgo(Ecdsa.ecdsa_secp256k1_sha256)
|
||||||
val signer = new Ecdsa.Signer(keys)
|
val keys = algo.generateKeyPair().get
|
||||||
|
val signer = algo.signer(keys)
|
||||||
val data = rndByteVector(10)
|
val data = rndByteVector(10)
|
||||||
|
|
||||||
val brokenSecret = keys.copy(secretKey = KeyPair.Secret(rndByteVector(10)))
|
|
||||||
val brokenSigner = new Ecdsa.Signer(brokenSecret)
|
|
||||||
|
|
||||||
the[CryptoErr] thrownBy brokenSigner.sign(data).get
|
|
||||||
|
|
||||||
val sign = signer.sign(data).get
|
val sign = signer.sign(data).get
|
||||||
|
|
||||||
the[CryptoErr] thrownBy Ecdsa.Checker.check(sign.copy(sign = rndByteVector(10)), data).get
|
the[CryptoErr] thrownBy algo.checker.check(sign.copy(sign = rndByteVector(10)), data).get
|
||||||
the[CryptoErr] thrownBy Ecdsa.Checker.check(sign.copy(publicKey = sign.publicKey.copy(value = rndByteVector(10))), data).get
|
the[CryptoErr] thrownBy algo.checker.check(sign.copy(publicKey = sign.publicKey.copy(value = rndByteVector(10))), data).get
|
||||||
}
|
}
|
||||||
|
|
||||||
"store and read key from file" in {
|
"store and read key from file" in {
|
||||||
val seed = rndBytes(32)
|
val algo = new SignAlgo(Ecdsa.ecdsa_secp256k1_sha256)
|
||||||
val keys = Ecdsa.ecdsa_secp256k1_sha256.generateKeyPair(new SecureRandom(seed)).get
|
val keys = algo.generateKeyPair().get
|
||||||
|
|
||||||
val keyFile = File.createTempFile("test", "")
|
val keyFile = File.createTempFile("test", "")
|
||||||
if (keyFile.exists()) keyFile.delete()
|
if (keyFile.exists()) keyFile.delete()
|
||||||
@ -93,12 +90,12 @@ class SignatureSpec extends WordSpec with Matchers with BeforeAndAfterAll {
|
|||||||
val keysReadE = storage.readKeyPair
|
val keysReadE = storage.readKeyPair
|
||||||
val keysRead = keysReadE.get
|
val keysRead = keysReadE.get
|
||||||
|
|
||||||
val signer = new Ecdsa.Signer(keys)
|
val signer = algo.signer(keys)
|
||||||
val data = rndByteVector(10)
|
val data = rndByteVector(10)
|
||||||
val sign = signer.sign(data).get
|
val sign = signer.sign(data).get
|
||||||
|
|
||||||
Ecdsa.Checker.check(sign.copy(publicKey = keysRead.publicKey), data).get shouldBe true
|
algo.checker.check(sign.copy(publicKey = keysRead.publicKey), data).get shouldBe true
|
||||||
Ecdsa.Checker.check(sign, data).get shouldBe true
|
algo.checker.check(sign, data).get shouldBe true
|
||||||
|
|
||||||
//try to store key into previously created file
|
//try to store key into previously created file
|
||||||
storage.storeSecretKey(keys).isFailure shouldBe true
|
storage.storeSecretKey(keys).isFailure shouldBe true
|
||||||
|
@ -29,6 +29,8 @@ import io.circe.syntax._
|
|||||||
import io.circe.{ Decoder, Encoder, HCursor, Json }
|
import io.circe.{ Decoder, Encoder, HCursor, Json }
|
||||||
import scodec.bits.ByteVector
|
import scodec.bits.ByteVector
|
||||||
|
|
||||||
|
import scala.language.higherKinds
|
||||||
|
|
||||||
case class KeyStore(keyPair: KeyPair)
|
case class KeyStore(keyPair: KeyPair)
|
||||||
|
|
||||||
class FileKeyStorage[F[_]](file: File)(implicit F: MonadError[F, Throwable]) {
|
class FileKeyStorage[F[_]](file: File)(implicit F: MonadError[F, Throwable]) {
|
||||||
|
49
src/main/scala/fluence/crypto/SignAlgo.scala
Normal file
49
src/main/scala/fluence/crypto/SignAlgo.scala
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2017 Fluence Labs Limited
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package fluence.crypto
|
||||||
|
|
||||||
|
import java.security.SecureRandom
|
||||||
|
|
||||||
|
import cats.MonadError
|
||||||
|
import fluence.crypto.algorithm.{ DumbSign, KeyGenerator, SignatureFunctions }
|
||||||
|
import fluence.crypto.keypair.KeyPair
|
||||||
|
import fluence.crypto.signature.{ Signature, SignatureChecker, Signer }
|
||||||
|
import scodec.bits.ByteVector
|
||||||
|
|
||||||
|
import scala.language.higherKinds
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class for generation keys, signers and checkers
|
||||||
|
* @param algo implementation of sign alghoritms, e.g. ECDSA
|
||||||
|
*/
|
||||||
|
class SignAlgo(algo: KeyGenerator with SignatureFunctions) {
|
||||||
|
|
||||||
|
def generateKeyPair[F[_]]()(implicit F: MonadError[F, Throwable]): F[KeyPair] = algo.generateKeyPair()
|
||||||
|
def generateKeyPair[F[_]](seed: ByteVector)(implicit F: MonadError[F, Throwable]): F[KeyPair] = algo.generateKeyPair(new SecureRandom(seed.toArray))
|
||||||
|
|
||||||
|
def signer[F[_]](kp: KeyPair)(implicit F: MonadError[F, Throwable]): Signer[F] = new Signer[F] {
|
||||||
|
override def sign(plain: ByteVector): F[Signature] = algo.sign(kp, plain)
|
||||||
|
override def publicKey: KeyPair.Public = kp.publicKey
|
||||||
|
}
|
||||||
|
|
||||||
|
def checker[F[_]](implicit F: MonadError[F, Throwable]): SignatureChecker[F] = (signature: Signature, plain: ByteVector) ⇒ algo.verify(signature, plain)
|
||||||
|
}
|
||||||
|
|
||||||
|
object SignAlgo {
|
||||||
|
val dumb = new SignAlgo(new DumbSign())
|
||||||
|
}
|
24
src/main/scala/fluence/crypto/algorithm/DumbSign.scala
Normal file
24
src/main/scala/fluence/crypto/algorithm/DumbSign.scala
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package fluence.crypto.algorithm
|
||||||
|
|
||||||
|
import java.security.SecureRandom
|
||||||
|
|
||||||
|
import cats.MonadError
|
||||||
|
import fluence.crypto.keypair.KeyPair
|
||||||
|
import fluence.crypto.signature.Signature
|
||||||
|
import scodec.bits.ByteVector
|
||||||
|
|
||||||
|
import scala.language.higherKinds
|
||||||
|
|
||||||
|
class DumbSign extends KeyGenerator with SignatureFunctions {
|
||||||
|
override def generateKeyPair[F[_]](random: SecureRandom)(implicit F: MonadError[F, Throwable]): F[KeyPair] =
|
||||||
|
F.pure(KeyPair.fromBytes(random.generateSeed(10), random.generateSeed(10)))
|
||||||
|
|
||||||
|
override def generateKeyPair[F[_]]()(implicit F: MonadError[F, Throwable]): F[KeyPair] =
|
||||||
|
generateKeyPair(new SecureRandom())
|
||||||
|
|
||||||
|
override def sign[F[_]](keyPair: KeyPair, message: ByteVector)(implicit F: MonadError[F, Throwable]): F[Signature] =
|
||||||
|
F.pure(Signature(keyPair.publicKey, message.reverse))
|
||||||
|
|
||||||
|
override def verify[F[_]](signature: Signature, message: ByteVector)(implicit F: MonadError[F, Throwable]): F[Boolean] =
|
||||||
|
F.pure(signature.sign == message.reverse)
|
||||||
|
}
|
@ -19,11 +19,12 @@ package fluence.crypto.algorithm
|
|||||||
|
|
||||||
import java.security.SecureRandom
|
import java.security.SecureRandom
|
||||||
|
|
||||||
|
import cats.MonadError
|
||||||
import fluence.crypto.keypair.KeyPair
|
import fluence.crypto.keypair.KeyPair
|
||||||
|
|
||||||
import scala.language.higherKinds
|
import scala.language.higherKinds
|
||||||
|
|
||||||
trait KeyGenerator[F[_]] {
|
trait KeyGenerator {
|
||||||
def generateKeyPair(random: SecureRandom): F[KeyPair]
|
def generateKeyPair[F[_]](random: SecureRandom)(implicit F: MonadError[F, Throwable]): F[KeyPair]
|
||||||
def generateKeyPair(): F[KeyPair]
|
def generateKeyPair[F[_]]()(implicit F: MonadError[F, Throwable]): F[KeyPair]
|
||||||
}
|
}
|
||||||
|
@ -17,11 +17,14 @@
|
|||||||
|
|
||||||
package fluence.crypto.algorithm
|
package fluence.crypto.algorithm
|
||||||
|
|
||||||
|
import cats.MonadError
|
||||||
import fluence.crypto.keypair.KeyPair
|
import fluence.crypto.keypair.KeyPair
|
||||||
import fluence.crypto.signature.Signature
|
import fluence.crypto.signature.Signature
|
||||||
import scodec.bits.ByteVector
|
import scodec.bits.ByteVector
|
||||||
|
|
||||||
trait SignatureFunctions[F[_]] {
|
import scala.language.higherKinds
|
||||||
def sign(keyPair: KeyPair, message: ByteVector): F[Signature]
|
|
||||||
def verify(signature: Signature, message: ByteVector): F[Boolean]
|
trait SignatureFunctions {
|
||||||
|
def sign[F[_]](keyPair: KeyPair, message: ByteVector)(implicit F: MonadError[F, Throwable]): F[Signature]
|
||||||
|
def verify[F[_]](signature: Signature, message: ByteVector)(implicit F: MonadError[F, Throwable]): F[Boolean]
|
||||||
}
|
}
|
||||||
|
@ -17,18 +17,10 @@
|
|||||||
|
|
||||||
package fluence.crypto.signature
|
package fluence.crypto.signature
|
||||||
|
|
||||||
import cats.MonadError
|
|
||||||
import scodec.bits.ByteVector
|
import scodec.bits.ByteVector
|
||||||
|
|
||||||
import scala.language.higherKinds
|
import scala.language.higherKinds
|
||||||
|
|
||||||
trait SignatureChecker {
|
trait SignatureChecker[F[_]] {
|
||||||
def check[F[_]](signature: Signature, plain: ByteVector)(implicit F: MonadError[F, Throwable]): F[Boolean]
|
def check(signature: Signature, plain: ByteVector): F[Boolean]
|
||||||
}
|
|
||||||
|
|
||||||
object SignatureChecker {
|
|
||||||
case object DumbChecker extends SignatureChecker {
|
|
||||||
override def check[F[_]](signature: Signature, plain: ByteVector)(implicit F: MonadError[F, Throwable]): F[Boolean] =
|
|
||||||
F.pure(signature.sign == plain.reverse)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -23,17 +23,17 @@ import scodec.bits.ByteVector
|
|||||||
|
|
||||||
import scala.language.higherKinds
|
import scala.language.higherKinds
|
||||||
|
|
||||||
trait Signer {
|
trait Signer[F[_]] {
|
||||||
def publicKey: KeyPair.Public
|
def publicKey: KeyPair.Public
|
||||||
|
|
||||||
def sign[F[_]](plain: ByteVector)(implicit F: MonadError[F, Throwable]): F[Signature]
|
def sign(plain: ByteVector): F[Signature]
|
||||||
}
|
}
|
||||||
|
|
||||||
object Signer {
|
object Signer {
|
||||||
class DumbSigner(keyPair: KeyPair) extends Signer {
|
class DumbSigner[F[_]](keyPair: KeyPair)(implicit F: MonadError[F, Throwable]) extends Signer[F] {
|
||||||
override def publicKey: KeyPair.Public = keyPair.publicKey
|
override def publicKey: KeyPair.Public = keyPair.publicKey
|
||||||
|
|
||||||
override def sign[F[_]](plain: ByteVector)(implicit F: MonadError[F, Throwable]): F[Signature] =
|
override def sign(plain: ByteVector): F[Signature] =
|
||||||
F.pure(Signature(keyPair.publicKey, plain.reverse))
|
F.pure(Signature(keyPair.publicKey, plain.reverse))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user