From 69d3eb50c152e521dc296b0b8b1285ed25519d6a Mon Sep 17 00:00:00 2001 From: Constantine Solovev Date: Thu, 29 Mar 2018 16:06:34 +0400 Subject: [PATCH] Sign merkle root part2 (#100) * client send signed versnio+merkleRoot * fix b-tree-client js compilation * change SignatureVerifier method notation add publish client signature from node * fix test * make integration test green again * fix test * fix test * move contract validation from 'Codec' to 'ContractValidate' * improve MerkleBTreeClientSpec * little changes * move 'contract-core' tests from 'jvm' area` to crossplatform area * review * review --- .../test/scala/fluence/crypto/EcdsaSpec.scala | 14 ++++++---- .../scala/fluence/crypto/SignatureSpec.scala | 26 +++++++++++-------- src/main/scala/fluence/crypto/SignAlgo.scala | 17 +++++++++--- .../fluence/crypto/signature/Signature.scala | 1 + .../crypto/signature/SignatureChecker.scala | 2 +- 5 files changed, 39 insertions(+), 21 deletions(-) diff --git a/js/src/test/scala/fluence/crypto/EcdsaSpec.scala b/js/src/test/scala/fluence/crypto/EcdsaSpec.scala index 9ade135..d866c12 100644 --- a/js/src/test/scala/fluence/crypto/EcdsaSpec.scala +++ b/js/src/test/scala/fluence/crypto/EcdsaSpec.scala @@ -20,6 +20,7 @@ package fluence.crypto import cats.data.EitherT import cats.instances.try_._ import fluence.crypto.algorithm.{CryptoErr, Ecdsa} +import fluence.crypto.keypair.KeyPair import org.scalatest.{Matchers, WordSpec} import scodec.bits.ByteVector @@ -64,27 +65,30 @@ class EcdsaSpec extends WordSpec with Matchers { val algo = Ecdsa.signAlgo val keys = algo.generateKeyPair().extract val signer = algo.signer(keys) + val checker = algo.checker(keys.publicKey) val data = rndByteVector(10) val sign = signer.sign(data).extract - algo.checker.check(sign, data).isOk shouldBe true + checker.check(sign.sign, data).isOk shouldBe true val randomSign = signer.sign(rndByteVector(10)).extract - algo.checker.check(randomSign, data).isOk shouldBe false + checker.check(randomSign.sign, data).isOk shouldBe false } "throw an errors on invalid data" in { val algo = Ecdsa.signAlgo val keys = algo.generateKeyPair().extract val signer = algo.signer(keys) + val checker = algo.checker(keys.publicKey) val data = rndByteVector(10) val sign = signer.sign(data).extract - 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) + the[CryptoErr] thrownBy checker.check(rndByteVector(10), data).value.flatMap(_.toTry).get + val invalidChecker = algo.checker(KeyPair.fromByteVectors(rndByteVector(10), rndByteVector(10)).publicKey) + the[CryptoErr] thrownBy invalidChecker + .check(sign.sign, data) .value .flatMap(_.toTry) .get diff --git a/jvm/src/test/scala/fluence/crypto/SignatureSpec.scala b/jvm/src/test/scala/fluence/crypto/SignatureSpec.scala index 6ae32e1..a34e5e6 100644 --- a/jvm/src/test/scala/fluence/crypto/SignatureSpec.scala +++ b/jvm/src/test/scala/fluence/crypto/SignatureSpec.scala @@ -22,6 +22,7 @@ import java.io.File import cats.data.EitherT import cats.instances.try_._ import fluence.crypto.algorithm.{CryptoErr, Ecdsa} +import fluence.crypto.keypair.KeyPair import org.scalatest.{Matchers, WordSpec} import scodec.bits.ByteVector @@ -66,30 +67,33 @@ class SignatureSpec extends WordSpec with Matchers { val algo = Ecdsa.signAlgo val keys = algo.generateKeyPair().extract val signer = algo.signer(keys) + val checker = algo.checker(keys.publicKey) val data = rndByteVector(10) - val sign = signer.sign(data).extract + val sign = signer.sign(data).extract.sign - algo.checker.check(sign, data).isOk shouldBe true + checker.check(sign, data).isOk shouldBe true - val randomSign = signer.sign(rndByteVector(10)).extract - algo.checker.check(randomSign, data).isOk shouldBe false + val randomSign = signer.sign(rndByteVector(10)).extract.sign + checker.check(randomSign, data).isOk shouldBe false } "throw an errors on invalid data" in { val algo = Ecdsa.signAlgo val keys = algo.generateKeyPair().extract val signer = algo.signer(keys) + val checker = algo.checker(keys.publicKey) val data = rndByteVector(10) - val sign = signer.sign(data).extract + val sign = signer.sign(data).extract.sign the[CryptoErr] thrownBy { - algo.checker.check(sign.copy(sign = rndByteVector(10)), data).value.flatMap(_.toTry).get + checker.check(rndByteVector(10), data).value.flatMap(_.toTry).get } + val invalidChecker = algo.checker(KeyPair.fromByteVectors(rndByteVector(10), rndByteVector(10)).publicKey) the[CryptoErr] thrownBy { - algo.checker - .check(sign.copy(publicKey = sign.publicKey.copy(value = rndByteVector(10))), data) + invalidChecker + .check(sign, data) .value .flatMap(_.toTry) .get @@ -111,10 +115,10 @@ class SignatureSpec extends WordSpec with Matchers { val signer = algo.signer(keys) val data = rndByteVector(10) - val sign = signer.sign(data).extract + val sign = signer.sign(data).extract.sign - algo.checker.check(sign.copy(publicKey = keysRead.publicKey), data).isOk shouldBe true - algo.checker.check(sign, data).isOk shouldBe true + algo.checker(keys.publicKey).check(sign, data).isOk shouldBe true + algo.checker(keysRead.publicKey).check(sign, data).isOk shouldBe true //try to store key into previously created file storage.storeSecretKey(keys).isFailure shouldBe true diff --git a/src/main/scala/fluence/crypto/SignAlgo.scala b/src/main/scala/fluence/crypto/SignAlgo.scala index 7ea15b4..a8c3728 100644 --- a/src/main/scala/fluence/crypto/SignAlgo.scala +++ b/src/main/scala/fluence/crypto/SignAlgo.scala @@ -19,6 +19,7 @@ package fluence.crypto import cats.Monad import cats.data.EitherT +import fluence.crypto.SignAlgo.CheckerFn import fluence.crypto.algorithm.{CryptoErr, DumbSign, KeyGenerator, SignatureFunctions} import fluence.crypto.keypair.KeyPair import fluence.crypto.signature.{Signature, SignatureChecker, Signer} @@ -49,18 +50,26 @@ class SignAlgo(name: String, algo: KeyGenerator with SignatureFunctions) { } /** - * Checker is single for each algo, and does not contain any state + * Checker is specific for public key + * @param publicKey Public key of signature maker + * @return */ - implicit val checker: SignatureChecker = new SignatureChecker { - override def check[F[_]: Monad](signature: Signature, plain: ByteVector): EitherT[F, CryptoErr, Unit] = - algo.verify(signature, plain) + def checker(publicKey: KeyPair.Public): SignatureChecker = new SignatureChecker { + override def check[F[_]: Monad](signature: ByteVector, plain: ByteVector): EitherT[F, CryptoErr, Unit] = + algo.verify(Signature(publicKey, signature), plain) override def toString: String = s"SignatureChecker($name)" } + /** Fn for creating checker for specified public key */ + implicit val checkerFn: CheckerFn = pubKey ⇒ checker(pubKey) + override def toString: String = s"SignAlgo($name)" } object SignAlgo { + + type CheckerFn = KeyPair.Public ⇒ SignatureChecker + val dumb = new SignAlgo("dumb", new DumbSign()) } diff --git a/src/main/scala/fluence/crypto/signature/Signature.scala b/src/main/scala/fluence/crypto/signature/Signature.scala index fb1f65e..559deee 100644 --- a/src/main/scala/fluence/crypto/signature/Signature.scala +++ b/src/main/scala/fluence/crypto/signature/Signature.scala @@ -20,4 +20,5 @@ package fluence.crypto.signature import fluence.crypto.keypair.KeyPair import scodec.bits.ByteVector +// todo remove PubKey from signature case class Signature(publicKey: KeyPair.Public, sign: ByteVector) diff --git a/src/main/scala/fluence/crypto/signature/SignatureChecker.scala b/src/main/scala/fluence/crypto/signature/SignatureChecker.scala index 53971a8..60fb2cd 100644 --- a/src/main/scala/fluence/crypto/signature/SignatureChecker.scala +++ b/src/main/scala/fluence/crypto/signature/SignatureChecker.scala @@ -25,5 +25,5 @@ import scodec.bits.ByteVector import scala.language.higherKinds trait SignatureChecker { - def check[F[_]: Monad](signature: Signature, plain: ByteVector): EitherT[F, CryptoErr, Unit] + def check[F[_]: Monad](signature: ByteVector, plain: ByteVector): EitherT[F, CryptoErr, Unit] }