Ecdsa for scalajs (#37)

* 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

* finally js crypto === java crypto

* facade for hash, EcdsaJS implementation, rewrite crypto logic to hex for cross-platform compatibility

* clean branch

* delete Main, add headers

* merge master

* small fixes

* todo

* refactoring, comments

* alphabet

* merge master

* fix tests

* fix PR comments

* fix PR comments
This commit is contained in:
Dima 2018-02-13 17:59:17 +03:00 committed by GitHub
parent 17a5930399
commit d182a92e98
12 changed files with 397 additions and 96 deletions

View File

@ -0,0 +1,86 @@
/*
* 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
import cats.data.EitherT
import cats.{ Monad, MonadError }
import fluence.crypto.facade.EC
import fluence.crypto.hash.{ CryptoHasher, JsCryptoHasher }
import fluence.crypto.keypair.KeyPair
import fluence.crypto.signature.Signature
import scodec.bits.ByteVector
import scala.language.higherKinds
import scala.scalajs.js
import scala.scalajs.js.JSConverters._
/**
* Return in all js methods hex, because in the other case we will receive javascript objects
* @param ec implementation of ecdsa logic for different curves
*/
class EcdsaJS(ec: EC, hasher: Option[CryptoHasher[Array[Byte], Array[Byte]]]) extends Algorithm with SignatureFunctions with KeyGenerator {
import CryptoErr._
override def generateKeyPair[F[_] : Monad](seed: Option[Array[Byte]] = None): EitherT[F, CryptoErr, KeyPair] = {
nonFatalHandling {
val seedJs = seed.map(bs js.Dynamic.literal(entropy = bs.toJSArray))
val key = ec.genKeyPair(seedJs)
val publicHex = key.getPublic(true, "hex")
val secretHex = key.getPrivate("hex")
val public = ByteVector.fromValidHex(publicHex)
val secret = ByteVector.fromValidHex(secretHex)
KeyPair.fromByteVectors(public, secret)
} ("Failed to generate key pair.")
}
override def sign[F[_] : Monad](keyPair: KeyPair, message: ByteVector): EitherT[F, CryptoErr, Signature] = {
for {
secret nonFatalHandling{
ec.keyFromPrivate(keyPair.secretKey.value.toHex, "hex")
}("Cannot get private key from key pair.")
hash hash(message)
signHex nonFatalHandling(secret.sign(hash).toDER("hex"))("Cannot sign message")
} yield Signature(keyPair.publicKey, ByteVector.fromValidHex(signHex))
}
def hash[F[_] : Monad](message: ByteVector): EitherT[F, CryptoErr, js.Array[Byte]] = {
val arr = message.toArray
hasher.fold(EitherT.pure[F, CryptoErr](arr)) { h
nonFatalHandling {
h.hash(message.toArray)
}("Cannot hash message.")
}.map(_.toJSArray)
}
override def verify[F[_] : Monad](signature: Signature, message: ByteVector): EitherT[F, CryptoErr, Unit] = {
for {
public nonFatalHandling{
val hex = signature.publicKey.value.toHex
ec.keyFromPublic(hex, "hex")
}("Incorrect public key format.")
hash hash(message)
verify nonFatalHandling(public.verify(hash, signature.sign.toHex))("Cannot verify message.")
_ EitherT.cond[F](verify, (), CryptoErr("Signature is not verified"))
} yield ()
}
}
object EcdsaJS {
def ecdsa_secp256k1_sha256 = new EcdsaJS(new EC("secp256k1"), Some(JsCryptoHasher.Sha256))
}

View File

@ -0,0 +1,52 @@
/*
* 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.facade
import scala.scalajs.js
import scala.scalajs.js.annotation._
//TODO hide enc argument in methods, make it `hex` by default
/**
* https://github.com/indutny/elliptic - fast elliptic-curve cryptography in a plain javascript implementation
*/
@js.native
@JSImport("elliptic", "ec")
class EC(curve: String) extends js.Object {
def genKeyPair(options: Option[js.Dynamic] = None): KeyPair = js.native
def keyPair(options: js.Dynamic): KeyPair = js.native
def keyFromPublic(pub: String, enc: String): KeyPair = js.native
def keyFromPrivate(priv: String, enc: String): KeyPair = js.native
}
@js.native
@JSImport("elliptic", "ec")
class KeyPair(ec: EC, options: js.Dynamic) extends js.Object {
def verify(msg: js.Array[Byte], signature: String): Boolean = js.native
def sign(msg: js.Array[Byte]): Signature = js.native
def getPublic(compact: Boolean, enc: String): String = js.native
def getPrivate(enc: String): String = js.native
val priv: js.Any = js.native
val pub: js.Any = js.native
}
@js.native
@JSImport("elliptic", "ec")
class Signature(der: String, enc: String = "hex") extends js.Object {
def toDER(enc: String): String = js.native
}

View File

@ -15,8 +15,18 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
object Main {
def main(args: Array[String]): Unit = {
println("Hello world!")
}
package fluence.crypto.facade
import scala.scalajs.js
import scala.scalajs.js.annotation.JSImport
//TODO hide enc argument in methods, make it `hex` by default
/**
* https://github.com/indutny/hash.js - part of elliptic library
*/
@js.native
@JSImport("hash.js", "sha256")
class SHA256() extends js.Object {
def update(msg: js.Array[Byte]): Unit = js.native
def digest(enc: String): String = js.native
}

View File

@ -0,0 +1,40 @@
/*
* 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.hash
import fluence.crypto.facade.SHA256
import scodec.bits.ByteVector
import scala.scalajs.js.JSConverters._
object JsCryptoHasher {
lazy val Sha256: CryptoHasher[Array[Byte], Array[Byte]] = new CryptoHasher[Array[Byte], Array[Byte]] {
override def hash(msg1: Array[Byte]): Array[Byte] = {
val sha256 = new SHA256()
sha256.update(msg1.toJSArray)
ByteVector.fromValidHex(sha256.digest("hex")).toArray
}
override def hash(msg1: Array[Byte], msg2: Array[Byte]*): Array[Byte] = {
hash(msg1 ++ msg2.flatten)
}
}
}

View File

@ -0,0 +1,83 @@
/*
* 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 cats.data.EitherT
import cats.instances.try_._
import fluence.crypto.algorithm.{ CryptoErr, EcdsaJS }
import org.scalatest.{ BeforeAndAfterAll, Matchers, WordSpec }
import scodec.bits.ByteVector
import scala.util.{ Random, Try }
class EcdsaJSSpec extends WordSpec with Matchers with BeforeAndAfterAll {
def rndBytes(size: Int) = Random.nextString(10).getBytes
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 {
"correct sign and verify data" in {
val algorithm = EcdsaJS.ecdsa_secp256k1_sha256
val keys = algorithm.generateKeyPair[Try]().extract
val data = rndByteVector(10)
val sign = algorithm.sign[Try](keys, data).extract
algorithm.verify[Try](sign, data).isOk shouldBe true
val randomData = rndByteVector(10)
val randomSign = algorithm.sign(keys, randomData).extract
algorithm.verify(sign.copy(sign = randomSign.sign), data).isOk shouldBe false
algorithm.verify(sign, randomData).isOk shouldBe false
}
"correctly work with signer and checker" in {
val algo = new SignAlgo(EcdsaJS.ecdsa_secp256k1_sha256)
val keys = algo.generateKeyPair().extract
val signer = algo.signer(keys)
val data = rndByteVector(10)
val sign = signer.sign(data).extract
algo.checker.check(sign, data).isOk shouldBe true
val randomSign = signer.sign(rndByteVector(10)).extract
algo.checker.check(randomSign, data).isOk shouldBe false
}
"throw an errors on invalid data" in {
val algo = new SignAlgo(EcdsaJS.ecdsa_secp256k1_sha256)
val keys = algo.generateKeyPair().extract
val signer = algo.signer(keys)
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).value.flatMap(_.toTry).get
}
}
}

View File

@ -26,13 +26,9 @@ import cats.syntax.functor._
import fluence.crypto.keypair.KeyPair
import io.circe.parser.decode
import io.circe.syntax._
import io.circe.{ Decoder, Encoder, HCursor, Json }
import scodec.bits.ByteVector
import scala.language.higherKinds
case class KeyStore(keyPair: KeyPair)
class FileKeyStorage[F[_]](file: File)(implicit F: MonadError[F, Throwable]) {
import KeyStore._
def readKeyPair: F[KeyPair] = {
@ -64,24 +60,3 @@ class FileKeyStorage[F[_]](file: File)(implicit F: MonadError[F, Throwable]) {
} yield newKeys
}
}
object KeyStore {
implicit val encodeKeyStorage: Encoder[KeyStore] = new Encoder[KeyStore] {
final def apply(ks: KeyStore): Json = Json.obj(("keystore", Json.obj(
("secret", Json.fromString(ks.keyPair.secretKey.value.toBase64)),
("public", Json.fromString(ks.keyPair.publicKey.value.toBase64)))))
}
implicit val decodeKeyStorage: Decoder[Option[KeyStore]] = new Decoder[Option[KeyStore]] {
final def apply(c: HCursor): Decoder.Result[Option[KeyStore]] =
for {
secret c.downField("keystore").downField("secret").as[String]
public c.downField("keystore").downField("public").as[String]
} yield {
for {
secret ByteVector.fromBase64(secret)
public ByteVector.fromBase64(public)
} yield KeyStore(KeyPair.fromByteVectors(public, secret))
}
}
}

View File

@ -22,66 +22,73 @@ import java.security._
import java.security.interfaces.ECPrivateKey
import cats.data.EitherT
import cats.{ Applicative, Monad, MonadError }
import cats.syntax.flatMap._
import cats.syntax.functor._
import cats.Monad
import fluence.crypto.hash.{ CryptoHasher, JdkCryptoHasher }
import fluence.crypto.keypair.KeyPair
import org.bouncycastle.jce.ECNamedCurveTable
import org.bouncycastle.jce.interfaces.ECPublicKey
import org.bouncycastle.jce.provider.BouncyCastleProvider
import org.bouncycastle.jce.spec.{ ECNamedCurveParameterSpec, ECParameterSpec, ECPrivateKeySpec, ECPublicKeySpec }
import org.bouncycastle.jce.spec.{ ECParameterSpec, ECPrivateKeySpec, ECPublicKeySpec }
import scodec.bits.ByteVector
import scala.language.higherKinds
import scala.util.control.NonFatal
/**
* Elliptic Curve Digital Signature Algorithm
* @param curveType http://www.bouncycastle.org/wiki/display/JA1/Supported+Curves+%28ECDSA+and+ECGOST%29
* @param scheme https://bouncycastle.org/specifications.html
*/
class Ecdsa(curveType: String, scheme: String) extends JavaAlgorithm
class Ecdsa(curveType: String, scheme: String, hasher: Option[CryptoHasher[Array[Byte], Array[Byte]]]) extends JavaAlgorithm
with SignatureFunctions with KeyGenerator {
import CryptoErr._
import Ecdsa._
private def nonFatalHandling[F[_] : Applicative, A](a: A)(errorText: String): EitherT[F, CryptoErr, A] = {
try EitherT.pure(a)
catch {
case NonFatal(e) EitherT.leftT(CryptoErr(errorText + " " + e.getLocalizedMessage))
}
}
val HEXradix = 16
override def generateKeyPair[F[_] : Monad](random: SecureRandom): EitherT[F, CryptoErr, KeyPair] =
override def generateKeyPair[F[_] : Monad](seed: Option[Array[Byte]]): EitherT[F, CryptoErr, KeyPair] = {
for {
ecSpec EitherT.fromOption[F](
Option(ECNamedCurveTable.getParameterSpec(curveType)),
CryptoErr("Parameter spec for the curve is not available."))
ecSpec EitherT.fromOption(Option(ECNamedCurveTable.getParameterSpec(curveType)), CryptoErr("Parameter spec for the curve is not available."))
g getKeyPairGenerator
_ nonFatalHandling(g.initialize(ecSpec, random))("Could not initialize KeyPairGenerator.")
_ nonFatalHandling(g.initialize(ecSpec, seed.map(new SecureRandom(_)).getOrElse(new SecureRandom())))("Could not initialize KeyPairGenerator.")
p EitherT.fromOption(
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
val pk = p.getPublic.asInstanceOf[ECPublicKey].getQ.getEncoded(true)
val sk = p.getPrivate.asInstanceOf[ECPrivateKey].getS.toByteArray
KeyPair.fromBytes(pk, sk)
}("Can't get public/private key from generated keypair")
val pk = ByteVector(p.getPublic.asInstanceOf[ECPublicKey].getQ.getEncoded(true))
val bg = p.getPrivate.asInstanceOf[ECPrivateKey].getS
val sk = ByteVector.fromValidHex(bg.toString(HEXradix))
KeyPair.fromByteVectors(pk, sk)
}("Could not generate KeyPair. Unexpected.")
} yield keyPair
}
override def generateKeyPair[F[_] : Monad](): EitherT[F, CryptoErr, KeyPair] =
generateKeyPair(new SecureRandom())
override def sign[F[_] : Monad](keyPair: KeyPair, message: ByteVector): EitherT[F, CryptoErr, fluence.crypto.signature.Signature] =
signMessage(keyPair.secretKey.value.toArray, message.toArray)
override def sign[F[_] : Monad](keyPair: KeyPair, message: ByteVector): EitherT[F, CryptoErr, fluence.crypto.signature.Signature] = {
signMessage(new BigInteger(keyPair.secretKey.value.toHex, HEXradix), message.toArray)
.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
verifySign(signature.publicKey.value.toArray, message.toArray, signature.sign.toArray)
}
private def signMessage[F[_] : Monad](privateKey: BigInteger, message: Array[Byte]): EitherT[F, CryptoErr, Array[Byte]] = {
for {
ec curveSpec
keySpec nonFatalHandling(new ECPrivateKeySpec(privateKey, ec))("Cannot read private key.")
keyFactory getKeyFactory
signProvider getSignatureProvider
sign {
nonFatalHandling {
signProvider.initSign(keyFactory.generatePrivate(keySpec))
signProvider.update(hasher.map(h h.hash(message)).getOrElse(message))
signProvider.sign()
}("Cannot sign message.")
}
} yield sign
}
private def verifySign[F[_] : Monad](publicKey: Array[Byte], message: Array[Byte], signature: Array[Byte]): EitherT[F, CryptoErr, Unit] = {
for {
ec curveSpec
keySpec nonFatalHandling(new ECPublicKeySpec(ec.getCurve.decodePoint(publicKey), ec))("Cannot read public key.")
@ -90,30 +97,14 @@ class Ecdsa(curveType: String, scheme: String) extends JavaAlgorithm
verify {
nonFatalHandling {
signProvider.initVerify(keyFactory.generatePublic(keySpec))
signProvider.update(messageBytes)
signProvider.verify(signatureBytes)
signProvider.update(hasher.map(h h.hash(message)).getOrElse(message))
signProvider.verify(signature)
}("Cannot verify message.")
}
_ EitherT.cond[F](verify, (), CryptoErr("Signature is not verified"))
} yield ()
}
private def signMessage[F[_] : Monad](privateKey: Array[Byte], message: Array[Byte]): EitherT[F, CryptoErr, Array[Byte]] = {
for {
ec curveSpec
keySpec nonFatalHandling(new ECPrivateKeySpec(new BigInteger(privateKey), ec))("Cannot read private key.")
keyFactory getKeyFactory
signProvider getSignatureProvider
sign {
nonFatalHandling {
signProvider.initSign(keyFactory.generatePrivate(keySpec))
signProvider.update(message)
signProvider.sign()
}("Cannot sign message.")
}
} yield sign
}
private def curveSpec[F[_] : Monad] =
nonFatalHandling(ECNamedCurveTable.getParameterSpec(curveType).asInstanceOf[ECParameterSpec])("Cannot get curve parameters.")
@ -134,7 +125,8 @@ object Ecdsa {
/**
* size of key is 256 bit
* `secp256k1` refers to the parameters of the ECDSA curve
* `SHA256withECDSA` Preferably the size of the key is greater than or equal to the digest algorithm
* `NONEwithECDSA with sha-256 hasher` Preferably the size of the key is greater than or equal to the digest algorithm
* don't use `SHA256WithECDSA` because of non-compatibility with javascript libraries
*/
lazy val ecdsa_secp256k1_sha256 = new Ecdsa("secp256k1", "SHA256withECDSA")
def ecdsa_secp256k1_sha256 = new Ecdsa("secp256k1", "NONEwithECDSA", Some(JdkCryptoHasher.Sha256))
}

View File

@ -0,0 +1,57 @@
/*
* 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 fluence.crypto.keypair.KeyPair
import io.circe.{ Decoder, Encoder, HCursor, Json }
import scodec.bits.{ Bases, ByteVector }
import scala.language.higherKinds
case class KeyStore(keyPair: KeyPair)
/**
* Json example:
* {
* "keystore" : {
* "secret" : "SFcDtZClfcxx75w9xJpQgBm09d6h9tVmVUEgHYxlews=",
* "public" : "AlTBivFrIYe++9Me4gr4R11BtRzjZ2WXZGDNWD/bEPka"
* }
* }
*/
object KeyStore {
private val alphabet = Bases.Alphabets.Base64Url
implicit val encodeKeyStorage: Encoder[KeyStore] = new Encoder[KeyStore] {
final def apply(ks: KeyStore): Json = Json.obj(("keystore", Json.obj(
("secret", Json.fromString(ks.keyPair.secretKey.value.toBase64(alphabet))),
("public", Json.fromString(ks.keyPair.publicKey.value.toBase64(alphabet))))))
}
implicit val decodeKeyStorage: Decoder[Option[KeyStore]] = new Decoder[Option[KeyStore]] {
final def apply(c: HCursor): Decoder.Result[Option[KeyStore]] =
for {
secret c.downField("keystore").downField("secret").as[String]
public c.downField("keystore").downField("public").as[String]
} yield {
for {
secret ByteVector.fromBase64(secret, alphabet)
public ByteVector.fromBase64(public, alphabet)
} yield KeyStore(KeyPair.fromByteVectors(public, secret))
}
}
}

View File

@ -17,10 +17,8 @@
package fluence.crypto
import java.security.SecureRandom
import cats.Monad
import cats.data.EitherT
import cats.{ Monad, MonadError }
import fluence.crypto.algorithm.{ CryptoErr, DumbSign, KeyGenerator, SignatureFunctions }
import fluence.crypto.keypair.KeyPair
import fluence.crypto.signature.{ Signature, SignatureChecker, Signer }
@ -34,12 +32,12 @@ import scala.language.higherKinds
*/
class SignAlgo(algo: KeyGenerator with SignatureFunctions) {
def generateKeyPair[F[_] : Monad](): EitherT[F, CryptoErr, KeyPair] = algo.generateKeyPair()
def generateKeyPair[F[_] : Monad](seed: ByteVector): EitherT[F, CryptoErr, KeyPair] = algo.generateKeyPair(new SecureRandom(seed.toArray))
def generateKeyPair[F[_] : Monad](seed: Option[ByteVector] = None): EitherT[F, CryptoErr, KeyPair] =
algo.generateKeyPair(seed.map(_.toArray))
def signer(kp: KeyPair): Signer = new Signer {
override def publicKey: KeyPair.Public = kp.publicKey
override def sign[F[_] : Monad](plain: ByteVector): EitherT[F, CryptoErr, Signature] = algo.sign(kp, plain)
override def publicKey: KeyPair.Public = kp.publicKey
}
def checker: SignatureChecker = new SignatureChecker {

View File

@ -17,6 +17,19 @@
package fluence.crypto.algorithm
import scala.util.control.NoStackTrace
import cats.Applicative
import cats.data.EitherT
import scala.language.higherKinds
import scala.util.control.{ NoStackTrace, NonFatal }
case class CryptoErr(errorMessage: String) extends Throwable(errorMessage) with NoStackTrace
object CryptoErr {
def nonFatalHandling[F[_] : Applicative, A](a: A)(errorText: String): EitherT[F, CryptoErr, A] = {
try EitherT.pure(a)
catch {
case NonFatal(e) EitherT.leftT(CryptoErr(errorText + " " + e.getLocalizedMessage))
}
}
}

View File

@ -14,7 +14,6 @@
* 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
import java.security.SecureRandom
@ -28,11 +27,11 @@ import scodec.bits.ByteVector
import scala.language.higherKinds
class DumbSign extends KeyGenerator with SignatureFunctions {
override def generateKeyPair[F[_] : Monad](random: SecureRandom): EitherT[F, CryptoErr, KeyPair] =
EitherT.pure(KeyPair.fromBytes(random.generateSeed(10), random.generateSeed(10)))
override def generateKeyPair[F[_] : Monad](): EitherT[F, CryptoErr, KeyPair] =
generateKeyPair(new SecureRandom())
override def generateKeyPair[F[_] : Monad](seed: Option[Array[Byte]] = None): EitherT[F, CryptoErr, KeyPair] = {
val s = seed.getOrElse(new SecureRandom().generateSeed(10))
EitherT.pure(KeyPair.fromBytes(s, s))
}
override def sign[F[_] : Monad](keyPair: KeyPair, message: ByteVector): EitherT[F, CryptoErr, Signature] =
EitherT.pure(Signature(keyPair.publicKey, message.reverse))

View File

@ -17,8 +17,6 @@
package fluence.crypto.algorithm
import java.security.SecureRandom
import cats.Monad
import cats.data.EitherT
import fluence.crypto.keypair.KeyPair
@ -26,7 +24,5 @@ import fluence.crypto.keypair.KeyPair
import scala.language.higherKinds
trait KeyGenerator {
def generateKeyPair[F[_] : Monad](random: SecureRandom): EitherT[F, CryptoErr, KeyPair]
def generateKeyPair[F[_] : Monad](): EitherT[F, CryptoErr, KeyPair]
def generateKeyPair[F[_] : Monad](seed: Option[Array[Byte]] = None): EitherT[F, CryptoErr, KeyPair]
}