diff --git a/build.sbt b/build.sbt
index 3e4b2af..1f06352 100644
--- a/build.sbt
+++ b/build.sbt
@@ -14,7 +14,7 @@ val scalaV = scalaVersion := "2.12.8"
val commons = Seq(
scalaV,
- version := "0.0.6",
+ version := "0.0.7",
fork in Test := true,
parallelExecution in Test := false,
organization := "one.fluence",
@@ -26,7 +26,7 @@ val commons = Seq(
bintrayOrganization := Some("fluencelabs"),
publishMavenStyle := true,
bintrayRepository := "releases",
- resolvers += Resolver.bintrayRepo("fluencelabs", "releases")
+ resolvers ++= Seq(Resolver.bintrayRepo("fluencelabs", "releases"), Resolver.sonatypeRepo("releases"))
)
commons
@@ -103,8 +103,10 @@ lazy val `crypto-hashsign` = crossProject(JVMPlatform, JSPlatform)
)
)
.jsSettings(
+ libraryDependencies += "io.scalajs" %%% "nodejs" % "0.4.2",
npmDependencies in Compile ++= Seq(
- "elliptic" -> "6.4.1"
+ "elliptic" -> "6.4.1",
+ "supercop.js" -> "2.0.1"
),
scalaJSModuleKind in Test := ModuleKind.CommonJSModule,
//all JavaScript dependencies will be concatenated to a single file *-jsdeps.js
diff --git a/cipher/js/src/main/scala/fluence/crypto/aes/AesCrypt.scala b/cipher/js/src/main/scala/fluence/crypto/aes/AesCrypt.scala
index e7f4ee2..0462e69 100644
--- a/cipher/js/src/main/scala/fluence/crypto/aes/AesCrypt.scala
+++ b/cipher/js/src/main/scala/fluence/crypto/aes/AesCrypt.scala
@@ -86,7 +86,7 @@ class AesCrypt(password: Array[Char], withIV: Boolean, config: AesConfig) {
//IV also needs to be transformed in byte array
val byteIv = iv.map(i ⇒ ByteVector.fromValidHex(i.toString))
byteIv.map(_.toArray ++ crypted.toArray).getOrElse(crypted.toArray)
- }("Cannot encrypt data.")
+ }("Cannot encrypt data")
}
private def decryptData[F[_]: Monad](key: Key, base64Data: String, iv: Option[String]) = {
@@ -95,7 +95,7 @@ class AesCrypt(password: Array[Char], withIV: Boolean, config: AesConfig) {
val cryptOptions = CryptOptions(iv = iv.map(i ⇒ CryptoJS.enc.Hex.parse(i)), padding = pad, mode = mode)
val dec = aes.decrypt(base64Data, key, cryptOptions)
ByteVector.fromValidHex(dec.toString)
- }("Cannot decrypt data.")
+ }("Cannot decrypt data")
}
/**
@@ -112,7 +112,7 @@ class AesCrypt(password: Array[Char], withIV: Boolean, config: AesConfig) {
val (ivOp, data) = dataWithParams
val base64 = ByteVector(data).toBase64
(ivOp, base64)
- }("Cannot detach data and IV.")
+ }("Cannot detach data and IV")
}
/**
@@ -123,7 +123,7 @@ class AesCrypt(password: Array[Char], withIV: Boolean, config: AesConfig) {
// get raw key from password and salt
val keyOption = KeyOptions(BITS, iterations = iterationCount, hasher = CryptoJS.algo.SHA256)
CryptoJS.PBKDF2(new String(password), salt, keyOption)
- }("Cannot init secret key.")
+ }("Cannot init secret key")
}
}
diff --git a/cipher/jvm/src/main/scala/fluence/crypto/aes/AesCrypt.scala b/cipher/jvm/src/main/scala/fluence/crypto/aes/AesCrypt.scala
index 4471f1b..643166e 100644
--- a/cipher/jvm/src/main/scala/fluence/crypto/aes/AesCrypt.scala
+++ b/cipher/jvm/src/main/scala/fluence/crypto/aes/AesCrypt.scala
@@ -113,7 +113,7 @@ class AesCrypt(password: Array[Char], withIV: Boolean, config: AesConfig) extend
): EitherT[F, CryptoError, Array[Byte]] =
nonFatalHandling {
PBEParametersGenerator.PKCS5PasswordToUTF8Bytes(password)
- }("Cannot init secret key.")
+ }("Cannot init secret key")
/**
* Setup AES CBC cipher
@@ -132,7 +132,7 @@ class AesCrypt(password: Array[Char], withIV: Boolean, config: AesConfig) extend
cipher.init(encrypt, params)
cipher
- }("Cannot setup aes cipher.")
+ }("Cannot setup aes cipher")
}
private def cipherBytes[F[_]: Monad](
@@ -146,7 +146,7 @@ class AesCrypt(password: Array[Char], withIV: Boolean, config: AesConfig) extend
val lastBlockLength = cipher.doFinal(buf, outputLength)
//remove padding
buf.slice(0, outputLength + lastBlockLength)
- }("Error in cipher processing.")
+ }("Error in cipher processing")
}
/**
@@ -176,7 +176,7 @@ class AesCrypt(password: Array[Char], withIV: Boolean, config: AesConfig) extend
val ivData = data.slice(0, ivSize)
val encData = data.slice(ivSize, data.length)
DetachedData(ivData, encData)
- }("Cannot detach data and IV.")
+ }("Cannot detach data and IV")
}
private def paramsWithIV[F[_]: Monad](
diff --git a/core/src/main/scala/fluence/crypto/CryptoError.scala b/core/src/main/scala/fluence/crypto/CryptoError.scala
index c5871ec..2021afe 100644
--- a/core/src/main/scala/fluence/crypto/CryptoError.scala
+++ b/core/src/main/scala/fluence/crypto/CryptoError.scala
@@ -20,6 +20,7 @@ package fluence.crypto
import cats.Applicative
import cats.data.EitherT
+import scala.language.higherKinds
import scala.util.control.{NoStackTrace, NonFatal}
case class CryptoError(message: String, causedBy: Option[Throwable] = None) extends NoStackTrace {
diff --git a/hashsign/js/src/main/scala/fluence/crypto/CryptoJsHelpers.scala b/hashsign/js/src/main/scala/fluence/crypto/CryptoJsHelpers.scala
new file mode 100644
index 0000000..3341580
--- /dev/null
+++ b/hashsign/js/src/main/scala/fluence/crypto/CryptoJsHelpers.scala
@@ -0,0 +1,29 @@
+/*
+ * 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 .
+ */
+
+package fluence.crypto
+
+import io.scalajs.nodejs.buffer.Buffer
+import scodec.bits.ByteVector
+
+import scala.language.higherKinds
+
+object CryptoJsHelpers {
+ implicit class ByteVectorOp(bv: ByteVector) {
+ def toJsBuffer: Buffer = Buffer.from(bv.toHex, "hex")
+ }
+}
diff --git a/hashsign/js/src/main/scala/fluence/crypto/ecdsa/Ecdsa.scala b/hashsign/js/src/main/scala/fluence/crypto/ecdsa/Ecdsa.scala
index b089ddb..bcf789b 100644
--- a/hashsign/js/src/main/scala/fluence/crypto/ecdsa/Ecdsa.scala
+++ b/hashsign/js/src/main/scala/fluence/crypto/ecdsa/Ecdsa.scala
@@ -37,38 +37,46 @@ import scala.scalajs.js.typedarray.Uint8Array
class Ecdsa(ec: EC, hasher: Option[Crypto.Hasher[Array[Byte], Array[Byte]]]) {
import CryptoError.nonFatalHandling
+ /**
+ * Restores key pair by secret key.
+ *
+ */
+ def restoreKeyPair[F[_]](secretKey: KeyPair.Secret)(implicit F: Monad[F]): EitherT[F, CryptoError, KeyPair] = {
+ for {
+ secret ← nonFatalHandling {
+ val key = ec.keyFromPrivate(secretKey.value.toHex, "hex")
+ val publicHex = key.getPublic(compact = true, "hex")
+ val secretHex = key.getPrivate("hex")
+ val public = ByteVector.fromValidHex(publicHex)
+ val secret = ByteVector.fromValidHex(secretHex)
+ KeyPair.fromByteVectors(public, secret)
+ }("Incorrect secret key format")
+ } yield secret
+ }
+
val generateKeyPair: Crypto.KeyPairGenerator =
new Crypto.Func[Option[Array[Byte]], KeyPair] {
override def apply[F[_]](input: Option[Array[Byte]])(implicit F: Monad[F]): EitherT[F, CryptoError, KeyPair] =
nonFatalHandling {
val seedJs = input.map(bs ⇒ js.Dynamic.literal(entropy = bs.toJSArray))
val key = ec.genKeyPair(seedJs)
- val publicHex = key.getPublic(true, "hex")
+ val publicHex = key.getPublic(compact = 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.")
+ }("Failed to generate key pair")
}
def sign[F[_]: Monad](keyPair: KeyPair, message: ByteVector): EitherT[F, CryptoError, Signature] =
for {
secret ← nonFatalHandling {
ec.keyFromPrivate(keyPair.secretKey.value.toHex, "hex")
- }("Cannot get private key from key pair.")
- hash ← hash(message)
+ }("Cannot get private key from key pair")
+ hash ← JsCryptoHasher.hashJs(message, hasher)
signHex ← nonFatalHandling(secret.sign(new Uint8Array(hash)).toDER("hex"))("Cannot sign message")
} yield Signature(ByteVector.fromValidHex(signHex))
- def hash[F[_]: Monad](message: ByteVector): EitherT[F, CryptoError, js.Array[Byte]] = {
- val arr = message.toArray
- hasher
- .fold(EitherT.pure[F, CryptoError](arr)) { h ⇒
- h[F](arr)
- }
- .map(_.toJSArray)
- }
-
def verify[F[_]: Monad](
pubKey: KeyPair.Public,
signature: Signature,
@@ -79,8 +87,8 @@ class Ecdsa(ec: EC, hasher: Option[Crypto.Hasher[Array[Byte], Array[Byte]]]) {
val hex = pubKey.value.toHex
ec.keyFromPublic(hex, "hex")
}("Incorrect public key format.")
- hash ← hash(message)
- verify ← nonFatalHandling(public.verify(new Uint8Array(hash), signature.sign.toHex))("Cannot verify message.")
+ hash ← JsCryptoHasher.hashJs(message, hasher)
+ verify ← nonFatalHandling(public.verify(new Uint8Array(hash), signature.sign.toHex))("Cannot verify message")
_ ← EitherT.cond[F](verify, (), CryptoError("Signature is not verified"))
} yield ()
}
diff --git a/hashsign/js/src/main/scala/fluence/crypto/ed25519/Ed25519.scala b/hashsign/js/src/main/scala/fluence/crypto/ed25519/Ed25519.scala
new file mode 100644
index 0000000..e1ca955
--- /dev/null
+++ b/hashsign/js/src/main/scala/fluence/crypto/ed25519/Ed25519.scala
@@ -0,0 +1,110 @@
+/*
+ * 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 .
+ */
+
+package fluence.crypto.ed25519
+
+import cats.Monad
+import cats.data.EitherT
+import fluence.crypto.CryptoError.nonFatalHandling
+import fluence.crypto.facade.ed25519.Supercop
+import fluence.crypto.hash.JsCryptoHasher
+import fluence.crypto.{Crypto, CryptoError, KeyPair, CryptoJsHelpers}
+import fluence.crypto.signature.{SignAlgo, Signature, SignatureChecker, Signer}
+import io.scalajs.nodejs.buffer.Buffer
+import scodec.bits.ByteVector
+
+import scala.language.higherKinds
+
+class Ed25519(hasher: Option[Crypto.Hasher[Array[Byte], Array[Byte]]]) {
+
+ import CryptoJsHelpers._
+
+ def sign[F[_]: Monad](keyPair: KeyPair, message: ByteVector): EitherT[F, CryptoError, Signature] =
+ for {
+ hash ← JsCryptoHasher.hash(message, hasher)
+ sign ← nonFatalHandling {
+ Supercop.sign(
+ Buffer.from(ByteVector(hash).toHex, "hex"),
+ keyPair.publicKey.value.toJsBuffer,
+ keyPair.secretKey.value.toJsBuffer
+ )
+ }("Error on signing message by js/ed25519 signature")
+ } yield Signature(ByteVector.fromValidHex(sign.toString("hex")))
+
+ def verify[F[_]: Monad](
+ pubKey: KeyPair.Public,
+ signature: Signature,
+ message: ByteVector
+ ): EitherT[F, CryptoError, Unit] =
+ for {
+ hash ← JsCryptoHasher.hash(message, hasher)
+ verify ← nonFatalHandling(
+ Supercop.verify(signature.sign.toJsBuffer, ByteVector(hash).toJsBuffer, pubKey.value.toJsBuffer)
+ )("Cannot verify message")
+ _ ← EitherT.cond[F](verify, (), CryptoError("Signature is not verified"))
+ } yield ()
+
+ val generateKeyPair: Crypto.KeyPairGenerator =
+ new Crypto.Func[Option[Array[Byte]], KeyPair] {
+ override def apply[F[_]](
+ input: Option[Array[Byte]]
+ )(implicit F: Monad[F]): EitherT[F, CryptoError, KeyPair] = {
+ for {
+ seed ← nonFatalHandling(input.map(ByteVector(_).toJsBuffer).getOrElse(Supercop.createSeed()))(
+ "Error on seed creation"
+ )
+ jsKeyPair ← nonFatalHandling(Supercop.createKeyPair(seed))("Error on key pair generation.")
+ keyPair ← nonFatalHandling(
+ KeyPair.fromByteVectors(
+ ByteVector.fromValidHex(jsKeyPair.publicKey.toString("hex")),
+ ByteVector.fromValidHex(jsKeyPair.secretKey.toString("hex"))
+ )
+ )("Error on decoding public and secret keys")
+ } yield keyPair
+ }
+ }
+}
+
+object Ed25519 {
+
+ val ed25519: Ed25519 = new Ed25519(Some(JsCryptoHasher.Sha256))
+
+ val signAlgo: SignAlgo = {
+ SignAlgo(
+ name = "ed25519",
+ generateKeyPair = ed25519.generateKeyPair,
+ signer = kp ⇒
+ Signer(
+ kp.publicKey,
+ new Crypto.Func[ByteVector, Signature] {
+ override def apply[F[_]](
+ input: ByteVector
+ )(implicit F: Monad[F]): EitherT[F, CryptoError, Signature] =
+ ed25519.sign(kp, input)
+ }
+ ),
+ checker = pk ⇒
+ new SignatureChecker {
+ override def check[F[_]: Monad](
+ signature: fluence.crypto.signature.Signature,
+ plain: ByteVector
+ ): EitherT[F, CryptoError, Unit] =
+ ed25519.verify(pk, signature, plain)
+ }
+ )
+ }
+}
diff --git a/hashsign/js/src/main/scala/fluence/crypto/facade/ed25519/Supercop.scala b/hashsign/js/src/main/scala/fluence/crypto/facade/ed25519/Supercop.scala
new file mode 100644
index 0000000..1e7699e
--- /dev/null
+++ b/hashsign/js/src/main/scala/fluence/crypto/facade/ed25519/Supercop.scala
@@ -0,0 +1,38 @@
+/*
+ * 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 .
+ */
+
+package fluence.crypto.facade.ed25519
+
+import io.scalajs.nodejs.buffer.Buffer
+
+import scala.scalajs.js
+import scala.scalajs.js.annotation.JSImport
+
+@js.native
+trait KeyPair extends js.Object {
+ val publicKey: Buffer
+ val secretKey: Buffer
+}
+
+@js.native
+@JSImport("supercop.js", JSImport.Namespace)
+object Supercop extends js.Object {
+ def verify(sig: Buffer, msg: Buffer, pubKey: Buffer): Boolean = js.native
+ def sign(msg: Buffer, pubKey: Buffer, privKey: Buffer): Buffer = js.native
+ def createKeyPair(seed: Buffer): KeyPair = js.native
+ def createSeed(): Buffer = js.native
+}
diff --git a/hashsign/js/src/main/scala/fluence/crypto/hash/JsCryptoHasher.scala b/hashsign/js/src/main/scala/fluence/crypto/hash/JsCryptoHasher.scala
index 314cda9..ca5f9da 100644
--- a/hashsign/js/src/main/scala/fluence/crypto/hash/JsCryptoHasher.scala
+++ b/hashsign/js/src/main/scala/fluence/crypto/hash/JsCryptoHasher.scala
@@ -17,10 +17,14 @@
package fluence.crypto.hash
+import cats.Monad
+import cats.data.EitherT
import fluence.crypto.{Crypto, CryptoError}
import fluence.crypto.facade.ecdsa.{SHA1, SHA256}
import scodec.bits.ByteVector
+import scala.language.higherKinds
+import scala.scalajs.js
import scala.scalajs.js.JSConverters._
import scala.scalajs.js.typedarray.Uint8Array
import scala.util.Try
@@ -44,4 +48,27 @@ object JsCryptoHasher {
ByteVector.fromValidHex(sha1.digest("hex")).toArray
}.toEither.left.map(err ⇒ CryptoError("Cannot calculate Sha256 hash", Some(err)))
}
+
+ /**
+ * Calculates hash of message.
+ *
+ * @return hash in JS array
+ */
+ def hashJs[F[_]: Monad](message: ByteVector, hasher: Option[Crypto.Hasher[Array[Byte], Array[Byte]]]): EitherT[F, CryptoError, js.Array[Byte]] = {
+ hash(message, hasher)
+ .map(_.toJSArray)
+ }
+
+ /**
+ * Calculates hash of message.
+ *
+ * @return hash in Scala array
+ */
+ def hash[F[_]: Monad](message: ByteVector, hasher: Option[Crypto.Hasher[Array[Byte], Array[Byte]]]): EitherT[F, CryptoError, Array[Byte]] = {
+ val arr = message.toArray
+ hasher
+ .fold(EitherT.pure[F, CryptoError](arr)) { h ⇒
+ h[F](arr)
+ }
+ }
}
diff --git a/hashsign/js/src/test/scala/fluence/crypto/Ed25519Spec.scala b/hashsign/js/src/test/scala/fluence/crypto/Ed25519Spec.scala
new file mode 100644
index 0000000..3a42374
--- /dev/null
+++ b/hashsign/js/src/test/scala/fluence/crypto/Ed25519Spec.scala
@@ -0,0 +1,97 @@
+/*
+ * 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 .
+ */
+
+package fluence.crypto
+
+import cats.data.EitherT
+import fluence.crypto.signature.Signature
+import org.scalatest.{Matchers, WordSpec}
+import scodec.bits.ByteVector
+import cats.instances.try_._
+import fluence.crypto.ed25519.Ed25519
+
+import scala.util.{Random, Try}
+
+class Ed25519Spec extends WordSpec with Matchers {
+ def rndBytes(size: Int): Array[Byte] = Random.nextString(10).getBytes
+
+ def rndByteVector(size: Int) = ByteVector(rndBytes(size))
+
+ private implicit class TryEitherTExtractor[A <: Throwable, B](et: EitherT[Try, A, B]) {
+
+ def extract: B =
+ et.value.map {
+ case Left(e) ⇒ fail(e) // for making test fail message more describable
+ case Right(v) ⇒ v
+ }.get
+
+ def isOk: Boolean = et.value.fold(_ ⇒ false, _.isRight)
+ }
+
+ "ed25519 algorithm" should {
+ "correct sign and verify data" in {
+ val algorithm = Ed25519.ed25519
+
+ val keys = algorithm.generateKeyPair.unsafe(None)
+ val pubKey = keys.publicKey
+ val data = rndByteVector(10)
+ val sign = algorithm.sign[Try](keys, data).extract
+
+ algorithm.verify[Try](pubKey, sign, data).isOk shouldBe true
+
+ val randomData = rndByteVector(10)
+ val randomSign = algorithm.sign(keys, randomData).extract
+
+ algorithm.verify(pubKey, randomSign, data).isOk shouldBe false
+
+ algorithm.verify(pubKey, sign, randomData).isOk shouldBe false
+ }
+
+ "correctly work with signer and checker" in {
+ val algo = Ed25519.signAlgo
+ val keys = algo.generateKeyPair.unsafe(None)
+ val signer = algo.signer(keys)
+ val checker = algo.checker(keys.publicKey)
+
+ val data = rndByteVector(10)
+ val sign = signer.sign(data).extract
+
+ checker.check(sign, data).isOk shouldBe true
+
+ val randomSign = signer.sign(rndByteVector(10)).extract
+ checker.check(randomSign, data).isOk shouldBe false
+ }
+
+ "throw an errors on invalid data" in {
+ val algo = Ed25519.signAlgo
+ val keys = algo.generateKeyPair.unsafe(None)
+ val signer = algo.signer(keys)
+ val checker = algo.checker(keys.publicKey)
+ val data = rndByteVector(10)
+
+ val sign = signer.sign(data).extract
+
+ the[CryptoError] thrownBy checker.check(Signature(rndByteVector(10)), data).value.flatMap(_.toTry).get
+ val invalidChecker = algo.checker(KeyPair.fromByteVectors(rndByteVector(10), rndByteVector(10)).publicKey)
+ the[CryptoError] thrownBy invalidChecker
+ .check(sign, data)
+ .value
+ .flatMap(_.toTry)
+ .get
+ }
+ }
+}
diff --git a/hashsign/js/src/test/scala/fluence/crypto/EcdsaSpec.scala b/hashsign/js/src/test/scala/fluence/crypto/EllipticSpec.scala
similarity index 96%
rename from hashsign/js/src/test/scala/fluence/crypto/EcdsaSpec.scala
rename to hashsign/js/src/test/scala/fluence/crypto/EllipticSpec.scala
index 8ddffae..e38c9e7 100644
--- a/hashsign/js/src/test/scala/fluence/crypto/EcdsaSpec.scala
+++ b/hashsign/js/src/test/scala/fluence/crypto/EllipticSpec.scala
@@ -26,9 +26,9 @@ import scodec.bits.ByteVector
import scala.util.{Random, Try}
-class EcdsaSpec extends WordSpec with Matchers {
+class EllipticSpec extends WordSpec with Matchers {
- def rndBytes(size: Int) = Random.nextString(10).getBytes
+ def rndBytes(size: Int): Array[Byte] = Random.nextString(10).getBytes
def rndByteVector(size: Int) = ByteVector(rndBytes(size))
diff --git a/hashsign/jvm/src/main/scala/fluence/crypto/ecdsa/Ecdsa.scala b/hashsign/jvm/src/main/scala/fluence/crypto/ecdsa/Ecdsa.scala
index 96b7e61..24d1de0 100644
--- a/hashsign/jvm/src/main/scala/fluence/crypto/ecdsa/Ecdsa.scala
+++ b/hashsign/jvm/src/main/scala/fluence/crypto/ecdsa/Ecdsa.scala
@@ -142,36 +142,36 @@ class Ecdsa(curveType: String, scheme: String, hasher: Option[Crypto.Hasher[Arra
): EitherT[F, CryptoError, Unit] =
for {
ec ← curveSpec
- keySpec ← nonFatalHandling(new ECPublicKeySpec(ec.getCurve.decodePoint(publicKey), ec))("Cannot read public key.")
+ 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(hasher.map(_.unsafe(message)).getOrElse(message))
signProvider.verify(signature)
- }("Cannot verify message.")
+ }("Cannot verify message")
_ ← EitherT.cond[F](verify, (), CryptoError("Signature is not verified"))
} yield ()
private def curveSpec[F[_]: Monad] =
nonFatalHandling(ECNamedCurveTable.getParameterSpec(curveType).asInstanceOf[ECParameterSpec])(
- "Cannot get curve parameters."
+ "Cannot get curve parameters"
)
private def getKeyPairGenerator[F[_]: Monad] =
nonFatalHandling(KeyPairGenerator.getInstance(ECDSA, BouncyCastleProvider.PROVIDER_NAME))(
- "Cannot get key pair generator."
+ "Cannot get key pair generator"
)
private def getKeyFactory[F[_]: Monad] =
nonFatalHandling(KeyFactory.getInstance(ECDSA, BouncyCastleProvider.PROVIDER_NAME))(
- "Cannot get key factory instance."
+ "Cannot get key factory instance"
)
private def getSignatureProvider[F[_]: Monad] =
nonFatalHandling(Signature.getInstance(scheme, BouncyCastleProvider.PROVIDER_NAME))(
- "Cannot get signature instance."
+ "Cannot get signature instance"
)
}
diff --git a/hashsign/jvm/src/main/scala/fluence/crypto/eddsa/Ed25519.scala b/hashsign/jvm/src/main/scala/fluence/crypto/eddsa/Ed25519.scala
index 55cda42..02d07fd 100644
--- a/hashsign/jvm/src/main/scala/fluence/crypto/eddsa/Ed25519.scala
+++ b/hashsign/jvm/src/main/scala/fluence/crypto/eddsa/Ed25519.scala
@@ -137,13 +137,21 @@ object Ed25519 {
/**
* Keys in tendermint are generating with a random seed of 32 bytes
*/
- val tendermintEd25519 = new Ed25519(256)
- val tendermintAlgo: SignAlgo = signAlgo(256)
+ val ed25519 = new Ed25519(256)
+ val signAlgo: SignAlgo = signAlgoInit(256)
- def ed25519(strength: Int) = new Ed25519(strength)
+ /**
+ *
+ * @param strength the size, in bits, of the keys we want to produce
+ */
+ def ed25519Init(strength: Int) = new Ed25519(strength)
- def signAlgo(strength: Int): SignAlgo = {
- val algo = ed25519(strength)
+ /**
+ *
+ * @param strength the size, in bits, of the keys we want to produce
+ */
+ def signAlgoInit(strength: Int): SignAlgo = {
+ val algo = ed25519Init(strength)
SignAlgo(
name = "ed25519",
generateKeyPair = algo.generateKeyPair,
diff --git a/hashsign/jvm/src/test/scala/fluence/crypto/Ed25519Spec.scala b/hashsign/jvm/src/test/scala/fluence/crypto/Ed25519Spec.scala
index e862302..9e0a422 100644
--- a/hashsign/jvm/src/test/scala/fluence/crypto/Ed25519Spec.scala
+++ b/hashsign/jvm/src/test/scala/fluence/crypto/Ed25519Spec.scala
@@ -48,7 +48,7 @@ class Ed25519Spec extends WordSpec with Matchers {
"ed25519 algorithm" should {
"correct sign and verify data" in {
- val algorithm = Ed25519.ed25519(32)
+ val algorithm = Ed25519.ed25519Init(32)
val keys = algorithm.generateKeyPair.unsafe(None)
val pubKey = keys.publicKey
@@ -66,7 +66,7 @@ class Ed25519Spec extends WordSpec with Matchers {
}
"correctly work with signer and checker" in {
- val algo = Ed25519.signAlgo(32)
+ val algo = Ed25519.signAlgo
val keys = algo.generateKeyPair.unsafe(None)
val signer = algo.signer(keys)
val checker = algo.checker(keys.publicKey)
@@ -81,7 +81,7 @@ class Ed25519Spec extends WordSpec with Matchers {
}
"throw an errors on invalid data" in {
- val algo = Ed25519.signAlgo(32)
+ val algo = Ed25519.signAlgo
val keys = algo.generateKeyPair.unsafe(None)
val signer = algo.signer(keys)
val checker = algo.checker(keys.publicKey)
@@ -103,7 +103,7 @@ class Ed25519Spec extends WordSpec with Matchers {
}
"store and read key from file" in {
- val algo = Ed25519.signAlgo(32)
+ val algo = Ed25519.signAlgo
val keys = algo.generateKeyPair.unsafe(None)
val keyFile = File.createTempFile("test", "")
@@ -127,10 +127,10 @@ class Ed25519Spec extends WordSpec with Matchers {
}
"restore key pair from secret key" in {
- val algo = Ed25519.signAlgo(32)
+ val algo = Ed25519.signAlgo
val testKeys = algo.generateKeyPair.unsafe(None)
- val ed25519 = Ed25519.ed25519(32)
+ val ed25519 = Ed25519.ed25519
val newKeys = ed25519.restorePairFromSecret(testKeys.secretKey).extract
@@ -158,7 +158,7 @@ class Ed25519Spec extends WordSpec with Matchers {
val privKey = ByteVector.fromBase64Descriptive(privKeyBase64).right.get
val pubKey = ByteVector.fromBase64Descriptive(pubKeyBase64).right.get
- val restored = Ed25519.tendermintEd25519
+ val restored = Ed25519.ed25519
.restorePairFromSecret[Try](KeyPair.Secret(privKey.dropRight(32)))
.value
.get
diff --git a/project/FluenceCrossType.scala b/project/FluenceCrossType.scala
index 74e64e6..acb39c5 100644
--- a/project/FluenceCrossType.scala
+++ b/project/FluenceCrossType.scala
@@ -26,4 +26,3 @@ object FluenceCrossType extends sbtcrossproject.CrossType {
override def sharedSrcDir(projectBase: File, conf: String) =
Some(shared(projectBase, conf))
}
-
diff --git a/project/plugins.sbt b/project/plugins.sbt
index 54f9b7b..e5413c4 100644
--- a/project/plugins.sbt
+++ b/project/plugins.sbt
@@ -4,7 +4,7 @@ addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.3.20")
addSbtPlugin("de.heikoseeberger" % "sbt-header" % "5.2.0")
-addSbtPlugin("org.scala-js" % "sbt-scalajs" % "0.6.27")
+addSbtPlugin("org.scala-js" % "sbt-scalajs" % "0.6.28")
addSbtPlugin("org.portable-scala" % "sbt-crossproject" % "0.6.0")
addSbtPlugin("org.portable-scala" % "sbt-scalajs-crossproject" % "0.6.0")