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 4e5a56149b..acb2f014b8 100644 --- a/core/src/test/kotlin/net/corda/core/crypto/X509NameConstraintsTest.kt +++ b/core/src/test/kotlin/net/corda/core/crypto/X509NameConstraintsTest.kt @@ -11,23 +11,31 @@ import org.bouncycastle.asn1.x509.GeneralSubtree import org.bouncycastle.asn1.x509.NameConstraints import org.bouncycastle.jce.provider.BouncyCastleProvider import org.junit.Test +import java.security.UnrecoverableKeyException import java.security.cert.CertPathValidator import java.security.cert.CertPathValidatorException import java.security.cert.PKIXParameters import javax.security.auth.x500.X500Principal +import kotlin.test.assertEquals import kotlin.test.assertFailsWith import kotlin.test.assertTrue class X509NameConstraintsTest { + companion object { + private const val storePassword = "storePassword" + private const val keyPassword = "entryPassword" + } + private fun makeKeyStores(subjectName: X500Name, nameConstraints: NameConstraints): Pair { val (rootCa, intermediateCa) = createDevIntermediateCaCertPath() - val trustStore = X509KeyStore("password").apply { + + val trustStore = X509KeyStore(storePassword).apply { setCertificate(X509Utilities.CORDA_ROOT_CA, rootCa.certificate) } - val keyStore = X509KeyStore("password").apply { + val keyStore = X509KeyStore(storePassword).apply { val nodeCaKeyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME) val nodeCaCert = X509Utilities.createCertificate( CertificateType.NODE_CA, @@ -43,7 +51,7 @@ class X509NameConstraintsTest { nodeCaKeyPair, X500Principal(subjectName.encoded), tlsKeyPair.public) - setPrivateKey(X509Utilities.CORDA_CLIENT_TLS, tlsKeyPair.private, listOf(tlsCert, nodeCaCert, intermediateCa.certificate, rootCa.certificate)) + setPrivateKey(X509Utilities.CORDA_CLIENT_TLS, tlsKeyPair.private, listOf(tlsCert, nodeCaCert, intermediateCa.certificate, rootCa.certificate), keyPassword) } return Pair(keyStore, trustStore) @@ -90,7 +98,6 @@ class X509NameConstraintsTest { .map { GeneralSubtree(GeneralName(X500Name(it))) }.toTypedArray() val nameConstraints = NameConstraints(acceptableNames, arrayOf()) - Crypto.ECDSA_SECP256R1_SHA256 val pathValidator = CertPathValidator.getInstance("PKIX", BouncyCastleProvider.PROVIDER_NAME) assertFailsWith(CertPathValidatorException::class) { @@ -127,4 +134,20 @@ class X509NameConstraintsTest { true } } + + @Test + fun `test private key retrieval`() { + val acceptableNames = listOf("CN=Bank A TLS, UID=", "O=Bank A") + .map { GeneralSubtree(GeneralName(X500Name(it))) }.toTypedArray() + + val nameConstraints = NameConstraints(acceptableNames, arrayOf()) + val (keystore, _) = makeKeyStores(X500Name("CN=Bank A"), nameConstraints) + + val privateKey = keystore.getPrivateKey(X509Utilities.CORDA_CLIENT_TLS, keyPassword) + assertEquals(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME.algorithmName, privateKey.algorithm) + + assertFailsWith(UnrecoverableKeyException::class) { + keystore.getPrivateKey(X509Utilities.CORDA_CLIENT_TLS, "gibberish") + } + } } diff --git a/experimental/notary-raft/src/main/kotlin/net/corda/notary/raft/RaftUniquenessProvider.kt b/experimental/notary-raft/src/main/kotlin/net/corda/notary/raft/RaftUniquenessProvider.kt index 8146178559..e9aac5a99e 100644 --- a/experimental/notary-raft/src/main/kotlin/net/corda/notary/raft/RaftUniquenessProvider.kt +++ b/experimental/notary-raft/src/main/kotlin/net/corda/notary/raft/RaftUniquenessProvider.kt @@ -161,9 +161,9 @@ class RaftUniquenessProvider( .withSsl() .withSslProtocol(SslProtocol.TLSv1_2) .withKeyStorePath(config.keyStore.path.toString()) - .withKeyStorePassword(config.keyStore.password) + .withKeyStorePassword(config.keyStore.storePassword) .withTrustStorePath(config.trustStore.path.toString()) - .withTrustStorePassword(config.trustStore.password) + .withTrustStorePassword(config.trustStore.storePassword) .build() } diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/DevIdentityGenerator.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/DevIdentityGenerator.kt index 456db77e9b..562af4472f 100644 --- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/DevIdentityGenerator.kt +++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/DevIdentityGenerator.kt @@ -30,9 +30,9 @@ object DevIdentityGenerator { /** Install a node key store for the given node directory using the given legal name. */ fun installKeyStoreWithNodeIdentity(nodeDir: Path, legalName: CordaX500Name): Party { val certificatesDirectory = nodeDir / "certificates" - val signingCertStore = FileBasedCertificateStoreSupplier(certificatesDirectory / "nodekeystore.jks", "cordacadevpass") - val p2pKeyStore = FileBasedCertificateStoreSupplier(certificatesDirectory / "sslkeystore.jks", "cordacadevpass") - val p2pTrustStore = FileBasedCertificateStoreSupplier(certificatesDirectory / "truststore.jks", "trustpass") + val signingCertStore = FileBasedCertificateStoreSupplier(certificatesDirectory / "nodekeystore.jks", DEV_CA_KEY_STORE_PASS, DEV_CA_KEY_STORE_PASS) + val p2pKeyStore = FileBasedCertificateStoreSupplier(certificatesDirectory / "sslkeystore.jks", DEV_CA_KEY_STORE_PASS, DEV_CA_KEY_STORE_PASS) + val p2pTrustStore = FileBasedCertificateStoreSupplier(certificatesDirectory / "truststore.jks", DEV_CA_TRUST_STORE_PASS, DEV_CA_TRUST_STORE_PRIVATE_KEY_PASS) val p2pSslConfig = SslConfiguration.mutual(p2pKeyStore, p2pTrustStore) certificatesDirectory.createDirectories() @@ -77,13 +77,16 @@ object DevIdentityGenerator { publicKey) } val distServKeyStoreFile = (nodeDir / "certificates").createDirectories() / "distributedService.jks" - X509KeyStore.fromFile(distServKeyStoreFile, "cordacadevpass", createNew = true).update { + X509KeyStore.fromFile(distServKeyStoreFile, DEV_CA_KEY_STORE_PASS, createNew = true).update { setCertificate("$DISTRIBUTED_NOTARY_ALIAS_PREFIX-composite-key", compositeKeyCert) setPrivateKey( "$DISTRIBUTED_NOTARY_ALIAS_PREFIX-private-key", keyPair.private, listOf(serviceKeyCert, DEV_INTERMEDIATE_CA.certificate, DEV_ROOT_CA.certificate), - "cordacadevkeypass") + DEV_CA_KEY_STORE_PASS // Unfortunately we have to use the same password for private key due to Artemis limitation, for more details please see: + // org.apache.activemq.artemis.core.remoting.impl.ssl.SSLSupport.loadKeyManagerFactory + // where it is calling `KeyManagerFactory.init()` with store password + /*DEV_CA_PRIVATE_KEY_PASS*/) } } } diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/KeyStoreConfigHelpers.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/KeyStoreConfigHelpers.kt index d8a856afa5..03caed3ca2 100644 --- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/KeyStoreConfigHelpers.kt +++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/KeyStoreConfigHelpers.kt @@ -27,7 +27,8 @@ fun CertificateStore.registerDevSigningCertificates(legalName: CordaX500Name, devNodeCa: CertificateAndKeyPair = createDevNodeCa(intermediateCa, legalName)) { update { - setPrivateKey(X509Utilities.CORDA_CLIENT_CA, devNodeCa.keyPair.private, listOf(devNodeCa.certificate, intermediateCa.certificate, rootCert)) + setPrivateKey(X509Utilities.CORDA_CLIENT_CA, devNodeCa.keyPair.private, listOf(devNodeCa.certificate, intermediateCa.certificate, rootCert), + this@registerDevSigningCertificates.entryPassword) } } @@ -39,7 +40,8 @@ fun CertificateStore.registerDevP2pCertificates(legalName: CordaX500Name, update { val tlsKeyPair = generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME) val tlsCert = X509Utilities.createCertificate(CertificateType.TLS, devNodeCa.certificate, devNodeCa.keyPair, legalName.x500Principal, tlsKeyPair.public) - setPrivateKey(X509Utilities.CORDA_CLIENT_TLS, tlsKeyPair.private, listOf(tlsCert, devNodeCa.certificate, intermediateCa.certificate, rootCert)) + setPrivateKey(X509Utilities.CORDA_CLIENT_TLS, tlsKeyPair.private, listOf(tlsCert, devNodeCa.certificate, intermediateCa.certificate, rootCert), + this@registerDevP2pCertificates.entryPassword) } } @@ -47,15 +49,14 @@ fun CertificateStore.storeLegalIdentity(alias: String, keyPair: KeyPair = Crypto val identityCertPath = query { val nodeCaCertPath = getCertificateChain(X509Utilities.CORDA_CLIENT_CA) // Assume key password = store password. - val nodeCaCertAndKeyPair = getCertificateAndKeyPair(X509Utilities.CORDA_CLIENT_CA) + val nodeCaCertAndKeyPair = getCertificateAndKeyPair(X509Utilities.CORDA_CLIENT_CA, this@storeLegalIdentity.entryPassword) // Create new keys and store in keystore. val identityCert = X509Utilities.createCertificate(CertificateType.LEGAL_IDENTITY, nodeCaCertAndKeyPair.certificate, nodeCaCertAndKeyPair.keyPair, nodeCaCertAndKeyPair.certificate.subjectX500Principal, keyPair.public) // TODO: X509Utilities.validateCertificateChain() - // Assume key password = store password. listOf(identityCert) + nodeCaCertPath } update { - setPrivateKey(alias, keyPair.private, identityCertPath) + setPrivateKey(alias, keyPair.private, identityCertPath, this@storeLegalIdentity.entryPassword) } return PartyAndCertificate(X509Utilities.buildCertPath(identityCertPath)) } @@ -96,6 +97,7 @@ const val DEV_CA_KEY_STORE_FILE: String = "cordadevcakeys.jks" const val DEV_CA_KEY_STORE_PASS: String = "cordacadevpass" const val DEV_CA_TRUST_STORE_FILE: String = "cordatruststore.jks" const val DEV_CA_TRUST_STORE_PASS: String = "trustpass" +const val DEV_CA_TRUST_STORE_PRIVATE_KEY_PASS: String = "trustpasskeypass" // We need a class so that we can get hold of the class loader internal object DevCaHelper { @@ -104,6 +106,8 @@ internal object DevCaHelper { } } -fun loadDevCaKeyStore(classLoader: ClassLoader = DevCaHelper::class.java.classLoader): CertificateStore = CertificateStore.fromResource("certificates/$DEV_CA_KEY_STORE_FILE", DEV_CA_KEY_STORE_PASS, classLoader) +fun loadDevCaKeyStore(classLoader: ClassLoader = DevCaHelper::class.java.classLoader): CertificateStore = CertificateStore.fromResource( + "certificates/$DEV_CA_KEY_STORE_FILE", DEV_CA_KEY_STORE_PASS, DEV_CA_PRIVATE_KEY_PASS, classLoader) -fun loadDevCaTrustStore(classLoader: ClassLoader = DevCaHelper::class.java.classLoader): CertificateStore = CertificateStore.fromResource("certificates/$DEV_CA_TRUST_STORE_FILE", DEV_CA_TRUST_STORE_PASS, classLoader) +fun loadDevCaTrustStore(classLoader: ClassLoader = DevCaHelper::class.java.classLoader): CertificateStore = CertificateStore.fromResource( + "certificates/$DEV_CA_TRUST_STORE_FILE", DEV_CA_TRUST_STORE_PASS, DEV_CA_TRUST_STORE_PRIVATE_KEY_PASS, classLoader) diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/config/CertificateStore.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/config/CertificateStore.kt index 3ca6be6d6b..526fa8eb9b 100644 --- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/config/CertificateStore.kt +++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/config/CertificateStore.kt @@ -14,17 +14,18 @@ interface CertificateStore : Iterable> { companion object { - fun of(store: X509KeyStore, password: String): CertificateStore = DelegatingCertificateStore(store, password) + fun of(store: X509KeyStore, password: String, entryPassword: String): CertificateStore = DelegatingCertificateStore(store, password, entryPassword) - fun fromFile(storePath: Path, password: String, createNew: Boolean): CertificateStore = DelegatingCertificateStore(X509KeyStore.fromFile(storePath, password, createNew), password) + fun fromFile(storePath: Path, password: String, entryPassword: String, createNew: Boolean): CertificateStore = DelegatingCertificateStore(X509KeyStore.fromFile(storePath, password, createNew), password, entryPassword) - fun fromInputStream(stream: InputStream, password: String): CertificateStore = DelegatingCertificateStore(X509KeyStore.fromInputStream(stream, password), password) + fun fromInputStream(stream: InputStream, password: String, entryPassword: String): CertificateStore = DelegatingCertificateStore(X509KeyStore.fromInputStream(stream, password), password, entryPassword) - fun fromResource(storeResourceName: String, password: String, classLoader: ClassLoader = Thread.currentThread().contextClassLoader): CertificateStore = fromInputStream(classLoader.getResourceAsStream(storeResourceName), password) + fun fromResource(storeResourceName: String, password: String, entryPassword: String, classLoader: ClassLoader = Thread.currentThread().contextClassLoader): CertificateStore = fromInputStream(classLoader.getResourceAsStream(storeResourceName), password, entryPassword) } val value: X509KeyStore val password: String + val entryPassword: String fun writeTo(stream: OutputStream) = value.internal.store(stream, password.toCharArray()) @@ -79,4 +80,4 @@ interface CertificateStore : Iterable> { } } -private class DelegatingCertificateStore(override val value: X509KeyStore, override val password: String) : CertificateStore \ No newline at end of file +private class DelegatingCertificateStore(override val value: X509KeyStore, override val password: String, override val entryPassword: String) : CertificateStore \ No newline at end of file diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/config/CertificateStoreSupplier.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/config/CertificateStoreSupplier.kt index 3703742813..7cdfeee79b 100644 --- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/config/CertificateStoreSupplier.kt +++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/config/CertificateStoreSupplier.kt @@ -18,7 +18,7 @@ interface CertificateStoreSupplier { } // TODO replace reference to FileBasedCertificateStoreSupplier with CertificateStoreSupplier, after coming up with a way of passing certificate stores to Artemis. -class FileBasedCertificateStoreSupplier(val path: Path, val password: String) : CertificateStoreSupplier { +class FileBasedCertificateStoreSupplier(val path: Path, val storePassword: String, val entryPassword: String) : CertificateStoreSupplier { - override fun get(createNew: Boolean) = CertificateStore.fromFile(path, password, createNew) + override fun get(createNew: Boolean) = CertificateStore.fromFile(path, storePassword, entryPassword, createNew) } \ No newline at end of file diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/config/ConfigUtilities.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/config/ConfigUtilities.kt index cf3245837c..7286fe8abc 100644 --- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/config/ConfigUtilities.kt +++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/config/ConfigUtilities.kt @@ -151,7 +151,7 @@ private fun Config.getSingleValue(path: String, type: KType, onUnknownKeys: (Set private fun ConfigException.Missing.relative(path: String, nestedPath: String?): ConfigException.Missing { return when { - nestedPath != null -> throw ConfigException.Missing("$nestedPath.$path") + nestedPath != null -> throw ConfigException.Missing("$nestedPath.$path", this) else -> this } } diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/crypto/X509KeyStore.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/crypto/X509KeyStore.kt index 5c0c4b501b..f039af0b3d 100644 --- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/crypto/X509KeyStore.kt +++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/crypto/X509KeyStore.kt @@ -53,17 +53,17 @@ class X509KeyStore private constructor(val internal: KeyStore, private val store return uncheckedCast(certArray.asList()) } - fun getCertificateAndKeyPair(alias: String, keyPassword: String = storePassword): CertificateAndKeyPair { + fun getCertificateAndKeyPair(alias: String, keyPassword: String): CertificateAndKeyPair { val cert = getCertificate(alias) val publicKey = Crypto.toSupportedPublicKey(cert.publicKey) return CertificateAndKeyPair(cert, KeyPair(publicKey, getPrivateKey(alias, keyPassword))) } - fun getPrivateKey(alias: String, keyPassword: String = storePassword): PrivateKey { + fun getPrivateKey(alias: String, keyPassword: String): PrivateKey { return internal.getSupportedKey(alias, keyPassword) } - fun setPrivateKey(alias: String, key: PrivateKey, certificates: List, keyPassword: String = storePassword) { + fun setPrivateKey(alias: String, key: PrivateKey, certificates: List, keyPassword: String) { internal.setKeyEntry(alias, key, keyPassword.toCharArray(), certificates.toTypedArray()) } diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/protonwrapper/netty/SSLHelper.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/protonwrapper/netty/SSLHelper.kt index 2024be3359..75d623d278 100644 --- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/protonwrapper/netty/SSLHelper.kt +++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/protonwrapper/netty/SSLHelper.kt @@ -159,7 +159,9 @@ internal fun initialiseTrustStoreAndEnableCrlChecking(trustStore: CertificateSto return CertPathTrustManagerParameters(pkixParams) } -fun KeyManagerFactory.init(keyStore: CertificateStore) = init(keyStore.value.internal, keyStore.password.toCharArray()) +// As per Javadoc in: https://docs.oracle.com/javase/8/docs/api/javax/net/ssl/KeyManagerFactory.html `init` method +// 2nd parameter `password` - the password for recovering keys in the KeyStore +fun KeyManagerFactory.init(keyStore: CertificateStore) = init(keyStore.value.internal, keyStore.entryPassword.toCharArray()) fun TrustManagerFactory.init(trustStore: CertificateStore) = init(trustStore.value.internal) diff --git a/node-api/src/test/kotlin/net/corda/nodeapi/internal/crypto/X509UtilitiesTest.kt b/node-api/src/test/kotlin/net/corda/nodeapi/internal/crypto/X509UtilitiesTest.kt index 3db9072041..e2cfff84ca 100644 --- a/node-api/src/test/kotlin/net/corda/nodeapi/internal/crypto/X509UtilitiesTest.kt +++ b/node-api/src/test/kotlin/net/corda/nodeapi/internal/crypto/X509UtilitiesTest.kt @@ -235,8 +235,9 @@ class X509UtilitiesTest { signingCertStore.get(createNew = true).also { it.registerDevSigningCertificates(MEGA_CORP.name, rootCa.certificate, intermediateCa, nodeCa) } p2pSslConfig.keyStore.get(createNew = true).also { it.registerDevP2pCertificates(MEGA_CORP.name, rootCa.certificate, intermediateCa, nodeCa) } // Load back server certificate - val serverKeyStore = signingCertStore.get().value - val (serverCert, serverKeyPair) = serverKeyStore.getCertificateAndKeyPair(X509Utilities.CORDA_CLIENT_CA) + val certStore = signingCertStore.get() + val serverKeyStore = certStore.value + val (serverCert, serverKeyPair) = serverKeyStore.getCertificateAndKeyPair(X509Utilities.CORDA_CLIENT_CA, certStore.entryPassword) serverCert.checkValidity() serverCert.verify(intermediateCa.certificate.publicKey) @@ -244,7 +245,7 @@ class X509UtilitiesTest { // Load back SSL certificate val sslKeyStoreReloaded = p2pSslConfig.keyStore.get() - val (sslCert) = sslKeyStoreReloaded.query { getCertificateAndKeyPair(X509Utilities.CORDA_CLIENT_TLS, p2pSslConfig.keyStore.password) } + val (sslCert) = sslKeyStoreReloaded.query { getCertificateAndKeyPair(X509Utilities.CORDA_CLIENT_TLS, sslKeyStoreReloaded.entryPassword) } sslCert.checkValidity() sslCert.verify(serverCert.publicKey) diff --git a/node-api/src/test/kotlin/net/corda/nodeapi/internal/protonwrapper/netty/SSLHelperTest.kt b/node-api/src/test/kotlin/net/corda/nodeapi/internal/protonwrapper/netty/SSLHelperTest.kt index 54d42edd0d..1791a48f4c 100644 --- a/node-api/src/test/kotlin/net/corda/nodeapi/internal/protonwrapper/netty/SSLHelperTest.kt +++ b/node-api/src/test/kotlin/net/corda/nodeapi/internal/protonwrapper/netty/SSLHelperTest.kt @@ -20,8 +20,10 @@ class SSLHelperTest { val keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()) val trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()) - keyManagerFactory.init(CertificateStore.fromFile(sslConfig.keyStore.path, sslConfig.keyStore.password, false)) - trustManagerFactory.init(initialiseTrustStoreAndEnableCrlChecking(CertificateStore.fromFile(sslConfig.trustStore.path, sslConfig.trustStore.password, false), false)) + val keyStore = sslConfig.keyStore + keyManagerFactory.init(CertificateStore.fromFile(keyStore.path, keyStore.storePassword, keyStore.entryPassword, false)) + val trustStore = sslConfig.trustStore + trustManagerFactory.init(initialiseTrustStoreAndEnableCrlChecking(CertificateStore.fromFile(trustStore.path, trustStore.storePassword, trustStore.entryPassword, false), false)) val sslHandler = createClientSslHelper(NetworkHostAndPort("localhost", 1234), setOf(legalName), keyManagerFactory, trustManagerFactory) val legalNameHash = SecureHash.sha256(legalName.toString()).toString().take(32).toLowerCase() diff --git a/node/src/integration-test/kotlin/net/corda/node/NodeKeystoreCheckTest.kt b/node/src/integration-test/kotlin/net/corda/node/NodeKeystoreCheckTest.kt index cf438f16f8..0abeec4144 100644 --- a/node/src/integration-test/kotlin/net/corda/node/NodeKeystoreCheckTest.kt +++ b/node/src/integration-test/kotlin/net/corda/node/NodeKeystoreCheckTest.kt @@ -25,7 +25,7 @@ class NodeKeystoreCheckTest { } @Test - fun `node should throw exception if cert path doesn't chain to the trust root`() { + fun `node should throw exception if cert path does not chain to the trust root`() { driver(DriverParameters(startNodesInProcess = true, notarySpecs = emptyList())) { // Create keystores. val keystorePassword = "password" @@ -49,9 +49,9 @@ class NodeKeystoreCheckTest { // Self signed root. val badRootKeyPair = Crypto.generateKeyPair() val badRoot = X509Utilities.createSelfSignedCACertificate(X500Principal("O=Bad Root,L=Lodnon,C=GB"), badRootKeyPair) - val nodeCA = getCertificateAndKeyPair(X509Utilities.CORDA_CLIENT_CA) + val nodeCA = getCertificateAndKeyPair(X509Utilities.CORDA_CLIENT_CA, signingCertStore.entryPassword) val badNodeCACert = X509Utilities.createCertificate(CertificateType.NODE_CA, badRoot, badRootKeyPair, ALICE_NAME.x500Principal, nodeCA.keyPair.public) - setPrivateKey(X509Utilities.CORDA_CLIENT_CA, nodeCA.keyPair.private, listOf(badNodeCACert, badRoot)) + setPrivateKey(X509Utilities.CORDA_CLIENT_CA, nodeCA.keyPair.private, listOf(badNodeCACert, badRoot), signingCertStore.entryPassword) } assertThatThrownBy { diff --git a/node/src/integration-test/kotlin/net/corda/node/amqp/CertificateRevocationListNodeTests.kt b/node/src/integration-test/kotlin/net/corda/node/amqp/CertificateRevocationListNodeTests.kt index 66682cffa4..4b18fa28be 100644 --- a/node/src/integration-test/kotlin/net/corda/node/amqp/CertificateRevocationListNodeTests.kt +++ b/node/src/integration-test/kotlin/net/corda/node/amqp/CertificateRevocationListNodeTests.kt @@ -423,17 +423,17 @@ class CertificateRevocationListNodeTests { val signingCertificateStore = first val p2pSslConfiguration = second val nodeKeyStore = signingCertificateStore.get() - val (nodeCert, nodeKeys) = nodeKeyStore.query { getCertificateAndKeyPair(X509Utilities.CORDA_CLIENT_CA) } + val (nodeCert, nodeKeys) = nodeKeyStore.query { getCertificateAndKeyPair(X509Utilities.CORDA_CLIENT_CA, nodeKeyStore.entryPassword) } val newNodeCert = replaceCrlDistPointCaCertificate(nodeCert, CertificateType.NODE_CA, INTERMEDIATE_CA.keyPair, nodeCaCrlDistPoint) val nodeCertChain = listOf(newNodeCert, INTERMEDIATE_CA.certificate, *nodeKeyStore.query { getCertificateChain(X509Utilities.CORDA_CLIENT_CA) }.drop(2).toTypedArray()) nodeKeyStore.update { internal.deleteEntry(X509Utilities.CORDA_CLIENT_CA) } nodeKeyStore.update { - setPrivateKey(X509Utilities.CORDA_CLIENT_CA, nodeKeys.private, nodeCertChain) + setPrivateKey(X509Utilities.CORDA_CLIENT_CA, nodeKeys.private, nodeCertChain, nodeKeyStore.entryPassword) } val sslKeyStore = p2pSslConfiguration.keyStore.get() - val (tlsCert, tlsKeys) = sslKeyStore.query { getCertificateAndKeyPair(X509Utilities.CORDA_CLIENT_TLS) } + val (tlsCert, tlsKeys) = sslKeyStore.query { getCertificateAndKeyPair(X509Utilities.CORDA_CLIENT_TLS, sslKeyStore.entryPassword) } val newTlsCert = replaceCrlDistPointCaCertificate(tlsCert, CertificateType.TLS, nodeKeys, tlsCrlDistPoint, X500Name.getInstance(ROOT_CA.certificate.subjectX500Principal.encoded)) val sslCertChain = listOf(newTlsCert, newNodeCert, INTERMEDIATE_CA.certificate, *sslKeyStore.query { getCertificateChain(X509Utilities.CORDA_CLIENT_TLS) }.drop(3).toTypedArray()) @@ -441,7 +441,7 @@ class CertificateRevocationListNodeTests { internal.deleteEntry(X509Utilities.CORDA_CLIENT_TLS) } sslKeyStore.update { - setPrivateKey(X509Utilities.CORDA_CLIENT_TLS, tlsKeys.private, sslCertChain) + setPrivateKey(X509Utilities.CORDA_CLIENT_TLS, tlsKeys.private, sslCertChain, sslKeyStore.entryPassword) } return newNodeCert } 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 7fb2986bc4..df860ef06a 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 @@ -105,11 +105,11 @@ class MQSecurityAsNodeTest : P2PMQSecurityTest() { val clientTLSCert = X509Utilities.createCertificate(CertificateType.TLS, clientCACert, clientKeyPair, CordaX500Name("MiniCorp", "London", "GB").x500Principal, tlsKeyPair.public) signingCertStore.get(createNew = true).update { - setPrivateKey(X509Utilities.CORDA_CLIENT_CA, clientKeyPair.private, listOf(clientCACert, DEV_INTERMEDIATE_CA.certificate, DEV_ROOT_CA.certificate)) + setPrivateKey(X509Utilities.CORDA_CLIENT_CA, clientKeyPair.private, listOf(clientCACert, DEV_INTERMEDIATE_CA.certificate, DEV_ROOT_CA.certificate), signingCertStore.entryPassword) } p2pSslConfig.keyStore.get(createNew = true).update { - setPrivateKey(X509Utilities.CORDA_CLIENT_TLS, tlsKeyPair.private, listOf(clientTLSCert, clientCACert, DEV_INTERMEDIATE_CA.certificate, DEV_ROOT_CA.certificate)) + setPrivateKey(X509Utilities.CORDA_CLIENT_TLS, tlsKeyPair.private, listOf(clientTLSCert, clientCACert, DEV_INTERMEDIATE_CA.certificate, DEV_ROOT_CA.certificate), p2pSslConfig.keyStore.entryPassword) } val attacker = clientTo(alice.node.configuration.p2pAddress, p2pSslConfig) 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 c196bf639e..72eb7e1bc1 100644 --- a/node/src/main/kotlin/net/corda/node/internal/AbstractNode.kt +++ b/node/src/main/kotlin/net/corda/node/internal/AbstractNode.kt @@ -862,7 +862,7 @@ abstract class AbstractNode(val configuration: NodeConfiguration, keyStore.storeLegalIdentity(privateKeyAlias, generateKeyPair()) } - val (x509Cert, keyPair) = keyStore.query { getCertificateAndKeyPair(privateKeyAlias) } + val (x509Cert, keyPair) = keyStore.query { getCertificateAndKeyPair(privateKeyAlias, keyStore.entryPassword) } // TODO: Use configuration to indicate composite key should be used instead of public key for the identity. val compositeKeyAlias = "$id-composite-key" 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 1b8d0507b8..bfae0e983c 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 @@ -86,9 +86,9 @@ fun MutualSslConfiguration.configureDevKeyAndTrustStores(myLegalName: CordaX500N } if (keyStore.getOptional() == null || signingCertificateStore.getOptional() == null) { - val signingKeyStore = FileBasedCertificateStoreSupplier(signingCertificateStore.path, signingCertificateStore.password).get(true).also { it.registerDevSigningCertificates(myLegalName) } + val signingKeyStore = FileBasedCertificateStoreSupplier(signingCertificateStore.path, signingCertificateStore.storePassword, signingCertificateStore.entryPassword).get(true).also { it.registerDevSigningCertificates(myLegalName) } - FileBasedCertificateStoreSupplier(keyStore.path, keyStore.password).get(true).also { it.registerDevP2pCertificates(myLegalName) } + FileBasedCertificateStoreSupplier(keyStore.path, keyStore.storePassword, keyStore.entryPassword).get(true).also { it.registerDevP2pCertificates(myLegalName) } // Move distributed service composite key (generated by IdentityGenerator.generateToDisk) to keystore if exists. val distributedServiceKeystore = certificatesDirectory / "distributedService.jks" @@ -97,7 +97,7 @@ fun MutualSslConfiguration.configureDevKeyAndTrustStores(myLegalName: CordaX500N signingKeyStore.update { serviceKeystore.aliases().forEach { if (serviceKeystore.internal.isKeyEntry(it)) { - setPrivateKey(it, serviceKeystore.getPrivateKey(it, DEV_CA_PRIVATE_KEY_PASS), serviceKeystore.getCertificateChain(it)) + setPrivateKey(it, serviceKeystore.getPrivateKey(it, DEV_CA_KEY_STORE_PASS), serviceKeystore.getCertificateChain(it), signingKeyStore.entryPassword) } else { setCertificate(it, serviceKeystore.getCertificate(it)) } diff --git a/node/src/main/kotlin/net/corda/node/services/config/NodeConfiguration.kt b/node/src/main/kotlin/net/corda/node/services/config/NodeConfiguration.kt index f7cf92aa36..ecf0c407f9 100644 --- a/node/src/main/kotlin/net/corda/node/services/config/NodeConfiguration.kt +++ b/node/src/main/kotlin/net/corda/node/services/config/NodeConfiguration.kt @@ -260,12 +260,16 @@ data class NodeConfigurationImpl( override val certificatesDirectory = baseDirectory / "certificates" private val signingCertificateStorePath = certificatesDirectory / "nodekeystore.jks" - override val signingCertificateStore = FileBasedCertificateStoreSupplier(signingCertificateStorePath, keyStorePassword) - private val p2pKeystorePath: Path get() = certificatesDirectory / "sslkeystore.jks" - private val p2pKeyStore = FileBasedCertificateStoreSupplier(p2pKeystorePath, keyStorePassword) + + // TODO: There are two implications here: + // 1. "signingCertificateStore" and "p2pKeyStore" have the same passwords. In the future we should re-visit this "rule" and see of they can be made different; + // 2. The passwords for store and for keys in this store are the same, this is due to limitations of Artemis. + override val signingCertificateStore = FileBasedCertificateStoreSupplier(signingCertificateStorePath, keyStorePassword, keyStorePassword) + private val p2pKeyStore = FileBasedCertificateStoreSupplier(p2pKeystorePath, keyStorePassword, keyStorePassword) + private val p2pTrustStoreFilePath: Path get() = certificatesDirectory / "truststore.jks" - private val p2pTrustStore = FileBasedCertificateStoreSupplier(p2pTrustStoreFilePath, trustStorePassword) + private val p2pTrustStore = FileBasedCertificateStoreSupplier(p2pTrustStoreFilePath, trustStorePassword, trustStorePassword) override val p2pSslOptions: MutualSslConfiguration = SslConfiguration.mutual(p2pKeyStore, p2pTrustStore) override val rpcOptions: NodeRpcOptions 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 eb1aac885b..e8f916dbb7 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 @@ -161,7 +161,7 @@ open class NetworkRegistrationHelper(private val certificatesDirectory: Path, println("Private key '$keyAlias' and certificate stored in node signing keystore.") } - private fun CertificateStore.loadOrCreateKeyPair(alias: String, privateKeyPassword: String = password): KeyPair { + private fun CertificateStore.loadOrCreateKeyPair(alias: String, entryPassword: String = password): KeyPair { // Create or load self signed keypair from the key store. // We use the self sign certificate to store the key temporarily in the keystore while waiting for the request approval. if (alias !in this) { @@ -170,11 +170,11 @@ open class NetworkRegistrationHelper(private val certificatesDirectory: Path, val selfSignCert = X509Utilities.createSelfSignedCACertificate(myLegalName.x500Principal, keyPair) // Save to the key store. with(value) { - setPrivateKey(alias, keyPair.private, listOf(selfSignCert), keyPassword = privateKeyPassword) + setPrivateKey(alias, keyPair.private, listOf(selfSignCert), keyPassword = entryPassword) save() } } - return query { getCertificateAndKeyPair(alias, privateKeyPassword) }.keyPair + return query { getCertificateAndKeyPair(alias, entryPassword) }.keyPair } /** @@ -281,7 +281,9 @@ class NodeRegistrationHelper( } private fun createSSLKeystore(nodeCAKeyPair: KeyPair, certificates: List, tlsCertCrlIssuer: X500Name?) { - config.p2pSslOptions.keyStore.get(createNew = true).update { + val keyStore = config.p2pSslOptions.keyStore + val certificateStore = keyStore.get(createNew = true) + certificateStore.update { println("Generating SSL certificate for node messaging service.") val sslKeyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME) val sslCert = X509Utilities.createCertificate( @@ -293,9 +295,9 @@ class NodeRegistrationHelper( crlDistPoint = config.tlsCertCrlDistPoint?.toString(), crlIssuer = tlsCertCrlIssuer) logger.info("Generated TLS certificate: $sslCert") - setPrivateKey(CORDA_CLIENT_TLS, sslKeyPair.private, listOf(sslCert) + certificates) + setPrivateKey(CORDA_CLIENT_TLS, sslKeyPair.private, listOf(sslCert) + certificates, certificateStore.entryPassword) } - println("SSL private key and certificate stored in ${config.p2pSslOptions.keyStore.path}.") + println("SSL private key and certificate stored in ${keyStore.path}.") } private fun createTruststore(rootCertificate: X509Certificate) { diff --git a/testing/node-driver/src/main/kotlin/net/corda/testing/node/internal/DriverDSLImpl.kt b/testing/node-driver/src/main/kotlin/net/corda/testing/node/internal/DriverDSLImpl.kt index e87557f716..cd46caf2fb 100644 --- a/testing/node-driver/src/main/kotlin/net/corda/testing/node/internal/DriverDSLImpl.kt +++ b/testing/node-driver/src/main/kotlin/net/corda/testing/node/internal/DriverDSLImpl.kt @@ -845,10 +845,10 @@ class DriverDSLImpl( config += "baseDirectory" to configuration.baseDirectory.toAbsolutePath().toString() config += "keyStorePath" to configuration.p2pSslOptions.keyStore.path.toString() - config += "keyStorePassword" to configuration.p2pSslOptions.keyStore.password + config += "keyStorePassword" to configuration.p2pSslOptions.keyStore.storePassword config += "trustStorePath" to configuration.p2pSslOptions.trustStore.path.toString() - config += "trustStorePassword" to configuration.p2pSslOptions.trustStore.password + config += "trustStorePassword" to configuration.p2pSslOptions.trustStore.storePassword return config } diff --git a/testing/test-common/src/main/kotlin/net/corda/testing/common/internal/UnsafeCertificatesFactory.kt b/testing/test-common/src/main/kotlin/net/corda/testing/common/internal/UnsafeCertificatesFactory.kt deleted file mode 100644 index bce2152d57..0000000000 --- a/testing/test-common/src/main/kotlin/net/corda/testing/common/internal/UnsafeCertificatesFactory.kt +++ /dev/null @@ -1,215 +0,0 @@ -package net.corda.testing.common.internal - -import net.corda.core.identity.CordaX500Name -import net.corda.core.internal.createFile -import net.corda.core.internal.deleteIfExists -import net.corda.core.internal.div -import net.corda.nodeapi.internal.config.FileBasedCertificateStoreSupplier -import net.corda.nodeapi.internal.config.SslConfiguration -import net.corda.nodeapi.internal.config.MutualSslConfiguration -import net.corda.nodeapi.internal.crypto.* -import org.apache.commons.io.FileUtils -import sun.security.tools.keytool.CertAndKeyGen -import sun.security.x509.X500Name -import java.nio.file.Files -import java.nio.file.Path -import java.security.KeyPair -import java.security.KeyStore -import java.security.PrivateKey -import java.security.cert.X509Certificate -import java.time.Duration -import java.time.Instant -import java.time.Instant.now -import java.time.temporal.ChronoUnit -import java.util.* -import javax.security.auth.x500.X500Principal - -class UnsafeCertificatesFactory( - defaults: Defaults = defaults(), - private val keyType: String = defaults.keyType, - private val signatureAlgorithm: String = defaults.signatureAlgorithm, - private val keySize: Int = defaults.keySize, - private val certificatesValidityWindow: CertificateValidityWindow = defaults.certificatesValidityWindow, - private val keyStoreType: String = defaults.keyStoreType) { - - companion object { - private const val KEY_TYPE_RSA = "RSA" - private const val SIG_ALG_SHA_RSA = "SHA1WithRSA" - private const val KEY_SIZE = 1024 - private val DEFAULT_DURATION = Duration.of(365, ChronoUnit.DAYS) - private const val DEFAULT_KEYSTORE_TYPE = "JKS" - - fun defaults() = Defaults(KEY_TYPE_RSA, SIG_ALG_SHA_RSA, KEY_SIZE, CertificateValidityWindow(now(), DEFAULT_DURATION), DEFAULT_KEYSTORE_TYPE) - } - - data class Defaults( - val keyType: String, - val signatureAlgorithm: String, - val keySize: Int, - val certificatesValidityWindow: CertificateValidityWindow, - val keyStoreType: String) - - fun createSelfSigned(name: X500Name): UnsafeCertificate = createSelfSigned(name, keyType, signatureAlgorithm, keySize, certificatesValidityWindow) - - fun createSelfSigned(name: CordaX500Name) = createSelfSigned(name.asX500Name()) - - fun createSignedBy(subject: X500Principal, issuer: UnsafeCertificate): UnsafeCertificate = issuer.createSigned(subject, keyType, signatureAlgorithm, keySize, certificatesValidityWindow) - - fun createSignedBy(name: CordaX500Name, issuer: UnsafeCertificate): UnsafeCertificate = issuer.createSigned(name, keyType, signatureAlgorithm, keySize, certificatesValidityWindow) - - fun newKeyStore(password: String) = UnsafeKeyStore.create(keyStoreType, password) - - fun newKeyStores(keyStorePassword: String, trustStorePassword: String): KeyStores = KeyStores(newKeyStore(keyStorePassword), newKeyStore(trustStorePassword)) -} - -class KeyStores(val keyStore: UnsafeKeyStore, val trustStore: UnsafeKeyStore) { - fun save(directory: Path = Files.createTempDirectory(null)): AutoClosableSSLConfiguration { - val keyStoreFile = keyStore.toTemporaryFile("sslkeystore", directory = directory) - val trustStoreFile = trustStore.toTemporaryFile("truststore", directory = directory) - - val sslConfiguration = sslConfiguration(keyStoreFile, trustStoreFile) - - return object : AutoClosableSSLConfiguration { - override val value = sslConfiguration - - override fun close() { - keyStoreFile.close() - trustStoreFile.close() - } - } - } - - private fun sslConfiguration(keyStoreFile: TemporaryFile, trustStoreFile: TemporaryFile): MutualSslConfiguration { - - val keyStore = FileBasedCertificateStoreSupplier(keyStoreFile.file, keyStore.password) - val trustStore = FileBasedCertificateStoreSupplier(trustStoreFile.file, trustStore.password) - return SslConfiguration.mutual(keyStore, trustStore) - } -} - -interface AutoClosableSSLConfiguration : AutoCloseable { - val value: MutualSslConfiguration -} - -typealias KeyStoreEntry = Pair - -data class UnsafeKeyStore(private val delegate: KeyStore, val password: String) : Iterable { - companion object { - private const val JKS_TYPE = "JKS" - - fun create(type: String, password: String) = UnsafeKeyStore(newKeyStore(type, password), password) - - fun createJKS(password: String) = create(JKS_TYPE, password) - } - - operator fun plus(entry: KeyStoreEntry) = set(entry.first, entry.second) - - override fun iterator(): Iterator> = delegate.aliases().toList().map { alias -> alias to get(alias) }.iterator() - - operator fun get(alias: String): UnsafeCertificate { - return when { - delegate.isKeyEntry(alias) -> delegate.getCertificateAndKeyPair(alias, password).unsafe() - else -> UnsafeCertificate(delegate.getX509Certificate(alias), null) - } - } - - operator fun set(alias: String, certificate: UnsafeCertificate) { - delegate.setCertificateEntry(alias, certificate.value) - delegate.setKeyEntry(alias, certificate.privateKey, password.toCharArray(), arrayOf(certificate.value)) - } - - fun save(path: Path) = delegate.save(path, password) - - fun toTemporaryFile(fileName: String, fileExtension: String? = delegate.type.toLowerCase(), directory: Path): TemporaryFile { - return TemporaryFile("$fileName.$fileExtension", directory).also { save(it.file) } - } -} - -class TemporaryFile(fileName: String, val directory: Path) : AutoCloseable { - val file: Path = (directory / fileName).createFile().toAbsolutePath() - - init { - file.toFile().deleteOnExit() - } - - override fun close() { - file.deleteIfExists() - } -} - -data class UnsafeCertificate(val value: X509Certificate, val privateKey: PrivateKey?) { - val keyPair = KeyPair(value.publicKey, privateKey) - - val principal: X500Principal get() = value.subjectX500Principal - - val issuer: X500Principal get() = value.issuerX500Principal - - fun createSigned(subject: X500Principal, keyType: String, signatureAlgorithm: String, keySize: Int, certificatesValidityWindow: CertificateValidityWindow): UnsafeCertificate { - val keyGen = keyGen(keyType, signatureAlgorithm, keySize) - - return UnsafeCertificate(X509Utilities.createCertificate( - certificateType = CertificateType.TLS, - issuer = value.subjectX500Principal, - issuerKeyPair = keyPair, - validityWindow = certificatesValidityWindow.datePair, - subject = subject, - subjectPublicKey = keyGen.publicKey - ), keyGen.privateKey) - } - - fun createSigned(name: CordaX500Name, keyType: String, signatureAlgorithm: String, keySize: Int, certificatesValidityWindow: CertificateValidityWindow) = createSigned(name.x500Principal, keyType, signatureAlgorithm, keySize, certificatesValidityWindow) -} - -data class CertificateValidityWindow(val from: Instant, val to: Instant) { - constructor(from: Instant, duration: Duration) : this(from, from.plus(duration)) - - val duration = Duration.between(from, to)!! - - val datePair = Date.from(from) to Date.from(to) -} - -private fun createSelfSigned(name: X500Name, keyType: String, signatureAlgorithm: String, keySize: Int, certificatesValidityWindow: CertificateValidityWindow): UnsafeCertificate { - val keyGen = keyGen(keyType, signatureAlgorithm, keySize) - return UnsafeCertificate(keyGen.getSelfCertificate(name, certificatesValidityWindow.duration.toMillis()), keyGen.privateKey) -} - -private fun CordaX500Name.asX500Name(): X500Name = X500Name.asX500Name(x500Principal) - -private fun CertificateAndKeyPair.unsafe() = UnsafeCertificate(certificate, keyPair.private) - -private fun keyGen(keyType: String, signatureAlgorithm: String, keySize: Int): CertAndKeyGen { - val keyGen = CertAndKeyGen(keyType, signatureAlgorithm) - keyGen.generate(keySize) - return keyGen -} - -private fun newKeyStore(type: String, password: String): KeyStore { - val keyStore = KeyStore.getInstance(type) - // Loading creates the store, can't do anything with it until it's loaded - keyStore.load(null, password.toCharArray()) - - return keyStore -} - -fun withKeyStores(server: KeyStores, client: KeyStores, action: (brokerSslOptions: MutualSslConfiguration, clientSslOptions: MutualSslConfiguration) -> Unit) { - val serverDir = Files.createTempDirectory(null) - FileUtils.forceDeleteOnExit(serverDir.toFile()) - - val clientDir = Files.createTempDirectory(null) - FileUtils.forceDeleteOnExit(clientDir.toFile()) - - server.save(serverDir).use { serverSslConfiguration -> - client.save(clientDir).use { clientSslConfiguration -> - action(serverSslConfiguration.value, clientSslConfiguration.value) - } - } - clientDir.deleteIfExists() - serverDir.deleteIfExists() -} - -fun withCertificates(factoryDefaults: UnsafeCertificatesFactory.Defaults = UnsafeCertificatesFactory.defaults(), action: (server: KeyStores, client: KeyStores, createSelfSigned: (name: CordaX500Name) -> UnsafeCertificate, createSignedBy: (name: CordaX500Name, issuer: UnsafeCertificate) -> UnsafeCertificate) -> Unit) { - val factory = UnsafeCertificatesFactory(factoryDefaults) - val server = factory.newKeyStores("serverKeyStorePass", "serverTrustKeyStorePass") - val client = factory.newKeyStores("clientKeyStorePass", "clientTrustKeyStorePass") - action(server, client, factory::createSelfSigned, factory::createSignedBy) -} \ No newline at end of file diff --git a/testing/test-utils/src/main/kotlin/net/corda/testing/internal/stubs/CertificateStoreStubs.kt b/testing/test-utils/src/main/kotlin/net/corda/testing/internal/stubs/CertificateStoreStubs.kt index 62f871ca8c..dfe21245f1 100644 --- a/testing/test-utils/src/main/kotlin/net/corda/testing/internal/stubs/CertificateStoreStubs.kt +++ b/testing/test-utils/src/main/kotlin/net/corda/testing/internal/stubs/CertificateStoreStubs.kt @@ -1,6 +1,9 @@ package net.corda.testing.internal.stubs import net.corda.core.internal.div +import net.corda.nodeapi.internal.DEV_CA_KEY_STORE_PASS +import net.corda.nodeapi.internal.DEV_CA_TRUST_STORE_PASS +import net.corda.nodeapi.internal.DEV_CA_TRUST_STORE_PRIVATE_KEY_PASS import net.corda.nodeapi.internal.config.FileBasedCertificateStoreSupplier import net.corda.nodeapi.internal.config.SslConfiguration import net.corda.nodeapi.internal.config.MutualSslConfiguration @@ -11,28 +14,27 @@ class CertificateStoreStubs { companion object { const val DEFAULT_CERTIFICATES_DIRECTORY_NAME = "certificates" - - @JvmStatic - fun withStoreAt(certificateStorePath: Path, password: String): FileBasedCertificateStoreSupplier = FileBasedCertificateStoreSupplier(certificateStorePath, password) } class Signing { companion object { - const val DEFAULT_STORE_FILE_NAME = "nodekeystore.jks" - const val DEFAULT_STORE_PASSWORD = "cordacadevpass" + private const val DEFAULT_STORE_FILE_NAME = "nodekeystore.jks" + private const val DEFAULT_STORE_PASSWORD = DEV_CA_KEY_STORE_PASS @JvmStatic - fun withCertificatesDirectory(certificatesDirectory: Path, password: String = DEFAULT_STORE_PASSWORD, certificateStoreFileName: String = DEFAULT_STORE_FILE_NAME): FileBasedCertificateStoreSupplier { + fun withCertificatesDirectory(certificatesDirectory: Path, password: String = DEFAULT_STORE_PASSWORD, + keyPassword: String = password, certificateStoreFileName: String = DEFAULT_STORE_FILE_NAME): FileBasedCertificateStoreSupplier { - return FileBasedCertificateStoreSupplier(certificatesDirectory / certificateStoreFileName, password) + return FileBasedCertificateStoreSupplier(certificatesDirectory / certificateStoreFileName, password, keyPassword) } @JvmStatic - fun withBaseDirectory(baseDirectory: Path, password: String = DEFAULT_STORE_PASSWORD, certificatesDirectoryName: String = DEFAULT_CERTIFICATES_DIRECTORY_NAME, certificateStoreFileName: String = DEFAULT_STORE_FILE_NAME): FileBasedCertificateStoreSupplier { + fun withBaseDirectory(baseDirectory: Path, password: String = DEFAULT_STORE_PASSWORD, keyPassword: String = password, + certificatesDirectoryName: String = DEFAULT_CERTIFICATES_DIRECTORY_NAME, certificateStoreFileName: String = DEFAULT_STORE_FILE_NAME): FileBasedCertificateStoreSupplier { - return FileBasedCertificateStoreSupplier(baseDirectory / certificatesDirectoryName / certificateStoreFileName, password) + return FileBasedCertificateStoreSupplier(baseDirectory / certificatesDirectoryName / certificateStoreFileName, password, keyPassword) } } } @@ -42,10 +44,13 @@ class CertificateStoreStubs { companion object { @JvmStatic - fun withCertificatesDirectory(certificatesDirectory: Path, keyStoreFileName: String = KeyStore.DEFAULT_STORE_FILE_NAME, keyStorePassword: String = KeyStore.DEFAULT_STORE_PASSWORD, trustStoreFileName: String = TrustStore.DEFAULT_STORE_FILE_NAME, trustStorePassword: String = TrustStore.DEFAULT_STORE_PASSWORD): MutualSslConfiguration { + fun withCertificatesDirectory(certificatesDirectory: Path, keyStoreFileName: String = KeyStore.DEFAULT_STORE_FILE_NAME, + keyStorePassword: String = KeyStore.DEFAULT_STORE_PASSWORD, keyPassword: String = keyStorePassword, + trustStoreFileName: String = TrustStore.DEFAULT_STORE_FILE_NAME, trustStorePassword: String = TrustStore.DEFAULT_STORE_PASSWORD, trustStoreKeyPassword: String = TrustStore.DEFAULT_KEY_PASSWORD, + useOpenSsl: Boolean = false): MutualSslConfiguration { - val keyStore = FileBasedCertificateStoreSupplier(certificatesDirectory / keyStoreFileName, keyStorePassword) - val trustStore = FileBasedCertificateStoreSupplier(certificatesDirectory / trustStoreFileName, trustStorePassword) + val keyStore = FileBasedCertificateStoreSupplier(certificatesDirectory / keyStoreFileName, keyStorePassword, keyPassword) + val trustStore = FileBasedCertificateStoreSupplier(certificatesDirectory / trustStoreFileName, trustStorePassword, trustStoreKeyPassword) return SslConfiguration.mutual(keyStore, trustStore) } @@ -61,18 +66,20 @@ class CertificateStoreStubs { companion object { const val DEFAULT_STORE_FILE_NAME = "sslkeystore.jks" - const val DEFAULT_STORE_PASSWORD = "cordacadevpass" + const val DEFAULT_STORE_PASSWORD = DEV_CA_KEY_STORE_PASS @JvmStatic - fun withCertificatesDirectory(certificatesDirectory: Path, password: String = DEFAULT_STORE_PASSWORD, certificateStoreFileName: String = DEFAULT_STORE_FILE_NAME): FileBasedCertificateStoreSupplier { + fun withCertificatesDirectory(certificatesDirectory: Path, password: String = DEFAULT_STORE_PASSWORD, keyPassword: String = password, + certificateStoreFileName: String = DEFAULT_STORE_FILE_NAME): FileBasedCertificateStoreSupplier { - return FileBasedCertificateStoreSupplier(certificatesDirectory / certificateStoreFileName, password) + return FileBasedCertificateStoreSupplier(certificatesDirectory / certificateStoreFileName, password, keyPassword) } @JvmStatic - fun withBaseDirectory(baseDirectory: Path, password: String = DEFAULT_STORE_PASSWORD, certificatesDirectoryName: String = DEFAULT_CERTIFICATES_DIRECTORY_NAME, certificateStoreFileName: String = DEFAULT_STORE_FILE_NAME): FileBasedCertificateStoreSupplier { + fun withBaseDirectory(baseDirectory: Path, password: String = DEFAULT_STORE_PASSWORD, keyPassword: String = password, + certificatesDirectoryName: String = DEFAULT_CERTIFICATES_DIRECTORY_NAME, certificateStoreFileName: String = DEFAULT_STORE_FILE_NAME): FileBasedCertificateStoreSupplier { - return FileBasedCertificateStoreSupplier(baseDirectory / certificatesDirectoryName / certificateStoreFileName, password) + return FileBasedCertificateStoreSupplier(baseDirectory / certificatesDirectoryName / certificateStoreFileName, password, keyPassword) } } } @@ -82,18 +89,21 @@ class CertificateStoreStubs { companion object { const val DEFAULT_STORE_FILE_NAME = "truststore.jks" - const val DEFAULT_STORE_PASSWORD = "trustpass" + const val DEFAULT_STORE_PASSWORD = DEV_CA_TRUST_STORE_PASS + const val DEFAULT_KEY_PASSWORD = DEV_CA_TRUST_STORE_PRIVATE_KEY_PASS @JvmStatic - fun withCertificatesDirectory(certificatesDirectory: Path, password: String = DEFAULT_STORE_PASSWORD, certificateStoreFileName: String = DEFAULT_STORE_FILE_NAME): FileBasedCertificateStoreSupplier { + fun withCertificatesDirectory(certificatesDirectory: Path, password: String = DEFAULT_STORE_PASSWORD, + keyPassword: String = DEFAULT_KEY_PASSWORD, certificateStoreFileName: String = DEFAULT_STORE_FILE_NAME): FileBasedCertificateStoreSupplier { - return FileBasedCertificateStoreSupplier(certificatesDirectory / certificateStoreFileName, password) + return FileBasedCertificateStoreSupplier(certificatesDirectory / certificateStoreFileName, password, keyPassword) } @JvmStatic - fun withBaseDirectory(baseDirectory: Path, password: String = DEFAULT_STORE_PASSWORD, certificatesDirectoryName: String = DEFAULT_CERTIFICATES_DIRECTORY_NAME, certificateStoreFileName: String = DEFAULT_STORE_FILE_NAME): FileBasedCertificateStoreSupplier { + fun withBaseDirectory(baseDirectory: Path, password: String = DEFAULT_STORE_PASSWORD, keyPassword: String = DEFAULT_KEY_PASSWORD, + certificatesDirectoryName: String = DEFAULT_CERTIFICATES_DIRECTORY_NAME, certificateStoreFileName: String = DEFAULT_STORE_FILE_NAME): FileBasedCertificateStoreSupplier { - return FileBasedCertificateStoreSupplier(baseDirectory / certificatesDirectoryName / certificateStoreFileName, password) + return FileBasedCertificateStoreSupplier(baseDirectory / certificatesDirectoryName / certificateStoreFileName, password, keyPassword) } } }