mirror of
https://github.com/corda/corda.git
synced 2025-03-15 08:41:04 +00:00
Merge pull request #1495 from corda/vkolomeyko/os-ent-merge
OS->Ent merge
This commit is contained in:
commit
51e0822d59
@ -130,7 +130,7 @@ class BridgeSmokeTest {
|
||||
setPrivateKey(
|
||||
X509Utilities.CORDA_CLIENT_TLS,
|
||||
tlsKeyPair.private,
|
||||
listOf(tlsCert, nodeCaCert, intermediateCa.certificate, rootCert))
|
||||
listOf(tlsCert, nodeCaCert, intermediateCa.certificate, rootCert), sslKeyStore.entryPassword)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -62,10 +62,10 @@ class AMQPListenerTest {
|
||||
val trustStoreBytes = bridgeConfig.p2pSslOptions.trustStore.path.readAll()
|
||||
// start listening
|
||||
amqpListenerService.provisionKeysAndActivate(keyStoreBytes,
|
||||
bridgeConfig.p2pSslOptions.keyStore.password.toCharArray(),
|
||||
bridgeConfig.p2pSslOptions.keyStore.password.toCharArray(),
|
||||
bridgeConfig.p2pSslOptions.keyStore.storePassword.toCharArray(),
|
||||
bridgeConfig.p2pSslOptions.keyStore.entryPassword.toCharArray(),
|
||||
trustStoreBytes,
|
||||
bridgeConfig.p2pSslOptions.trustStore.password.toCharArray())
|
||||
bridgeConfig.p2pSslOptions.trustStore.storePassword.toCharArray())
|
||||
// Fire lots of activity to prove we are good
|
||||
assertEquals(TestAuditService.AuditEvent.STATUS_CHANGE, auditFollower.next())
|
||||
assertEquals(true, amqpListenerService.active)
|
||||
@ -137,21 +137,21 @@ class AMQPListenerTest {
|
||||
val trustStoreBytes = bridgeConfig.p2pSslOptions.trustStore.path.readAll()
|
||||
// start listening
|
||||
amqpListenerService.provisionKeysAndActivate(keyStoreBytes,
|
||||
bridgeConfig.p2pSslOptions.keyStore.password.toCharArray(),
|
||||
bridgeConfig.p2pSslOptions.keyStore.password.toCharArray(),
|
||||
bridgeConfig.p2pSslOptions.keyStore.storePassword.toCharArray(),
|
||||
bridgeConfig.p2pSslOptions.keyStore.entryPassword.toCharArray(),
|
||||
trustStoreBytes,
|
||||
bridgeConfig.p2pSslOptions.trustStore.password.toCharArray())
|
||||
bridgeConfig.p2pSslOptions.trustStore.storePassword.toCharArray())
|
||||
val connectionFollower = amqpListenerService.onConnection.toBlocking().iterator
|
||||
val auditFollower = auditService.onAuditEvent.toBlocking().iterator
|
||||
val clientKeys = Crypto.generateKeyPair(ECDSA_SECP256R1_SHA256)
|
||||
val clientCert = X509Utilities.createSelfSignedCACertificate(ALICE_NAME.x500Principal, clientKeys)
|
||||
val clientKeyStoreRaw = X509KeyStore("password")
|
||||
clientKeyStoreRaw.setPrivateKey("TLS_CERT", clientKeys.private, listOf(clientCert))
|
||||
val clientKeyStore = CertificateStore.of(clientKeyStoreRaw, "password")
|
||||
clientKeyStoreRaw.setPrivateKey("TLS_CERT", clientKeys.private, listOf(clientCert), "password")
|
||||
val clientKeyStore = CertificateStore.of(clientKeyStoreRaw, "password", "password")
|
||||
|
||||
val clientTrustStoreRaw = X509KeyStore("password")
|
||||
clientTrustStoreRaw.setCertificate("TLS_ROOT", clientCert)
|
||||
val clientTrustStore = CertificateStore.of(clientTrustStoreRaw, "password")
|
||||
val clientTrustStore = CertificateStore.of(clientTrustStoreRaw, "password", "password")
|
||||
val amqpConfig = object : AMQPConfiguration {
|
||||
override val keyStore = clientKeyStore
|
||||
override val trustStore = clientTrustStore
|
||||
|
@ -22,8 +22,8 @@ data class BridgeSSLConfigurationImpl(private val sslKeystore: Path,
|
||||
private val crlCheckSoftFail: Boolean,
|
||||
override val useOpenSsl: Boolean = false) : BridgeSSLConfiguration {
|
||||
|
||||
override val keyStore = FileBasedCertificateStoreSupplier(sslKeystore, keyStorePassword)
|
||||
override val trustStore = FileBasedCertificateStoreSupplier(trustStoreFile, trustStorePassword)
|
||||
override val keyStore = FileBasedCertificateStoreSupplier(sslKeystore, keyStorePassword, keyStorePassword)
|
||||
override val trustStore = FileBasedCertificateStoreSupplier(trustStoreFile, trustStorePassword, trustStorePassword)
|
||||
}
|
||||
|
||||
data class BridgeOutboundConfigurationImpl(override val artemisBrokerAddress: NetworkHostAndPort,
|
||||
@ -81,9 +81,9 @@ data class FirewallConfigurationImpl(
|
||||
}
|
||||
|
||||
private val p2pKeystorePath = sslKeystore
|
||||
private val p2pKeyStore = FileBasedCertificateStoreSupplier(p2pKeystorePath, keyStorePassword)
|
||||
private val p2pKeyStore = FileBasedCertificateStoreSupplier(p2pKeystorePath, keyStorePassword, keyStorePassword)
|
||||
private val p2pTrustStoreFilePath = trustStoreFile
|
||||
private val p2pTrustStore = FileBasedCertificateStoreSupplier(p2pTrustStoreFilePath, trustStorePassword)
|
||||
private val p2pTrustStore = FileBasedCertificateStoreSupplier(p2pTrustStoreFilePath, trustStorePassword, trustStorePassword)
|
||||
override val p2pSslOptions: MutualSslConfiguration = SslConfiguration.mutual(p2pKeyStore, p2pTrustStore)
|
||||
}
|
||||
|
||||
|
@ -48,8 +48,8 @@ class BridgeAMQPListenerServiceImpl(val conf: FirewallConfiguration,
|
||||
require(active) { "AuditService must be active" }
|
||||
require(keyStorePassword !== keyStorePrivateKeyPassword) { "keyStorePassword and keyStorePrivateKeyPassword must reference distinct arrays!" }
|
||||
|
||||
val keyStore = CertificateStore.of(loadKeyStore(keyStoreBytes, keyStorePassword), java.lang.String.valueOf(keyStorePrivateKeyPassword)).also { wipeKeys(keyStoreBytes, keyStorePassword) }
|
||||
val trustStore = CertificateStore.of(loadKeyStore(trustStoreBytes, trustStorePassword), java.lang.String.valueOf(trustStorePassword)).also { wipeKeys(trustStoreBytes, trustStorePassword) }
|
||||
val keyStore = CertificateStore.of(loadKeyStore(keyStoreBytes, keyStorePassword), java.lang.String.valueOf(keyStorePrivateKeyPassword), java.lang.String.valueOf(keyStorePrivateKeyPassword)).also { wipeKeys(keyStoreBytes, keyStorePassword) }
|
||||
val trustStore = CertificateStore.of(loadKeyStore(trustStoreBytes, trustStorePassword), java.lang.String.valueOf(trustStorePassword), java.lang.String.valueOf(trustStorePassword)).also { wipeKeys(trustStoreBytes, trustStorePassword) }
|
||||
val bindAddress = conf.inboundConfig!!.listeningAddress
|
||||
val amqpConfiguration = object : AMQPConfiguration {
|
||||
override val keyStore = keyStore
|
||||
|
@ -35,10 +35,10 @@ class InProcessBridgeReceiverService(val conf: FirewallConfiguration,
|
||||
val keyStoreBytes = sslConfiguration.keyStore.path.readAll()
|
||||
val trustStoreBytes = sslConfiguration.trustStore.path.readAll()
|
||||
amqpListenerService.provisionKeysAndActivate(keyStoreBytes,
|
||||
sslConfiguration.keyStore.password.toCharArray(),
|
||||
sslConfiguration.keyStore.password.toCharArray(),
|
||||
sslConfiguration.keyStore.storePassword.toCharArray(),
|
||||
sslConfiguration.keyStore.entryPassword.toCharArray(),
|
||||
trustStoreBytes,
|
||||
sslConfiguration.trustStore.password.toCharArray())
|
||||
sslConfiguration.trustStore.storePassword.toCharArray())
|
||||
} else {
|
||||
if (amqpListenerService.running) {
|
||||
amqpListenerService.wipeKeysAndDeactivate()
|
||||
|
@ -118,7 +118,7 @@ class TunnelingBridgeReceiverService(val conf: FirewallConfiguration,
|
||||
freshKeyStorePassword,
|
||||
freshKeyStoreKeyPassword,
|
||||
trustStoreBytes,
|
||||
floatListenerSSLConfiguration.trustStore.password.toCharArray())
|
||||
floatListenerSSLConfiguration.trustStore.storePassword.toCharArray())
|
||||
val amqpActivateMessage = amqpControlClient!!.createMessage(activateMessage.serialize(context = SerializationDefaults.P2P_CONTEXT).bytes,
|
||||
FLOAT_CONTROL_TOPIC,
|
||||
expectedCertificateSubject.toString(),
|
||||
@ -141,7 +141,7 @@ class TunnelingBridgeReceiverService(val conf: FirewallConfiguration,
|
||||
// Recode KeyStore to use a fresh random password for entries and overall
|
||||
private fun recodeKeyStore(sslConfiguration: MutualSslConfiguration): Triple<CharArray, CharArray, ByteArray> {
|
||||
val keyStoreOriginal = sslConfiguration.keyStore.get().value.internal
|
||||
val originalKeyStorePassword = sslConfiguration.keyStore.password.toCharArray()
|
||||
val originalKeyStorePassword = sslConfiguration.keyStore.storePassword.toCharArray()
|
||||
val freshKeyStorePassword = CharArray(20) { secureRandom.nextInt(0xD800).toChar() } // Stick to single character Unicode range
|
||||
val freshPrivateKeyPassword = CharArray(20) { secureRandom.nextInt(0xD800).toChar() } // Stick to single character Unicode range
|
||||
for (alias in keyStoreOriginal.aliases()) {
|
||||
|
@ -76,7 +76,8 @@ fun MutualSslConfiguration.createBridgeKeyStores(legalName: CordaX500Name,
|
||||
setPrivateKey(
|
||||
X509Utilities.CORDA_CLIENT_TLS,
|
||||
tlsKeyPair.private,
|
||||
listOf(tlsCert, nodeCaCert, intermediateCa.certificate, rootCert))
|
||||
listOf(tlsCert, nodeCaCert, intermediateCa.certificate, rootCert),
|
||||
sslKeyStore.entryPassword)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -73,13 +73,13 @@ class ConfigTest {
|
||||
val config = createAndLoadConfigFromResource(tempFolder.root.toPath(), configResource)
|
||||
assertEquals(Paths.get("outboundcerts/outboundkeys.jks"), config.outboundConfig!!.customSSLConfiguration!!.keyStore.path)
|
||||
assertEquals(Paths.get("outboundcerts/outboundtrust.jks"), config.outboundConfig!!.customSSLConfiguration!!.trustStore.path)
|
||||
assertEquals("outboundkeypassword", config.outboundConfig!!.customSSLConfiguration!!.keyStore.password)
|
||||
assertEquals("outboundtrustpassword", config.outboundConfig!!.customSSLConfiguration!!.trustStore.password)
|
||||
assertEquals("outboundkeypassword", config.outboundConfig!!.customSSLConfiguration!!.keyStore.storePassword)
|
||||
assertEquals("outboundtrustpassword", config.outboundConfig!!.customSSLConfiguration!!.trustStore.storePassword)
|
||||
assertNull(config.inboundConfig)
|
||||
assertEquals(Paths.get("tunnelcerts/tunnelkeys.jks"), config.bridgeInnerConfig!!.customSSLConfiguration!!.keyStore.path)
|
||||
assertEquals(Paths.get("tunnelcerts/tunneltrust.jks"), config.bridgeInnerConfig!!.customSSLConfiguration!!.trustStore.path)
|
||||
assertEquals("tunnelkeypassword", config.bridgeInnerConfig!!.customSSLConfiguration!!.keyStore.password)
|
||||
assertEquals("tunneltrustpassword", config.bridgeInnerConfig!!.customSSLConfiguration!!.trustStore.password)
|
||||
assertEquals("tunnelkeypassword", config.bridgeInnerConfig!!.customSSLConfiguration!!.keyStore.storePassword)
|
||||
assertEquals("tunneltrustpassword", config.bridgeInnerConfig!!.customSSLConfiguration!!.trustStore.storePassword)
|
||||
assertNull(config.floatOuterConfig)
|
||||
}
|
||||
|
||||
@ -89,13 +89,13 @@ class ConfigTest {
|
||||
val config = createAndLoadConfigFromResource(tempFolder.root.toPath(), configResource)
|
||||
assertEquals(Paths.get("inboundcerts/inboundkeys.jks"), config.inboundConfig!!.customSSLConfiguration!!.keyStore.path)
|
||||
assertEquals(Paths.get("inboundcerts/inboundtrust.jks"), config.inboundConfig!!.customSSLConfiguration!!.trustStore.path)
|
||||
assertEquals("inboundkeypassword", config.inboundConfig!!.customSSLConfiguration!!.keyStore.password)
|
||||
assertEquals("inboundtrustpassword", config.inboundConfig!!.customSSLConfiguration!!.trustStore.password)
|
||||
assertEquals("inboundkeypassword", config.inboundConfig!!.customSSLConfiguration!!.keyStore.storePassword)
|
||||
assertEquals("inboundtrustpassword", config.inboundConfig!!.customSSLConfiguration!!.trustStore.storePassword)
|
||||
assertNull(config.outboundConfig)
|
||||
assertEquals(Paths.get("tunnelcerts/tunnelkeys.jks"), config.floatOuterConfig!!.customSSLConfiguration!!.keyStore.path)
|
||||
assertEquals(Paths.get("tunnelcerts/tunneltrust.jks"), config.floatOuterConfig!!.customSSLConfiguration!!.trustStore.path)
|
||||
assertEquals("tunnelkeypassword", config.floatOuterConfig!!.customSSLConfiguration!!.keyStore.password)
|
||||
assertEquals("tunneltrustpassword", config.floatOuterConfig!!.customSSLConfiguration!!.trustStore.password)
|
||||
assertEquals("tunnelkeypassword", config.floatOuterConfig!!.customSSLConfiguration!!.keyStore.storePassword)
|
||||
assertEquals("tunneltrustpassword", config.floatOuterConfig!!.customSSLConfiguration!!.trustStore.storePassword)
|
||||
assertNull(config.bridgeInnerConfig)
|
||||
}
|
||||
|
||||
|
@ -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<X509KeyStore, X509KeyStore> {
|
||||
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")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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()
|
||||
}
|
||||
|
||||
|
BIN
lib/quasar.jar
BIN
lib/quasar.jar
Binary file not shown.
@ -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*/)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -14,17 +14,18 @@ interface CertificateStore : Iterable<Pair<String, X509Certificate>> {
|
||||
|
||||
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())
|
||||
|
||||
@ -80,4 +81,4 @@ interface CertificateStore : Iterable<Pair<String, X509Certificate>> {
|
||||
}
|
||||
}
|
||||
|
||||
private class DelegatingCertificateStore(override val value: X509KeyStore, override val password: String) : CertificateStore
|
||||
private class DelegatingCertificateStore(override val value: X509KeyStore, override val password: String, override val entryPassword: String) : CertificateStore
|
@ -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)
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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<X509Certificate>, keyPassword: String = storePassword) {
|
||||
fun setPrivateKey(alias: String, key: PrivateKey, certificates: List<X509Certificate>, keyPassword: String) {
|
||||
internal.setKeyEntry(alias, key, keyPassword.toCharArray(), certificates.toTypedArray())
|
||||
}
|
||||
|
||||
|
@ -238,7 +238,9 @@ internal fun splitKeystore(config: AMQPConfiguration): Map<String, CertHoldingKe
|
||||
}.toMap()
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
|
@ -247,8 +247,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)
|
||||
@ -256,7 +257,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)
|
||||
|
@ -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()
|
||||
|
@ -36,7 +36,7 @@ class NodeKeystoreCheckTest : IntegrationTest() {
|
||||
}
|
||||
|
||||
@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"
|
||||
@ -60,9 +60,9 @@ class NodeKeystoreCheckTest : IntegrationTest() {
|
||||
// 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 {
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -892,7 +892,7 @@ abstract class AbstractNode<S>(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"
|
||||
|
@ -101,9 +101,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"
|
||||
@ -112,7 +112,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))
|
||||
}
|
||||
|
@ -316,12 +316,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, useOpenSsl)
|
||||
|
||||
override val rpcOptions: NodeRpcOptions
|
||||
|
@ -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<X509Certificate>, 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) {
|
||||
|
@ -887,10 +887,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
|
||||
}
|
||||
|
@ -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<String, UnsafeCertificate>
|
||||
|
||||
data class UnsafeKeyStore(private val delegate: KeyStore, val password: String) : Iterable<KeyStoreEntry> {
|
||||
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<Pair<String, UnsafeCertificate>> = 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)
|
||||
}
|
@ -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, useOpenSsl: Boolean = false): 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, useOpenSsl)
|
||||
}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user