mirror of
https://github.com/corda/corda.git
synced 2025-04-07 11:27:01 +00:00
CORDA-579: Move X509EdDSAEngine into net.corda.core.internal package (#1563)
* Add reflection based X509EdDSAEngine * Rewrite X509EdDSAEngine to use public API rather than the direct equivalent functions * Add unit tests for X509EdDSAEngine * Remove unused imports * Add unit tests for X509Key verification * Add explicit x509 construct from eddsa key This allows testing of conversion engine * Review Comments
This commit is contained in:
parent
29e648d11c
commit
22be9fd6df
1
.idea/compiler.xml
generated
1
.idea/compiler.xml
generated
@ -93,6 +93,7 @@
|
||||
<module name="smoke-test-utils_test" target="1.8" />
|
||||
<module name="test-common_main" target="1.8" />
|
||||
<module name="test-common_test" target="1.8" />
|
||||
<module name="test-utils_integrationTest" target="1.8" />
|
||||
<module name="test-utils_main" target="1.8" />
|
||||
<module name="test-utils_test" target="1.8" />
|
||||
<module name="testing-node-driver_integrationTest" target="1.8" />
|
||||
|
@ -1,5 +1,6 @@
|
||||
package net.corda.core.crypto
|
||||
|
||||
import net.corda.core.internal.X509EdDSAEngine
|
||||
import net.corda.core.serialization.serialize
|
||||
import net.i2p.crypto.eddsa.*
|
||||
import net.i2p.crypto.eddsa.math.GroupElement
|
||||
|
@ -1,5 +1,7 @@
|
||||
package net.i2p.crypto.eddsa
|
||||
package net.corda.core.internal
|
||||
|
||||
import net.i2p.crypto.eddsa.EdDSAEngine
|
||||
import net.i2p.crypto.eddsa.EdDSAPublicKey
|
||||
import java.security.*
|
||||
import java.security.spec.AlgorithmParameterSpec
|
||||
import java.security.spec.X509EncodedKeySpec
|
||||
@ -16,33 +18,34 @@ class X509EdDSAEngine : Signature {
|
||||
constructor() : super(EdDSAEngine.SIGNATURE_ALGORITHM) {
|
||||
engine = EdDSAEngine()
|
||||
}
|
||||
|
||||
constructor(digest: MessageDigest) : super(EdDSAEngine.SIGNATURE_ALGORITHM) {
|
||||
engine = EdDSAEngine(digest)
|
||||
}
|
||||
|
||||
override fun engineInitSign(privateKey: PrivateKey) = engine.engineInitSign(privateKey)
|
||||
override fun engineInitSign(privateKey: PrivateKey) = engine.initSign(privateKey)
|
||||
override fun engineInitSign(privateKey: PrivateKey, random: SecureRandom) = engine.initSign(privateKey, random)
|
||||
|
||||
override fun engineInitVerify(publicKey: PublicKey) {
|
||||
val parsedKey = if (publicKey is sun.security.x509.X509Key) {
|
||||
EdDSAPublicKey(X509EncodedKeySpec(publicKey.encoded))
|
||||
} else {
|
||||
publicKey
|
||||
}
|
||||
engine.engineInitVerify(parsedKey)
|
||||
|
||||
engine.initVerify(parsedKey)
|
||||
}
|
||||
|
||||
override fun engineVerify(sigBytes: ByteArray): Boolean = engine.engineVerify(sigBytes)
|
||||
override fun engineSign(): ByteArray = engine.engineSign()
|
||||
override fun engineUpdate(b: Byte) = engine.engineUpdate(b)
|
||||
override fun engineUpdate(b: ByteArray, off: Int, len: Int) = engine.engineUpdate(b, off, len)
|
||||
override fun engineGetParameters(): AlgorithmParameters {
|
||||
val method = engine.javaClass.getMethod("engineGetParameters")
|
||||
return method.invoke(engine) as AlgorithmParameters
|
||||
}
|
||||
override fun engineSign(): ByteArray = engine.sign()
|
||||
override fun engineVerify(sigBytes: ByteArray): Boolean = engine.verify(sigBytes)
|
||||
|
||||
override fun engineUpdate(b: Byte) = engine.update(b)
|
||||
override fun engineUpdate(b: ByteArray, off: Int, len: Int) = engine.update(b, off, len)
|
||||
|
||||
override fun engineGetParameters(): AlgorithmParameters = engine.parameters
|
||||
override fun engineSetParameter(params: AlgorithmParameterSpec) = engine.setParameter(params)
|
||||
override fun engineGetParameter(param: String): Any = engine.engineGetParameter(param)
|
||||
override fun engineSetParameter(param: String, value: Any?) = engine.engineSetParameter(param, value)
|
||||
override fun engineInitSign(privateKey: PrivateKey, random: SecureRandom) {
|
||||
val method = engine.javaClass.getMethod("engineInitSign", PrivateKey::class.java, SecureRandom::class.java)
|
||||
method.invoke(engine, privateKey, random)
|
||||
}
|
||||
@Suppress("DEPRECATION")
|
||||
override fun engineGetParameter(param: String): Any = engine.getParameter(param)
|
||||
@Suppress("DEPRECATION")
|
||||
override fun engineSetParameter(param: String, value: Any?) = engine.setParameter(param, value)
|
||||
}
|
@ -0,0 +1,117 @@
|
||||
package net.corda.core.internal
|
||||
|
||||
import net.corda.core.crypto.Crypto
|
||||
import net.i2p.crypto.eddsa.EdDSAEngine
|
||||
import net.i2p.crypto.eddsa.EdDSAPublicKey
|
||||
import org.junit.Test
|
||||
import sun.security.util.BitArray
|
||||
import sun.security.util.ObjectIdentifier
|
||||
import sun.security.x509.AlgorithmId
|
||||
import sun.security.x509.X509Key
|
||||
import java.math.BigInteger
|
||||
import java.security.InvalidKeyException
|
||||
import java.util.*
|
||||
import kotlin.test.assertFailsWith
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
class TestX509Key(algorithmId: AlgorithmId, key: BitArray) : X509Key() {
|
||||
init {
|
||||
this.algid = algorithmId
|
||||
this.setKey(key)
|
||||
this.encode()
|
||||
}
|
||||
}
|
||||
|
||||
class X509EdDSAEngineTest {
|
||||
companion object {
|
||||
private const val SEED = 20170920L
|
||||
private const val TEST_DATA_SIZE = 2000
|
||||
|
||||
// offset into an EdDSA header indicating where the key header and actual key start
|
||||
// in the underlying byte array
|
||||
private const val keyHeaderStart = 9
|
||||
private const val keyStart = 12
|
||||
|
||||
private fun toX509Key(publicKey: EdDSAPublicKey): X509Key {
|
||||
val internals = publicKey.encoded
|
||||
|
||||
// key size in the header includes the count unused bits at the end of the key
|
||||
// [keyHeaderStart + 2] but NOT the key header ID [keyHeaderStart] so the
|
||||
// actual length of the key blob is size - 1
|
||||
val keySize = (internals[keyHeaderStart + 1].toInt()) - 1
|
||||
|
||||
val key = ByteArray(keySize)
|
||||
System.arraycopy(internals, keyStart, key, 0, keySize)
|
||||
|
||||
// 1.3.101.102 is the EdDSA OID
|
||||
return TestX509Key(AlgorithmId(ObjectIdentifier("1.3.101.112")), BitArray(keySize * 8, key))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Put the X509EdDSA engine through basic tests to verify that the functions are hooked up correctly.
|
||||
*/
|
||||
@Test
|
||||
fun `sign and verify`() {
|
||||
val engine = X509EdDSAEngine()
|
||||
val keyPair = Crypto.deriveKeyPairFromEntropy(Crypto.EDDSA_ED25519_SHA512, BigInteger.valueOf(SEED))
|
||||
val publicKey = keyPair.public as EdDSAPublicKey
|
||||
val randomBytes = ByteArray(TEST_DATA_SIZE)
|
||||
Random(SEED).nextBytes(randomBytes)
|
||||
engine.initSign(keyPair.private)
|
||||
engine.update(randomBytes[0])
|
||||
engine.update(randomBytes, 1, randomBytes.size - 1)
|
||||
|
||||
// Now verify the signature
|
||||
val signature = engine.sign()
|
||||
|
||||
engine.initVerify(publicKey)
|
||||
engine.update(randomBytes)
|
||||
assertTrue { engine.verify(signature) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that signing with an X509Key wrapped EdDSA key works.
|
||||
*/
|
||||
@Test
|
||||
fun `sign and verify with X509Key`() {
|
||||
val engine = X509EdDSAEngine()
|
||||
val keyPair = Crypto.deriveKeyPairFromEntropy(Crypto.EDDSA_ED25519_SHA512, BigInteger.valueOf(SEED + 1))
|
||||
val publicKey = toX509Key(keyPair.public as EdDSAPublicKey)
|
||||
val randomBytes = ByteArray(TEST_DATA_SIZE)
|
||||
Random(SEED + 1).nextBytes(randomBytes)
|
||||
engine.initSign(keyPair.private)
|
||||
engine.update(randomBytes[0])
|
||||
engine.update(randomBytes, 1, randomBytes.size - 1)
|
||||
|
||||
// Now verify the signature
|
||||
val signature = engine.sign()
|
||||
|
||||
engine.initVerify(publicKey)
|
||||
engine.update(randomBytes)
|
||||
assertTrue { engine.verify(signature) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that signing with an X509Key wrapped EdDSA key fails when using the underlying EdDSAEngine.
|
||||
*/
|
||||
@Test
|
||||
fun `sign and verify with X509Key and old engine fails`() {
|
||||
val engine = EdDSAEngine()
|
||||
val keyPair = Crypto.deriveKeyPairFromEntropy(Crypto.EDDSA_ED25519_SHA512, BigInteger.valueOf(SEED + 1))
|
||||
val publicKey = toX509Key(keyPair.public as EdDSAPublicKey)
|
||||
val randomBytes = ByteArray(TEST_DATA_SIZE)
|
||||
Random(SEED + 1).nextBytes(randomBytes)
|
||||
engine.initSign(keyPair.private)
|
||||
engine.update(randomBytes[0])
|
||||
engine.update(randomBytes, 1, randomBytes.size - 1)
|
||||
|
||||
// Now verify the signature
|
||||
val signature = engine.sign()
|
||||
assertFailsWith<InvalidKeyException> {
|
||||
engine.initVerify(publicKey)
|
||||
engine.update(randomBytes)
|
||||
engine.verify(signature)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user