mirror of
https://github.com/fluencelabs/crypto
synced 2025-07-02 06:11:33 +00:00
Compare commits
2 Commits
Author | SHA1 | Date | |
---|---|---|---|
3e0d21d197 | |||
d938192ef6 |
63
README.md
63
README.md
@ -1,2 +1,63 @@
|
|||||||
# crypto
|
[](https://travis-ci.org/fluencelabs/crypto)
|
||||||
|
[](https://gitter.im/fluencelabs/crypto?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
||||||
|
|
||||||
|
# Сrypto
|
||||||
|
|
||||||
Cryptography for Scala and Scala.js, FP-flavoured.
|
Cryptography for Scala and Scala.js, FP-flavoured.
|
||||||
|
|
||||||
|
APIs are mostly based on [codec](https://github.com/fluencelabs/codec) approach with partial bijections, using `CryptoError` case class for errors.
|
||||||
|
|
||||||
|
## Submodules
|
||||||
|
|
||||||
|
### crypto-core
|
||||||
|
|
||||||
|
Provides APIs and data types for various cryptographical operations, but without implementations.
|
||||||
|
|
||||||
|
This library should be added as dependency to both implementations of crypto algorithms and on the user side, if particular app doesn't require a particular algorithm.
|
||||||
|
|
||||||
|
### crypto-hashsign
|
||||||
|
|
||||||
|
Cross-platform hashing and signing algos.
|
||||||
|
|
||||||
|
Use a `fluence.crypto.hash.CryptoHashers` to access a hashing algorithm. Currently `Sha1` and `Sha256` are provided.
|
||||||
|
|
||||||
|
`fluence.crypto.ecdsa.Ecdsa.signAlgo` is an instance of `SignAlgo` with `ecdsa_secp256k1_sha256` under the hood.
|
||||||
|
|
||||||
|
### crypto-cipher
|
||||||
|
|
||||||
|
Encryption and decryption algorithms, coded as arrows and bijections. Currently contains `AES` ciphering.
|
||||||
|
|
||||||
|
### crypto-keystore
|
||||||
|
|
||||||
|
Provides a JSON format for serializing a keypair, using `codec-circe` for JSON processing.
|
||||||
|
|
||||||
|
For Scala on JVM, storing on the disc is implemented with use of `cats-effect`.
|
||||||
|
|
||||||
|
### crypto-jwt
|
||||||
|
|
||||||
|
Simplified JWT implementation, meaning a JSON-serialized header and claim with signature checking.
|
||||||
|
|
||||||
|
`codec-circe` is used for JSON encoding/decoding, and `codec-bits` for binary data manipulations.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
```scala
|
||||||
|
// Bintray repo is used so far. Migration to Maven Central is planned
|
||||||
|
resolvers += Resolver.bintrayRepo("fluencelabs", "releases")
|
||||||
|
|
||||||
|
val cryptoV = "0.0.1"
|
||||||
|
|
||||||
|
libraryDependencies ++= Seq(
|
||||||
|
"one.fluence" %%% "crypto-core" % cryptoV, // basic types and APIs
|
||||||
|
"one.fluence" %%% "crypto-hashsign" % cryptoV, // hashers and signatures
|
||||||
|
"one.fluence" %%% "crypto-cipher" % cryptoV, // encoding and decoding
|
||||||
|
"one.fluence" %%% "crypto-keystore" % cryptoV, // serialize and store a keypair
|
||||||
|
"one.fluence" %%% "crypto-jwt" % cryptoV // simple JWT implementation
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Fluence is free software; you can redistribute it and/or modify it under the terms of the GNU Affero General Public License v3 (AGPLv3) as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
Fluence includes some [external modules](https://github.com/fluencelabs/crypto/blob/master/build.sbt) that carry their own licensing.
|
15
build.sbt
15
build.sbt
@ -14,7 +14,7 @@ val scalaV = scalaVersion := "2.12.5"
|
|||||||
|
|
||||||
val commons = Seq(
|
val commons = Seq(
|
||||||
scalaV,
|
scalaV,
|
||||||
version := "0.0.1",
|
version := "0.0.2",
|
||||||
fork in Test := true,
|
fork in Test := true,
|
||||||
parallelExecution in Test := false,
|
parallelExecution in Test := false,
|
||||||
organization := "one.fluence",
|
organization := "one.fluence",
|
||||||
@ -25,20 +25,21 @@ val commons = Seq(
|
|||||||
headerLicense := Some(License.AGPLv3("2017", organizationName.value)),
|
headerLicense := Some(License.AGPLv3("2017", organizationName.value)),
|
||||||
bintrayOrganization := Some("fluencelabs"),
|
bintrayOrganization := Some("fluencelabs"),
|
||||||
publishMavenStyle := true,
|
publishMavenStyle := true,
|
||||||
bintrayRepository := "releases"
|
bintrayRepository := "releases",
|
||||||
|
resolvers += Resolver.bintrayRepo("fluencelabs", "releases")
|
||||||
)
|
)
|
||||||
|
|
||||||
commons
|
commons
|
||||||
|
|
||||||
val CodecV = "0.0.3"
|
val CodecV = "0.0.3"
|
||||||
|
|
||||||
val CatsEffectV = "1.0.0-RC"
|
val CatsEffectV = "1.0.0-RC3"
|
||||||
|
|
||||||
val SloggingV = "0.6.1"
|
val SloggingV = "0.6.1"
|
||||||
|
|
||||||
val ScalatestV = "3.0.+"
|
val ScalatestV = "3.0.+"
|
||||||
|
|
||||||
val bouncyCastle = "org.bouncycastle" % "bcprov-jdk15on" % "1.59"
|
val bouncyCastle = "org.bouncycastle" % "bcprov-jdk15on" % "1.59"
|
||||||
|
|
||||||
enablePlugins(AutomateHeaderPlugin)
|
enablePlugins(AutomateHeaderPlugin)
|
||||||
|
|
||||||
@ -157,12 +158,12 @@ lazy val `crypto-jwt` = crossProject(JVMPlatform, JSPlatform)
|
|||||||
.settings(
|
.settings(
|
||||||
commons,
|
commons,
|
||||||
libraryDependencies ++= Seq(
|
libraryDependencies ++= Seq(
|
||||||
"one.fluence" %%% "codec-circe" % CodecV,
|
"one.fluence" %%% "codec-circe" % CodecV,
|
||||||
"org.scalatest" %%% "scalatest" % ScalatestV % Test
|
"org.scalatest" %%% "scalatest" % ScalatestV % Test
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.jsSettings(
|
.jsSettings(
|
||||||
fork in Test := false,
|
fork in Test := false,
|
||||||
scalaJSModuleKind := ModuleKind.CommonJSModule
|
scalaJSModuleKind := ModuleKind.CommonJSModule
|
||||||
)
|
)
|
||||||
.enablePlugins(AutomateHeaderPlugin)
|
.enablePlugins(AutomateHeaderPlugin)
|
||||||
|
@ -23,6 +23,7 @@ import java.security.interfaces.ECPrivateKey
|
|||||||
|
|
||||||
import cats.Monad
|
import cats.Monad
|
||||||
import cats.data.EitherT
|
import cats.data.EitherT
|
||||||
|
import fluence.crypto.KeyPair.Secret
|
||||||
import fluence.crypto.{KeyPair, _}
|
import fluence.crypto.{KeyPair, _}
|
||||||
import fluence.crypto.hash.JdkCryptoHasher
|
import fluence.crypto.hash.JdkCryptoHasher
|
||||||
import fluence.crypto.signature.{SignAlgo, SignatureChecker, Signer}
|
import fluence.crypto.signature.{SignAlgo, SignatureChecker, Signer}
|
||||||
@ -72,6 +73,31 @@ class Ecdsa(curveType: String, scheme: String, hasher: Option[Crypto.Hasher[Arra
|
|||||||
} yield keyPair
|
} 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](
|
def sign[F[_]: Monad](
|
||||||
keyPair: KeyPair,
|
keyPair: KeyPair,
|
||||||
message: ByteVector
|
message: ByteVector
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
package fluence.crypto
|
package fluence.crypto
|
||||||
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.math.BigInteger
|
||||||
|
|
||||||
import cats.data.EitherT
|
import cats.data.EitherT
|
||||||
import cats.instances.try_._
|
import cats.instances.try_._
|
||||||
@ -31,7 +32,7 @@ import scala.util.{Random, Try}
|
|||||||
|
|
||||||
class SignatureSpec extends WordSpec with Matchers {
|
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))
|
def rndByteVector(size: Int) = ByteVector(rndBytes(size))
|
||||||
|
|
||||||
@ -125,5 +126,16 @@ class SignatureSpec extends WordSpec with Matchers {
|
|||||||
//try to store key into previously created file
|
//try to store key into previously created file
|
||||||
storage.storeKeyPair(keys).attempt.unsafeRunSync().isLeft shouldBe true
|
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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1 +1 @@
|
|||||||
sbt.version = 1.1.4
|
sbt.version = 1.2.1
|
||||||
|
Reference in New Issue
Block a user