mirror of
https://github.com/fluencelabs/crypto
synced 2025-05-29 23:01:18 +00:00
Contact jwt (#36)
* EitherT in Crypto * main codebase compiles * tests compiles * crypto tests fixed * Contact test * In Node's codec, check that Kademlia Key conforms Contact's Public Key * b64url alphabet for PK encoding in JWT
This commit is contained in:
parent
73ae64cc6a
commit
17a5930399
@ -1,3 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
object Main {
|
object Main {
|
||||||
def main(args: Array[String]): Unit = {
|
def main(args: Array[String]): Unit = {
|
||||||
println("Hello world!")
|
println("Hello world!")
|
||||||
|
@ -21,7 +21,8 @@ import java.math.BigInteger
|
|||||||
import java.security._
|
import java.security._
|
||||||
import java.security.interfaces.ECPrivateKey
|
import java.security.interfaces.ECPrivateKey
|
||||||
|
|
||||||
import cats.MonadError
|
import cats.data.EitherT
|
||||||
|
import cats.{ Applicative, Monad, 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
|
||||||
@ -42,47 +43,62 @@ import scala.util.control.NonFatal
|
|||||||
class Ecdsa(curveType: String, scheme: String) extends JavaAlgorithm
|
class Ecdsa(curveType: String, scheme: String) extends JavaAlgorithm
|
||||||
with SignatureFunctions with KeyGenerator {
|
with SignatureFunctions with KeyGenerator {
|
||||||
import Ecdsa._
|
import Ecdsa._
|
||||||
private def nonFatalHandling[F[_], A](a: ⇒ A)(errorText: String)(implicit F: MonadError[F, Throwable]): F[A] = {
|
|
||||||
try F.pure(a)
|
private def nonFatalHandling[F[_] : Applicative, A](a: ⇒ A)(errorText: String): EitherT[F, CryptoErr, A] = {
|
||||||
|
try EitherT.pure(a)
|
||||||
catch {
|
catch {
|
||||||
case NonFatal(e) ⇒ F.raiseError(CryptoErr(errorText + " " + e.getLocalizedMessage))
|
case NonFatal(e) ⇒ EitherT.leftT(CryptoErr(errorText + " " + e.getLocalizedMessage))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override def generateKeyPair[F[_]](random: SecureRandom)(implicit F: MonadError[F, Throwable]): F[KeyPair] = {
|
override def generateKeyPair[F[_] : Monad](random: SecureRandom): EitherT[F, CryptoErr, KeyPair] =
|
||||||
for {
|
for {
|
||||||
ecSpecOp ← F.pure(Option(ECNamedCurveTable.getParameterSpec(curveType)))
|
ecSpec ← EitherT.fromOption[F](
|
||||||
ecSpec ← ecSpecOp match {
|
Option(ECNamedCurveTable.getParameterSpec(curveType)),
|
||||||
case Some(ecs) ⇒ F.pure(ecs)
|
CryptoErr("Parameter spec for the curve is not available."))
|
||||||
case None ⇒ F.raiseError[ECNamedCurveParameterSpec](CryptoErr("Parameter spec for the curve is not available."))
|
|
||||||
}
|
|
||||||
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 {
|
p ← EitherT.fromOption(
|
||||||
case Some(p) ⇒
|
Option(g.generateKeyPair()),
|
||||||
|
CryptoErr("Could not generate KeyPair. Unexpected."))
|
||||||
|
|
||||||
|
keyPair ← nonFatalHandling {
|
||||||
//store S number for private key and compressed Q point on curve for public key
|
//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 pk = p.getPublic.asInstanceOf[ECPublicKey].getQ.getEncoded(true)
|
||||||
val sk = p.getPrivate.asInstanceOf[ECPrivateKey].getS.toByteArray
|
val sk = p.getPrivate.asInstanceOf[ECPrivateKey].getS.toByteArray
|
||||||
F.pure(KeyPair.fromBytes(pk, sk))
|
KeyPair.fromBytes(pk, sk)
|
||||||
case None ⇒ F.raiseError[KeyPair](CryptoErr("Could not generate KeyPair. Unexpected."))
|
}("Can't get public/private key from generated keypair")
|
||||||
}
|
|
||||||
} yield keyPair
|
} yield keyPair
|
||||||
}
|
|
||||||
|
|
||||||
override def generateKeyPair[F[_]]()(implicit F: MonadError[F, Throwable]): F[KeyPair] = {
|
override def generateKeyPair[F[_] : Monad](): EitherT[F, CryptoErr, KeyPair] =
|
||||||
generateKeyPair(new SecureRandom())
|
generateKeyPair(new SecureRandom())
|
||||||
}
|
|
||||||
|
|
||||||
override def sign[F[_]](keyPair: KeyPair, message: ByteVector)(implicit F: MonadError[F, Throwable]): F[fluence.crypto.signature.Signature] = {
|
override def sign[F[_] : Monad](keyPair: KeyPair, message: ByteVector): EitherT[F, CryptoErr, 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[F[_] : Monad](signature: fluence.crypto.signature.Signature, message: ByteVector): EitherT[F, CryptoErr, Unit] = {
|
||||||
|
val publicKey = signature.publicKey.value.toArray
|
||||||
|
val messageBytes = message.toArray
|
||||||
|
val signatureBytes = signature.sign.toArray
|
||||||
|
|
||||||
|
for {
|
||||||
|
ec ← curveSpec
|
||||||
|
keySpec ← nonFatalHandling(new ECPublicKeySpec(ec.getCurve.decodePoint(publicKey), ec))("Cannot read public key.")
|
||||||
|
keyFactory ← getKeyFactory
|
||||||
|
signProvider ← getSignatureProvider
|
||||||
|
verify ← {
|
||||||
|
nonFatalHandling {
|
||||||
|
signProvider.initVerify(keyFactory.generatePublic(keySpec))
|
||||||
|
signProvider.update(messageBytes)
|
||||||
|
signProvider.verify(signatureBytes)
|
||||||
|
}("Cannot verify message.")
|
||||||
|
}
|
||||||
|
_ ← EitherT.cond[F](verify, (), CryptoErr("Signature is not verified"))
|
||||||
|
} yield ()
|
||||||
}
|
}
|
||||||
|
|
||||||
override def verify[F[_]](signature: fluence.crypto.signature.Signature, message: ByteVector)(implicit F: MonadError[F, Throwable]): F[Boolean] = {
|
private def signMessage[F[_] : Monad](privateKey: Array[Byte], message: Array[Byte]): EitherT[F, CryptoErr, Array[Byte]] = {
|
||||||
verifySign(signature.publicKey.value.toArray, message.toArray, signature.sign.toArray)
|
|
||||||
}
|
|
||||||
|
|
||||||
private def signMessage[F[_]](privateKey: Array[Byte], message: Array[Byte])(implicit F: MonadError[F, Throwable]): F[Array[Byte]] = {
|
|
||||||
for {
|
for {
|
||||||
ec ← curveSpec
|
ec ← curveSpec
|
||||||
keySpec ← nonFatalHandling(new ECPrivateKeySpec(new BigInteger(privateKey), ec))("Cannot read private key.")
|
keySpec ← nonFatalHandling(new ECPrivateKeySpec(new BigInteger(privateKey), ec))("Cannot read private key.")
|
||||||
@ -98,32 +114,16 @@ class Ecdsa(curveType: String, scheme: String) extends JavaAlgorithm
|
|||||||
} yield sign
|
} yield sign
|
||||||
}
|
}
|
||||||
|
|
||||||
private def verifySign[F[_]](publicKey: Array[Byte], message: Array[Byte], signature: Array[Byte])(implicit F: MonadError[F, Throwable]): F[Boolean] = {
|
private def curveSpec[F[_] : Monad] =
|
||||||
for {
|
|
||||||
ec ← curveSpec
|
|
||||||
keySpec ← nonFatalHandling(new ECPublicKeySpec(ec.getCurve.decodePoint(publicKey), ec))("Cannot read public key.")
|
|
||||||
keyFactory ← getKeyFactory
|
|
||||||
signProvider ← getSignatureProvider
|
|
||||||
verify ← {
|
|
||||||
nonFatalHandling {
|
|
||||||
signProvider.initVerify(keyFactory.generatePublic(keySpec))
|
|
||||||
signProvider.update(message)
|
|
||||||
signProvider.verify(signature)
|
|
||||||
}("Cannot verify message.")
|
|
||||||
}
|
|
||||||
} yield verify
|
|
||||||
}
|
|
||||||
|
|
||||||
private def curveSpec[F[_]](implicit F: MonadError[F, Throwable]) =
|
|
||||||
nonFatalHandling(ECNamedCurveTable.getParameterSpec(curveType).asInstanceOf[ECParameterSpec])("Cannot get curve parameters.")
|
nonFatalHandling(ECNamedCurveTable.getParameterSpec(curveType).asInstanceOf[ECParameterSpec])("Cannot get curve parameters.")
|
||||||
|
|
||||||
private def getKeyPairGenerator[F[_]](implicit F: MonadError[F, Throwable]) =
|
private def getKeyPairGenerator[F[_] : Monad] =
|
||||||
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 def getKeyFactory[F[_]](implicit F: MonadError[F, Throwable]) =
|
private def getKeyFactory[F[_] : Monad] =
|
||||||
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 def getSignatureProvider[F[_]](implicit F: MonadError[F, Throwable]) =
|
private def getSignatureProvider[F[_] : Monad] =
|
||||||
nonFatalHandling(Signature.getInstance(scheme, BouncyCastleProvider.PROVIDER_NAME))("Cannot get signature instance.")
|
nonFatalHandling(Signature.getInstance(scheme, BouncyCastleProvider.PROVIDER_NAME))("Cannot get signature instance.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,68 +18,74 @@
|
|||||||
package fluence.crypto
|
package fluence.crypto
|
||||||
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.security.SecureRandom
|
|
||||||
|
|
||||||
|
import cats.data.EitherT
|
||||||
import cats.instances.try_._
|
import cats.instances.try_._
|
||||||
import fluence.crypto.algorithm.{ CryptoErr, Ecdsa }
|
import fluence.crypto.algorithm.{ CryptoErr, Ecdsa }
|
||||||
import fluence.crypto.keypair.KeyPair
|
|
||||||
import org.scalatest.{ BeforeAndAfterAll, Matchers, WordSpec }
|
import org.scalatest.{ BeforeAndAfterAll, Matchers, WordSpec }
|
||||||
import scodec.bits.ByteVector
|
import scodec.bits.ByteVector
|
||||||
|
|
||||||
import scala.util.Random
|
import scala.util.{ Random, Try }
|
||||||
|
|
||||||
class SignatureSpec extends WordSpec with Matchers with BeforeAndAfterAll {
|
class SignatureSpec extends WordSpec with Matchers with BeforeAndAfterAll {
|
||||||
|
|
||||||
def rndBytes(size: Int) = Random.nextString(10).getBytes
|
def rndBytes(size: Int) = Random.nextString(10).getBytes
|
||||||
|
|
||||||
def rndByteVector(size: Int) = ByteVector(rndBytes(size))
|
def rndByteVector(size: Int) = ByteVector(rndBytes(size))
|
||||||
|
|
||||||
|
private implicit class TryEitherTExtractor[A, B](et: EitherT[Try, A, B]) {
|
||||||
|
def extract: B = et.value.get.right.get
|
||||||
|
|
||||||
|
def isOk: Boolean = et.value.fold(_ ⇒ false, _.isRight)
|
||||||
|
}
|
||||||
|
|
||||||
"ecdsa algorithm" should {
|
"ecdsa algorithm" should {
|
||||||
"correct sign and verify data" in {
|
"correct sign and verify data" in {
|
||||||
val algorithm = Ecdsa.ecdsa_secp256k1_sha256
|
val algorithm = Ecdsa.ecdsa_secp256k1_sha256
|
||||||
|
|
||||||
val keys = algorithm.generateKeyPair().get
|
val keys = algorithm.generateKeyPair[Try]().extract
|
||||||
val data = rndByteVector(10)
|
val data = rndByteVector(10)
|
||||||
val sign = algorithm.sign(keys, data).get
|
val sign = algorithm.sign[Try](keys, data).extract
|
||||||
|
|
||||||
algorithm.verify(sign, data).get shouldBe true
|
algorithm.verify[Try](sign, data).isOk shouldBe true
|
||||||
|
|
||||||
val randomData = rndByteVector(10)
|
val randomData = rndByteVector(10)
|
||||||
val randomSign = algorithm.sign(keys, randomData).get
|
val randomSign = algorithm.sign(keys, randomData).extract
|
||||||
|
|
||||||
algorithm.verify(sign.copy(sign = randomSign.sign), data).get shouldBe false
|
algorithm.verify(sign.copy(sign = randomSign.sign), data).isOk shouldBe false
|
||||||
|
|
||||||
algorithm.verify(sign, randomData).get shouldBe false
|
algorithm.verify(sign, randomData).isOk shouldBe false
|
||||||
}
|
}
|
||||||
|
|
||||||
"correctly work with signer and checker" in {
|
"correctly work with signer and checker" in {
|
||||||
val algo = new SignAlgo(Ecdsa.ecdsa_secp256k1_sha256)
|
val algo = new SignAlgo(Ecdsa.ecdsa_secp256k1_sha256)
|
||||||
val keys = algo.generateKeyPair().get
|
val keys = algo.generateKeyPair().extract
|
||||||
val signer = algo.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).extract
|
||||||
|
|
||||||
algo.checker.check(sign, data).get shouldBe true
|
algo.checker.check(sign, data).isOk shouldBe true
|
||||||
|
|
||||||
val randomSign = signer.sign(rndByteVector(10)).get
|
val randomSign = signer.sign(rndByteVector(10)).extract
|
||||||
algo.checker.check(randomSign, data).get shouldBe false
|
algo.checker.check(randomSign, data).isOk shouldBe false
|
||||||
}
|
}
|
||||||
|
|
||||||
"throw an errors on invalid data" in {
|
"throw an errors on invalid data" in {
|
||||||
val algo = new SignAlgo(Ecdsa.ecdsa_secp256k1_sha256)
|
val algo = new SignAlgo(Ecdsa.ecdsa_secp256k1_sha256)
|
||||||
val keys = algo.generateKeyPair().get
|
val keys = algo.generateKeyPair().extract
|
||||||
val signer = algo.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).extract
|
||||||
|
|
||||||
the[CryptoErr] thrownBy algo.checker.check(sign.copy(sign = rndByteVector(10)), data).get
|
the[CryptoErr] thrownBy algo.checker.check(sign.copy(sign = rndByteVector(10)), data).value.flatMap(_.toTry).get
|
||||||
the[CryptoErr] thrownBy algo.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).value.flatMap(_.toTry).get
|
||||||
}
|
}
|
||||||
|
|
||||||
"store and read key from file" in {
|
"store and read key from file" in {
|
||||||
val algo = new SignAlgo(Ecdsa.ecdsa_secp256k1_sha256)
|
val algo = new SignAlgo(Ecdsa.ecdsa_secp256k1_sha256)
|
||||||
val keys = algo.generateKeyPair().get
|
val keys = algo.generateKeyPair().extract
|
||||||
|
|
||||||
val keyFile = File.createTempFile("test", "")
|
val keyFile = File.createTempFile("test", "")
|
||||||
if (keyFile.exists()) keyFile.delete()
|
if (keyFile.exists()) keyFile.delete()
|
||||||
@ -92,10 +98,10 @@ class SignatureSpec extends WordSpec with Matchers with BeforeAndAfterAll {
|
|||||||
|
|
||||||
val signer = algo.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).extract
|
||||||
|
|
||||||
algo.checker.check(sign.copy(publicKey = keysRead.publicKey), data).get shouldBe true
|
algo.checker.check(sign.copy(publicKey = keysRead.publicKey), data).isOk shouldBe true
|
||||||
algo.checker.check(sign, data).get shouldBe true
|
algo.checker.check(sign, data).isOk 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
|
||||||
|
@ -19,8 +19,9 @@ package fluence.crypto
|
|||||||
|
|
||||||
import java.security.SecureRandom
|
import java.security.SecureRandom
|
||||||
|
|
||||||
import cats.MonadError
|
import cats.data.EitherT
|
||||||
import fluence.crypto.algorithm.{ DumbSign, KeyGenerator, SignatureFunctions }
|
import cats.{ Monad, MonadError }
|
||||||
|
import fluence.crypto.algorithm.{ CryptoErr, DumbSign, KeyGenerator, SignatureFunctions }
|
||||||
import fluence.crypto.keypair.KeyPair
|
import fluence.crypto.keypair.KeyPair
|
||||||
import fluence.crypto.signature.{ Signature, SignatureChecker, Signer }
|
import fluence.crypto.signature.{ Signature, SignatureChecker, Signer }
|
||||||
import scodec.bits.ByteVector
|
import scodec.bits.ByteVector
|
||||||
@ -33,15 +34,17 @@ import scala.language.higherKinds
|
|||||||
*/
|
*/
|
||||||
class SignAlgo(algo: KeyGenerator with SignatureFunctions) {
|
class SignAlgo(algo: KeyGenerator with SignatureFunctions) {
|
||||||
|
|
||||||
def generateKeyPair[F[_]]()(implicit F: MonadError[F, Throwable]): F[KeyPair] = algo.generateKeyPair()
|
def generateKeyPair[F[_] : Monad](): EitherT[F, CryptoErr, KeyPair] = algo.generateKeyPair()
|
||||||
def generateKeyPair[F[_]](seed: ByteVector)(implicit F: MonadError[F, Throwable]): F[KeyPair] = algo.generateKeyPair(new SecureRandom(seed.toArray))
|
def generateKeyPair[F[_] : Monad](seed: ByteVector): EitherT[F, CryptoErr, KeyPair] = algo.generateKeyPair(new SecureRandom(seed.toArray))
|
||||||
|
|
||||||
def signer[F[_]](kp: KeyPair)(implicit F: MonadError[F, Throwable]): Signer[F] = new Signer[F] {
|
def signer(kp: KeyPair): Signer = new Signer {
|
||||||
override def sign(plain: ByteVector): F[Signature] = algo.sign(kp, plain)
|
|
||||||
override def publicKey: KeyPair.Public = kp.publicKey
|
override def publicKey: KeyPair.Public = kp.publicKey
|
||||||
|
override def sign[F[_] : Monad](plain: ByteVector): EitherT[F, CryptoErr, Signature] = algo.sign(kp, plain)
|
||||||
}
|
}
|
||||||
|
|
||||||
def checker[F[_]](implicit F: MonadError[F, Throwable]): SignatureChecker[F] = (signature: Signature, plain: ByteVector) ⇒ algo.verify(signature, plain)
|
def checker: SignatureChecker = new SignatureChecker {
|
||||||
|
override def check[F[_] : Monad](signature: Signature, plain: ByteVector): EitherT[F, CryptoErr, Unit] = algo.verify(signature, plain)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object SignAlgo {
|
object SignAlgo {
|
||||||
|
@ -1,8 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* 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.algorithm
|
package fluence.crypto.algorithm
|
||||||
|
|
||||||
import java.security.SecureRandom
|
import java.security.SecureRandom
|
||||||
|
|
||||||
import cats.MonadError
|
import cats.Monad
|
||||||
|
import cats.data.EitherT
|
||||||
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
|
||||||
@ -10,15 +28,15 @@ import scodec.bits.ByteVector
|
|||||||
import scala.language.higherKinds
|
import scala.language.higherKinds
|
||||||
|
|
||||||
class DumbSign extends KeyGenerator with SignatureFunctions {
|
class DumbSign extends KeyGenerator with SignatureFunctions {
|
||||||
override def generateKeyPair[F[_]](random: SecureRandom)(implicit F: MonadError[F, Throwable]): F[KeyPair] =
|
override def generateKeyPair[F[_] : Monad](random: SecureRandom): EitherT[F, CryptoErr, KeyPair] =
|
||||||
F.pure(KeyPair.fromBytes(random.generateSeed(10), random.generateSeed(10)))
|
EitherT.pure(KeyPair.fromBytes(random.generateSeed(10), random.generateSeed(10)))
|
||||||
|
|
||||||
override def generateKeyPair[F[_]]()(implicit F: MonadError[F, Throwable]): F[KeyPair] =
|
override def generateKeyPair[F[_] : Monad](): EitherT[F, CryptoErr, KeyPair] =
|
||||||
generateKeyPair(new SecureRandom())
|
generateKeyPair(new SecureRandom())
|
||||||
|
|
||||||
override def sign[F[_]](keyPair: KeyPair, message: ByteVector)(implicit F: MonadError[F, Throwable]): F[Signature] =
|
override def sign[F[_] : Monad](keyPair: KeyPair, message: ByteVector): EitherT[F, CryptoErr, Signature] =
|
||||||
F.pure(Signature(keyPair.publicKey, message.reverse))
|
EitherT.pure(Signature(keyPair.publicKey, message.reverse))
|
||||||
|
|
||||||
override def verify[F[_]](signature: Signature, message: ByteVector)(implicit F: MonadError[F, Throwable]): F[Boolean] =
|
override def verify[F[_] : Monad](signature: Signature, message: ByteVector): EitherT[F, CryptoErr, Unit] =
|
||||||
F.pure(signature.sign == message.reverse)
|
EitherT.cond[F](signature.sign == message.reverse, (), CryptoErr("Invalid Signature"))
|
||||||
}
|
}
|
||||||
|
@ -19,12 +19,14 @@ package fluence.crypto.algorithm
|
|||||||
|
|
||||||
import java.security.SecureRandom
|
import java.security.SecureRandom
|
||||||
|
|
||||||
import cats.MonadError
|
import cats.Monad
|
||||||
|
import cats.data.EitherT
|
||||||
import fluence.crypto.keypair.KeyPair
|
import fluence.crypto.keypair.KeyPair
|
||||||
|
|
||||||
import scala.language.higherKinds
|
import scala.language.higherKinds
|
||||||
|
|
||||||
trait KeyGenerator {
|
trait KeyGenerator {
|
||||||
def generateKeyPair[F[_]](random: SecureRandom)(implicit F: MonadError[F, Throwable]): F[KeyPair]
|
def generateKeyPair[F[_] : Monad](random: SecureRandom): EitherT[F, CryptoErr, KeyPair]
|
||||||
def generateKeyPair[F[_]]()(implicit F: MonadError[F, Throwable]): F[KeyPair]
|
|
||||||
|
def generateKeyPair[F[_] : Monad](): EitherT[F, CryptoErr, KeyPair]
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,8 @@
|
|||||||
|
|
||||||
package fluence.crypto.algorithm
|
package fluence.crypto.algorithm
|
||||||
|
|
||||||
import cats.MonadError
|
import cats.Monad
|
||||||
|
import cats.data.EitherT
|
||||||
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
|
||||||
@ -25,6 +26,7 @@ import scodec.bits.ByteVector
|
|||||||
import scala.language.higherKinds
|
import scala.language.higherKinds
|
||||||
|
|
||||||
trait SignatureFunctions {
|
trait SignatureFunctions {
|
||||||
def sign[F[_]](keyPair: KeyPair, message: ByteVector)(implicit F: MonadError[F, Throwable]): F[Signature]
|
def sign[F[_] : Monad](keyPair: KeyPair, message: ByteVector): EitherT[F, CryptoErr, Signature]
|
||||||
def verify[F[_]](signature: Signature, message: ByteVector)(implicit F: MonadError[F, Throwable]): F[Boolean]
|
|
||||||
|
def verify[F[_] : Monad](signature: Signature, message: ByteVector): EitherT[F, CryptoErr, Unit]
|
||||||
}
|
}
|
||||||
|
@ -17,10 +17,13 @@
|
|||||||
|
|
||||||
package fluence.crypto.signature
|
package fluence.crypto.signature
|
||||||
|
|
||||||
|
import cats.Monad
|
||||||
|
import cats.data.EitherT
|
||||||
|
import fluence.crypto.algorithm.CryptoErr
|
||||||
import scodec.bits.ByteVector
|
import scodec.bits.ByteVector
|
||||||
|
|
||||||
import scala.language.higherKinds
|
import scala.language.higherKinds
|
||||||
|
|
||||||
trait SignatureChecker[F[_]] {
|
trait SignatureChecker {
|
||||||
def check(signature: Signature, plain: ByteVector): F[Boolean]
|
def check[F[_] : Monad](signature: Signature, plain: ByteVector): EitherT[F, CryptoErr, Unit]
|
||||||
}
|
}
|
||||||
|
@ -17,23 +17,27 @@
|
|||||||
|
|
||||||
package fluence.crypto.signature
|
package fluence.crypto.signature
|
||||||
|
|
||||||
import cats.MonadError
|
import cats.Monad
|
||||||
|
import cats.data.EitherT
|
||||||
|
import fluence.crypto.algorithm.CryptoErr
|
||||||
import fluence.crypto.keypair.KeyPair
|
import fluence.crypto.keypair.KeyPair
|
||||||
import scodec.bits.ByteVector
|
import scodec.bits.ByteVector
|
||||||
|
|
||||||
import scala.language.higherKinds
|
import scala.language.higherKinds
|
||||||
|
|
||||||
trait Signer[F[_]] {
|
trait Signer {
|
||||||
def publicKey: KeyPair.Public
|
def publicKey: KeyPair.Public
|
||||||
|
|
||||||
def sign(plain: ByteVector): F[Signature]
|
def sign[F[_] : Monad](plain: ByteVector): EitherT[F, CryptoErr, Signature]
|
||||||
}
|
}
|
||||||
|
|
||||||
object Signer {
|
object Signer {
|
||||||
class DumbSigner[F[_]](keyPair: KeyPair)(implicit F: MonadError[F, Throwable]) extends Signer[F] {
|
|
||||||
|
class DumbSigner(keyPair: KeyPair) extends Signer {
|
||||||
override def publicKey: KeyPair.Public = keyPair.publicKey
|
override def publicKey: KeyPair.Public = keyPair.publicKey
|
||||||
|
|
||||||
override def sign(plain: ByteVector): F[Signature] =
|
override def sign[F[_] : Monad](plain: ByteVector): EitherT[F, CryptoErr, Signature] =
|
||||||
F.pure(Signature(keyPair.publicKey, plain.reverse))
|
EitherT.pure(Signature(keyPair.publicKey, plain.reverse))
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user