Skip to content

Commit

Permalink
Ecdsa recreate pair from secret (#2)
Browse files Browse the repository at this point in the history
* add possibility to re-create public key from private key for ECDSA alghorithm

* change version

* change version

* add comments, change version of cats-effect

* add comments, change method name

* change comment

* typo
  • Loading branch information
DieMyst authored Aug 22, 2018
1 parent d938192 commit 3e0d21d
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 8 deletions.
12 changes: 6 additions & 6 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ val scalaV = scalaVersion := "2.12.5"

val commons = Seq(
scalaV,
version := "0.0.1",
version := "0.0.2",
fork in Test := true,
parallelExecution in Test := false,
organization := "one.fluence",
Expand All @@ -33,13 +33,13 @@ commons

val CodecV = "0.0.3"

val CatsEffectV = "1.0.0-RC"
val CatsEffectV = "1.0.0-RC3"

val SloggingV = "0.6.1"

val ScalatestV = "3.0.+"

val bouncyCastle = "org.bouncycastle" % "bcprov-jdk15on" % "1.59"
val bouncyCastle = "org.bouncycastle" % "bcprov-jdk15on" % "1.59"

enablePlugins(AutomateHeaderPlugin)

Expand Down Expand Up @@ -158,12 +158,12 @@ lazy val `crypto-jwt` = crossProject(JVMPlatform, JSPlatform)
.settings(
commons,
libraryDependencies ++= Seq(
"one.fluence" %%% "codec-circe" % CodecV,
"org.scalatest" %%% "scalatest" % ScalatestV % Test
"one.fluence" %%% "codec-circe" % CodecV,
"org.scalatest" %%% "scalatest" % ScalatestV % Test
)
)
.jsSettings(
fork in Test := false,
fork in Test := false,
scalaJSModuleKind := ModuleKind.CommonJSModule
)
.enablePlugins(AutomateHeaderPlugin)
Expand Down
26 changes: 26 additions & 0 deletions hashsign/jvm/src/main/scala/fluence/crypto/ecdsa/Ecdsa.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import java.security.interfaces.ECPrivateKey

import cats.Monad
import cats.data.EitherT
import fluence.crypto.KeyPair.Secret
import fluence.crypto.{KeyPair, _}
import fluence.crypto.hash.JdkCryptoHasher
import fluence.crypto.signature.{SignAlgo, SignatureChecker, Signer}
Expand Down Expand Up @@ -72,6 +73,31 @@ class Ecdsa(curveType: String, scheme: String, hasher: Option[Crypto.Hasher[Arra
} yield keyPair
}

/**
* Restores pair of keys from the known secret key.
* The public key will be the same each method call with the same secret key.
* @param sk secret key
* @return key pair
*/
def restorePairFromSecret[F[_]: Monad](sk: Secret): EitherT[F, CryptoError, KeyPair] =
for {
ecSpec EitherT.fromOption(
Option(ECNamedCurveTable.getParameterSpec(curveType)),
CryptoError("Parameter spec for the curve is not available.")
)
keyPair nonFatalHandling {
val hex = sk.value.toHex
val d = new BigInteger(hex, HEXradix)
// to re-create public key from private we need to multiply known from curve point G with D (private key)
// result will be point Q (public key)
// https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm
val g = ecSpec.getG
val q = g.multiply(d)
val pk = ByteVector(q.getEncoded(true))
KeyPair.fromByteVectors(pk, sk.value)
}("Could not generate KeyPair from private key. Unexpected.")
} yield keyPair

def sign[F[_]: Monad](
keyPair: KeyPair,
message: ByteVector
Expand Down
14 changes: 13 additions & 1 deletion hashsign/jvm/src/test/scala/fluence/crypto/SignatureSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
package fluence.crypto

import java.io.File
import java.math.BigInteger

import cats.data.EitherT
import cats.instances.try_._
Expand All @@ -31,7 +32,7 @@ import scala.util.{Random, Try}

class SignatureSpec 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))

Expand Down Expand Up @@ -125,5 +126,16 @@ class SignatureSpec extends WordSpec with Matchers {
//try to store key into previously created file
storage.storeKeyPair(keys).attempt.unsafeRunSync().isLeft shouldBe true
}

"restore key pair from secret key" in {
val algo = Ecdsa.signAlgo
val testKeys = algo.generateKeyPair.unsafe(None)

val ecdsa = Ecdsa.ecdsa_secp256k1_sha256

val newKeys = ecdsa.restorePairFromSecret(testKeys.secretKey).extract

testKeys shouldBe newKeys
}
}
}
2 changes: 1 addition & 1 deletion project/build.properties
Original file line number Diff line number Diff line change
@@ -1 +1 @@
sbt.version = 1.1.4
sbt.version = 1.2.1

0 comments on commit 3e0d21d

Please sign in to comment.