add EdDSA Provider and update i2p dependency to 0.2.0

This commit is contained in:
Konstantinos Chalkias 2017-04-20 15:25:28 +01:00
parent 4e86443cac
commit 2ff8d14491
6 changed files with 49 additions and 25 deletions

View File

@ -71,7 +71,7 @@ dependencies {
compile "com.fasterxml.jackson.core:jackson-databind:${jackson_version}"
// Java ed25519 implementation. See https://github.com/str4d/ed25519-java/
compile 'net.i2p.crypto:eddsa:0.1.0'
compile 'net.i2p.crypto:eddsa:0.2.0'
// Bouncy castle support needed for X509 certificate manipulation
compile "org.bouncycastle:bcprov-jdk15on:${bouncycastle_version}"

View File

@ -29,6 +29,7 @@ import java.security.spec.X509EncodedKeySpec
object Crypto {
init {
Security.addProvider(I2PProvider()) // register I2P Crypto Provider, required for EdDSA.
Security.addProvider(BouncyCastleProvider()) // register Bouncy Castle Crypto Provider (for RSA, ECDSA).
Security.addProvider(BouncyCastlePQCProvider()) // register Bouncy Castle Post-Quantum Crypto Provider (for SPHINCS-256).
}
@ -79,10 +80,10 @@ object Crypto {
4,
"EDDSA_ED25519_SHA512",
"EdDSA",
EdDSAEngine(),
EdDSAKeyFactory,
net.i2p.crypto.eddsa.KeyPairGenerator(), // EdDSA engine uses a custom KeyPairGenerator Vs BouncyCastle.
EdDSANamedCurveTable.getByName("ed25519-sha-512"),
Signature.getInstance("SHA512withEdDSA", "I2P"),
KeyFactory.getInstance("EdDSA", "I2P"),
KeyPairGenerator.getInstance("EdDSA", "I2P"),
EdDSANamedCurveTable.getByName("ED25519"),
256,
"EdDSA signature scheme using the ed25519 twisted Edwards curve."
)

View File

@ -53,7 +53,7 @@ fun PrivateKey.signWithECDSA(bytesToSign: ByteArray, publicKey: PublicKey): Digi
return DigitalSignature.WithKey(publicKey, signWithECDSA(bytesToSign).bytes)
}
val ed25519Curve: EdDSANamedCurveSpec = EdDSANamedCurveTable.getByName(EdDSANamedCurveTable.CURVE_ED25519_SHA512)
val ed25519Curve: EdDSANamedCurveSpec = EdDSANamedCurveTable.getByName("ED25519")
fun KeyPair.signWithECDSA(bytesToSign: ByteArray) = private.signWithECDSA(bytesToSign, public)
fun KeyPair.signWithECDSA(bytesToSign: OpaqueBytes) = private.signWithECDSA(bytesToSign.bytes, public)
@ -150,7 +150,7 @@ fun generateKeyPair(): KeyPair = Crypto.generateKeyPair()
* you want hard-coded private keys.
*/
fun entropyToKeyPair(entropy: BigInteger): KeyPair {
val params = EdDSANamedCurveTable.getByName(EdDSANamedCurveTable.CURVE_ED25519_SHA512)
val params = ed25519Curve
val bytes = entropy.toByteArray().copyOf(params.curve.field.getb() / 8)
val priv = EdDSAPrivateKeySpec(bytes, params)
val pub = EdDSAPublicKeySpec(priv.a, params)

View File

@ -1,10 +0,0 @@
package net.corda.core.crypto
import java.security.KeyFactory
/**
* Custom [KeyFactory] for EdDSA with null security [Provider].
* This is required as a [SignatureScheme] requires a [java.security.KeyFactory] property, but i2p has
* its own KeyFactory for EdDSA, thus this actually a Proxy Pattern over i2p's KeyFactory.
*/
object EdDSAKeyFactory : KeyFactory(net.i2p.crypto.eddsa.KeyFactory(), null, "EDDSA_ED25519_SHA512")

View File

@ -2,8 +2,6 @@ package net.corda.core.crypto
import com.google.common.collect.Sets
import net.i2p.crypto.eddsa.EdDSAKey
import net.i2p.crypto.eddsa.EdDSAPrivateKey
import net.i2p.crypto.eddsa.EdDSAPublicKey
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo
@ -413,15 +411,16 @@ class CryptoUtilsTest {
fun `EdDSA encode decode keys - required for serialization`() {
// Generate key pair.
val keyPair = Crypto.generateKeyPair("EDDSA_ED25519_SHA512")
val privKey: EdDSAPrivateKey = keyPair.private as EdDSAPrivateKey
val pubKey: EdDSAPublicKey = keyPair.public as EdDSAPublicKey
val (privKey, pubKey) = keyPair
val kf = KeyFactory.getInstance("EDDSA", "I2P")
// Encode and decode private key.
val privKey2 = EdDSAKeyFactory.generatePrivate(PKCS8EncodedKeySpec(privKey.encoded))
val privKey2 = kf.generatePrivate(PKCS8EncodedKeySpec(privKey.encoded))
assertEquals(privKey2, privKey)
// Encode and decode public key.
val pubKey2 = EdDSAKeyFactory.generatePublic(X509EncodedKeySpec(pubKey.encoded))
val pubKey2 = kf.generatePublic(X509EncodedKeySpec(pubKey.encoded))
assertEquals(pubKey2, pubKey)
}
@ -499,9 +498,9 @@ class CryptoUtilsTest {
val (privEd, pubEd) = keyPairEd
assertEquals(privEd.algorithm, "EdDSA")
assertEquals((privEd as EdDSAKey).params, EdDSANamedCurveTable.getByName("ed25519-sha-512"))
assertEquals((privEd as EdDSAKey).params, EdDSANamedCurveTable.getByName("ED25519"))
assertEquals(pubEd.algorithm, "EdDSA")
assertEquals((pubEd as EdDSAKey).params, EdDSANamedCurveTable.getByName("ed25519-sha-512"))
assertEquals((pubEd as EdDSAKey).params, EdDSANamedCurveTable.getByName("ED25519"))
}
@Test

View File

@ -0,0 +1,34 @@
package net.corda.core.crypto
import java.security.Provider
/**
* A simple I2P [Provider] that supports the EdDSA signature scheme.
*/
class I2PProvider : Provider("I2P", 0.1, "I2P Security Provider v0.1, implementing I2P's EdDSA 25519.") {
init { setup() }
private fun setup() {
// Key OID: 1.3.101.100; Sig OID: 1.3.101.101
put("KeyFactory.EdDSA", "net.i2p.crypto.eddsa.KeyFactory")
put("KeyPairGenerator.EdDSA", "net.i2p.crypto.eddsa.KeyPairGenerator")
put("Signature.SHA512withEdDSA", "net.i2p.crypto.eddsa.EdDSAEngine")
// without these, Certificate.verify() fails.
put("Alg.Alias.KeyFactory.1.3.101.100", "EdDSA")
put("Alg.Alias.KeyFactory.OID.1.3.101.100", "EdDSA")
// Without these, keytool fails with:
// keytool error: java.security.NoSuchAlgorithmException: unrecognized algorithm name: SHA512withEdDSA.
put("Alg.Alias.KeyPairGenerator.1.3.101.100", "EdDSA")
put("Alg.Alias.KeyPairGenerator.OID.1.3.101.100", "EdDSA")
// with this setting, keytool's keygen doesn't work.
// java.security.cert.CertificateException: Signature algorithm mismatch.
// It must match the key setting (1.3.101.100) to work,
// but this works fine with programmatic cert generation.
put("Alg.Alias.Signature.1.3.101.101", "SHA512withEdDSA")
put("Alg.Alias.Signature.OID.1.3.101.101", "SHA512withEdDSA")
}
}