diff --git a/client/jackson/src/main/kotlin/net/corda/jackson/JacksonSupport.kt b/client/jackson/src/main/kotlin/net/corda/jackson/JacksonSupport.kt index 674b2beb3b..48dfdca9e3 100644 --- a/client/jackson/src/main/kotlin/net/corda/jackson/JacksonSupport.kt +++ b/client/jackson/src/main/kotlin/net/corda/jackson/JacksonSupport.kt @@ -207,7 +207,7 @@ object JacksonSupport { object PublicKeySerializer : JsonSerializer() { override fun serialize(obj: EdDSAPublicKey, generator: JsonGenerator, provider: SerializerProvider) { - check(obj.params == ed25519Curve) + check(obj.params == Crypto.EDDSA_ED25519_SHA512.algSpec) generator.writeString(obj.toBase58String()) } } diff --git a/core/src/main/kotlin/net/corda/core/crypto/CompositeSignature.kt b/core/src/main/kotlin/net/corda/core/crypto/CompositeSignature.kt index 896a101863..69214c380b 100644 --- a/core/src/main/kotlin/net/corda/core/crypto/CompositeSignature.kt +++ b/core/src/main/kotlin/net/corda/core/crypto/CompositeSignature.kt @@ -75,7 +75,7 @@ class CompositeSignature : Signature(ALGORITHM) { val sig = sigBytes.deserialize() return if (verifyKey.isFulfilledBy(sig.sigs.map { it.by })) { val clearData = buffer.toByteArray() - sig.sigs.all { it.isValidForECDSA(clearData) } + sig.sigs.all { it.isValid(clearData) } } else { false } diff --git a/core/src/main/kotlin/net/corda/core/crypto/Crypto.kt b/core/src/main/kotlin/net/corda/core/crypto/Crypto.kt index c20dbd23ec..21593d46da 100644 --- a/core/src/main/kotlin/net/corda/core/crypto/Crypto.kt +++ b/core/src/main/kotlin/net/corda/core/crypto/Crypto.kt @@ -1,6 +1,8 @@ package net.corda.core.crypto +import net.i2p.crypto.eddsa.EdDSAEngine import net.i2p.crypto.eddsa.EdDSAKey +import net.i2p.crypto.eddsa.EdDSASecurityProvider import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable import org.bouncycastle.jce.ECNamedCurveTable import org.bouncycastle.jce.interfaces.ECKey @@ -26,62 +28,61 @@ import java.security.spec.X509EncodedKeySpec * */ object Crypto { + // This map is required to defend against users that forcibly call Security.addProvider / Security.removeProvider + // that could cause unexpected and suspicious behaviour. + // i.e. if someone removes a Provider and then he/she adds a new one with the same name. + // The val is private to avoid any harmful state changes. + private val providerMap = mapOf( + EdDSASecurityProvider.PROVIDER_NAME to EdDSASecurityProvider(), + BouncyCastleProvider.PROVIDER_NAME to BouncyCastleProvider(), + "BCPQC" to BouncyCastlePQCProvider()) // unfortunately, provider's name is not final in BouncyCastlePQCProvider, so we explicitly set it. - 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). - } /** * RSA_SHA256 signature scheme using SHA256 as hash algorithm and MGF1 (with SHA256) as mask generation function. * Note: Recommended key size >= 3072 bits. */ - private val RSA_SHA256 = SignatureScheme( + val RSA_SHA256 = SignatureScheme( 1, "RSA_SHA256", + BouncyCastleProvider.PROVIDER_NAME, "RSA", - Signature.getInstance("SHA256WITHRSAANDMGF1", "BC"), - KeyFactory.getInstance("RSA", "BC"), - KeyPairGenerator.getInstance("RSA", "BC"), + "SHA256WITHRSAANDMGF1", null, 3072, "RSA_SHA256 signature scheme using SHA256 as hash algorithm and MGF1 (with SHA256) as mask generation function." ) /** ECDSA signature scheme using the secp256k1 Koblitz curve. */ - private val ECDSA_SECP256K1_SHA256 = SignatureScheme( + val ECDSA_SECP256K1_SHA256 = SignatureScheme( 2, "ECDSA_SECP256K1_SHA256", + BouncyCastleProvider.PROVIDER_NAME, "ECDSA", - Signature.getInstance("SHA256withECDSA", "BC"), - KeyFactory.getInstance("ECDSA", "BC"), - KeyPairGenerator.getInstance("ECDSA", "BC"), + "SHA256withECDSA", ECNamedCurveTable.getParameterSpec("secp256k1"), 256, "ECDSA signature scheme using the secp256k1 Koblitz curve." ) /** ECDSA signature scheme using the secp256r1 (NIST P-256) curve. */ - private val ECDSA_SECP256R1_SHA256 = SignatureScheme( + val ECDSA_SECP256R1_SHA256 = SignatureScheme( 3, "ECDSA_SECP256R1_SHA256", + BouncyCastleProvider.PROVIDER_NAME, "ECDSA", - Signature.getInstance("SHA256withECDSA", "BC"), - KeyFactory.getInstance("ECDSA", "BC"), - KeyPairGenerator.getInstance("ECDSA", "BC"), + "SHA256withECDSA", ECNamedCurveTable.getParameterSpec("secp256r1"), 256, "ECDSA signature scheme using the secp256r1 (NIST P-256) curve." ) /** EdDSA signature scheme using the ed255519 twisted Edwards curve. */ - private val EDDSA_ED25519_SHA512 = SignatureScheme( + val EDDSA_ED25519_SHA512 = SignatureScheme( 4, "EDDSA_ED25519_SHA512", - "EdDSA", - Signature.getInstance("SHA512withEdDSA", "I2P"), - KeyFactory.getInstance("EdDSA", "I2P"), - KeyPairGenerator.getInstance("EdDSA", "I2P"), + EdDSASecurityProvider.PROVIDER_NAME, + EdDSAKey.KEY_ALGORITHM, + EdDSAEngine.SIGNATURE_ALGORITHM, EdDSANamedCurveTable.getByName("ED25519"), 256, "EdDSA signature scheme using the ed25519 twisted Edwards curve." @@ -91,13 +92,12 @@ object Crypto { * SPHINCS-256 hash-based signature scheme. It provides 128bit security against post-quantum attackers * at the cost of larger key sizes and loss of compatibility. */ - private val SPHINCS256_SHA256 = SignatureScheme( + val SPHINCS256_SHA256 = SignatureScheme( 5, "SPHINCS-256_SHA512", - "SPHINCS-256", - Signature.getInstance("SHA512WITHSPHINCS256", "BCPQC"), - KeyFactory.getInstance("SPHINCS256", "BCPQC"), - KeyPairGenerator.getInstance("SPHINCS256", "BCPQC"), + "BCPQC", + "SPHINCS256", + "SHA512WITHSPHINCS256", SPHINCS256KeyGenParameterSpec(SPHINCS256KeyGenParameterSpec.SHA512_256), 256, "SPHINCS-256 hash-based signature scheme. It provides 128bit security against post-quantum attackers " + @@ -105,20 +105,19 @@ object Crypto { ) /** Our default signature scheme if no algorithm is specified (e.g. for key generation). */ - private val DEFAULT_SIGNATURE_SCHEME = EDDSA_ED25519_SHA512 + val DEFAULT_SIGNATURE_SCHEME = EDDSA_ED25519_SHA512 /** * Supported digital signature schemes. * Note: Only the schemes added in this map will be supported (see [Crypto]). - * Do not forget to add the DEFAULT_SIGNATURE_SCHEME as well. */ - private val supportedSignatureSchemes = mapOf( - RSA_SHA256.schemeCodeName to RSA_SHA256, - ECDSA_SECP256K1_SHA256.schemeCodeName to ECDSA_SECP256K1_SHA256, - ECDSA_SECP256R1_SHA256.schemeCodeName to ECDSA_SECP256R1_SHA256, - EDDSA_ED25519_SHA512.schemeCodeName to EDDSA_ED25519_SHA512, - SPHINCS256_SHA256.schemeCodeName to SPHINCS256_SHA256 - ) + val supportedSignatureSchemes = listOf( + RSA_SHA256, + ECDSA_SECP256K1_SHA256, + ECDSA_SECP256R1_SHA256, + EDDSA_ED25519_SHA512, + SPHINCS256_SHA256 + ).associateBy { it.schemeCodeName } /** * Factory pattern to retrieve the corresponding [SignatureScheme] based on the type of the [String] input. @@ -128,17 +127,7 @@ object Crypto { * @return a currently supported SignatureScheme. * @throws IllegalArgumentException if the requested signature scheme is not supported. */ - private fun findSignatureScheme(schemeCodeName: String): SignatureScheme = supportedSignatureSchemes[schemeCodeName] ?: throw IllegalArgumentException("Unsupported key/algorithm for metadata schemeCodeName: $schemeCodeName") - - /** - * Retrieve the corresponding [SignatureScheme] based on the type of the input [KeyPair]. - * Note that only the Corda platform standard schemes are supported (see [Crypto]). - * This function is usually called when requiring to sign signatures. - * @param keyPair a cryptographic [KeyPair]. - * @return a currently supported SignatureScheme or null. - * @throws IllegalArgumentException if the requested signature scheme is not supported. - */ - private fun findSignatureScheme(keyPair: KeyPair): SignatureScheme = findSignatureScheme(keyPair.private) + fun findSignatureScheme(schemeCodeName: String): SignatureScheme = supportedSignatureSchemes[schemeCodeName] ?: throw IllegalArgumentException("Unsupported key/algorithm for metadata schemeCodeName: $schemeCodeName") /** * Retrieve the corresponding [SignatureScheme] based on the type of the input [Key]. @@ -150,9 +139,11 @@ object Crypto { * @return a currently supported SignatureScheme. * @throws IllegalArgumentException if the requested key type is not supported. */ - private fun findSignatureScheme(key: Key): SignatureScheme { + fun findSignatureScheme(key: Key): SignatureScheme { for (sig in supportedSignatureSchemes.values) { - val algorithm = key.algorithm + var algorithm = key.algorithm + if (algorithm == "EC") algorithm = "ECDSA" // required to read ECC keys from Keystore, because encoding may change algorithm name from ECDSA to EC. + if (algorithm == "SPHINCS-256") algorithm = "SPHINCS256" // because encoding may change algorithm name from SPHINCS256 to SPHINCS-256. if (algorithm == sig.algorithmName) { // If more than one ECDSA schemes are supported, we should distinguish between them by checking their curve parameters. // TODO: change 'continue' to 'break' if only one EdDSA curve will be used. @@ -170,26 +161,18 @@ object Crypto { throw IllegalArgumentException("Unsupported key/algorithm for the private key: ${key.encoded.toBase58()}") } - /** - * Retrieve the corresponding signature scheme code name based on the type of the input [Key]. - * See [Crypto] for the supported scheme code names. - * @param key either private or public. - * @return signatureSchemeCodeName for a [Key]. - * @throws IllegalArgumentException if the requested key type is not supported. - */ - fun findSignatureSchemeCodeName(key: Key): String = findSignatureScheme(key).schemeCodeName - /** * Decode a PKCS8 encoded key to its [PrivateKey] object. + * Use this method if the key type is a-priori unknown. * @param encodedKey a PKCS8 encoded private key. * @throws IllegalArgumentException on not supported scheme or if the given key specification * is inappropriate for this key factory to produce a private key. */ @Throws(IllegalArgumentException::class) fun decodePrivateKey(encodedKey: ByteArray): PrivateKey { - for ((_, _, _, _, keyFactory) in supportedSignatureSchemes.values) { + for ((_, _, providerName, algorithmName) in supportedSignatureSchemes.values) { try { - return keyFactory.generatePrivate(PKCS8EncodedKeySpec(encodedKey)) + return KeyFactory.getInstance(algorithmName, providerMap[providerName]).generatePrivate(PKCS8EncodedKeySpec(encodedKey)) } catch (ikse: InvalidKeySpecException) { // ignore it - only used to bypass the scheme that causes an exception. } @@ -199,17 +182,27 @@ object Crypto { /** * Decode a PKCS8 encoded key to its [PrivateKey] object based on the input scheme code name. - * This will be used by Kryo deserialisation. - * @param encodedKey a PKCS8 encoded private key. + * This should be used when the type key is known, e.g. during Kryo deserialisation or with key caches or key managers. * @param schemeCodeName a [String] that should match a key in supportedSignatureSchemes map (e.g. ECDSA_SECP256K1_SHA256). + * @param encodedKey a PKCS8 encoded private key. * @throws IllegalArgumentException on not supported scheme or if the given key specification * is inappropriate for this key factory to produce a private key. */ @Throws(IllegalArgumentException::class, InvalidKeySpecException::class) - fun decodePrivateKey(encodedKey: ByteArray, schemeCodeName: String): PrivateKey { - val sig = findSignatureScheme(schemeCodeName) + fun decodePrivateKey(schemeCodeName: String, encodedKey: ByteArray): PrivateKey = decodePrivateKey(findSignatureScheme(schemeCodeName), encodedKey) + + /** + * Decode a PKCS8 encoded key to its [PrivateKey] object based on the input scheme code name. + * This should be used when the type key is known, e.g. during Kryo deserialisation or with key caches or key managers. + * @param signatureScheme a signature scheme (e.g. ECDSA_SECP256K1_SHA256). + * @param encodedKey a PKCS8 encoded private key. + * @throws IllegalArgumentException on not supported scheme or if the given key specification + * is inappropriate for this key factory to produce a private key. + */ + @Throws(IllegalArgumentException::class, InvalidKeySpecException::class) + fun decodePrivateKey(signatureScheme: SignatureScheme, encodedKey: ByteArray): PrivateKey { try { - return sig.keyFactory.generatePrivate(PKCS8EncodedKeySpec(encodedKey)) + return KeyFactory.getInstance(signatureScheme.algorithmName, providerMap[signatureScheme.providerName]).generatePrivate(PKCS8EncodedKeySpec(encodedKey)) } catch (ikse: InvalidKeySpecException) { throw InvalidKeySpecException("This private key cannot be decoded, please ensure it is PKCS8 encoded and that it corresponds to the input scheme's code name.", ikse) } @@ -217,16 +210,16 @@ object Crypto { /** * Decode an X509 encoded key to its [PublicKey] object. + * Use this method if the key type is a-priori unknown. * @param encodedKey an X509 encoded public key. - * @throws UnsupportedSchemeException on not supported scheme. * @throws IllegalArgumentException on not supported scheme or if the given key specification * is inappropriate for this key factory to produce a private key. */ @Throws(IllegalArgumentException::class) fun decodePublicKey(encodedKey: ByteArray): PublicKey { - for ((_, _, _, _, keyFactory) in supportedSignatureSchemes.values) { + for ((_, _, providerName, algorithmName) in supportedSignatureSchemes.values) { try { - return keyFactory.generatePublic(X509EncodedKeySpec(encodedKey)) + return KeyFactory.getInstance(algorithmName, providerMap[providerName]).generatePublic(X509EncodedKeySpec(encodedKey)) } catch (ikse: InvalidKeySpecException) { // ignore it - only used to bypass the scheme that causes an exception. } @@ -236,39 +229,34 @@ object Crypto { /** * Decode an X509 encoded key to its [PrivateKey] object based on the input scheme code name. - * This will be used by Kryo deserialisation. - * @param encodedKey an X509 encoded public key. + * This should be used when the type key is known, e.g. during Kryo deserialisation or with key caches or key managers. * @param schemeCodeName a [String] that should match a key in supportedSignatureSchemes map (e.g. ECDSA_SECP256K1_SHA256). + * @param encodedKey an X509 encoded public key. * @throws IllegalArgumentException if the requested scheme is not supported * @throws InvalidKeySpecException if the given key specification * is inappropriate for this key factory to produce a public key. */ @Throws(IllegalArgumentException::class, InvalidKeySpecException::class) - fun decodePublicKey(encodedKey: ByteArray, schemeCodeName: String): PublicKey { - val sig = findSignatureScheme(schemeCodeName) + fun decodePublicKey(schemeCodeName: String, encodedKey: ByteArray): PublicKey = decodePublicKey(findSignatureScheme(schemeCodeName), encodedKey) + + /** + * Decode an X509 encoded key to its [PrivateKey] object based on the input scheme code name. + * This should be used when the type key is known, e.g. during Kryo deserialisation or with key caches or key managers. + * @param signatureScheme a signature scheme (e.g. ECDSA_SECP256K1_SHA256). + * @param encodedKey an X509 encoded public key. + * @throws IllegalArgumentException if the requested scheme is not supported + * @throws InvalidKeySpecException if the given key specification + * is inappropriate for this key factory to produce a public key. + */ + @Throws(IllegalArgumentException::class, InvalidKeySpecException::class) + fun decodePublicKey(signatureScheme: SignatureScheme, encodedKey: ByteArray): PublicKey { try { - return sig.keyFactory.generatePublic(X509EncodedKeySpec(encodedKey)) + return KeyFactory.getInstance(signatureScheme.algorithmName, providerMap[signatureScheme.providerName]).generatePublic(X509EncodedKeySpec(encodedKey)) } catch (ikse: InvalidKeySpecException) { throw throw InvalidKeySpecException("This public key cannot be decoded, please ensure it is X509 encoded and that it corresponds to the input scheme's code name.", ikse) } } - /** - * Utility to simplify the act of generating keys. - * Normally, we don't expect other errors here, assuming that key generation parameters for every supported signature scheme have been unit-tested. - * @param schemeCodeName a signature scheme's code name (e.g. ECDSA_SECP256K1_SHA256). - * @return a KeyPair for the requested scheme. - * @throws IllegalArgumentException if the requested signature scheme is not supported. - */ - @Throws(IllegalArgumentException::class) - fun generateKeyPair(schemeCodeName: String): KeyPair = findSignatureScheme(schemeCodeName).keyPairGenerator.generateKeyPair() - - /** - * Generate a KeyPair using the default signature scheme. - * @return a new KeyPair. - */ - fun generateKeyPair(): KeyPair = DEFAULT_SIGNATURE_SCHEME.keyPairGenerator.generateKeyPair() - /** * Generic way to sign [ByteArray] data with a [PrivateKey]. Strategy on on identifying the actual signing scheme is based * on the [PrivateKey] type, but if the schemeCodeName is known, then better use doSign(signatureScheme: String, privateKey: PrivateKey, clearData: ByteArray). @@ -280,7 +268,7 @@ object Crypto { * @throws SignatureException if signing is not possible due to malformed data or private key. */ @Throws(IllegalArgumentException::class, InvalidKeyException::class, SignatureException::class) - fun doSign(privateKey: PrivateKey, clearData: ByteArray) = doSign(findSignatureScheme(privateKey).sig, privateKey, clearData) + fun doSign(privateKey: PrivateKey, clearData: ByteArray) = doSign(findSignatureScheme(privateKey), privateKey, clearData) /** * Generic way to sign [ByteArray] data with a [PrivateKey] and a known schemeCodeName [String]. @@ -293,11 +281,11 @@ object Crypto { * @throws SignatureException if signing is not possible due to malformed data or private key. */ @Throws(IllegalArgumentException::class, InvalidKeyException::class, SignatureException::class) - fun doSign(schemeCodeName: String, privateKey: PrivateKey, clearData: ByteArray) = doSign(findSignatureScheme(schemeCodeName).sig, privateKey, clearData) + fun doSign(schemeCodeName: String, privateKey: PrivateKey, clearData: ByteArray) = doSign(findSignatureScheme(schemeCodeName), privateKey, clearData) /** * Generic way to sign [ByteArray] data with a [PrivateKey] and a known [Signature]. - * @param signature a [Signature] object, retrieved from supported signature schemes, see [Crypto]. + * @param signatureScheme a [SignatureScheme] object, retrieved from supported signature schemes, see [Crypto]. * @param privateKey the signer's [PrivateKey]. * @param clearData the data/message to be signed in [ByteArray] form (usually the Merkle root). * @return the digital signature (in [ByteArray]) on the input message. @@ -306,7 +294,10 @@ object Crypto { * @throws SignatureException if signing is not possible due to malformed data or private key. */ @Throws(IllegalArgumentException::class, InvalidKeyException::class, SignatureException::class) - private fun doSign(signature: Signature, privateKey: PrivateKey, clearData: ByteArray): ByteArray { + fun doSign(signatureScheme: SignatureScheme, privateKey: PrivateKey, clearData: ByteArray): ByteArray { + if (!supportedSignatureSchemes.containsKey(signatureScheme.schemeCodeName)) + throw IllegalArgumentException("Unsupported key/algorithm for schemeCodeName: $signatureScheme.schemeCodeName") + val signature = Signature.getInstance(signatureScheme.signatureName, providerMap[signatureScheme.providerName]) if (clearData.isEmpty()) throw Exception("Signing of an empty array is not permitted!") signature.initSign(privateKey) signature.update(clearData) @@ -336,6 +327,7 @@ object Crypto { /** * Utility to simplify the act of verifying a digital signature. * It returns true if it succeeds, but it always throws an exception if verification fails. + * @param schemeCodeName a signature scheme's code name (e.g. ECDSA_SECP256K1_SHA256). * @param publicKey the signer's [PublicKey]. * @param signatureData the signatureData on a message. * @param clearData the clear data/message that was signed (usually the Merkle root). @@ -347,7 +339,7 @@ object Crypto { * @throws IllegalArgumentException if the signature scheme is not supported or if any of the clear or signature data is empty. */ @Throws(InvalidKeyException::class, SignatureException::class, IllegalArgumentException::class) - fun doVerify(schemeCodeName: String, publicKey: PublicKey, signatureData: ByteArray, clearData: ByteArray) = doVerify(findSignatureScheme(schemeCodeName).sig, publicKey, signatureData, clearData) + fun doVerify(schemeCodeName: String, publicKey: PublicKey, signatureData: ByteArray, clearData: ByteArray) = doVerify(findSignatureScheme(schemeCodeName), publicKey, signatureData, clearData) /** * Utility to simplify the act of verifying a digital signature by identifying the signature scheme used from the input public key's type. @@ -365,12 +357,12 @@ object Crypto { * @throws IllegalArgumentException if the signature scheme is not supported or if any of the clear or signature data is empty. */ @Throws(InvalidKeyException::class, SignatureException::class, IllegalArgumentException::class) - fun doVerify(publicKey: PublicKey, signatureData: ByteArray, clearData: ByteArray) = doVerify(findSignatureScheme(publicKey).sig, publicKey, signatureData, clearData) + fun doVerify(publicKey: PublicKey, signatureData: ByteArray, clearData: ByteArray) = doVerify(findSignatureScheme(publicKey), publicKey, signatureData, clearData) /** * Method to verify a digital signature. * It returns true if it succeeds, but it always throws an exception if verification fails. - * @param signature a [Signature] object, retrieved from supported signature schemes, see [Crypto]. + * @param signatureScheme a [SignatureScheme] object, retrieved from supported signature schemes, see [Crypto]. * @param publicKey the signer's [PublicKey]. * @param signatureData the signatureData on a message. * @param clearData the clear data/message that was signed (usually the Merkle root). @@ -379,14 +371,15 @@ object Crypto { * @throws SignatureException if this signatureData object is not initialized properly, * the passed-in signatureData is improperly encoded or of the wrong type, * if this signatureData scheme is unable to process the input data provided, if the verification is not possible. - * @throws IllegalArgumentException if any of the clear or signature data is empty. + * @throws IllegalArgumentException if the signature scheme is not supported or if any of the clear or signature data is empty. */ - private fun doVerify(signature: Signature, publicKey: PublicKey, signatureData: ByteArray, clearData: ByteArray): Boolean { + @Throws(InvalidKeyException::class, SignatureException::class, IllegalArgumentException::class) + fun doVerify(signatureScheme: SignatureScheme, publicKey: PublicKey, signatureData: ByteArray, clearData: ByteArray): Boolean { + if (!supportedSignatureSchemes.containsKey(signatureScheme.schemeCodeName)) + throw IllegalArgumentException("Unsupported key/algorithm for schemeCodeName: $signatureScheme.schemeCodeName") if (signatureData.isEmpty()) throw IllegalArgumentException("Signature data is empty!") if (clearData.isEmpty()) throw IllegalArgumentException("Clear data is empty, nothing to verify!") - signature.initVerify(publicKey) - signature.update(clearData) - val verificationResult = signature.verify(signatureData) + val verificationResult = isValid(signatureScheme, publicKey, signatureData, clearData) if (verificationResult) { return true } else { @@ -413,15 +406,82 @@ object Crypto { } /** - * Check if the requested signature scheme is supported by the system. - * @param schemeCodeName a signature scheme's code name (e.g. ECDSA_SECP256K1_SHA256). - * @return true if the signature scheme is supported. + * Utility to simplify the act of verifying a digital signature by identifying the signature scheme used from the input public key's type. + * It returns true if it succeeds and false if not. In comparison to [doVerify] if the key and signature + * do not match it returns false rather than throwing an exception. Normally you should use the function which throws, + * as it avoids the risk of failing to test the result. + * Use this method if the signature scheme is not a-priori known. + * @param publicKey the signer's [PublicKey]. + * @param signatureData the signatureData on a message. + * @param clearData the clear data/message that was signed (usually the Merkle root). + * @return true if verification passes or false if verification fails. + * @throws SignatureException if this signatureData object is not initialized properly, + * the passed-in signatureData is improperly encoded or of the wrong type, + * if this signatureData scheme is unable to process the input data provided, if the verification is not possible. */ + @Throws(SignatureException::class) + fun isValid(publicKey: PublicKey, signatureData: ByteArray, clearData: ByteArray) = isValid(findSignatureScheme(publicKey), publicKey, signatureData, clearData) + + /** + * Method to verify a digital signature. In comparison to [doVerify] if the key and signature + * do not match it returns false rather than throwing an exception. + * Use this method if the signature scheme type is a-priori unknown. + * @param signatureScheme a [SignatureScheme] object, retrieved from supported signature schemes, see [Crypto]. + * @param publicKey the signer's [PublicKey]. + * @param signatureData the signatureData on a message. + * @param clearData the clear data/message that was signed (usually the Merkle root). + * @return true if verification passes or false if verification fails. + * @throws SignatureException if this signatureData object is not initialized properly, + * the passed-in signatureData is improperly encoded or of the wrong type, + * if this signatureData scheme is unable to process the input data provided, if the verification is not possible. + * @throws IllegalArgumentException if the requested signature scheme is not supported. + */ + @Throws(SignatureException::class, IllegalArgumentException::class) + fun isValid(signatureScheme: SignatureScheme, publicKey: PublicKey, signatureData: ByteArray, clearData: ByteArray): Boolean { + if (!supportedSignatureSchemes.containsKey(signatureScheme.schemeCodeName)) + throw IllegalArgumentException("Unsupported key/algorithm for schemeCodeName: $signatureScheme.schemeCodeName") + val signature = Signature.getInstance(signatureScheme.signatureName, providerMap[signatureScheme.providerName]) + signature.initVerify(publicKey) + signature.update(clearData) + return signature.verify(signatureData) + } + + /** + * Utility to simplify the act of generating keys. + * Normally, we don't expect other errors here, assuming that key generation parameters for every supported signature scheme have been unit-tested. + * @param schemeCodeName a signature scheme's code name (e.g. ECDSA_SECP256K1_SHA256). + * @return a KeyPair for the requested signature scheme code name. + * @throws IllegalArgumentException if the requested signature scheme is not supported. + */ + @Throws(IllegalArgumentException::class) + fun generateKeyPair(schemeCodeName: String): KeyPair = generateKeyPair(findSignatureScheme(schemeCodeName)) + + /** + * Generate a [KeyPair] for the selected [SignatureScheme]. + * Note that RSA is the sole algorithm initialized specifically by its supported keySize. + * @param signatureScheme a supported [SignatureScheme], see [Crypto]. + * @return a new [KeyPair] for the requested [SignatureScheme]. + * @throws IllegalArgumentException if the requested signature scheme is not supported. + */ + @Throws(IllegalArgumentException::class) + fun generateKeyPair(signatureScheme: SignatureScheme): KeyPair { + if (!supportedSignatureSchemes.containsKey(signatureScheme.schemeCodeName)) + throw IllegalArgumentException("Unsupported key/algorithm for schemeCodeName: $signatureScheme.schemeCodeName") + val keyPairGenerator = KeyPairGenerator.getInstance(signatureScheme.algorithmName, providerMap[signatureScheme.providerName]) + if (signatureScheme.algSpec != null) + keyPairGenerator.initialize(signatureScheme.algSpec, newSecureRandom()) + else + keyPairGenerator.initialize(signatureScheme.keySize, newSecureRandom()) + return keyPairGenerator.generateKeyPair() + } + + /** + * Generate a [KeyPair] using the default signature scheme. + * @return a new [KeyPair]. + */ + fun generateKeyPair(): KeyPair = generateKeyPair(DEFAULT_SIGNATURE_SCHEME) + + /** Check if the requested signature scheme is supported by the system. */ fun isSupportedSignatureScheme(schemeCodeName: String): Boolean = schemeCodeName in supportedSignatureSchemes - - /** @return the default signature scheme's code name. */ - fun getDefaultSignatureSchemeCodeName(): String = DEFAULT_SIGNATURE_SCHEME.schemeCodeName - - /** @return a [List] of Strings with the scheme code names defined in [SignatureScheme] for all of our supported signature schemes, see [Crypto]. */ - fun listSupportedSignatureSchemes(): List = supportedSignatureSchemes.keys.toList() + fun isSupportedSignatureScheme(signatureScheme: SignatureScheme): Boolean = signatureScheme.schemeCodeName in supportedSignatureSchemes } diff --git a/core/src/main/kotlin/net/corda/core/crypto/CryptoUtils.kt b/core/src/main/kotlin/net/corda/core/crypto/CryptoUtils.kt index 9b7c171763..29f0c4e91c 100644 --- a/core/src/main/kotlin/net/corda/core/crypto/CryptoUtils.kt +++ b/core/src/main/kotlin/net/corda/core/crypto/CryptoUtils.kt @@ -4,11 +4,8 @@ package net.corda.core.crypto import net.corda.core.serialization.CordaSerializable import net.corda.core.serialization.OpaqueBytes -import net.i2p.crypto.eddsa.EdDSAEngine import net.i2p.crypto.eddsa.EdDSAPrivateKey import net.i2p.crypto.eddsa.EdDSAPublicKey -import net.i2p.crypto.eddsa.KeyPairGenerator -import net.i2p.crypto.eddsa.spec.EdDSANamedCurveSpec import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable import net.i2p.crypto.eddsa.spec.EdDSAPrivateKeySpec import net.i2p.crypto.eddsa.spec.EdDSAPublicKeySpec @@ -40,34 +37,45 @@ class DummyPublicKey(val s: String) : PublicKey, Comparable { @CordaSerializable object NullSignature : DigitalSignature.WithKey(NullPublicKey, ByteArray(32)) -/** Utility to simplify the act of signing a byte array */ -fun PrivateKey.signWithECDSA(bytes: ByteArray): DigitalSignature { - val signer = EdDSAEngine() - signer.initSign(this) - signer.update(bytes) - val sig = signer.sign() - return DigitalSignature(sig) +/** + * Utility to simplify the act of signing a byte array. + * @param bytesToSign the data/message to be signed in [ByteArray] form (usually the Merkle root). + * @return the [DigitalSignature] object on the input message. + * @throws IllegalArgumentException if the signature scheme is not supported for this private key. + * @throws InvalidKeyException if the private key is invalid. + * @throws SignatureException if signing is not possible due to malformed data or private key. + */ +@Throws(IllegalArgumentException::class, InvalidKeyException::class, SignatureException::class) +fun PrivateKey.sign(bytesToSign: ByteArray): DigitalSignature { + return DigitalSignature(Crypto.doSign(this, bytesToSign)) } -fun PrivateKey.signWithECDSA(bytesToSign: ByteArray, publicKey: PublicKey): DigitalSignature.WithKey { - return DigitalSignature.WithKey(publicKey, signWithECDSA(bytesToSign).bytes) +fun PrivateKey.sign(bytesToSign: ByteArray, publicKey: PublicKey): DigitalSignature.WithKey { + return DigitalSignature.WithKey(publicKey, this.sign(bytesToSign).bytes) } -val ed25519Curve: EdDSANamedCurveSpec = EdDSANamedCurveTable.getByName("ED25519") +/** + * Helper function to sign with a key pair. + * @param bytesToSign the data/message to be signed in [ByteArray] form (usually the Merkle root). + * @return the digital signature (in [ByteArray]) on the input message. + * @throws IllegalArgumentException if the signature scheme is not supported for this private key. + * @throws InvalidKeyException if the private key is invalid. + * @throws SignatureException if signing is not possible due to malformed data or private key. + */ +@Throws(IllegalArgumentException::class, InvalidKeyException::class, SignatureException::class) +fun KeyPair.sign(bytesToSign: ByteArray) = private.sign(bytesToSign, public) +fun KeyPair.sign(bytesToSign: OpaqueBytes) = private.sign(bytesToSign.bytes, public) +fun KeyPair.sign(bytesToSign: OpaqueBytes, party: Party) = sign(bytesToSign.bytes, party) -fun KeyPair.signWithECDSA(bytesToSign: ByteArray) = private.signWithECDSA(bytesToSign, public) -fun KeyPair.signWithECDSA(bytesToSign: OpaqueBytes) = private.signWithECDSA(bytesToSign.bytes, public) -fun KeyPair.signWithECDSA(bytesToSign: OpaqueBytes, party: Party) = signWithECDSA(bytesToSign.bytes, party) // TODO This case will need more careful thinking, as party owningKey can be a CompositeKey. One way of doing that is // implementation of CompositeSignature. @Throws(InvalidKeyException::class) -fun KeyPair.signWithECDSA(bytesToSign: ByteArray, party: Party): DigitalSignature.LegallyIdentifiable { - val sig = signWithECDSA(bytesToSign) +fun KeyPair.sign(bytesToSign: ByteArray, party: Party): DigitalSignature.LegallyIdentifiable { + val sig = sign(bytesToSign) val sigKey = when (party.owningKey) { // Quick workaround when we have CompositeKey as Party owningKey. is CompositeKey -> throw InvalidKeyException("Signing for parties with CompositeKey not supported.") else -> party.owningKey } - sigKey.verifyWithECDSA(bytesToSign, sig) return DigitalSignature.LegallyIdentifiable(party, sig.bytes) } @@ -77,18 +85,14 @@ fun KeyPair.signWithECDSA(bytesToSign: ByteArray, party: Party): DigitalSignatur * @throws InvalidKeyException if the key to verify the signature with is not valid (i.e. wrong key type for the * signature). * @throws SignatureException if the signature is invalid (i.e. damaged), or does not match the key (incorrect). + * @throws IllegalArgumentException if the signature scheme is not supported or if any of the clear or signature data is empty. */ // TODO: SignatureException should be used only for a damaged signature, as per `java.security.Signature.verify()`, -// we should use another exception (perhaps IllegalArgumentException) for indicating the signature is valid but does -// not match. -@Throws(IllegalStateException::class, SignatureException::class) -fun PublicKey.verifyWithECDSA(content: ByteArray, signature: DigitalSignature) { - if (!isValidForECDSA(content, signature)) - throw SignatureException("Signature did not match") -} +@Throws(SignatureException::class, IllegalArgumentException::class, InvalidKeyException::class) +fun PublicKey.verify(content: ByteArray, signature: DigitalSignature) = Crypto.doVerify(this, signature.bytes, content) /** - * Utility to simplify the act of verifying a signature. In comparison to [verifyWithECDSA] if the key and signature + * Utility to simplify the act of verifying a signature. In comparison to [verify] if the key and signature * do not match it returns false rather than throwing an exception. Normally you should use the function which throws, * as it avoids the risk of failing to test the result, but this is for uses such as [java.security.Signature.verify] * implementations. @@ -96,18 +100,14 @@ fun PublicKey.verifyWithECDSA(content: ByteArray, signature: DigitalSignature) { * @throws InvalidKeyException if the key to verify the signature with is not valid (i.e. wrong key type for the * signature). * @throws SignatureException if the signature is invalid (i.e. damaged). + * @throws IllegalArgumentException if the signature scheme is not supported or if any of the clear or signature data is empty. * @return whether the signature is correct for this key. */ -@Throws(IllegalStateException::class, SignatureException::class) -fun PublicKey.isValidForECDSA(content: ByteArray, signature: DigitalSignature) : Boolean { - val pubKey = when (this) { - is CompositeKey -> throw IllegalStateException("Verification of CompositeKey signatures currently not supported.") // TODO CompositeSignature verification. - else -> this - } - val verifier = EdDSAEngine() - verifier.initVerify(pubKey) - verifier.update(content) - return verifier.verify(signature.bytes) +@Throws(IllegalStateException::class, SignatureException::class, IllegalArgumentException::class) +fun PublicKey.isValid(content: ByteArray, signature: DigitalSignature) : Boolean { + if (this is CompositeKey) + throw IllegalStateException("Verification of CompositeKey signatures currently not supported.") // TODO CompositeSignature verification. + return Crypto.isValid(this, signature.bytes, content) } /** Render a public key to a string, using a short form if it's an elliptic curve public key */ @@ -148,27 +148,17 @@ fun generateKeyPair(): KeyPair = Crypto.generateKeyPair() /** * Returns a key pair derived from the given private key entropy. This is useful for unit tests and other cases where * you want hard-coded private keys. + * This currently works for EdDSA ED25519 only. */ fun entropyToKeyPair(entropy: BigInteger): KeyPair { - val params = ed25519Curve + val params = EdDSANamedCurveTable.getByName("ED25519") val bytes = entropy.toByteArray().copyOf(params.curve.field.getb() / 8) val priv = EdDSAPrivateKeySpec(bytes, params) val pub = EdDSAPublicKeySpec(priv.a, params) - val key = KeyPair(EdDSAPublicKey(pub), EdDSAPrivateKey(priv)) - return key + val keyPair = KeyPair(EdDSAPublicKey(pub), EdDSAPrivateKey(priv)) + return keyPair } -/** - * Helper function for signing. - * @param clearData the data/message to be signed in [ByteArray] form (usually the Merkle root). - * @return the digital signature (in [ByteArray]) on the input message. - * @throws IllegalArgumentException if the signature scheme is not supported for this private key. - * @throws InvalidKeyException if the private key is invalid. - * @throws SignatureException if signing is not possible due to malformed data or private key. - */ -@Throws(IllegalArgumentException::class, InvalidKeyException::class, SignatureException::class) -fun PrivateKey.sign(clearData: ByteArray): ByteArray = Crypto.doSign(this, clearData) - /** * Helper function for signing. * @param metaData tha attached MetaData object. @@ -180,17 +170,6 @@ fun PrivateKey.sign(clearData: ByteArray): ByteArray = Crypto.doSign(this, clear @Throws(InvalidKeyException::class, SignatureException::class, IllegalArgumentException::class) fun PrivateKey.sign(metaData: MetaData): TransactionSignature = Crypto.doSign(this, metaData) -/** - * Helper function to sign with a key pair. - * @param clearData the data/message to be signed in [ByteArray] form (usually the Merkle root). - * @return the digital signature (in [ByteArray]) on the input message. - * @throws IllegalArgumentException if the signature scheme is not supported for this private key. - * @throws InvalidKeyException if the private key is invalid. - * @throws SignatureException if signing is not possible due to malformed data or private key. - */ -@Throws(IllegalArgumentException::class, InvalidKeyException::class, SignatureException::class) -fun KeyPair.sign(clearData: ByteArray): ByteArray = Crypto.doSign(this.private, clearData) - /** * Helper function to verify a signature. * @param signatureData the signature on a message. diff --git a/core/src/main/kotlin/net/corda/core/crypto/DigitalSignature.kt b/core/src/main/kotlin/net/corda/core/crypto/DigitalSignature.kt index 4e77576180..f9967d103f 100644 --- a/core/src/main/kotlin/net/corda/core/crypto/DigitalSignature.kt +++ b/core/src/main/kotlin/net/corda/core/crypto/DigitalSignature.kt @@ -22,7 +22,7 @@ open class DigitalSignature(bits: ByteArray) : OpaqueBytes(bits) { * @throws SignatureException if the signature is invalid (i.e. damaged), or does not match the key (incorrect). */ @Throws(InvalidKeyException::class, SignatureException::class) - fun verifyWithECDSA(content: ByteArray) = by.verifyWithECDSA(content, this) + fun verify(content: ByteArray) = by.verify(content, this) /** * Utility to simplify the act of verifying a signature. * @@ -31,9 +31,9 @@ open class DigitalSignature(bits: ByteArray) : OpaqueBytes(bits) { * @throws SignatureException if the signature is invalid (i.e. damaged), or does not match the key (incorrect). */ @Throws(InvalidKeyException::class, SignatureException::class) - fun verifyWithECDSA(content: OpaqueBytes) = by.verifyWithECDSA(content.bytes, this) + fun verify(content: OpaqueBytes) = by.verify(content.bytes, this) /** - * Utility to simplify the act of verifying a signature. In comparison to [verifyWithECDSA] doesn't throw an + * Utility to simplify the act of verifying a signature. In comparison to [verify] doesn't throw an * exception, making it more suitable where a boolean is required, but normally you should use the function * which throws, as it avoids the risk of failing to test the result. * @@ -43,7 +43,7 @@ open class DigitalSignature(bits: ByteArray) : OpaqueBytes(bits) { * @return whether the signature is correct for this key. */ @Throws(InvalidKeyException::class, SignatureException::class) - fun isValidForECDSA(content: ByteArray) = by.isValidForECDSA(content, this) + fun isValid(content: ByteArray) = by.isValid(content, this) } // TODO: consider removing this as whoever needs to identify the signer should be able to derive it from the public key diff --git a/core/src/main/kotlin/net/corda/core/crypto/I2PProvider.kt b/core/src/main/kotlin/net/corda/core/crypto/I2PProvider.kt deleted file mode 100644 index fafc8b2c92..0000000000 --- a/core/src/main/kotlin/net/corda/core/crypto/I2PProvider.kt +++ /dev/null @@ -1,34 +0,0 @@ -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") - } -} diff --git a/core/src/main/kotlin/net/corda/core/crypto/SignatureScheme.kt b/core/src/main/kotlin/net/corda/core/crypto/SignatureScheme.kt index 0a135b8713..39031fe6c9 100644 --- a/core/src/main/kotlin/net/corda/core/crypto/SignatureScheme.kt +++ b/core/src/main/kotlin/net/corda/core/crypto/SignatureScheme.kt @@ -1,7 +1,5 @@ package net.corda.core.crypto -import java.security.KeyFactory -import java.security.KeyPairGeneratorSpi import java.security.Signature import java.security.spec.AlgorithmParameterSpec @@ -9,12 +7,9 @@ import java.security.spec.AlgorithmParameterSpec * This class is used to define a digital signature scheme. * @param schemeNumberID we assign a number ID for more efficient on-wire serialisation. Please ensure uniqueness between schemes. * @param schemeCodeName code name for this signature scheme (e.g. RSA_SHA256, ECDSA_SECP256K1_SHA256, ECDSA_SECP256R1_SHA256, EDDSA_ED25519_SHA512, SPHINCS-256_SHA512). + * @param providerName the provider's name (e.g. "BC"). * @param algorithmName which signature algorithm is used (e.g. RSA, ECDSA. EdDSA, SPHINCS-256). - * @param sig the [Signature] class that provides the functionality of a digital signature scheme. - * eg. Signature.getInstance("SHA256withECDSA", "BC"). - * @param keyFactory the KeyFactory for this scheme (e.g. KeyFactory.getInstance("RSA", "BC")). - * @param keyPairGenerator defines the Service Provider Interface (SPI) for the {@code KeyPairGenerator} class. - * e.g. KeyPairGenerator.getInstance("ECDSA", "BC"). + * @param signatureName a signature-scheme name as required to create [Signature] objects (e.g. "SHA256withECDSA") * @param algSpec parameter specs for the underlying algorithm. Note that RSA is defined by the key size rather than algSpec. * eg. ECGenParameterSpec("secp256k1"). * @param keySize the private key size (currently used for RSA only). @@ -23,22 +18,9 @@ import java.security.spec.AlgorithmParameterSpec data class SignatureScheme( val schemeNumberID: Int, val schemeCodeName: String, + val providerName: String, val algorithmName: String, - val sig: Signature, - val keyFactory: KeyFactory, - val keyPairGenerator: KeyPairGeneratorSpi, + val signatureName: String, val algSpec: AlgorithmParameterSpec?, val keySize: Int, - val desc: String) { - - /** - * KeyPair generators are always initialized once we create them, as no re-initialization is required. - * Note that RSA is the sole algorithm initialized specifically by its supported keySize. - */ - init { - if (algSpec != null) - keyPairGenerator.initialize(algSpec, newSecureRandom()) - else - keyPairGenerator.initialize(keySize, newSecureRandom()) - } -} + val desc: String) diff --git a/core/src/main/kotlin/net/corda/core/crypto/SignedData.kt b/core/src/main/kotlin/net/corda/core/crypto/SignedData.kt index b026e94dca..f1262f84af 100644 --- a/core/src/main/kotlin/net/corda/core/crypto/SignedData.kt +++ b/core/src/main/kotlin/net/corda/core/crypto/SignedData.kt @@ -22,7 +22,7 @@ open class SignedData(val raw: SerializedBytes, val sig: DigitalSign */ @Throws(SignatureException::class) fun verified(): T { - sig.by.verifyWithECDSA(raw.bytes, sig) + sig.by.verify(raw.bytes, sig) val data = raw.deserialize() verifyData(data) return data diff --git a/core/src/main/kotlin/net/corda/core/serialization/DefaultKryoCustomizer.kt b/core/src/main/kotlin/net/corda/core/serialization/DefaultKryoCustomizer.kt index 0bac6a20cb..b553a0f67f 100644 --- a/core/src/main/kotlin/net/corda/core/serialization/DefaultKryoCustomizer.kt +++ b/core/src/main/kotlin/net/corda/core/serialization/DefaultKryoCustomizer.kt @@ -18,6 +18,12 @@ import net.corda.core.utilities.NonEmptySetSerializer import net.i2p.crypto.eddsa.EdDSAPrivateKey import net.i2p.crypto.eddsa.EdDSAPublicKey import org.bouncycastle.asn1.x500.X500Name +import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey +import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey +import org.bouncycastle.jcajce.provider.asymmetric.rsa.BCRSAPrivateCrtKey +import org.bouncycastle.jcajce.provider.asymmetric.rsa.BCRSAPublicKey +import org.bouncycastle.pqc.jcajce.provider.sphincs.BCSphincs256PrivateKey +import org.bouncycastle.pqc.jcajce.provider.sphincs.BCSphincs256PublicKey import org.objenesis.strategy.StdInstantiatorStrategy import org.slf4j.Logger import java.io.BufferedInputStream @@ -93,6 +99,13 @@ object DefaultKryoCustomizer { register(X500Name::class.java, X500NameSerializer) + register(BCECPrivateKey::class.java, PrivateKeySerializer) + register(BCECPublicKey::class.java, PublicKeySerializer) + register(BCRSAPrivateCrtKey::class.java, PrivateKeySerializer) + register(BCRSAPublicKey::class.java, PublicKeySerializer) + register(BCSphincs256PrivateKey::class.java, PrivateKeySerializer) + register(BCSphincs256PublicKey::class.java, PublicKeySerializer) + val customization = KryoSerializationCustomization(this) pluginRegistries.forEach { it.customizeSerialization(customization) } } diff --git a/core/src/main/kotlin/net/corda/core/serialization/Kryo.kt b/core/src/main/kotlin/net/corda/core/serialization/Kryo.kt index 2ea8fc8f83..bdd23b170e 100644 --- a/core/src/main/kotlin/net/corda/core/serialization/Kryo.kt +++ b/core/src/main/kotlin/net/corda/core/serialization/Kryo.kt @@ -12,6 +12,7 @@ import net.corda.core.node.AttachmentsClassLoader import net.corda.core.transactions.WireTransaction import net.i2p.crypto.eddsa.EdDSAPrivateKey import net.i2p.crypto.eddsa.EdDSAPublicKey +import net.i2p.crypto.eddsa.spec.EdDSANamedCurveSpec import net.i2p.crypto.eddsa.spec.EdDSAPrivateKeySpec import net.i2p.crypto.eddsa.spec.EdDSAPublicKeySpec import org.bouncycastle.asn1.ASN1InputStream @@ -22,6 +23,7 @@ import java.io.* import java.lang.reflect.InvocationTargetException import java.nio.file.Files import java.nio.file.Path +import java.security.PrivateKey import java.security.PublicKey import java.security.spec.InvalidKeySpecException import java.time.Instant @@ -340,13 +342,13 @@ object WireTransactionSerializer : Serializer() { @ThreadSafe object Ed25519PrivateKeySerializer : Serializer() { override fun write(kryo: Kryo, output: Output, obj: EdDSAPrivateKey) { - check(obj.params == ed25519Curve) + check(obj.params == Crypto.EDDSA_ED25519_SHA512.algSpec ) output.writeBytesWithLength(obj.seed) } override fun read(kryo: Kryo, input: Input, type: Class): EdDSAPrivateKey { val seed = input.readBytesWithLength() - return EdDSAPrivateKey(EdDSAPrivateKeySpec(seed, ed25519Curve)) + return EdDSAPrivateKey(EdDSAPrivateKeySpec(seed, Crypto.EDDSA_ED25519_SHA512.algSpec as EdDSANamedCurveSpec)) } } @@ -354,13 +356,13 @@ object Ed25519PrivateKeySerializer : Serializer() { @ThreadSafe object Ed25519PublicKeySerializer : Serializer() { override fun write(kryo: Kryo, output: Output, obj: EdDSAPublicKey) { - check(obj.params == ed25519Curve) + check(obj.params == Crypto.EDDSA_ED25519_SHA512.algSpec) output.writeBytesWithLength(obj.abyte) } override fun read(kryo: Kryo, input: Input, type: Class): EdDSAPublicKey { val A = input.readBytesWithLength() - return EdDSAPublicKey(EdDSAPublicKeySpec(A, ed25519Curve)) + return EdDSAPublicKey(EdDSAPublicKeySpec(A, Crypto.EDDSA_ED25519_SHA512.algSpec as EdDSANamedCurveSpec)) } } @@ -382,6 +384,31 @@ object CompositeKeySerializer : Serializer() { } } +@ThreadSafe +object PrivateKeySerializer : Serializer() { + override fun write(kryo: Kryo, output: Output, obj: PrivateKey) { + output.writeBytesWithLength(obj.encoded) + } + + override fun read(kryo: Kryo, input: Input, type: Class): PrivateKey { + val A = input.readBytesWithLength() + return Crypto.decodePrivateKey(A) + } +} + +/** For serialising a public key */ +@ThreadSafe +object PublicKeySerializer : Serializer() { + override fun write(kryo: Kryo, output: Output, obj: PublicKey) { + output.writeBytesWithLength(obj.encoded) + } + + override fun read(kryo: Kryo, input: Input, type: Class): PublicKey { + val A = input.readBytesWithLength() + return Crypto.decodePublicKey(A) + } +} + /** * Helper function for reading lists with number of elements at the beginning. * @param minLen minimum number of elements we expect for list to include, defaults to 1 @@ -525,7 +552,7 @@ object MetaDataSerializer : Serializer() { val visibleInputs = kryo.readClassAndObject(input) as BitSet? val signedInputs = kryo.readClassAndObject(input) as BitSet? val merkleRoot = input.readBytesWithLength() - val publicKey = Crypto.decodePublicKey(input.readBytesWithLength(), schemeCodeName) + val publicKey = Crypto.decodePublicKey(schemeCodeName, input.readBytesWithLength()) return MetaData(schemeCodeName, versionID, signatureType, timestamp, visibleInputs, signedInputs, merkleRoot, publicKey) } } diff --git a/core/src/main/kotlin/net/corda/core/transactions/SignedTransaction.kt b/core/src/main/kotlin/net/corda/core/transactions/SignedTransaction.kt index c3d6bea73a..e4358a9092 100644 --- a/core/src/main/kotlin/net/corda/core/transactions/SignedTransaction.kt +++ b/core/src/main/kotlin/net/corda/core/transactions/SignedTransaction.kt @@ -7,7 +7,7 @@ import net.corda.core.node.ServiceHub import net.corda.core.crypto.DigitalSignature import net.corda.core.crypto.SecureHash import net.corda.core.crypto.isFulfilledBy -import net.corda.core.crypto.signWithECDSA +import net.corda.core.crypto.sign import net.corda.core.serialization.CordaSerializable import net.corda.core.serialization.SerializedBytes import java.security.KeyPair @@ -93,7 +93,7 @@ data class SignedTransaction(val txBits: SerializedBytes, @Throws(SignatureException::class) fun checkSignaturesAreValid() { for (sig in sigs) { - sig.verifyWithECDSA(id.bytes) + sig.verify(id.bytes) } } @@ -153,7 +153,7 @@ data class SignedTransaction(val txBits: SerializedBytes, * * @return a digital signature of the transaction. */ - fun signWithECDSA(keyPair: KeyPair) = keyPair.signWithECDSA(this.id.bytes) + fun signWithECDSA(keyPair: KeyPair) = keyPair.sign(this.id.bytes) override fun toString(): String = "${javaClass.simpleName}(id=$id)" } diff --git a/core/src/main/kotlin/net/corda/core/transactions/TransactionBuilder.kt b/core/src/main/kotlin/net/corda/core/transactions/TransactionBuilder.kt index 8f99c0c358..dbbd0a4856 100644 --- a/core/src/main/kotlin/net/corda/core/transactions/TransactionBuilder.kt +++ b/core/src/main/kotlin/net/corda/core/transactions/TransactionBuilder.kt @@ -97,7 +97,7 @@ open class TransactionBuilder( fun signWith(key: KeyPair): TransactionBuilder { check(currentSigs.none { it.by == key.public }) { "This partial transaction was already signed by ${key.public}" } val data = toWireTransaction().id - addSignatureUnchecked(key.signWithECDSA(data.bytes)) + addSignatureUnchecked(key.sign(data.bytes)) return this } @@ -121,7 +121,7 @@ open class TransactionBuilder( */ fun checkSignature(sig: DigitalSignature.WithKey) { require(commands.any { it.signers.any { sig.by in it.keys } }) { "Signature key doesn't match any command" } - sig.verifyWithECDSA(toWireTransaction().id) + sig.verify(toWireTransaction().id) } /** Adds the signature directly to the transaction, without checking it for validity. */ diff --git a/core/src/main/kotlin/net/corda/flows/AbstractStateReplacementFlow.kt b/core/src/main/kotlin/net/corda/flows/AbstractStateReplacementFlow.kt index 2744bf4cbb..601ff3df33 100644 --- a/core/src/main/kotlin/net/corda/flows/AbstractStateReplacementFlow.kt +++ b/core/src/main/kotlin/net/corda/flows/AbstractStateReplacementFlow.kt @@ -98,7 +98,7 @@ abstract class AbstractStateReplacementFlow { val response = sendAndReceive(party, proposal) return response.unwrap { check(party.owningKey.isFulfilledBy(it.by)) { "Not signed by the required participant" } - it.verifyWithECDSA(stx.id) + it.verify(stx.id) it } } @@ -157,7 +157,7 @@ abstract class AbstractStateReplacementFlow { // TODO: This step should not be necessary, as signatures are re-checked in verifySignatures. val allSignatures = swapSignatures.unwrap { signatures -> - signatures.forEach { it.verifyWithECDSA(stx.id) } + signatures.forEach { it.verify(stx.id) } signatures } @@ -187,7 +187,7 @@ abstract class AbstractStateReplacementFlow { private fun sign(stx: SignedTransaction): DigitalSignature.WithKey { val myKey = serviceHub.legalIdentityKey - return myKey.signWithECDSA(stx.id) + return myKey.sign(stx.id) } } } diff --git a/core/src/main/kotlin/net/corda/flows/NotaryFlow.kt b/core/src/main/kotlin/net/corda/flows/NotaryFlow.kt index 40fbbc90bd..7c74a8d618 100644 --- a/core/src/main/kotlin/net/corda/flows/NotaryFlow.kt +++ b/core/src/main/kotlin/net/corda/flows/NotaryFlow.kt @@ -77,7 +77,7 @@ object NotaryFlow { private fun validateSignature(sig: DigitalSignature.WithKey, data: ByteArray) { check(sig.by in notaryParty.owningKey.keys) { "Invalid signer for the notary result" } - sig.verifyWithECDSA(data) + sig.verify(data) } } @@ -142,7 +142,7 @@ object NotaryFlow { private fun sign(bits: ByteArray): DigitalSignature.WithKey { val mySigningKey = serviceHub.notaryIdentityKey - return mySigningKey.signWithECDSA(bits) + return mySigningKey.sign(bits) } private fun notaryException(txId: SecureHash, e: UniquenessException): NotaryException { diff --git a/core/src/main/kotlin/net/corda/flows/TwoPartyDealFlow.kt b/core/src/main/kotlin/net/corda/flows/TwoPartyDealFlow.kt index cc31c183a9..a0e86838c2 100644 --- a/core/src/main/kotlin/net/corda/flows/TwoPartyDealFlow.kt +++ b/core/src/main/kotlin/net/corda/flows/TwoPartyDealFlow.kt @@ -144,7 +144,7 @@ object TwoPartyDealFlow { open fun computeOurSignature(partialTX: SignedTransaction): DigitalSignature.WithKey { progressTracker.currentStep = SIGNING - return myKeyPair.signWithECDSA(partialTX.id) + return myKeyPair.sign(partialTX.id) } @Suspendable diff --git a/core/src/test/kotlin/net/corda/core/contracts/TransactionTests.kt b/core/src/test/kotlin/net/corda/core/contracts/TransactionTests.kt index 373817db98..a38c156ea2 100644 --- a/core/src/test/kotlin/net/corda/core/contracts/TransactionTests.kt +++ b/core/src/test/kotlin/net/corda/core/contracts/TransactionTests.kt @@ -5,7 +5,7 @@ import net.corda.core.crypto.CompositeKey import net.corda.core.crypto.Party import net.corda.core.crypto.SecureHash import net.corda.core.crypto.generateKeyPair -import net.corda.core.crypto.signWithECDSA +import net.corda.core.crypto.sign import net.corda.core.serialization.SerializedBytes import net.corda.core.transactions.LedgerTransaction import net.corda.core.transactions.SignedTransaction @@ -26,7 +26,7 @@ class TransactionTests { private fun makeSigned(wtx: WireTransaction, vararg keys: KeyPair): SignedTransaction { val bytes: SerializedBytes = wtx.serialized - return SignedTransaction(bytes, keys.map { it.signWithECDSA(wtx.id.bytes) }) + return SignedTransaction(bytes, keys.map { it.sign(wtx.id.bytes) }) } @Test diff --git a/core/src/test/kotlin/net/corda/core/crypto/CompositeKeyTests.kt b/core/src/test/kotlin/net/corda/core/crypto/CompositeKeyTests.kt index 7890412991..8d2bed5a73 100644 --- a/core/src/test/kotlin/net/corda/core/crypto/CompositeKeyTests.kt +++ b/core/src/test/kotlin/net/corda/core/crypto/CompositeKeyTests.kt @@ -4,7 +4,6 @@ import net.corda.core.serialization.OpaqueBytes import net.corda.core.serialization.serialize import org.junit.Test import kotlin.test.assertEquals -import kotlin.test.assertFailsWith import kotlin.test.assertFalse import kotlin.test.assertTrue @@ -19,9 +18,9 @@ class CompositeKeyTests { val message = OpaqueBytes("Transaction".toByteArray()) - val aliceSignature = aliceKey.signWithECDSA(message) - val bobSignature = bobKey.signWithECDSA(message) - val charlieSignature = charlieKey.signWithECDSA(message) + val aliceSignature = aliceKey.sign(message) + val bobSignature = bobKey.sign(message) + val charlieSignature = charlieKey.sign(message) val compositeAliceSignature = CompositeSignaturesWithKeys(listOf(aliceSignature)) @Test diff --git a/core/src/test/kotlin/net/corda/core/crypto/CryptoUtilsTest.kt b/core/src/test/kotlin/net/corda/core/crypto/CryptoUtilsTest.kt index f66b0bf899..6f4e2acb01 100644 --- a/core/src/test/kotlin/net/corda/core/crypto/CryptoUtilsTest.kt +++ b/core/src/test/kotlin/net/corda/core/crypto/CryptoUtilsTest.kt @@ -11,9 +11,6 @@ import org.bouncycastle.pqc.jcajce.provider.sphincs.BCSphincs256PrivateKey import org.bouncycastle.pqc.jcajce.provider.sphincs.BCSphincs256PublicKey import org.junit.Assert.assertNotEquals import org.junit.Test -import java.security.KeyFactory -import java.security.spec.PKCS8EncodedKeySpec -import java.security.spec.X509EncodedKeySpec import java.util.* import kotlin.test.assertEquals import kotlin.test.assertNotNull @@ -32,11 +29,11 @@ class CryptoUtilsTest { @Test fun `Generate key pairs`() { // testing supported algorithms - val rsaKeyPair = Crypto.generateKeyPair("RSA_SHA256") - val ecdsaKKeyPair = Crypto.generateKeyPair("ECDSA_SECP256K1_SHA256") - val ecdsaRKeyPair = Crypto.generateKeyPair("ECDSA_SECP256R1_SHA256") - val eddsaKeyPair = Crypto.generateKeyPair("EDDSA_ED25519_SHA512") - val sphincsKeyPair = Crypto.generateKeyPair("SPHINCS-256_SHA512") + val rsaKeyPair = Crypto.generateKeyPair(Crypto.RSA_SHA256) + val ecdsaKKeyPair = Crypto.generateKeyPair(Crypto.ECDSA_SECP256K1_SHA256) + val ecdsaRKeyPair = Crypto.generateKeyPair(Crypto.ECDSA_SECP256R1_SHA256) + val eddsaKeyPair = Crypto.generateKeyPair(Crypto.EDDSA_ED25519_SHA512) + val sphincsKeyPair = Crypto.generateKeyPair(Crypto.SPHINCS256_SHA256) // not null private keys assertNotNull(rsaKeyPair.private) @@ -65,17 +62,16 @@ class CryptoUtilsTest { @Test fun `RSA full process keygen-sign-verify`() { - - val keyPair = Crypto.generateKeyPair("RSA_SHA256") - + val keyPair = Crypto.generateKeyPair(Crypto.RSA_SHA256) + val (privKey, pubKey) = keyPair // test for some data - val signedData = keyPair.sign(testBytes) - val verification = keyPair.verify(signedData, testBytes) + val signedData = Crypto.doSign(privKey, testBytes) + val verification = Crypto.doVerify(pubKey, signedData, testBytes) assertTrue(verification) // test for empty data signing try { - keyPair.sign(ByteArray(0)) + Crypto.doSign(privKey, ByteArray(0)) fail() } catch (e: Exception) { // expected @@ -83,7 +79,7 @@ class CryptoUtilsTest { // test for empty source data when verifying try { - keyPair.verify(testBytes, ByteArray(0)) + Crypto.doVerify(pubKey, testBytes, ByteArray(0)) fail() } catch (e: Exception) { // expected @@ -91,88 +87,83 @@ class CryptoUtilsTest { // test for empty signed data when verifying try { - keyPair.verify(ByteArray(0), testBytes) + Crypto.doVerify(pubKey, ByteArray(0), testBytes) fail() } catch (e: Exception) { // expected } // test for zero bytes data - val signedDataZeros = keyPair.sign(ByteArray(100)) - val verificationZeros = keyPair.verify(signedDataZeros, ByteArray(100)) + val signedDataZeros = Crypto.doSign(privKey, ByteArray(100)) + val verificationZeros = Crypto.doVerify(pubKey, signedDataZeros, ByteArray(100)) assertTrue(verificationZeros) // test for 1MB of data (I successfully tested it locally for 1GB as well) val MBbyte = ByteArray(1000000) // 1.000.000 Random().nextBytes(MBbyte) - val signedDataBig = keyPair.sign(MBbyte) - val verificationBig = keyPair.verify(signedDataBig, MBbyte) - assertTrue(verificationBig) - - // test on malformed signatures (even if they change for 1 bit) - for (i in 0..signedData.size - 1) { - val b = signedData[i] - signedData[i] = b.inc() - try { - keyPair.verify(signedData, testBytes) - fail() - } catch (e: Exception) { - // expected - } - signedData[i] = b.dec() - } - } - - @Test - fun `ECDSA secp256k1 full process keygen-sign-verify`() { - - val keyPair = Crypto.generateKeyPair("ECDSA_SECP256K1_SHA256") - - // test for some data - val signedData = keyPair.sign(testBytes) - val verification = keyPair.verify(signedData, testBytes) - assertTrue(verification) - - // test for empty data signing - try { - keyPair.sign(ByteArray(0)) - fail() - } catch (e: Exception) { - // expected - } - - // test for empty source data when verifying - try { - keyPair.verify(testBytes, ByteArray(0)) - fail() - } catch (e: Exception) { - // expected - } - - // test for empty signed data when verifying - try { - keyPair.verify(ByteArray(0), testBytes) - fail() - } catch (e: Exception) { - // expected - } - - // test for zero bytes data - val signedDataZeros = keyPair.sign(ByteArray(100)) - val verificationZeros = keyPair.verify(signedDataZeros, ByteArray(100)) - assertTrue(verificationZeros) - - // test for 1MB of data (I successfully tested it locally for 1GB as well) - val MBbyte = ByteArray(1000000) // 1.000.000 - Random().nextBytes(MBbyte) - val signedDataBig = keyPair.sign(MBbyte) - val verificationBig = keyPair.verify(signedDataBig, MBbyte) + val signedDataBig = Crypto.doSign(privKey, MBbyte) + val verificationBig = Crypto.doVerify(pubKey, signedDataBig, MBbyte) assertTrue(verificationBig) // test on malformed signatures (even if they change for 1 bit) signedData[0] = signedData[0].inc() try { - keyPair.verify(signedData, testBytes) + Crypto.doVerify(pubKey, signedData, testBytes) + fail() + } catch (e: Exception) { + // expected + } + } + + @Test + fun `ECDSA secp256k1 full process keygen-sign-verify`() { + val keyPair = Crypto.generateKeyPair(Crypto.ECDSA_SECP256K1_SHA256) + val (privKey, pubKey) = keyPair + // test for some data + val signedData = Crypto.doSign(privKey, testBytes) + val verification = Crypto.doVerify(pubKey, signedData, testBytes) + assertTrue(verification) + + // test for empty data signing + try { + Crypto.doSign(privKey, ByteArray(0)) + fail() + } catch (e: Exception) { + // expected + } + + // test for empty source data when verifying + try { + Crypto.doVerify(pubKey, testBytes, ByteArray(0)) + fail() + } catch (e: Exception) { + // expected + } + + // test for empty signed data when verifying + try { + Crypto.doVerify(pubKey, ByteArray(0), testBytes) + fail() + } catch (e: Exception) { + // expected + } + + // test for zero bytes data + val signedDataZeros = Crypto.doSign(privKey, ByteArray(100)) + val verificationZeros = Crypto.doVerify(pubKey, signedDataZeros, ByteArray(100)) + assertTrue(verificationZeros) + + // test for 1MB of data (I successfully tested it locally for 1GB as well) + val MBbyte = ByteArray(1000000) // 1.000.000 + Random().nextBytes(MBbyte) + val signedDataBig = Crypto.doSign(privKey, MBbyte) + val verificationBig = Crypto.doVerify(pubKey, signedDataBig, MBbyte) + assertTrue(verificationBig) + + // test on malformed signatures (even if they change for 1 bit) + signedData[0] = signedData[0].inc() + try { + Crypto.doVerify(pubKey, signedData, testBytes) fail() } catch (e: Exception) { // expected @@ -181,17 +172,16 @@ class CryptoUtilsTest { @Test fun `ECDSA secp256r1 full process keygen-sign-verify`() { - - val keyPair = Crypto.generateKeyPair("ECDSA_SECP256R1_SHA256") - + val keyPair = Crypto.generateKeyPair(Crypto.ECDSA_SECP256R1_SHA256) + val (privKey, pubKey) = keyPair // test for some data - val signedData = keyPair.sign(testBytes) - val verification = keyPair.verify(signedData, testBytes) + val signedData = Crypto.doSign(privKey, testBytes) + val verification = Crypto.doVerify(pubKey, signedData, testBytes) assertTrue(verification) // test for empty data signing try { - keyPair.sign(ByteArray(0)) + Crypto.doSign(privKey, ByteArray(0)) fail() } catch (e: Exception) { // expected @@ -199,7 +189,7 @@ class CryptoUtilsTest { // test for empty source data when verifying try { - keyPair.verify(testBytes, ByteArray(0)) + Crypto.doVerify(pubKey, testBytes, ByteArray(0)) fail() } catch (e: Exception) { // expected @@ -207,28 +197,28 @@ class CryptoUtilsTest { // test for empty signed data when verifying try { - keyPair.verify(ByteArray(0), testBytes) + Crypto.doVerify(pubKey, ByteArray(0), testBytes) fail() } catch (e: Exception) { // expected } // test for zero bytes data - val signedDataZeros = keyPair.sign(ByteArray(100)) - val verificationZeros = keyPair.verify(signedDataZeros, ByteArray(100)) + val signedDataZeros = Crypto.doSign(privKey, ByteArray(100)) + val verificationZeros = Crypto.doVerify(pubKey, signedDataZeros, ByteArray(100)) assertTrue(verificationZeros) // test for 1MB of data (I successfully tested it locally for 1GB as well) val MBbyte = ByteArray(1000000) // 1.000.000 Random().nextBytes(MBbyte) - val signedDataBig = keyPair.sign(MBbyte) - val verificationBig = keyPair.verify(signedDataBig, MBbyte) + val signedDataBig = Crypto.doSign(privKey, MBbyte) + val verificationBig = Crypto.doVerify(pubKey, signedDataBig, MBbyte) assertTrue(verificationBig) // test on malformed signatures (even if they change for 1 bit) signedData[0] = signedData[0].inc() try { - keyPair.verify(signedData, testBytes) + Crypto.doVerify(pubKey, signedData, testBytes) fail() } catch (e: Exception) { // expected @@ -237,17 +227,16 @@ class CryptoUtilsTest { @Test fun `EDDSA ed25519 full process keygen-sign-verify`() { - - val keyPair = Crypto.generateKeyPair("EDDSA_ED25519_SHA512") - + val keyPair = Crypto.generateKeyPair(Crypto.EDDSA_ED25519_SHA512) + val (privKey, pubKey) = keyPair // test for some data - val signedData = keyPair.sign(testBytes) - val verification = keyPair.verify(signedData, testBytes) + val signedData = Crypto.doSign(privKey, testBytes) + val verification = Crypto.doVerify(pubKey, signedData, testBytes) assertTrue(verification) // test for empty data signing try { - keyPair.sign(ByteArray(0)) + Crypto.doSign(privKey, ByteArray(0)) fail() } catch (e: Exception) { // expected @@ -255,7 +244,7 @@ class CryptoUtilsTest { // test for empty source data when verifying try { - keyPair.verify(testBytes, ByteArray(0)) + Crypto.doVerify(pubKey, testBytes, ByteArray(0)) fail() } catch (e: Exception) { // expected @@ -263,28 +252,28 @@ class CryptoUtilsTest { // test for empty signed data when verifying try { - keyPair.verify(ByteArray(0), testBytes) + Crypto.doVerify(pubKey, ByteArray(0), testBytes) fail() } catch (e: Exception) { // expected } // test for zero bytes data - val signedDataZeros = keyPair.sign(ByteArray(100)) - val verificationZeros = keyPair.verify(signedDataZeros, ByteArray(100)) + val signedDataZeros = Crypto.doSign(privKey, ByteArray(100)) + val verificationZeros = Crypto.doVerify(pubKey, signedDataZeros, ByteArray(100)) assertTrue(verificationZeros) // test for 1MB of data (I successfully tested it locally for 1GB as well) val MBbyte = ByteArray(1000000) // 1.000.000 Random().nextBytes(MBbyte) - val signedDataBig = keyPair.sign(MBbyte) - val verificationBig = keyPair.verify(signedDataBig, MBbyte) + val signedDataBig = Crypto.doSign(privKey, MBbyte) + val verificationBig = Crypto.doVerify(pubKey, signedDataBig, MBbyte) assertTrue(verificationBig) // test on malformed signatures (even if they change for 1 bit) signedData[0] = signedData[0].inc() try { - keyPair.verify(signedData, testBytes) + Crypto.doVerify(pubKey, signedData, testBytes) fail() } catch (e: Exception) { // expected @@ -293,17 +282,16 @@ class CryptoUtilsTest { @Test fun `SPHINCS-256 full process keygen-sign-verify`() { - - val keyPair = Crypto.generateKeyPair("SPHINCS-256_SHA512") - + val keyPair = Crypto.generateKeyPair(Crypto.SPHINCS256_SHA256) + val (privKey, pubKey) = keyPair // test for some data - val signedData = keyPair.sign(testBytes) - val verification = keyPair.verify(signedData, testBytes) + val signedData = Crypto.doSign(privKey, testBytes) + val verification = Crypto.doVerify(pubKey, signedData, testBytes) assertTrue(verification) // test for empty data signing try { - keyPair.sign(ByteArray(0)) + Crypto.doSign(privKey, ByteArray(0)) fail() } catch (e: Exception) { // expected @@ -311,7 +299,7 @@ class CryptoUtilsTest { // test for empty source data when verifying try { - keyPair.verify(testBytes, ByteArray(0)) + Crypto.doVerify(pubKey, testBytes, ByteArray(0)) fail() } catch (e: Exception) { // expected @@ -319,28 +307,28 @@ class CryptoUtilsTest { // test for empty signed data when verifying try { - keyPair.verify(ByteArray(0), testBytes) + Crypto.doVerify(pubKey, ByteArray(0), testBytes) fail() } catch (e: Exception) { // expected } // test for zero bytes data - val signedDataZeros = keyPair.sign(ByteArray(100)) - val verificationZeros = keyPair.verify(signedDataZeros, ByteArray(100)) + val signedDataZeros = Crypto.doSign(privKey, ByteArray(100)) + val verificationZeros = Crypto.doVerify(pubKey, signedDataZeros, ByteArray(100)) assertTrue(verificationZeros) // test for 1MB of data (I successfully tested it locally for 1GB as well) val MBbyte = ByteArray(1000000) // 1.000.000 Random().nextBytes(MBbyte) - val signedDataBig = keyPair.sign(MBbyte) - val verificationBig = keyPair.verify(signedDataBig, MBbyte) + val signedDataBig = Crypto.doSign(privKey, MBbyte) + val verificationBig = Crypto.doVerify(pubKey, signedDataBig, MBbyte) assertTrue(verificationBig) // test on malformed signatures (even if they change for 1 bit) signedData[0] = signedData[0].inc() try { - keyPair.verify(signedData, testBytes) + Crypto.doVerify(pubKey, signedData, testBytes) fail() } catch (e: Exception) { // expected @@ -350,7 +338,7 @@ class CryptoUtilsTest { // test list of supported algorithms @Test fun `Check supported algorithms`() { - val algList: List = Crypto.listSupportedSignatureSchemes() + val algList: List = Crypto.supportedSignatureSchemes.keys.toList() val expectedAlgSet = setOf("RSA_SHA256", "ECDSA_SECP256K1_SHA256", "ECDSA_SECP256R1_SHA256", "EDDSA_ED25519_SHA512", "SPHINCS-256_SHA512") assertTrue { Sets.symmetricDifference(expectedAlgSet, algList.toSet()).isEmpty(); } } @@ -359,88 +347,76 @@ class CryptoUtilsTest { @Test fun `RSA encode decode keys - required for serialization`() { // Generate key pair. - val keyPair = Crypto.generateKeyPair("RSA_SHA256") + val keyPair = Crypto.generateKeyPair(Crypto.RSA_SHA256) val (privKey, pubKey) = keyPair - val keyFactory = KeyFactory.getInstance("RSA", "BC") - // Encode and decode private key. - val privKey2 = keyFactory.generatePrivate(PKCS8EncodedKeySpec(privKey.encoded)) + val privKey2 = Crypto.decodePrivateKey(privKey.encoded) assertEquals(privKey2, privKey) // Encode and decode public key. - val pubKey2 = keyFactory.generatePublic(X509EncodedKeySpec(pubKey.encoded)) + val pubKey2 = Crypto.decodePublicKey(pubKey.encoded) assertEquals(pubKey2, pubKey) } @Test fun `ECDSA secp256k1 encode decode keys - required for serialization`() { // Generate key pair. - val keyPair = Crypto.generateKeyPair("ECDSA_SECP256K1_SHA256") + val keyPair = Crypto.generateKeyPair(Crypto.ECDSA_SECP256K1_SHA256) val (privKey, pubKey) = keyPair - val kf = KeyFactory.getInstance("ECDSA", "BC") - // Encode and decode private key. - val privKey2 = kf.generatePrivate(PKCS8EncodedKeySpec(privKey.encoded)) + val privKey2 = Crypto.decodePrivateKey(privKey.encoded) assertEquals(privKey2, privKey) // Encode and decode public key. - val pubKey2 = kf.generatePublic(X509EncodedKeySpec(pubKey.encoded)) + val pubKey2 = Crypto.decodePublicKey(pubKey.encoded) assertEquals(pubKey2, pubKey) } @Test fun `ECDSA secp256r1 encode decode keys - required for serialization`() { // Generate key pair. - val keyPair = Crypto.generateKeyPair("ECDSA_SECP256R1_SHA256") + val keyPair = Crypto.generateKeyPair(Crypto.ECDSA_SECP256R1_SHA256) val (privKey, pubKey) = keyPair - val kf = KeyFactory.getInstance("ECDSA", "BC") - // Encode and decode private key. - val privKey2 = kf.generatePrivate(PKCS8EncodedKeySpec(privKey.encoded)) + val privKey2 = Crypto.decodePrivateKey(privKey.encoded) assertEquals(privKey2, privKey) // Encode and decode public key. - val pubKey2 = kf.generatePublic(X509EncodedKeySpec(pubKey.encoded)) + val pubKey2 = Crypto.decodePublicKey(pubKey.encoded) assertEquals(pubKey2, pubKey) } @Test fun `EdDSA encode decode keys - required for serialization`() { // Generate key pair. - val keyPair = Crypto.generateKeyPair("EDDSA_ED25519_SHA512") + val keyPair = Crypto.generateKeyPair(Crypto.EDDSA_ED25519_SHA512) val (privKey, pubKey) = keyPair - val kf = KeyFactory.getInstance("EDDSA", "I2P") - // Encode and decode private key. - val privKey2 = kf.generatePrivate(PKCS8EncodedKeySpec(privKey.encoded)) + val privKey2 = Crypto.decodePrivateKey(privKey.encoded) assertEquals(privKey2, privKey) // Encode and decode public key. - val pubKey2 = kf.generatePublic(X509EncodedKeySpec(pubKey.encoded)) + val pubKey2 = Crypto.decodePublicKey(pubKey.encoded) assertEquals(pubKey2, pubKey) } @Test fun `SPHINCS-256 encode decode keys - required for serialization`() { // Generate key pair. - val keyPair = Crypto.generateKeyPair("SPHINCS-256_SHA512") + val keyPair = Crypto.generateKeyPair(Crypto.SPHINCS256_SHA256) val privKey: BCSphincs256PrivateKey = keyPair.private as BCSphincs256PrivateKey val pubKey: BCSphincs256PublicKey = keyPair.public as BCSphincs256PublicKey //1st method for encoding/decoding - - val keyFactory = KeyFactory.getInstance("SPHINCS256", "BCPQC") - - // Encode and decode private key. - val privKey2 = keyFactory.generatePrivate(PKCS8EncodedKeySpec(privKey.encoded)) + val privKey2 = Crypto.decodePrivateKey(privKey.encoded) assertEquals(privKey2, privKey) // Encode and decode public key. - val pubKey2 = keyFactory.generatePublic(X509EncodedKeySpec(pubKey.encoded)) + val pubKey2 = Crypto.decodePublicKey(pubKey.encoded) assertEquals(pubKey2, pubKey) //2nd method for encoding/decoding @@ -453,14 +429,14 @@ class CryptoUtilsTest { // Encode and decode public key. val pubKeyInfo: SubjectPublicKeyInfo = SubjectPublicKeyInfo.getInstance(pubKey.encoded) - val extractedPubKey = BCSphincs256PublicKey(pubKeyInfo) + val decodedPubKey = BCSphincs256PublicKey(pubKeyInfo) // Check that decoded private key is equal to the initial one. - assertEquals(extractedPubKey, pubKey) + assertEquals(decodedPubKey, pubKey) } @Test fun `RSA scheme finder by key type`() { - val keyPairRSA = Crypto.generateKeyPair("RSA_SHA256") + val keyPairRSA = Crypto.generateKeyPair(Crypto.RSA_SHA256) val (privRSA, pubRSA) = keyPairRSA assertEquals(privRSA.algorithm, "RSA") assertEquals(pubRSA.algorithm, "RSA") @@ -468,23 +444,22 @@ class CryptoUtilsTest { @Test fun `ECDSA secp256k1 scheme finder by key type`() { - val keyPairK1 = Crypto.generateKeyPair("ECDSA_SECP256K1_SHA256") - val (privK1, pubK1) = keyPairK1 + val keyPair = Crypto.generateKeyPair(Crypto.ECDSA_SECP256K1_SHA256) + val (privKey, pubKey) = keyPair - // Encode and decode keys as they would be transferred. - val kf = KeyFactory.getInstance("ECDSA", "BC") - val privK1Decoded = kf.generatePrivate(PKCS8EncodedKeySpec(privK1.encoded)) - val pubK1Decoded = kf.generatePublic(X509EncodedKeySpec(pubK1.encoded)) + // Encode and decode private key. + val privKeyDecoded = Crypto.decodePrivateKey(privKey.encoded) + val pubKeyDecoded = Crypto.decodePublicKey(pubKey.encoded) - assertEquals(privK1Decoded.algorithm, "ECDSA") - assertEquals((privK1Decoded as ECKey).parameters, ECNamedCurveTable.getParameterSpec("secp256k1")) - assertEquals(pubK1Decoded.algorithm, "ECDSA") - assertEquals((pubK1Decoded as ECKey).parameters, ECNamedCurveTable.getParameterSpec("secp256k1")) + assertEquals(privKeyDecoded.algorithm, "ECDSA") + assertEquals((privKeyDecoded as ECKey).parameters, ECNamedCurveTable.getParameterSpec("secp256k1")) + assertEquals(pubKeyDecoded.algorithm, "ECDSA") + assertEquals((pubKeyDecoded as ECKey).parameters, ECNamedCurveTable.getParameterSpec("secp256k1")) } @Test fun `ECDSA secp256r1 scheme finder by key type`() { - val keyPairR1 = Crypto.generateKeyPair("ECDSA_SECP256R1_SHA256") + val keyPairR1 = Crypto.generateKeyPair(Crypto.ECDSA_SECP256R1_SHA256) val (privR1, pubR1) = keyPairR1 assertEquals(privR1.algorithm, "ECDSA") assertEquals((privR1 as ECKey).parameters, ECNamedCurveTable.getParameterSpec("secp256r1")) @@ -494,7 +469,7 @@ class CryptoUtilsTest { @Test fun `EdDSA scheme finder by key type`() { - val keyPairEd = Crypto.generateKeyPair("EDDSA_ED25519_SHA512") + val keyPairEd = Crypto.generateKeyPair(Crypto.EDDSA_ED25519_SHA512) val (privEd, pubEd) = keyPairEd assertEquals(privEd.algorithm, "EdDSA") @@ -505,7 +480,7 @@ class CryptoUtilsTest { @Test fun `SPHINCS-256 scheme finder by key type`() { - val keyPairSP = Crypto.generateKeyPair("SPHINCS-256_SHA512") + val keyPairSP = Crypto.generateKeyPair(Crypto.SPHINCS256_SHA256) val (privSP, pubSP) = keyPairSP assertEquals(privSP.algorithm, "SPHINCS-256") assertEquals(pubSP.algorithm, "SPHINCS-256") @@ -513,7 +488,7 @@ class CryptoUtilsTest { @Test fun `Automatic EdDSA key-type detection and decoding`() { - val keyPairEd = Crypto.generateKeyPair("EDDSA_ED25519_SHA512") + val keyPairEd = Crypto.generateKeyPair(Crypto.EDDSA_ED25519_SHA512) val (privEd, pubEd) = keyPairEd val encodedPrivEd = privEd.encoded val encodedPubEd = pubEd.encoded @@ -529,7 +504,7 @@ class CryptoUtilsTest { @Test fun `Automatic ECDSA secp256k1 key-type detection and decoding`() { - val keyPairK1 = Crypto.generateKeyPair("ECDSA_SECP256K1_SHA256") + val keyPairK1 = Crypto.generateKeyPair(Crypto.ECDSA_SECP256K1_SHA256) val (privK1, pubK1) = keyPairK1 val encodedPrivK1 = privK1.encoded val encodedPubK1 = pubK1.encoded @@ -545,7 +520,7 @@ class CryptoUtilsTest { @Test fun `Automatic ECDSA secp256r1 key-type detection and decoding`() { - val keyPairR1 = Crypto.generateKeyPair("ECDSA_SECP256R1_SHA256") + val keyPairR1 = Crypto.generateKeyPair(Crypto.ECDSA_SECP256R1_SHA256) val (privR1, pubR1) = keyPairR1 val encodedPrivR1 = privR1.encoded val encodedPubR1 = pubR1.encoded @@ -561,7 +536,7 @@ class CryptoUtilsTest { @Test fun `Automatic RSA key-type detection and decoding`() { - val keyPairRSA = Crypto.generateKeyPair("RSA_SHA256") + val keyPairRSA = Crypto.generateKeyPair(Crypto.RSA_SHA256) val (privRSA, pubRSA) = keyPairRSA val encodedPrivRSA = privRSA.encoded val encodedPubRSA = pubRSA.encoded @@ -577,7 +552,7 @@ class CryptoUtilsTest { @Test fun `Automatic SPHINCS-256 key-type detection and decoding`() { - val keyPairSP = Crypto.generateKeyPair("SPHINCS-256_SHA512") + val keyPairSP = Crypto.generateKeyPair(Crypto.SPHINCS256_SHA256) val (privSP, pubSP) = keyPairSP val encodedPrivSP = privSP.encoded val encodedPubSP = pubSP.encoded @@ -593,12 +568,12 @@ class CryptoUtilsTest { @Test fun `Failure test between K1 and R1 keys`() { - val keyPairK1 = Crypto.generateKeyPair("ECDSA_SECP256K1_SHA256") + val keyPairK1 = Crypto.generateKeyPair(Crypto.ECDSA_SECP256K1_SHA256) val privK1 = keyPairK1.private val encodedPrivK1 = privK1.encoded val decodedPrivK1 = Crypto.decodePrivateKey(encodedPrivK1) - val keyPairR1 = Crypto.generateKeyPair("ECDSA_SECP256R1_SHA256") + val keyPairR1 = Crypto.generateKeyPair(Crypto.ECDSA_SECP256R1_SHA256) val privR1 = keyPairR1.private val encodedPrivR1 = privR1.encoded val decodedPrivR1 = Crypto.decodePrivateKey(encodedPrivR1) @@ -608,7 +583,7 @@ class CryptoUtilsTest { @Test fun `Decoding Failure on randomdata as key`() { - val keyPairK1 = Crypto.generateKeyPair("ECDSA_SECP256K1_SHA256") + val keyPairK1 = Crypto.generateKeyPair(Crypto.ECDSA_SECP256K1_SHA256) val privK1 = keyPairK1.private val encodedPrivK1 = privK1.encoded @@ -628,7 +603,7 @@ class CryptoUtilsTest { @Test fun `Decoding Failure on malformed keys`() { - val keyPairK1 = Crypto.generateKeyPair("ECDSA_SECP256K1_SHA256") + val keyPairK1 = Crypto.generateKeyPair(Crypto.ECDSA_SECP256K1_SHA256) val privK1 = keyPairK1.private val encodedPrivK1 = privK1.encoded diff --git a/core/src/test/kotlin/net/corda/core/crypto/SignedDataTest.kt b/core/src/test/kotlin/net/corda/core/crypto/SignedDataTest.kt index 56ed35eba9..cb83d847da 100644 --- a/core/src/test/kotlin/net/corda/core/crypto/SignedDataTest.kt +++ b/core/src/test/kotlin/net/corda/core/crypto/SignedDataTest.kt @@ -12,7 +12,7 @@ class SignedDataTest { @Test fun `make sure correctly signed data is released`() { val keyPair = generateKeyPair() - val sig = keyPair.private.signWithECDSA(serialized.bytes, keyPair.public) + val sig = keyPair.private.sign(serialized.bytes, keyPair.public) val wrappedData = SignedData(serialized, sig) val unwrappedData = wrappedData.verified() @@ -23,7 +23,7 @@ class SignedDataTest { fun `make sure incorrectly signed data raises an exception`() { val keyPairA = generateKeyPair() val keyPairB = generateKeyPair() - val sig = keyPairA.private.signWithECDSA(serialized.bytes, keyPairB.public) + val sig = keyPairA.private.sign(serialized.bytes, keyPairB.public) val wrappedData = SignedData(serialized, sig) wrappedData.verified() } diff --git a/core/src/test/kotlin/net/corda/core/serialization/KryoTests.kt b/core/src/test/kotlin/net/corda/core/serialization/KryoTests.kt index ddde679fd8..5d30f4b17d 100644 --- a/core/src/test/kotlin/net/corda/core/serialization/KryoTests.kt +++ b/core/src/test/kotlin/net/corda/core/serialization/KryoTests.kt @@ -76,15 +76,14 @@ class KryoTests { val keyPair = generateKeyPair() val bitsToSign: ByteArray = Ints.toByteArray(0x01234567) val wrongBits: ByteArray = Ints.toByteArray(0x76543210) - val signature = keyPair.signWithECDSA(bitsToSign) - signature.verifyWithECDSA(bitsToSign) - assertThatThrownBy { signature.verifyWithECDSA(wrongBits) } + val signature = keyPair.sign(bitsToSign) + signature.verify(bitsToSign) + assertThatThrownBy { signature.verify(wrongBits) } val deserialisedKeyPair = keyPair.serialize(kryo).deserialize(kryo) - val deserialisedSignature = deserialisedKeyPair.signWithECDSA(bitsToSign) - assertThat(deserialisedSignature).isEqualTo(signature) - deserialisedSignature.verifyWithECDSA(bitsToSign) - assertThatThrownBy { deserialisedSignature.verifyWithECDSA(wrongBits) } + val deserialisedSignature = deserialisedKeyPair.sign(bitsToSign) + deserialisedSignature.verify(bitsToSign) + assertThatThrownBy { deserialisedSignature.verify(wrongBits) } } @Test diff --git a/docs/source/example-code/src/main/kotlin/net/corda/docs/FxTransactionBuildTutorial.kt b/docs/source/example-code/src/main/kotlin/net/corda/docs/FxTransactionBuildTutorial.kt index 0181264fd5..8e9ab5129e 100644 --- a/docs/source/example-code/src/main/kotlin/net/corda/docs/FxTransactionBuildTutorial.kt +++ b/docs/source/example-code/src/main/kotlin/net/corda/docs/FxTransactionBuildTutorial.kt @@ -9,7 +9,7 @@ import net.corda.core.contracts.TransactionType import net.corda.core.crypto.DigitalSignature import net.corda.core.crypto.Party import net.corda.core.crypto.SecureHash -import net.corda.core.crypto.signWithECDSA +import net.corda.core.crypto.sign import net.corda.core.flows.FlowLogic import net.corda.core.node.PluginServiceHub import net.corda.core.node.ServiceHub @@ -258,7 +258,7 @@ class ForeignExchangeRemoteFlow(val source: Party) : FlowLogic() { } // assuming we have completed state and business level validation we can sign the trade - val ourSignature = serviceHub.legalIdentityKey.signWithECDSA(proposedTrade.id) + val ourSignature = serviceHub.legalIdentityKey.sign(proposedTrade.id) // send the other side our signature. send(source, ourSignature) diff --git a/docs/source/example-code/src/main/kotlin/net/corda/docs/WorkflowTransactionBuildTutorial.kt b/docs/source/example-code/src/main/kotlin/net/corda/docs/WorkflowTransactionBuildTutorial.kt index 371891fe32..c3e50d0bec 100644 --- a/docs/source/example-code/src/main/kotlin/net/corda/docs/WorkflowTransactionBuildTutorial.kt +++ b/docs/source/example-code/src/main/kotlin/net/corda/docs/WorkflowTransactionBuildTutorial.kt @@ -250,7 +250,7 @@ class RecordCompletionFlow(val source: Party) : FlowLogic() { } // DOCEND 3 // Having verified the SignedTransaction passed to us we can sign it too - val ourSignature = serviceHub.legalIdentityKey.signWithECDSA(completeTx.tx.id) + val ourSignature = serviceHub.legalIdentityKey.sign(completeTx.tx.id) // Send our signature to the other party. send(source, ourSignature) // N.B. The FinalityProtocol will be responsible for Notarising the SignedTransaction diff --git a/finance/src/main/kotlin/net/corda/flows/TwoPartyTradeFlow.kt b/finance/src/main/kotlin/net/corda/flows/TwoPartyTradeFlow.kt index 2c6501b251..f5a0351646 100644 --- a/finance/src/main/kotlin/net/corda/flows/TwoPartyTradeFlow.kt +++ b/finance/src/main/kotlin/net/corda/flows/TwoPartyTradeFlow.kt @@ -135,7 +135,7 @@ object TwoPartyTradeFlow { open fun calculateOurSignature(partialTX: SignedTransaction): DigitalSignature.WithKey { progressTracker.currentStep = SIGNING - return myKeyPair.signWithECDSA(partialTX.id) + return myKeyPair.sign(partialTX.id) } } diff --git a/node/src/main/kotlin/net/corda/node/services/network/NetworkMapService.kt b/node/src/main/kotlin/net/corda/node/services/network/NetworkMapService.kt index 3610931e43..ba86a8b57a 100644 --- a/node/src/main/kotlin/net/corda/node/services/network/NetworkMapService.kt +++ b/node/src/main/kotlin/net/corda/node/services/network/NetworkMapService.kt @@ -323,7 +323,7 @@ data class NodeRegistration(val node: NodeInfo, val serial: Long, val type: AddO */ fun toWire(privateKey: PrivateKey): WireNodeRegistration { val regSerialized = this.serialize() - val regSig = privateKey.signWithECDSA(regSerialized.bytes, node.legalIdentity.owningKey) + val regSig = privateKey.sign(regSerialized.bytes, node.legalIdentity.owningKey) return WireNodeRegistration(regSerialized, regSig) } diff --git a/node/src/main/kotlin/net/corda/node/services/transactions/BFTSMaRt.kt b/node/src/main/kotlin/net/corda/node/services/transactions/BFTSMaRt.kt index 89f7a98510..d1219f5bfb 100644 --- a/node/src/main/kotlin/net/corda/node/services/transactions/BFTSMaRt.kt +++ b/node/src/main/kotlin/net/corda/node/services/transactions/BFTSMaRt.kt @@ -198,7 +198,7 @@ object BFTSMaRt { protected fun sign(bytes: ByteArray): DigitalSignature.WithKey { val mySigningKey = db.transaction { services.notaryIdentityKey } - return mySigningKey.signWithECDSA(bytes) + return mySigningKey.sign(bytes) } // TODO: diff --git a/node/src/test/kotlin/net/corda/node/services/transactions/NotaryServiceTests.kt b/node/src/test/kotlin/net/corda/node/services/transactions/NotaryServiceTests.kt index 2cbe2104dc..ee01595eb2 100644 --- a/node/src/test/kotlin/net/corda/node/services/transactions/NotaryServiceTests.kt +++ b/node/src/test/kotlin/net/corda/node/services/transactions/NotaryServiceTests.kt @@ -54,7 +54,7 @@ class NotaryServiceTests { val future = runNotaryClient(stx) val signatures = future.getOrThrow() - signatures.forEach { it.verifyWithECDSA(stx.id) } + signatures.forEach { it.verify(stx.id) } } @Test fun `should sign a unique transaction without a timestamp`() { @@ -67,7 +67,7 @@ class NotaryServiceTests { val future = runNotaryClient(stx) val signatures = future.getOrThrow() - signatures.forEach { it.verifyWithECDSA(stx.id) } + signatures.forEach { it.verify(stx.id) } } @Test fun `should report error for transaction with an invalid timestamp`() { diff --git a/samples/irs-demo/src/main/kotlin/net/corda/irs/api/NodeInterestRates.kt b/samples/irs-demo/src/main/kotlin/net/corda/irs/api/NodeInterestRates.kt index 23de6aa059..fb07a2db9c 100644 --- a/samples/irs-demo/src/main/kotlin/net/corda/irs/api/NodeInterestRates.kt +++ b/samples/irs-demo/src/main/kotlin/net/corda/irs/api/NodeInterestRates.kt @@ -7,7 +7,7 @@ import net.corda.core.crypto.DigitalSignature import net.corda.core.crypto.MerkleTreeException import net.corda.core.crypto.Party import net.corda.core.crypto.keys -import net.corda.core.crypto.signWithECDSA +import net.corda.core.crypto.sign import net.corda.core.flows.FlowLogic import net.corda.core.math.CubicSplineInterpolator import net.corda.core.math.Interpolator @@ -224,7 +224,7 @@ object NodeInterestRates { // Note that we will happily sign an invalid transaction, as we are only being presented with a filtered // version so we can't resolve or check it ourselves. However, that doesn't matter much, as if we sign // an invalid transaction the signature is worthless. - return signingKey.signWithECDSA(ftx.rootHash.bytes, identity) + return signingKey.sign(ftx.rootHash.bytes, identity) } // DOCEND 1 } diff --git a/test-utils/src/main/kotlin/net/corda/testing/TestDSL.kt b/test-utils/src/main/kotlin/net/corda/testing/TestDSL.kt index c8450a5635..393ed62eaa 100644 --- a/test-utils/src/main/kotlin/net/corda/testing/TestDSL.kt +++ b/test-utils/src/main/kotlin/net/corda/testing/TestDSL.kt @@ -337,7 +337,7 @@ fun signAll(transactionsToSign: List, extraKeys: List) } wtx.mustSign.expandedCompositeKeys.forEach { val key = keyLookup[it] ?: throw IllegalArgumentException("Missing required key for ${it.toStringShort()}") - signatures += key.signWithECDSA(wtx.id) + signatures += key.sign(wtx.id) } SignedTransaction(bits, signatures) }