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 60b5306cb6c..88724674f17 100644 --- a/core/src/test/kotlin/net/corda/core/crypto/CompositeKeyTests.kt +++ b/core/src/test/kotlin/net/corda/core/crypto/CompositeKeyTests.kt @@ -8,7 +8,7 @@ import net.corda.core.internal.div import net.corda.core.serialization.serialize import net.corda.core.utilities.OpaqueBytes import net.corda.core.utilities.toBase58String -import net.corda.node.utilities.* +import net.corda.nodeapi.internal.crypto.* import net.corda.testing.kryoSpecific import net.corda.testing.SerializationEnvironmentRule import org.junit.Rule diff --git a/core/src/test/kotlin/net/corda/core/crypto/X509NameConstraintsTest.kt b/core/src/test/kotlin/net/corda/core/crypto/X509NameConstraintsTest.kt index 88854550a41..b3b1f332e23 100644 --- a/core/src/test/kotlin/net/corda/core/crypto/X509NameConstraintsTest.kt +++ b/core/src/test/kotlin/net/corda/core/crypto/X509NameConstraintsTest.kt @@ -3,7 +3,7 @@ package net.corda.core.crypto import net.corda.core.identity.CordaX500Name import net.corda.core.internal.toTypedArray import net.corda.core.internal.cert -import net.corda.node.utilities.* +import net.corda.nodeapi.internal.crypto.* import org.bouncycastle.asn1.x500.X500Name import org.bouncycastle.asn1.x509.GeneralName import org.bouncycastle.asn1.x509.GeneralSubtree @@ -50,7 +50,7 @@ class X509NameConstraintsTest { val nameConstraints = NameConstraints(acceptableNames, arrayOf()) val pathValidator = CertPathValidator.getInstance("PKIX") - val certFactory = CertificateFactory.getInstance("X509") + val certFactory = X509CertificateFactory().delegate assertFailsWith(CertPathValidatorException::class) { val (keystore, trustStore) = makeKeyStores(X500Name("CN=Bank B"), nameConstraints) @@ -85,7 +85,7 @@ class X509NameConstraintsTest { .map { GeneralSubtree(GeneralName(X500Name(it))) }.toTypedArray() val nameConstraints = NameConstraints(acceptableNames, arrayOf()) - val certFactory = CertificateFactory.getInstance("X509") + val certFactory = X509CertificateFactory().delegate Crypto.ECDSA_SECP256R1_SHA256 val pathValidator = CertPathValidator.getInstance("PKIX", BouncyCastleProvider.PROVIDER_NAME) diff --git a/core/src/test/kotlin/net/corda/core/identity/PartyAndCertificateTest.kt b/core/src/test/kotlin/net/corda/core/identity/PartyAndCertificateTest.kt index 0b839c08e8a..bd6ef220a8d 100644 --- a/core/src/test/kotlin/net/corda/core/identity/PartyAndCertificateTest.kt +++ b/core/src/test/kotlin/net/corda/core/identity/PartyAndCertificateTest.kt @@ -4,8 +4,8 @@ import net.corda.core.crypto.entropyToKeyPair import net.corda.core.internal.read import net.corda.core.serialization.deserialize import net.corda.core.serialization.serialize -import net.corda.node.utilities.KEYSTORE_TYPE -import net.corda.node.utilities.save +import net.corda.nodeapi.internal.crypto.KEYSTORE_TYPE +import net.corda.nodeapi.internal.crypto.save import net.corda.testing.SerializationEnvironmentRule import net.corda.testing.getTestPartyAndCertificate import org.assertj.core.api.Assertions.assertThat diff --git a/node/src/main/kotlin/net/corda/node/utilities/ContentSignerBuilder.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/crypto/ContentSignerBuilder.kt similarity index 97% rename from node/src/main/kotlin/net/corda/node/utilities/ContentSignerBuilder.kt rename to node-api/src/main/kotlin/net/corda/nodeapi/internal/crypto/ContentSignerBuilder.kt index f2a365bf897..bfcf1f66317 100644 --- a/node/src/main/kotlin/net/corda/node/utilities/ContentSignerBuilder.kt +++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/crypto/ContentSignerBuilder.kt @@ -1,4 +1,4 @@ -package net.corda.node.utilities +package net.corda.nodeapi.internal.crypto import net.corda.core.crypto.SignatureScheme import org.bouncycastle.asn1.x509.AlgorithmIdentifier diff --git a/node/src/main/kotlin/net/corda/node/utilities/KeyStoreUtilities.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/crypto/KeyStoreUtilities.kt similarity index 77% rename from node/src/main/kotlin/net/corda/node/utilities/KeyStoreUtilities.kt rename to node-api/src/main/kotlin/net/corda/nodeapi/internal/crypto/KeyStoreUtilities.kt index 0257302d6d8..b49493ded26 100644 --- a/node/src/main/kotlin/net/corda/node/utilities/KeyStoreUtilities.kt +++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/crypto/KeyStoreUtilities.kt @@ -1,9 +1,8 @@ @file:JvmName("KeyStoreUtilities") -package net.corda.node.utilities +package net.corda.nodeapi.internal.crypto import net.corda.core.crypto.Crypto -import net.corda.core.identity.CordaX500Name import net.corda.core.internal.* import org.bouncycastle.cert.X509CertificateHolder import java.io.IOException @@ -11,9 +10,7 @@ import java.io.InputStream import java.io.OutputStream import java.nio.file.Path import java.security.* -import java.security.cert.CertPath import java.security.cert.Certificate -import java.security.cert.CertificateFactory import java.security.cert.X509Certificate const val KEYSTORE_TYPE = "JKS" @@ -169,44 +166,3 @@ fun KeyStore.getSupportedKey(alias: String, keyPassword: String): PrivateKey { val key = getKey(alias, keyPass) as PrivateKey return Crypto.toSupportedPrivateKey(key) } - -class KeyStoreWrapper(private val storePath: Path, private val storePassword: String) { - private val keyStore = storePath.read { loadKeyStore(it, storePassword) } - - private fun createCertificate(serviceName: CordaX500Name, pubKey: PublicKey): CertPath { - val clientCertPath = keyStore.getCertificateChain(X509Utilities.CORDA_CLIENT_CA) - // Assume key password = store password. - val clientCA = certificateAndKeyPair(X509Utilities.CORDA_CLIENT_CA) - // Create new keys and store in keystore. - val cert = X509Utilities.createCertificate(CertificateType.IDENTITY, clientCA.certificate, clientCA.keyPair, serviceName, pubKey) - val certPath = CertificateFactory.getInstance("X509").generateCertPath(listOf(cert.cert) + clientCertPath) - require(certPath.certificates.isNotEmpty()) { "Certificate path cannot be empty" } - // TODO: X509Utilities.validateCertificateChain() - return certPath - } - - fun signAndSaveNewKeyPair(serviceName: CordaX500Name, privateKeyAlias: String, keyPair: KeyPair) { - val certPath = createCertificate(serviceName, keyPair.public) - // Assume key password = store password. - keyStore.addOrReplaceKey(privateKeyAlias, keyPair.private, storePassword.toCharArray(), certPath.certificates.toTypedArray()) - keyStore.save(storePath, storePassword) - } - - fun savePublicKey(serviceName: CordaX500Name, pubKeyAlias: String, pubKey: PublicKey) { - val certPath = createCertificate(serviceName, pubKey) - // Assume key password = store password. - keyStore.addOrReplaceCertificate(pubKeyAlias, certPath.certificates.first()) - keyStore.save(storePath, storePassword) - } - - // Delegate methods to keystore. Sadly keystore doesn't have an interface. - fun containsAlias(alias: String) = keyStore.containsAlias(alias) - - fun getX509Certificate(alias: String) = keyStore.getX509Certificate(alias) - - fun getCertificateChain(alias: String): Array = keyStore.getCertificateChain(alias) - - fun getCertificate(alias: String): Certificate = keyStore.getCertificate(alias) - - fun certificateAndKeyPair(alias: String): CertificateAndKeyPair = keyStore.getCertificateAndKeyPair(alias, storePassword) -} diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/crypto/KeyStoreWrapper.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/crypto/KeyStoreWrapper.kt new file mode 100644 index 00000000000..3e0d526a58f --- /dev/null +++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/crypto/KeyStoreWrapper.kt @@ -0,0 +1,52 @@ +package net.corda.nodeapi.internal.crypto + +import net.corda.core.identity.CordaX500Name +import net.corda.core.internal.cert +import net.corda.core.internal.read +import java.nio.file.Path +import java.security.KeyPair +import java.security.PublicKey +import java.security.cert.CertPath +import java.security.cert.Certificate +import java.security.cert.CertificateFactory + +class KeyStoreWrapper(private val storePath: Path, private val storePassword: String) { + private val keyStore = storePath.read { loadKeyStore(it, storePassword) } + + private fun createCertificate(serviceName: CordaX500Name, pubKey: PublicKey): CertPath { + val clientCertPath = keyStore.getCertificateChain(X509Utilities.CORDA_CLIENT_CA) + // Assume key password = store password. + val clientCA = certificateAndKeyPair(X509Utilities.CORDA_CLIENT_CA) + // Create new keys and store in keystore. + val cert = X509Utilities.createCertificate(CertificateType.IDENTITY, clientCA.certificate, clientCA.keyPair, serviceName, pubKey) + val certPath = X509CertificateFactory().delegate.generateCertPath(listOf(cert.cert) + clientCertPath) + require(certPath.certificates.isNotEmpty()) { "Certificate path cannot be empty" } + // TODO: X509Utilities.validateCertificateChain() + return certPath + } + + fun signAndSaveNewKeyPair(serviceName: CordaX500Name, privateKeyAlias: String, keyPair: KeyPair) { + val certPath = createCertificate(serviceName, keyPair.public) + // Assume key password = store password. + keyStore.addOrReplaceKey(privateKeyAlias, keyPair.private, storePassword.toCharArray(), certPath.certificates.toTypedArray()) + keyStore.save(storePath, storePassword) + } + + fun savePublicKey(serviceName: CordaX500Name, pubKeyAlias: String, pubKey: PublicKey) { + val certPath = createCertificate(serviceName, pubKey) + // Assume key password = store password. + keyStore.addOrReplaceCertificate(pubKeyAlias, certPath.certificates.first()) + keyStore.save(storePath, storePassword) + } + + // Delegate methods to keystore. Sadly keystore doesn't have an interface. + fun containsAlias(alias: String) = keyStore.containsAlias(alias) + + fun getX509Certificate(alias: String) = keyStore.getX509Certificate(alias) + + fun getCertificateChain(alias: String): Array = keyStore.getCertificateChain(alias) + + fun getCertificate(alias: String): Certificate = keyStore.getCertificate(alias) + + fun certificateAndKeyPair(alias: String): CertificateAndKeyPair = keyStore.getCertificateAndKeyPair(alias, storePassword) +} \ No newline at end of file diff --git a/node/src/main/kotlin/net/corda/node/utilities/X509Utilities.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/crypto/X509Utilities.kt similarity index 76% rename from node/src/main/kotlin/net/corda/node/utilities/X509Utilities.kt rename to node-api/src/main/kotlin/net/corda/nodeapi/internal/crypto/X509Utilities.kt index 4dfa07ec099..def4ee98790 100644 --- a/node/src/main/kotlin/net/corda/node/utilities/X509Utilities.kt +++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/crypto/X509Utilities.kt @@ -1,9 +1,11 @@ -package net.corda.node.utilities +package net.corda.nodeapi.internal.crypto import net.corda.core.crypto.Crypto import net.corda.core.crypto.SignatureScheme import net.corda.core.crypto.random63BitValue import net.corda.core.identity.CordaX500Name +import net.corda.core.internal.read +import net.corda.core.internal.write import net.corda.core.internal.x500Name import net.corda.core.utilities.days import net.corda.core.utilities.millis @@ -25,10 +27,10 @@ import org.bouncycastle.operator.jcajce.JcaContentVerifierProviderBuilder import org.bouncycastle.pkcs.PKCS10CertificationRequest import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequestBuilder import org.bouncycastle.util.io.pem.PemReader -import java.io.FileReader import java.io.FileWriter import java.io.InputStream import java.math.BigInteger +import java.nio.file.Files import java.nio.file.Path import java.security.KeyPair import java.security.PublicKey @@ -52,6 +54,7 @@ object X509Utilities { const val CORDA_CLIENT_CA_CN = "Corda Client CA Certificate" private val DEFAULT_VALIDITY_WINDOW = Pair(0.millis, 3650.days) + /** * Helper function to return the latest out of an instant and an optional date. */ @@ -89,7 +92,9 @@ object X509Utilities { * Create a de novo root self-signed X509 v3 CA cert. */ @JvmStatic - fun createSelfSignedCACertificate(subject: CordaX500Name, keyPair: KeyPair, validityWindow: Pair = DEFAULT_VALIDITY_WINDOW): X509CertificateHolder { + fun createSelfSignedCACertificate(subject: CordaX500Name, + keyPair: KeyPair, + validityWindow: Pair = DEFAULT_VALIDITY_WINDOW): X509CertificateHolder { val window = getCertificateValidityWindow(validityWindow.first, validityWindow.second) return createCertificate(CertificateType.ROOT_CA, subject.x500Name, keyPair, subject.x500Name, keyPair.public, window) } @@ -114,8 +119,9 @@ object X509Utilities { subject: CordaX500Name, subjectPublicKey: PublicKey, validityWindow: Pair = DEFAULT_VALIDITY_WINDOW, - nameConstraints: NameConstraints? = null): X509CertificateHolder - = createCertificate(certificateType, issuerCertificate, issuerKeyPair, subject.x500Name, subjectPublicKey, validityWindow, nameConstraints) + nameConstraints: NameConstraints? = null): X509CertificateHolder { + return createCertificate(certificateType, issuerCertificate, issuerKeyPair, subject.x500Name, subjectPublicKey, validityWindow, nameConstraints) + } /** * Create a X509 v3 certificate for use as a CA or for TLS. This does not require a [CordaX500Name] because the @@ -145,10 +151,9 @@ object X509Utilities { @Throws(CertPathValidatorException::class) fun validateCertificateChain(trustedRoot: X509Certificate, vararg certificates: Certificate) { require(certificates.isNotEmpty()) { "Certificate path must contain at least one certificate" } - val certFactory = CertificateFactory.getInstance("X509") val params = PKIXParameters(setOf(TrustAnchor(trustedRoot, null))) params.isRevocationEnabled = false - val certPath = certFactory.generateCertPath(certificates.toList()) + val certPath = X509CertificateFactory().delegate.generateCertPath(certificates.toList()) val pathValidator = CertPathValidator.getInstance("PKIX") pathValidator.validate(certPath, params) } @@ -156,30 +161,29 @@ object X509Utilities { /** * Helper method to store a .pem/.cer format file copy of a certificate if required for import into a PC/Mac, or for inspection. * @param x509Certificate certificate to save. - * @param filename Target filename. + * @param file Target file. */ @JvmStatic - fun saveCertificateAsPEMFile(x509Certificate: X509CertificateHolder, filename: Path) { - FileWriter(filename.toFile()).use { - JcaPEMWriter(it).use { - it.writeObject(x509Certificate) - } + fun saveCertificateAsPEMFile(x509Certificate: X509CertificateHolder, file: Path) { + JcaPEMWriter(file.toFile().writer()).use { + it.writeObject(x509Certificate) } } /** * Helper method to load back a .pem/.cer format file copy of a certificate. - * @param filename Source filename. + * @param file Source file. * @return The X509Certificate that was encoded in the file. */ @JvmStatic - fun loadCertificateFromPEMFile(filename: Path): X509CertificateHolder { - val reader = PemReader(FileReader(filename.toFile())) - val pemObject = reader.readPemObject() - val cert = X509CertificateHolder(pemObject.content) - return cert.apply { - isValidOn(Date()) + fun loadCertificateFromPEMFile(file: Path): X509CertificateHolder { + val cert = file.read { + val reader = PemReader(it.reader()) + val pemObject = reader.readPemObject() + X509CertificateHolder(pemObject.content) } + cert.isValidOn(Date()) + return cert } /** @@ -243,13 +247,13 @@ object X509Utilities { * @param validityWindow the time period the certificate is valid for. * @param nameConstraints any name constraints to impose on certificates signed by the generated certificate. */ - internal fun createCertificate(certificateType: CertificateType, - issuer: X500Name, - issuerSigner: ContentSigner, - subject: CordaX500Name, - subjectPublicKey: PublicKey, - validityWindow: Pair, - nameConstraints: NameConstraints? = null): X509CertificateHolder { + fun createCertificate(certificateType: CertificateType, + issuer: X500Name, + issuerSigner: ContentSigner, + subject: CordaX500Name, + subjectPublicKey: PublicKey, + validityWindow: Pair, + nameConstraints: NameConstraints? = null): X509CertificateHolder { val builder = createCertificate(certificateType, issuer, subject.x500Name, subjectPublicKey, validityWindow, nameConstraints) return builder.build(issuerSigner).apply { require(isValidOn(Date())) @@ -266,11 +270,13 @@ object X509Utilities { * @param validityWindow the time period the certificate is valid for. * @param nameConstraints any name constraints to impose on certificates signed by the generated certificate. */ - internal fun createCertificate(certificateType: CertificateType, issuer: X500Name, issuerKeyPair: KeyPair, - subject: X500Name, subjectPublicKey: PublicKey, - validityWindow: Pair, - nameConstraints: NameConstraints? = null): X509CertificateHolder { - + fun createCertificate(certificateType: CertificateType, + issuer: X500Name, + issuerKeyPair: KeyPair, + subject: X500Name, + subjectPublicKey: PublicKey, + validityWindow: Pair, + nameConstraints: NameConstraints? = null): X509CertificateHolder { val signatureScheme = Crypto.findSignatureScheme(issuerKeyPair.private) val provider = Crypto.findProvider(signatureScheme.providerName) val builder = createCertificate(certificateType, issuer, subject, subjectPublicKey, validityWindow, nameConstraints) @@ -285,28 +291,71 @@ object X509Utilities { /** * Create certificate signing request using provided information. */ - internal fun createCertificateSigningRequest(subject: CordaX500Name, email: String, keyPair: KeyPair, signatureScheme: SignatureScheme): PKCS10CertificationRequest { + private fun createCertificateSigningRequest(subject: CordaX500Name, + email: String, + keyPair: KeyPair, + signatureScheme: SignatureScheme): PKCS10CertificationRequest { val signer = ContentSignerBuilder.build(signatureScheme, keyPair.private, Crypto.findProvider(signatureScheme.providerName)) return JcaPKCS10CertificationRequestBuilder(subject.x500Name, keyPair.public).addAttribute(BCStyle.E, DERUTF8String(email)).build(signer) } - fun createCertificateSigningRequest(subject: CordaX500Name, email: String, keyPair: KeyPair) = createCertificateSigningRequest(subject, email, keyPair, DEFAULT_TLS_SIGNATURE_SCHEME) + fun createCertificateSigningRequest(subject: CordaX500Name, email: String, keyPair: KeyPair): PKCS10CertificationRequest { + return createCertificateSigningRequest(subject, email, keyPair, DEFAULT_TLS_SIGNATURE_SCHEME) + } +} + +/** + * Wraps a [CertificateFactory] to remove boilerplate. It's unclear whether [CertificateFactory] is threadsafe so best + * so assume this class is not. + */ +class X509CertificateFactory { + val delegate: CertificateFactory = CertificateFactory.getInstance("X.509") + fun generateCertificate(input: InputStream): X509Certificate { + return delegate.generateCertificate(input) as X509Certificate + } } +enum class CertificateType(val keyUsage: KeyUsage, vararg val purposes: KeyPurposeId, val isCA: Boolean) { + ROOT_CA( + KeyUsage(KeyUsage.digitalSignature or KeyUsage.keyCertSign or KeyUsage.cRLSign), + KeyPurposeId.id_kp_serverAuth, + KeyPurposeId.id_kp_clientAuth, + KeyPurposeId.anyExtendedKeyUsage, + isCA = true + ), -class CertificateStream(val input: InputStream) { - private val certificateFactory = CertificateFactory.getInstance("X.509") + INTERMEDIATE_CA( + KeyUsage(KeyUsage.digitalSignature or KeyUsage.keyCertSign or KeyUsage.cRLSign), + KeyPurposeId.id_kp_serverAuth, + KeyPurposeId.id_kp_clientAuth, + KeyPurposeId.anyExtendedKeyUsage, + isCA = true + ), - fun nextCertificate(): X509Certificate = certificateFactory.generateCertificate(input) as X509Certificate -} + CLIENT_CA( + KeyUsage(KeyUsage.digitalSignature or KeyUsage.keyCertSign or KeyUsage.cRLSign), + KeyPurposeId.id_kp_serverAuth, + KeyPurposeId.id_kp_clientAuth, + KeyPurposeId.anyExtendedKeyUsage, + isCA = true + ), + + TLS( + KeyUsage(KeyUsage.digitalSignature or KeyUsage.keyEncipherment or KeyUsage.keyAgreement), + KeyPurposeId.id_kp_serverAuth, + KeyPurposeId.id_kp_clientAuth, + KeyPurposeId.anyExtendedKeyUsage, + isCA = false + ), -enum class CertificateType(val keyUsage: KeyUsage, vararg val purposes: KeyPurposeId, val isCA: Boolean) { - ROOT_CA(KeyUsage(KeyUsage.digitalSignature or KeyUsage.keyCertSign or KeyUsage.cRLSign), KeyPurposeId.id_kp_serverAuth, KeyPurposeId.id_kp_clientAuth, KeyPurposeId.anyExtendedKeyUsage, isCA = true), - INTERMEDIATE_CA(KeyUsage(KeyUsage.digitalSignature or KeyUsage.keyCertSign or KeyUsage.cRLSign), KeyPurposeId.id_kp_serverAuth, KeyPurposeId.id_kp_clientAuth, KeyPurposeId.anyExtendedKeyUsage, isCA = true), - CLIENT_CA(KeyUsage(KeyUsage.digitalSignature or KeyUsage.keyCertSign or KeyUsage.cRLSign), KeyPurposeId.id_kp_serverAuth, KeyPurposeId.id_kp_clientAuth, KeyPurposeId.anyExtendedKeyUsage, isCA = true), - TLS(KeyUsage(KeyUsage.digitalSignature or KeyUsage.keyEncipherment or KeyUsage.keyAgreement), KeyPurposeId.id_kp_serverAuth, KeyPurposeId.id_kp_clientAuth, KeyPurposeId.anyExtendedKeyUsage, isCA = false), // TODO: Identity certs should have only limited depth (i.e. 1) CA signing capability, with tight name constraints - IDENTITY(KeyUsage(KeyUsage.digitalSignature or KeyUsage.keyCertSign), KeyPurposeId.id_kp_serverAuth, KeyPurposeId.id_kp_clientAuth, KeyPurposeId.anyExtendedKeyUsage, isCA = true) + IDENTITY( + KeyUsage(KeyUsage.digitalSignature or KeyUsage.keyCertSign), + KeyPurposeId.id_kp_serverAuth, + KeyPurposeId.id_kp_clientAuth, + KeyPurposeId.anyExtendedKeyUsage, + isCA = true + ) } data class CertificateAndKeyPair(val certificate: X509CertificateHolder, val keyPair: KeyPair) diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/X509CertificateSerializer.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/X509CertificateSerializer.kt index a1e3c17b8f7..2942153bba2 100644 --- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/X509CertificateSerializer.kt +++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/X509CertificateSerializer.kt @@ -1,9 +1,9 @@ package net.corda.nodeapi.internal.serialization.amqp.custom +import net.corda.nodeapi.internal.crypto.X509CertificateFactory import net.corda.nodeapi.internal.serialization.amqp.* import org.apache.qpid.proton.codec.Data import java.lang.reflect.Type -import java.security.cert.CertificateFactory import java.security.cert.X509Certificate object X509CertificateSerializer : CustomSerializer.Implements(X509Certificate::class.java) { @@ -22,6 +22,6 @@ object X509CertificateSerializer : CustomSerializer.Implements( override fun readObject(obj: Any, schema: Schema, input: DeserializationInput): X509Certificate { val bits = input.readObject(obj, schema, ByteArray::class.java) as ByteArray - return CertificateFactory.getInstance("X.509").generateCertificate(bits.inputStream()) as X509Certificate + return X509CertificateFactory().generateCertificate(bits.inputStream()) } } diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/kryo/Kryo.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/kryo/Kryo.kt index d3927dd47dc..18b598919c0 100644 --- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/kryo/Kryo.kt +++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/kryo/Kryo.kt @@ -22,6 +22,7 @@ import net.corda.core.serialization.SerializedBytes import net.corda.core.toFuture import net.corda.core.toObservable import net.corda.core.transactions.* +import net.corda.nodeapi.internal.crypto.X509CertificateFactory import net.corda.nodeapi.internal.serialization.CordaClassResolver import net.corda.nodeapi.internal.serialization.serializationContextKey import org.slf4j.Logger @@ -486,8 +487,7 @@ object CertPathSerializer : Serializer() { @ThreadSafe object X509CertificateSerializer : Serializer() { override fun read(kryo: Kryo, input: Input, type: Class): X509Certificate { - val factory = CertificateFactory.getInstance("X.509") - return factory.generateCertificate(input.readBytesWithLength().inputStream()) as X509Certificate + return X509CertificateFactory().generateCertificate(input.readBytesWithLength().inputStream()) } override fun write(kryo: Kryo, output: Output, obj: X509Certificate) { diff --git a/node/src/integration-test/kotlin/net/corda/services/messaging/MQSecurityAsNodeTest.kt b/node/src/integration-test/kotlin/net/corda/services/messaging/MQSecurityAsNodeTest.kt index 2d7b09cf1d9..bd579f4f170 100644 --- a/node/src/integration-test/kotlin/net/corda/services/messaging/MQSecurityAsNodeTest.kt +++ b/node/src/integration-test/kotlin/net/corda/services/messaging/MQSecurityAsNodeTest.kt @@ -2,11 +2,11 @@ package net.corda.services.messaging import net.corda.core.crypto.Crypto import net.corda.core.internal.* -import net.corda.node.utilities.* import net.corda.nodeapi.internal.ArtemisMessagingComponent.Companion.NODE_USER import net.corda.nodeapi.internal.ArtemisMessagingComponent.Companion.PEER_USER import net.corda.nodeapi.RPCApi import net.corda.nodeapi.config.SSLConfiguration +import net.corda.nodeapi.internal.crypto.* import net.corda.testing.MEGA_CORP import net.corda.testing.MINI_CORP import net.corda.testing.messaging.SimpleMQClient diff --git a/node/src/main/kotlin/net/corda/node/internal/AbstractNode.kt b/node/src/main/kotlin/net/corda/node/internal/AbstractNode.kt index 79583b374f9..16d0f09f055 100644 --- a/node/src/main/kotlin/net/corda/node/internal/AbstractNode.kt +++ b/node/src/main/kotlin/net/corda/node/internal/AbstractNode.kt @@ -57,7 +57,10 @@ import net.corda.node.services.upgrade.ContractUpgradeServiceImpl import net.corda.node.services.vault.NodeVaultService import net.corda.node.services.vault.VaultSoftLockManager import net.corda.node.shell.InteractiveShell -import net.corda.node.utilities.* +import net.corda.node.utilities.AffinityExecutor +import net.corda.node.utilities.CordaPersistence +import net.corda.node.utilities.configureDatabase +import net.corda.nodeapi.internal.crypto.* import org.apache.activemq.artemis.utils.ReusableLatch import org.slf4j.Logger import rx.Observable @@ -66,7 +69,6 @@ import java.lang.reflect.InvocationTargetException import java.security.KeyPair import java.security.KeyStoreException import java.security.PublicKey -import java.security.cert.CertificateFactory import java.security.cert.X509Certificate import java.sql.Connection import java.time.Clock @@ -697,7 +699,7 @@ abstract class AbstractNode(val configuration: NodeConfiguration, throw ConfigurationException("The name '$singleName' for $id doesn't match what's in the key store: $subject") } - val certPath = CertificateFactory.getInstance("X509").generateCertPath(certificates) + val certPath = X509CertificateFactory().delegate.generateCertPath(certificates) return Pair(PartyAndCertificate(certPath), keyPair) } diff --git a/node/src/main/kotlin/net/corda/node/services/config/ConfigUtilities.kt b/node/src/main/kotlin/net/corda/node/services/config/ConfigUtilities.kt index 9ba6a09c9f1..17c927f3b6e 100644 --- a/node/src/main/kotlin/net/corda/node/services/config/ConfigUtilities.kt +++ b/node/src/main/kotlin/net/corda/node/services/config/ConfigUtilities.kt @@ -8,8 +8,8 @@ import net.corda.core.crypto.Crypto import net.corda.core.crypto.SignatureScheme import net.corda.core.identity.CordaX500Name import net.corda.core.internal.* -import net.corda.node.utilities.* import net.corda.nodeapi.config.SSLConfiguration +import net.corda.nodeapi.internal.crypto.* import org.bouncycastle.asn1.x509.GeneralName import org.bouncycastle.asn1.x509.GeneralSubtree import org.bouncycastle.asn1.x509.NameConstraints diff --git a/node/src/main/kotlin/net/corda/node/services/identity/InMemoryIdentityService.kt b/node/src/main/kotlin/net/corda/node/services/identity/InMemoryIdentityService.kt index 77997cd721c..7fbbd810b8a 100644 --- a/node/src/main/kotlin/net/corda/node/services/identity/InMemoryIdentityService.kt +++ b/node/src/main/kotlin/net/corda/node/services/identity/InMemoryIdentityService.kt @@ -10,6 +10,7 @@ import net.corda.core.node.services.UnknownAnonymousPartyException import net.corda.core.serialization.SingletonSerializeAsToken import net.corda.core.utilities.contextLogger import net.corda.core.utilities.trace +import net.corda.nodeapi.internal.crypto.X509CertificateFactory import org.bouncycastle.cert.X509CertificateHolder import java.security.InvalidAlgorithmParameterException import java.security.PublicKey @@ -63,7 +64,7 @@ class InMemoryIdentityService(identities: Iterable = emptyS log.error("Certificate validation failed for ${identity.name} against trusted root ${trustAnchor.trustedCert.subjectX500Principal}.") log.error("Certificate path :") identity.certPath.certificates.reversed().forEachIndexed { index, certificate -> - val space = (0 until index).map { " " }.joinToString("") + val space = (0 until index).joinToString("") { " " } log.error("$space${certificate.toX509CertHolder().subject}") } throw e @@ -78,8 +79,7 @@ class InMemoryIdentityService(identities: Iterable = emptyS if (firstCertWithThisName != identity.certificate) { val certificates = identity.certPath.certificates val idx = certificates.lastIndexOf(firstCertWithThisName) - val certFactory = CertificateFactory.getInstance("X509") - val firstPath = certFactory.generateCertPath(certificates.slice(idx..certificates.size - 1)) + val firstPath = X509CertificateFactory().delegate.generateCertPath(certificates.slice(idx until certificates.size)) verifyAndRegisterIdentity(PartyAndCertificate(firstPath)) } @@ -104,7 +104,7 @@ class InMemoryIdentityService(identities: Iterable = emptyS val candidate = partyFromKey(party.owningKey) // TODO: This should be done via the network map cache, which is the authoritative source of well known identities return if (candidate != null) { - require(party.nameOrNull() == null || party.nameOrNull() == candidate.name) { "Candidate party ${candidate} does not match expected ${party}" } + require(party.nameOrNull() == null || party.nameOrNull() == candidate.name) { "Candidate party $candidate does not match expected $party" } wellKnownPartyFromX500Name(candidate.name) } else { null diff --git a/node/src/main/kotlin/net/corda/node/services/identity/PersistentIdentityService.kt b/node/src/main/kotlin/net/corda/node/services/identity/PersistentIdentityService.kt index a108ae0744c..282e519a381 100644 --- a/node/src/main/kotlin/net/corda/node/services/identity/PersistentIdentityService.kt +++ b/node/src/main/kotlin/net/corda/node/services/identity/PersistentIdentityService.kt @@ -9,13 +9,13 @@ import net.corda.core.internal.toX509CertHolder import net.corda.core.node.services.IdentityService import net.corda.core.node.services.UnknownAnonymousPartyException import net.corda.core.serialization.SingletonSerializeAsToken -import net.corda.core.utilities.debug import net.corda.core.utilities.MAX_HASH_HEX_SIZE import net.corda.core.utilities.contextLogger +import net.corda.core.utilities.debug import net.corda.node.utilities.AppendOnlyPersistentMap import net.corda.node.utilities.NODE_DATABASE_PREFIX +import net.corda.nodeapi.internal.crypto.X509CertificateFactory import org.bouncycastle.cert.X509CertificateHolder -import java.io.ByteArrayInputStream import java.security.InvalidAlgorithmParameterException import java.security.PublicKey import java.security.cert.* @@ -32,16 +32,15 @@ class PersistentIdentityService(override val trustRoot: X509Certificate, companion object { private val log = contextLogger() - private val certFactory: CertificateFactory = CertificateFactory.getInstance("X.509") fun createPKMap(): AppendOnlyPersistentMap { return AppendOnlyPersistentMap( toPersistentEntityKey = { it.toString() }, fromPersistentEntity = { - Pair(SecureHash.parse(it.publicKeyHash), - PartyAndCertificate(ByteArrayInputStream(it.identity).use { - certFactory.generateCertPath(it) - })) + Pair( + SecureHash.parse(it.publicKeyHash), + PartyAndCertificate(X509CertificateFactory().delegate.generateCertPath(it.identity.inputStream())) + ) }, toPersistentEntity = { key: SecureHash, value: PartyAndCertificate -> PersistentIdentity(key.toString(), value.certPath.encoded) @@ -135,8 +134,7 @@ class PersistentIdentityService(override val trustRoot: X509Certificate, if (firstCertWithThisName != identity.certificate) { val certificates = identity.certPath.certificates val idx = certificates.lastIndexOf(firstCertWithThisName) - val certFactory = CertificateFactory.getInstance("X509") - val firstPath = certFactory.generateCertPath(certificates.slice(idx until certificates.size)) + val firstPath = X509CertificateFactory().delegate.generateCertPath(certificates.slice(idx until certificates.size)) verifyAndRegisterIdentity(PartyAndCertificate(firstPath)) } diff --git a/node/src/main/kotlin/net/corda/node/services/keys/KMSUtils.kt b/node/src/main/kotlin/net/corda/node/services/keys/KMSUtils.kt index 2e12b053514..6f520f37f12 100644 --- a/node/src/main/kotlin/net/corda/node/services/keys/KMSUtils.kt +++ b/node/src/main/kotlin/net/corda/node/services/keys/KMSUtils.kt @@ -6,14 +6,14 @@ import net.corda.core.internal.cert import net.corda.core.internal.toX509CertHolder import net.corda.core.node.services.IdentityService import net.corda.core.utilities.days -import net.corda.node.utilities.CertificateType -import net.corda.node.utilities.ContentSignerBuilder -import net.corda.node.utilities.X509Utilities +import net.corda.nodeapi.internal.crypto.CertificateType +import net.corda.nodeapi.internal.crypto.ContentSignerBuilder +import net.corda.nodeapi.internal.crypto.X509CertificateFactory +import net.corda.nodeapi.internal.crypto.X509Utilities import org.bouncycastle.operator.ContentSigner import java.security.KeyPair import java.security.PublicKey import java.security.Security -import java.security.cert.CertificateFactory import java.security.cert.X509Certificate import java.time.Duration @@ -37,8 +37,7 @@ fun freshCertificate(identityService: IdentityService, val window = X509Utilities.getCertificateValidityWindow(Duration.ZERO, 3650.days, issuerCert) val ourCertificate = X509Utilities.createCertificate(CertificateType.IDENTITY, issuerCert.subject, issuerSigner, issuer.name, subjectPublicKey, window) - val certFactory = CertificateFactory.getInstance("X509") - val ourCertPath = certFactory.generateCertPath(listOf(ourCertificate.cert) + issuer.certPath.certificates) + val ourCertPath = X509CertificateFactory().delegate.generateCertPath(listOf(ourCertificate.cert) + issuer.certPath.certificates) val anonymisedIdentity = PartyAndCertificate(ourCertPath) identityService.verifyAndRegisterIdentity(anonymisedIdentity) return anonymisedIdentity diff --git a/node/src/main/kotlin/net/corda/node/services/messaging/ArtemisMessagingServer.kt b/node/src/main/kotlin/net/corda/node/services/messaging/ArtemisMessagingServer.kt index 68e9b0f79cd..5fa25f3d86b 100644 --- a/node/src/main/kotlin/net/corda/node/services/messaging/ArtemisMessagingServer.kt +++ b/node/src/main/kotlin/net/corda/node/services/messaging/ArtemisMessagingServer.kt @@ -20,10 +20,10 @@ import net.corda.node.services.messaging.NodeLoginModule.Companion.NODE_ROLE import net.corda.node.services.messaging.NodeLoginModule.Companion.PEER_ROLE import net.corda.node.services.messaging.NodeLoginModule.Companion.RPC_ROLE import net.corda.node.services.messaging.NodeLoginModule.Companion.VERIFIER_ROLE -import net.corda.node.utilities.X509Utilities -import net.corda.node.utilities.X509Utilities.CORDA_CLIENT_TLS -import net.corda.node.utilities.X509Utilities.CORDA_ROOT_CA -import net.corda.node.utilities.loadKeyStore +import net.corda.nodeapi.internal.crypto.X509Utilities +import net.corda.nodeapi.internal.crypto.X509Utilities.CORDA_CLIENT_TLS +import net.corda.nodeapi.internal.crypto.X509Utilities.CORDA_ROOT_CA +import net.corda.nodeapi.internal.crypto.loadKeyStore import net.corda.nodeapi.* import net.corda.nodeapi.internal.ArtemisMessagingComponent.Companion.INTERNAL_PREFIX import net.corda.nodeapi.internal.ArtemisMessagingComponent.Companion.NODE_USER diff --git a/node/src/main/kotlin/net/corda/node/services/messaging/P2PMessagingClient.kt b/node/src/main/kotlin/net/corda/node/services/messaging/P2PMessagingClient.kt index 8b56a45e704..8a045265ddb 100644 --- a/node/src/main/kotlin/net/corda/node/services/messaging/P2PMessagingClient.kt +++ b/node/src/main/kotlin/net/corda/node/services/messaging/P2PMessagingClient.kt @@ -10,23 +10,23 @@ import net.corda.core.serialization.SerializationDefaults import net.corda.core.serialization.SingletonSerializeAsToken import net.corda.core.serialization.deserialize import net.corda.core.serialization.serialize -import net.corda.core.utilities.* import net.corda.core.utilities.NetworkHostAndPort +import net.corda.core.utilities.contextLogger import net.corda.core.utilities.sequence import net.corda.core.utilities.trace import net.corda.node.VersionInfo import net.corda.node.services.config.NodeConfiguration import net.corda.node.services.statemachine.StateMachineManagerImpl import net.corda.node.utilities.* +import net.corda.nodeapi.internal.ArtemisMessagingComponent +import net.corda.nodeapi.internal.ArtemisMessagingComponent.* import net.corda.nodeapi.internal.ArtemisMessagingComponent.Companion.P2P_QUEUE -import net.corda.nodeapi.internal.ArtemisMessagingComponent.ArtemisAddress -import net.corda.nodeapi.internal.ArtemisMessagingComponent.NodeAddress -import net.corda.nodeapi.internal.ArtemisMessagingComponent.ServiceAddress import org.apache.activemq.artemis.api.core.ActiveMQObjectClosedException import org.apache.activemq.artemis.api.core.Message.* import org.apache.activemq.artemis.api.core.RoutingType import org.apache.activemq.artemis.api.core.SimpleString -import org.apache.activemq.artemis.api.core.client.* +import org.apache.activemq.artemis.api.core.client.ClientConsumer +import org.apache.activemq.artemis.api.core.client.ClientMessage import java.security.PublicKey import java.time.Instant import java.util.* diff --git a/node/src/main/kotlin/net/corda/node/services/messaging/RPCMessagingClient.kt b/node/src/main/kotlin/net/corda/node/services/messaging/RPCMessagingClient.kt index 4aeb8339fa1..c7033b6baf7 100644 --- a/node/src/main/kotlin/net/corda/node/services/messaging/RPCMessagingClient.kt +++ b/node/src/main/kotlin/net/corda/node/services/messaging/RPCMessagingClient.kt @@ -5,14 +5,17 @@ import net.corda.core.messaging.RPCOps import net.corda.core.serialization.SingletonSerializeAsToken import net.corda.core.utilities.NetworkHostAndPort import net.corda.node.services.RPCUserService -import net.corda.node.utilities.* -import net.corda.nodeapi.internal.ArtemisMessagingComponent.Companion.NODE_USER import net.corda.nodeapi.config.SSLConfiguration +import net.corda.nodeapi.internal.ArtemisMessagingComponent.Companion.NODE_USER +import net.corda.nodeapi.internal.crypto.X509Utilities +import net.corda.nodeapi.internal.crypto.getX509Certificate +import net.corda.nodeapi.internal.crypto.loadKeyStore import org.apache.activemq.artemis.api.core.management.ActiveMQServerControl class RPCMessagingClient(private val config: SSLConfiguration, serverAddress: NetworkHostAndPort) : SingletonSerializeAsToken() { private val artemis = ArtemisMessagingClient(config, serverAddress) private var rpcServer: RPCServer? = null + fun start(rpcOps: RPCOps, userService: RPCUserService) = synchronized(this) { val locator = artemis.start().sessionFactory.serverLocator val myCert = loadKeyStore(config.sslKeystore, config.keyStorePassword).getX509Certificate(X509Utilities.CORDA_CLIENT_TLS) diff --git a/node/src/main/kotlin/net/corda/node/utilities/ServiceIdentityGenerator.kt b/node/src/main/kotlin/net/corda/node/utilities/ServiceIdentityGenerator.kt index 051f68c63c7..a0aad8c6d2e 100644 --- a/node/src/main/kotlin/net/corda/node/utilities/ServiceIdentityGenerator.kt +++ b/node/src/main/kotlin/net/corda/node/utilities/ServiceIdentityGenerator.kt @@ -8,6 +8,7 @@ import net.corda.core.internal.cert import net.corda.core.internal.createDirectories import net.corda.core.internal.div import net.corda.core.utilities.trace +import net.corda.nodeapi.internal.crypto.* import org.slf4j.LoggerFactory import java.nio.file.Path diff --git a/node/src/main/kotlin/net/corda/node/utilities/registration/HTTPNetworkRegistrationService.kt b/node/src/main/kotlin/net/corda/node/utilities/registration/HTTPNetworkRegistrationService.kt index 8461ff2e19f..88d9230a613 100644 --- a/node/src/main/kotlin/net/corda/node/utilities/registration/HTTPNetworkRegistrationService.kt +++ b/node/src/main/kotlin/net/corda/node/utilities/registration/HTTPNetworkRegistrationService.kt @@ -2,7 +2,7 @@ package net.corda.node.utilities.registration import com.google.common.net.MediaType import net.corda.core.internal.openHttpConnection -import net.corda.node.utilities.CertificateStream +import net.corda.nodeapi.internal.crypto.X509CertificateFactory import org.apache.commons.io.IOUtils import org.bouncycastle.pkcs.PKCS10CertificationRequest import java.io.IOException @@ -32,9 +32,9 @@ class HTTPNetworkRegistrationService(compatibilityZoneURL: URL) : NetworkRegistr return when (conn.responseCode) { HTTP_OK -> ZipInputStream(conn.inputStream).use { val certificates = ArrayList() - val stream = CertificateStream(it) + val factory = X509CertificateFactory() while (it.nextEntry != null) { - certificates.add(stream.nextCertificate()) + certificates += factory.generateCertificate(it) } certificates.toTypedArray() } diff --git a/node/src/main/kotlin/net/corda/node/utilities/registration/NetworkRegistrationHelper.kt b/node/src/main/kotlin/net/corda/node/utilities/registration/NetworkRegistrationHelper.kt index bd00c4673fb..c350c3dd97e 100644 --- a/node/src/main/kotlin/net/corda/node/utilities/registration/NetworkRegistrationHelper.kt +++ b/node/src/main/kotlin/net/corda/node/utilities/registration/NetworkRegistrationHelper.kt @@ -5,10 +5,10 @@ import net.corda.core.identity.CordaX500Name import net.corda.core.internal.* import net.corda.core.utilities.seconds import net.corda.node.services.config.NodeConfiguration -import net.corda.node.utilities.* -import net.corda.node.utilities.X509Utilities.CORDA_CLIENT_CA -import net.corda.node.utilities.X509Utilities.CORDA_CLIENT_TLS -import net.corda.node.utilities.X509Utilities.CORDA_ROOT_CA +import net.corda.nodeapi.internal.crypto.* +import net.corda.nodeapi.internal.crypto.X509Utilities.CORDA_CLIENT_CA +import net.corda.nodeapi.internal.crypto.X509Utilities.CORDA_CLIENT_TLS +import net.corda.nodeapi.internal.crypto.X509Utilities.CORDA_ROOT_CA import org.bouncycastle.openssl.jcajce.JcaPEMWriter import org.bouncycastle.util.io.pem.PemObject import java.io.StringWriter diff --git a/node/src/test/kotlin/net/corda/node/services/identity/InMemoryIdentityServiceTests.kt b/node/src/test/kotlin/net/corda/node/services/identity/InMemoryIdentityServiceTests.kt index 63d6a80e30c..85857636dd3 100644 --- a/node/src/test/kotlin/net/corda/node/services/identity/InMemoryIdentityServiceTests.kt +++ b/node/src/test/kotlin/net/corda/node/services/identity/InMemoryIdentityServiceTests.kt @@ -6,16 +6,15 @@ import net.corda.core.identity.AnonymousParty import net.corda.core.identity.CordaX500Name import net.corda.core.identity.Party import net.corda.core.identity.PartyAndCertificate +import net.corda.core.internal.cert import net.corda.core.internal.toX509CertHolder import net.corda.core.node.services.UnknownAnonymousPartyException -import net.corda.core.internal.cert -import net.corda.node.services.identity.InMemoryIdentityService -import net.corda.node.utilities.CertificateAndKeyPair -import net.corda.node.utilities.CertificateType -import net.corda.node.utilities.X509Utilities +import net.corda.nodeapi.internal.crypto.CertificateAndKeyPair +import net.corda.nodeapi.internal.crypto.CertificateType +import net.corda.nodeapi.internal.crypto.X509CertificateFactory +import net.corda.nodeapi.internal.crypto.X509Utilities import net.corda.testing.* import org.junit.Test -import java.security.cert.CertificateFactory import kotlin.test.assertEquals import kotlin.test.assertFailsWith import kotlin.test.assertNull @@ -156,12 +155,11 @@ class InMemoryIdentityServiceTests { } private fun createParty(x500Name: CordaX500Name, ca: CertificateAndKeyPair): Pair { - val certFactory = CertificateFactory.getInstance("X509") val issuerKeyPair = generateKeyPair() val issuer = getTestPartyAndCertificate(x500Name, issuerKeyPair.public, ca) val txKey = Crypto.generateKeyPair() val txCert = X509Utilities.createCertificate(CertificateType.IDENTITY, issuer.certificate.toX509CertHolder(), issuerKeyPair, x500Name, txKey.public) - val txCertPath = certFactory.generateCertPath(listOf(txCert.cert) + issuer.certPath.certificates) + val txCertPath = X509CertificateFactory().delegate.generateCertPath(listOf(txCert.cert) + issuer.certPath.certificates) return Pair(issuer, PartyAndCertificate(txCertPath)) } diff --git a/node/src/test/kotlin/net/corda/node/services/identity/PersistentIdentityServiceTests.kt b/node/src/test/kotlin/net/corda/node/services/identity/PersistentIdentityServiceTests.kt index e4d57e09c26..04ac68ed846 100644 --- a/node/src/test/kotlin/net/corda/node/services/identity/PersistentIdentityServiceTests.kt +++ b/node/src/test/kotlin/net/corda/node/services/identity/PersistentIdentityServiceTests.kt @@ -6,20 +6,20 @@ import net.corda.core.identity.AnonymousParty import net.corda.core.identity.CordaX500Name import net.corda.core.identity.Party import net.corda.core.identity.PartyAndCertificate +import net.corda.core.internal.cert import net.corda.core.internal.toX509CertHolder import net.corda.core.node.services.IdentityService import net.corda.core.node.services.UnknownAnonymousPartyException -import net.corda.core.internal.cert -import net.corda.node.utilities.CertificateAndKeyPair -import net.corda.node.utilities.CertificateType import net.corda.node.utilities.CordaPersistence -import net.corda.node.utilities.X509Utilities +import net.corda.nodeapi.internal.crypto.CertificateAndKeyPair +import net.corda.nodeapi.internal.crypto.CertificateType +import net.corda.nodeapi.internal.crypto.X509CertificateFactory +import net.corda.nodeapi.internal.crypto.X509Utilities import net.corda.testing.* import net.corda.testing.node.MockServices import org.junit.After import org.junit.Before import org.junit.Test -import java.security.cert.CertificateFactory import kotlin.test.assertEquals import kotlin.test.assertFailsWith import kotlin.test.assertNull @@ -28,10 +28,9 @@ import kotlin.test.assertNull * Tests for the in memory identity service. */ class PersistentIdentityServiceTests { - - lateinit var database: CordaPersistence - lateinit var services: MockServices - lateinit var identityService: IdentityService + private lateinit var database: CordaPersistence + private lateinit var services: MockServices + private lateinit var identityService: IdentityService @Before fun setup() { @@ -254,12 +253,11 @@ class PersistentIdentityServiceTests { } private fun createParty(x500Name: CordaX500Name, ca: CertificateAndKeyPair): Pair { - val certFactory = CertificateFactory.getInstance("X509") val issuerKeyPair = generateKeyPair() val issuer = getTestPartyAndCertificate(x500Name, issuerKeyPair.public, ca) val txKey = Crypto.generateKeyPair() val txCert = X509Utilities.createCertificate(CertificateType.IDENTITY, issuer.certificate.toX509CertHolder(), issuerKeyPair, x500Name, txKey.public) - val txCertPath = certFactory.generateCertPath(listOf(txCert.cert) + issuer.certPath.certificates) + val txCertPath = X509CertificateFactory().delegate.generateCertPath(listOf(txCert.cert) + issuer.certPath.certificates) return Pair(issuer, PartyAndCertificate(txCertPath)) } diff --git a/node/src/test/kotlin/net/corda/node/services/network/NetworkMapClientTest.kt b/node/src/test/kotlin/net/corda/node/services/network/NetworkMapClientTest.kt index b973992489b..a2bf02db4df 100644 --- a/node/src/test/kotlin/net/corda/node/services/network/NetworkMapClientTest.kt +++ b/node/src/test/kotlin/net/corda/node/services/network/NetworkMapClientTest.kt @@ -10,8 +10,8 @@ import net.corda.core.serialization.serialize import net.corda.core.utilities.NetworkHostAndPort import net.corda.core.utilities.seconds import net.corda.node.services.network.TestNodeInfoFactory.createNodeInfo -import net.corda.node.utilities.CertificateType -import net.corda.node.utilities.X509Utilities +import net.corda.nodeapi.internal.crypto.CertificateType +import net.corda.nodeapi.internal.crypto.X509Utilities import net.corda.testing.SerializationEnvironmentRule import org.assertj.core.api.Assertions.assertThat import org.bouncycastle.asn1.x500.X500Name diff --git a/node/src/test/kotlin/net/corda/node/services/network/TestNodeInfoFactory.kt b/node/src/test/kotlin/net/corda/node/services/network/TestNodeInfoFactory.kt index 78840967fc8..13ac5c56573 100644 --- a/node/src/test/kotlin/net/corda/node/services/network/TestNodeInfoFactory.kt +++ b/node/src/test/kotlin/net/corda/node/services/network/TestNodeInfoFactory.kt @@ -8,15 +8,14 @@ import net.corda.core.identity.PartyAndCertificate import net.corda.core.node.NodeInfo import net.corda.core.serialization.serialize import net.corda.core.utilities.NetworkHostAndPort -import net.corda.node.utilities.CertificateType -import net.corda.node.utilities.X509Utilities +import net.corda.nodeapi.internal.crypto.CertificateType +import net.corda.nodeapi.internal.crypto.X509CertificateFactory +import net.corda.nodeapi.internal.crypto.X509Utilities import org.bouncycastle.asn1.x500.X500Name import org.bouncycastle.cert.X509CertificateHolder -import java.io.ByteArrayInputStream import java.security.KeyPair import java.security.cert.CertPath import java.security.cert.Certificate -import java.security.cert.CertificateFactory import java.security.cert.X509Certificate object TestNodeInfoFactory { @@ -40,11 +39,11 @@ object TestNodeInfoFactory { } private fun buildCertPath(vararg certificates: Certificate): CertPath { - return CertificateFactory.getInstance("X509").generateCertPath(certificates.asList()) + return X509CertificateFactory().delegate.generateCertPath(certificates.asList()) } private fun X509CertificateHolder.toX509Certificate(): X509Certificate { - return CertificateFactory.getInstance("X509").generateCertificate(ByteArrayInputStream(encoded)) as X509Certificate + return X509CertificateFactory().generateCertificate(encoded.inputStream()) } } \ No newline at end of file diff --git a/node/src/test/kotlin/net/corda/node/utilities/TLSAuthenticationTests.kt b/node/src/test/kotlin/net/corda/node/utilities/TLSAuthenticationTests.kt index 0d6eb5e8fcc..837686aee6c 100644 --- a/node/src/test/kotlin/net/corda/node/utilities/TLSAuthenticationTests.kt +++ b/node/src/test/kotlin/net/corda/node/utilities/TLSAuthenticationTests.kt @@ -5,6 +5,7 @@ import net.corda.core.crypto.SignatureScheme import net.corda.core.crypto.newSecureRandom import net.corda.core.identity.CordaX500Name import net.corda.core.internal.* +import net.corda.nodeapi.internal.crypto.* import org.junit.Rule import org.junit.Test import org.junit.rules.TemporaryFolder diff --git a/node/src/test/kotlin/net/corda/node/utilities/X509UtilitiesTest.kt b/node/src/test/kotlin/net/corda/node/utilities/X509UtilitiesTest.kt index df81bef948b..2ae3da9f748 100644 --- a/node/src/test/kotlin/net/corda/node/utilities/X509UtilitiesTest.kt +++ b/node/src/test/kotlin/net/corda/node/utilities/X509UtilitiesTest.kt @@ -13,10 +13,11 @@ import net.corda.core.serialization.deserialize import net.corda.core.serialization.serialize import net.corda.node.serialization.KryoServerSerializationScheme import net.corda.node.services.config.createKeystoreForCordaNode +import net.corda.nodeapi.internal.crypto.* import net.corda.nodeapi.internal.serialization.AllWhitelist -import net.corda.nodeapi.internal.serialization.kryo.KryoHeaderV0_1 import net.corda.nodeapi.internal.serialization.SerializationContextImpl import net.corda.nodeapi.internal.serialization.SerializationFactoryImpl +import net.corda.nodeapi.internal.serialization.kryo.KryoHeaderV0_1 import net.corda.testing.ALICE import net.corda.testing.BOB import net.corda.testing.BOB_PUBKEY @@ -41,7 +42,6 @@ import java.security.PrivateKey import java.security.SecureRandom import java.security.cert.CertPath import java.security.cert.Certificate -import java.security.cert.CertificateFactory import java.security.cert.X509Certificate import java.util.* import java.util.stream.Stream @@ -49,7 +49,6 @@ import javax.net.ssl.* import kotlin.concurrent.thread import kotlin.test.* - class X509UtilitiesTest { @Rule @JvmField @@ -360,10 +359,16 @@ class X509UtilitiesTest { trustStorePassword: String ): KeyStore { val rootCAKey = generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME) - val rootCACert = X509Utilities.createSelfSignedCACertificate(CordaX500Name(commonName = "Corda Node Root CA", organisation = "R3CEV", locality = "London", country = "GB"), rootCAKey) + val baseName = CordaX500Name(organisation = "R3CEV", locality = "London", country = "GB") + val rootCACert = X509Utilities.createSelfSignedCACertificate(baseName.copy(commonName = "Corda Node Root CA"), rootCAKey) val intermediateCAKeyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME) - val intermediateCACert = X509Utilities.createCertificate(CertificateType.INTERMEDIATE_CA, rootCACert, rootCAKey, CordaX500Name(commonName = "Corda Node Intermediate CA", organisation = "R3CEV", locality = "London", country = "GB"), intermediateCAKeyPair.public) + val intermediateCACert = X509Utilities.createCertificate( + CertificateType.INTERMEDIATE_CA, + rootCACert, + rootCAKey, + baseName.copy(commonName = "Corda Node Intermediate CA"), + intermediateCAKeyPair.public) val keyPass = keyPassword.toCharArray() val keyStore = loadOrCreateKeyStore(keyStoreFilePath, storePassword) @@ -426,11 +431,10 @@ class X509UtilitiesTest { emptyMap(), true, SerializationContext.UseCase.P2P) - val certFactory = CertificateFactory.getInstance("X509") val rootCAKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME) val rootCACert = X509Utilities.createSelfSignedCACertificate(ALICE.name, rootCAKey) val certificate = X509Utilities.createCertificate(CertificateType.TLS, rootCACert, rootCAKey, BOB.name.x500Name, BOB_PUBKEY) - val expected = certFactory.generateCertPath(listOf(certificate.cert, rootCACert.cert)) + val expected = X509CertificateFactory().delegate.generateCertPath(listOf(certificate.cert, rootCACert.cert)) val serialized = expected.serialize(factory, context).bytes val actual: CertPath = serialized.deserialize(factory, context) assertEquals(expected, actual) diff --git a/node/src/test/kotlin/net/corda/node/utilities/registration/NetworkisRegistrationHelperTest.kt b/node/src/test/kotlin/net/corda/node/utilities/registration/NetworkisRegistrationHelperTest.kt index 8454a03cd91..65745b7f3d0 100644 --- a/node/src/test/kotlin/net/corda/node/utilities/registration/NetworkisRegistrationHelperTest.kt +++ b/node/src/test/kotlin/net/corda/node/utilities/registration/NetworkisRegistrationHelperTest.kt @@ -5,9 +5,9 @@ import net.corda.core.crypto.Crypto import net.corda.core.crypto.SecureHash import net.corda.core.identity.CordaX500Name import net.corda.core.internal.* -import net.corda.node.utilities.X509Utilities -import net.corda.node.utilities.getX509Certificate -import net.corda.node.utilities.loadKeyStore +import net.corda.nodeapi.internal.crypto.X509Utilities +import net.corda.nodeapi.internal.crypto.getX509Certificate +import net.corda.nodeapi.internal.crypto.loadKeyStore import net.corda.testing.ALICE import net.corda.testing.rigorousMock import net.corda.testing.testNodeConfiguration diff --git a/testing/test-utils/src/main/kotlin/net/corda/testing/CoreTestUtils.kt b/testing/test-utils/src/main/kotlin/net/corda/testing/CoreTestUtils.kt index 1f95993b372..f483a74f252 100644 --- a/testing/test-utils/src/main/kotlin/net/corda/testing/CoreTestUtils.kt +++ b/testing/test-utils/src/main/kotlin/net/corda/testing/CoreTestUtils.kt @@ -12,24 +12,22 @@ import net.corda.core.identity.Party import net.corda.core.identity.PartyAndCertificate import net.corda.core.internal.cert import net.corda.core.node.NodeInfo -import net.corda.core.node.services.IdentityService import net.corda.core.utilities.NetworkHostAndPort import net.corda.core.utilities.OpaqueBytes import net.corda.core.utilities.loggerFor import net.corda.finance.contracts.asset.DUMMY_CASH_ISSUER import net.corda.node.services.config.configureDevKeyAndTrustStores -import net.corda.node.services.identity.InMemoryIdentityService -import net.corda.node.utilities.CertificateAndKeyPair -import net.corda.node.utilities.CertificateType -import net.corda.node.utilities.X509Utilities import net.corda.nodeapi.config.SSLConfiguration +import net.corda.nodeapi.internal.crypto.CertificateAndKeyPair +import net.corda.nodeapi.internal.crypto.CertificateType +import net.corda.nodeapi.internal.crypto.X509CertificateFactory +import net.corda.nodeapi.internal.crypto.X509Utilities import net.corda.nodeapi.internal.serialization.amqp.AMQP_ENABLED import org.mockito.internal.stubbing.answers.ThrowsException import org.mockito.stubbing.Answer import java.nio.file.Files import java.security.KeyPair import java.security.PublicKey -import java.security.cert.CertificateFactory import java.util.concurrent.atomic.AtomicInteger /** @@ -131,9 +129,8 @@ fun configureTestSSL(legalName: CordaX500Name = MEGA_CORP.name): SSLConfiguratio } fun getTestPartyAndCertificate(party: Party, trustRoot: CertificateAndKeyPair = DEV_CA): PartyAndCertificate { - val certFactory = CertificateFactory.getInstance("X509") val certHolder = X509Utilities.createCertificate(CertificateType.IDENTITY, trustRoot.certificate, trustRoot.keyPair, party.name, party.owningKey) - val certPath = certFactory.generateCertPath(listOf(certHolder.cert, trustRoot.certificate.cert)) + val certPath = X509CertificateFactory().delegate.generateCertPath(listOf(certHolder.cert, trustRoot.certificate.cert)) return PartyAndCertificate(certPath) } diff --git a/testing/test-utils/src/main/kotlin/net/corda/testing/TestConstants.kt b/testing/test-utils/src/main/kotlin/net/corda/testing/TestConstants.kt index d4b2290b40c..96f452e74ce 100644 --- a/testing/test-utils/src/main/kotlin/net/corda/testing/TestConstants.kt +++ b/testing/test-utils/src/main/kotlin/net/corda/testing/TestConstants.kt @@ -10,10 +10,10 @@ import net.corda.core.identity.CordaX500Name import net.corda.core.identity.Party import net.corda.core.identity.PartyAndCertificate import net.corda.core.internal.toX509CertHolder -import net.corda.node.utilities.CertificateAndKeyPair -import net.corda.node.utilities.X509Utilities -import net.corda.node.utilities.getCertificateAndKeyPair -import net.corda.node.utilities.loadKeyStore +import net.corda.nodeapi.internal.crypto.CertificateAndKeyPair +import net.corda.nodeapi.internal.crypto.X509Utilities +import net.corda.nodeapi.internal.crypto.getCertificateAndKeyPair +import net.corda.nodeapi.internal.crypto.loadKeyStore import org.bouncycastle.cert.X509CertificateHolder import java.math.BigInteger import java.security.KeyPair