Clean up of network-management to make more use of the existing X509 utilities (#419)

This commit is contained in:
Shams Asari 2018-01-29 12:49:58 +00:00 committed by GitHub
parent 3d32760dcc
commit 2432b1380e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 126 additions and 164 deletions

2
.idea/compiler.xml generated
View File

@ -17,6 +17,8 @@
<module name="business-network-demo_integrationTest" target="1.8" /> <module name="business-network-demo_integrationTest" target="1.8" />
<module name="business-network-demo_main" target="1.8" /> <module name="business-network-demo_main" target="1.8" />
<module name="business-network-demo_test" target="1.8" /> <module name="business-network-demo_test" target="1.8" />
<module name="capsule-hsm-cert-generator_main" target="1.8" />
<module name="capsule-hsm-cert-generator_test" target="1.8" />
<module name="capsule-hsm_main" target="1.8" /> <module name="capsule-hsm_main" target="1.8" />
<module name="capsule-hsm_test" target="1.8" /> <module name="capsule-hsm_test" target="1.8" />
<module name="client_main" target="1.8" /> <module name="client_main" target="1.8" />

View File

@ -6,7 +6,7 @@ import com.r3.corda.networkmanage.hsm.authentication.createProvider
import com.r3.corda.networkmanage.hsm.generator.run import com.r3.corda.networkmanage.hsm.generator.run
import com.r3.corda.networkmanage.hsm.persistence.ApprovedCertificateRequestData import com.r3.corda.networkmanage.hsm.persistence.ApprovedCertificateRequestData
import com.r3.corda.networkmanage.hsm.signer.HsmCsrSigner import com.r3.corda.networkmanage.hsm.signer.HsmCsrSigner
import com.r3.corda.networkmanage.hsm.signer.HsmNetworkMapSigner import com.r3.corda.networkmanage.hsm.signer.HsmSigner
import net.corda.core.crypto.Crypto.generateKeyPair import net.corda.core.crypto.Crypto.generateKeyPair
import net.corda.core.crypto.secureRandomBytes import net.corda.core.crypto.secureRandomBytes
import net.corda.core.identity.CordaX500Name.Companion.parse import net.corda.core.identity.CordaX500Name.Companion.parse
@ -48,7 +48,7 @@ class HsmSigningServiceTest : HsmCertificateTest() {
val userInput = givenHsmUserAuthenticationInput() val userInput = givenHsmUserAuthenticationInput()
// given HSM network map signer // given HSM network map signer
val signer = HsmNetworkMapSigner(Authenticator( val signer = HsmSigner(Authenticator(
provider = hsmSigningServiceConfig.createProvider(hsmSigningServiceConfig.networkMapKeyGroup), provider = hsmSigningServiceConfig.createProvider(hsmSigningServiceConfig.networkMapKeyGroup),
inputReader = userInput)) inputReader = userInput))

View File

@ -2,7 +2,6 @@ package com.r3.corda.networkmanage.hsm
import com.nhaarman.mockito_kotlin.* import com.nhaarman.mockito_kotlin.*
import com.r3.corda.networkmanage.common.persistence.configureDatabase import com.r3.corda.networkmanage.common.persistence.configureDatabase
import com.r3.corda.networkmanage.common.utils.buildCertPath
import com.r3.corda.networkmanage.doorman.DoormanConfig import com.r3.corda.networkmanage.doorman.DoormanConfig
import com.r3.corda.networkmanage.doorman.NetworkManagementServer import com.r3.corda.networkmanage.doorman.NetworkManagementServer
import com.r3.corda.networkmanage.hsm.persistence.ApprovedCertificateRequestData import com.r3.corda.networkmanage.hsm.persistence.ApprovedCertificateRequestData
@ -19,7 +18,9 @@ import net.corda.node.services.config.NodeConfiguration
import net.corda.node.utilities.registration.HTTPNetworkRegistrationService import net.corda.node.utilities.registration.HTTPNetworkRegistrationService
import net.corda.node.utilities.registration.NetworkRegistrationHelper import net.corda.node.utilities.registration.NetworkRegistrationHelper
import net.corda.nodeapi.internal.createDevNodeCa import net.corda.nodeapi.internal.createDevNodeCa
import net.corda.nodeapi.internal.crypto.* import net.corda.nodeapi.internal.crypto.CertificateAndKeyPair
import net.corda.nodeapi.internal.crypto.X509KeyStore
import net.corda.nodeapi.internal.crypto.X509Utilities
import net.corda.nodeapi.internal.persistence.DatabaseConfig import net.corda.nodeapi.internal.persistence.DatabaseConfig
import net.corda.testing.core.ALICE_NAME import net.corda.testing.core.ALICE_NAME
import net.corda.testing.core.SerializationEnvironmentRule import net.corda.testing.core.SerializationEnvironmentRule
@ -76,7 +77,7 @@ class SigningServiceIntegrationTest {
for (approvedRequest in approvedRequests) { for (approvedRequest in approvedRequests) {
JcaPKCS10CertificationRequest(approvedRequest.request).run { JcaPKCS10CertificationRequest(approvedRequest.request).run {
val nodeCa = createDevNodeCa(intermediateCa, CordaX500Name.parse(subject.toString())) val nodeCa = createDevNodeCa(intermediateCa, CordaX500Name.parse(subject.toString()))
approvedRequest.certPath = buildCertPath(nodeCa.certificate, intermediateCa.certificate, rootCaCert) approvedRequest.certPath = X509Utilities.buildCertPath(nodeCa.certificate, intermediateCa.certificate, rootCaCert)
} }
} }
storage.store(approvedRequests, listOf("TEST")) storage.store(approvedRequests, listOf("TEST"))

View File

@ -4,11 +4,11 @@ import com.r3.corda.networkmanage.common.persistence.CertificateData
import com.r3.corda.networkmanage.common.persistence.CertificateSigningRequest import com.r3.corda.networkmanage.common.persistence.CertificateSigningRequest
import com.r3.corda.networkmanage.common.persistence.CertificateStatus import com.r3.corda.networkmanage.common.persistence.CertificateStatus
import com.r3.corda.networkmanage.common.persistence.RequestStatus import com.r3.corda.networkmanage.common.persistence.RequestStatus
import com.r3.corda.networkmanage.common.utils.buildCertPath
import net.corda.core.crypto.SecureHash import net.corda.core.crypto.SecureHash
import org.bouncycastle.pkcs.PKCS10CertificationRequest import org.bouncycastle.pkcs.PKCS10CertificationRequest
import org.hibernate.envers.Audited import org.hibernate.envers.Audited
import java.security.cert.CertPath import java.security.cert.CertPath
import java.security.cert.CertificateFactory
import java.time.Instant import java.time.Instant
import javax.persistence.* import javax.persistence.*
@ -114,5 +114,5 @@ class CertificateDataEntity(
) )
} }
private fun toCertificatePath(): CertPath = CertificateFactory.getInstance("X.509").generateCertPath(certificatePathBytes.inputStream()) private fun toCertificatePath(): CertPath = buildCertPath(certificatePathBytes)
} }

View File

@ -8,6 +8,7 @@ import joptsimple.OptionParser
import net.corda.core.crypto.sha256 import net.corda.core.crypto.sha256
import net.corda.core.internal.SignedDataWithCert import net.corda.core.internal.SignedDataWithCert
import net.corda.nodeapi.internal.crypto.X509CertificateFactory import net.corda.nodeapi.internal.crypto.X509CertificateFactory
import net.corda.nodeapi.internal.crypto.X509KeyStore
import net.corda.nodeapi.internal.network.NetworkMap import net.corda.nodeapi.internal.network.NetworkMap
import net.corda.nodeapi.internal.network.NetworkParameters import net.corda.nodeapi.internal.network.NetworkParameters
import java.security.KeyPair import java.security.KeyPair
@ -50,10 +51,12 @@ fun Array<out String>.toConfigWithOptions(registerOptions: OptionParser.() -> Un
class ShowHelpException(val parser: OptionParser, val errorMessage: String? = null) : Exception() class ShowHelpException(val parser: OptionParser, val errorMessage: String? = null) : Exception()
fun buildCertPath(vararg certificates: X509Certificate): CertPath = X509CertificateFactory().generateCertPath(certificates.asList())
fun buildCertPath(certPathBytes: ByteArray): CertPath = X509CertificateFactory().delegate.generateCertPath(certPathBytes.inputStream()) fun buildCertPath(certPathBytes: ByteArray): CertPath = X509CertificateFactory().delegate.generateCertPath(certPathBytes.inputStream())
fun X509KeyStore.getCertPathAndKey(alias: String, privateKeyPassword: String): CertPathAndKey {
return CertPathAndKey(getCertificateChain(alias), getPrivateKey(alias, privateKeyPassword))
}
private fun String.toCamelcase(): String { private fun String.toCamelcase(): String {
return if (contains('_') || contains('-')) { return if (contains('_') || contains('-')) {
CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, this.replace("-", "_")) CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, this.replace("-", "_"))

View File

@ -94,6 +94,7 @@ fun parseParameters(vararg args: String): NetworkManagementServerParameters {
val configFile = if (argConfig.hasPath("configFile")) { val configFile = if (argConfig.hasPath("configFile")) {
Paths.get(argConfig.getString("configFile")) Paths.get(argConfig.getString("configFile"))
} else { } else {
// TODO Remove this default
Paths.get(".") / "network-management.conf" Paths.get(".") / "network-management.conf"
} }
require(configFile.isRegularFile()) { "Config file $configFile does not exist" } require(configFile.isRegularFile()) { "Config file $configFile does not exist" }

View File

@ -6,20 +6,18 @@ import com.r3.corda.networkmanage.common.persistence.configureDatabase
import com.r3.corda.networkmanage.common.utils.CORDA_NETWORK_MAP import com.r3.corda.networkmanage.common.utils.CORDA_NETWORK_MAP
import com.r3.corda.networkmanage.common.utils.CertPathAndKey import com.r3.corda.networkmanage.common.utils.CertPathAndKey
import com.r3.corda.networkmanage.common.utils.ShowHelpException import com.r3.corda.networkmanage.common.utils.ShowHelpException
import com.r3.corda.networkmanage.common.utils.getCertPathAndKey
import com.r3.corda.networkmanage.doorman.signer.LocalSigner import com.r3.corda.networkmanage.doorman.signer.LocalSigner
import com.r3.corda.networkmanage.hsm.configuration.Parameters.Companion.DEFAULT_CSR_CERTIFICATE_NAME import com.r3.corda.networkmanage.hsm.configuration.Parameters.Companion.DEFAULT_CSR_CERTIFICATE_NAME
import net.corda.core.serialization.internal.SerializationEnvironmentImpl import net.corda.core.serialization.internal.SerializationEnvironmentImpl
import net.corda.core.serialization.internal.nodeSerializationEnv import net.corda.core.serialization.internal.nodeSerializationEnv
import net.corda.core.utilities.NetworkHostAndPort import net.corda.core.utilities.NetworkHostAndPort
import net.corda.nodeapi.internal.crypto.getCertificateAndKeyPair import net.corda.nodeapi.internal.crypto.X509KeyStore
import net.corda.nodeapi.internal.crypto.getSupportedKey
import net.corda.nodeapi.internal.crypto.loadOrCreateKeyStore
import net.corda.nodeapi.internal.network.NetworkParameters import net.corda.nodeapi.internal.network.NetworkParameters
import net.corda.nodeapi.internal.serialization.AMQP_P2P_CONTEXT import net.corda.nodeapi.internal.serialization.AMQP_P2P_CONTEXT
import net.corda.nodeapi.internal.serialization.SerializationFactoryImpl import net.corda.nodeapi.internal.serialization.SerializationFactoryImpl
import net.corda.nodeapi.internal.serialization.amqp.AMQPClientSerializationScheme import net.corda.nodeapi.internal.serialization.amqp.AMQPClientSerializationScheme
import org.bouncycastle.pkcs.PKCS10CertificationRequest import org.bouncycastle.pkcs.PKCS10CertificationRequest
import java.security.cert.X509Certificate
import java.time.Instant import java.time.Instant
import kotlin.concurrent.thread import kotlin.concurrent.thread
@ -33,17 +31,9 @@ private fun processKeyStore(parameters: NetworkManagementServerParameters): Pair
// Get password from console if not in config. // Get password from console if not in config.
val keyStorePassword = parameters.keystorePassword ?: readPassword("Key store password: ") val keyStorePassword = parameters.keystorePassword ?: readPassword("Key store password: ")
val privateKeyPassword = parameters.caPrivateKeyPassword ?: readPassword("Private key password: ") val privateKeyPassword = parameters.caPrivateKeyPassword ?: readPassword("Private key password: ")
val keyStore = loadOrCreateKeyStore(parameters.keystorePath, keyStorePassword) val keyStore = X509KeyStore.fromFile(parameters.keystorePath, keyStorePassword)
val csrCertPathAndKey = keyStore.getCertPathAndKey(DEFAULT_CSR_CERTIFICATE_NAME, privateKeyPassword)
val csrCertPathAndKey = keyStore.run {
CertPathAndKey(
keyStore.getCertificateChain(DEFAULT_CSR_CERTIFICATE_NAME).map { it as X509Certificate },
keyStore.getSupportedKey(DEFAULT_CSR_CERTIFICATE_NAME, privateKeyPassword)
)
}
val networkMapSigner = LocalSigner(keyStore.getCertificateAndKeyPair(CORDA_NETWORK_MAP, privateKeyPassword)) val networkMapSigner = LocalSigner(keyStore.getCertificateAndKeyPair(CORDA_NETWORK_MAP, privateKeyPassword))
return Pair(csrCertPathAndKey, networkMapSigner) return Pair(csrCertPathAndKey, networkMapSigner)
} }

View File

@ -11,8 +11,8 @@ import java.nio.file.Path
import javax.security.auth.x500.X500Principal import javax.security.auth.x500.X500Principal
import kotlin.system.exitProcess import kotlin.system.exitProcess
private val cordaX500Name = "OU=Corda,O=R3 Ltd,L=London,C=GB" // TODO The cert subjects need to be configurable
private const val CORDA_X500_BASE = "O=R3 HoldCo LLC,OU=Corda,L=New York,C=US"
const val NETWORK_ROOT_TRUSTSTORE_FILENAME = "network-root-truststore.jks" const val NETWORK_ROOT_TRUSTSTORE_FILENAME = "network-root-truststore.jks"
/** Read password from console, do a readLine instead if console is null (e.g. when debugging in IDE). */ /** Read password from console, do a readLine instead if console is null (e.g. when debugging in IDE). */
@ -32,10 +32,10 @@ fun generateRootKeyPair(rootStoreFile: Path, rootKeystorePass: String?, rootPriv
val rootKeystorePassword = rootKeystorePass ?: readPassword("Root Keystore Password: ") val rootKeystorePassword = rootKeystorePass ?: readPassword("Root Keystore Password: ")
// Ensure folder exists. // Ensure folder exists.
rootStoreFile.parent.createDirectories() rootStoreFile.parent.createDirectories()
val rootStore = loadOrCreateKeyStore(rootStoreFile, rootKeystorePassword) val rootStore = X509KeyStore.fromFile(rootStoreFile, rootKeystorePassword, createNew = true)
val rootPrivateKeyPassword = rootPrivateKeyPass ?: readPassword("Root Private Key Password: ") val rootPrivateKeyPassword = rootPrivateKeyPass ?: readPassword("Root Private Key Password: ")
if (rootStore.containsAlias(X509Utilities.CORDA_ROOT_CA)) { if (X509Utilities.CORDA_ROOT_CA in rootStore) {
println("${X509Utilities.CORDA_ROOT_CA} already exists in keystore, process will now terminate.") println("${X509Utilities.CORDA_ROOT_CA} already exists in keystore, process will now terminate.")
println(rootStore.getCertificate(X509Utilities.CORDA_ROOT_CA)) println(rootStore.getCertificate(X509Utilities.CORDA_ROOT_CA))
exitProcess(1) exitProcess(1)
@ -43,22 +43,24 @@ fun generateRootKeyPair(rootStoreFile: Path, rootKeystorePass: String?, rootPriv
val selfSignKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME) val selfSignKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
// TODO Make the cert subject configurable // TODO Make the cert subject configurable
val selfSignCert = X509Utilities.createSelfSignedCACertificate( val rootCert = X509Utilities.createSelfSignedCACertificate(
X500Principal("CN=Corda Root CA,$cordaX500Name"), X500Principal("CN=Corda Root CA,$CORDA_X500_BASE"),
selfSignKey) selfSignKey)
rootStore.addOrReplaceKey(X509Utilities.CORDA_ROOT_CA, selfSignKey.private, rootPrivateKeyPassword.toCharArray(), arrayOf(selfSignCert)) rootStore.update {
rootStore.save(rootStoreFile, rootKeystorePassword) setPrivateKey(X509Utilities.CORDA_ROOT_CA, selfSignKey.private, listOf(rootCert), rootPrivateKeyPassword)
}
val trustStorePath = (rootStoreFile.parent / "distribute-nodes").createDirectories() / NETWORK_ROOT_TRUSTSTORE_FILENAME val trustStorePath = (rootStoreFile.parent / "distribute-nodes").createDirectories() / NETWORK_ROOT_TRUSTSTORE_FILENAME
val networkRootTrustPassword = networkRootTrustPass ?: readPassword("Network Root Trust Store Password: ") val networkRootTrustPassword = networkRootTrustPass ?: readPassword("Network Root Trust Store Password: ")
val networkRootTrustStore = loadOrCreateKeyStore(trustStorePath, networkRootTrustPassword)
networkRootTrustStore.addOrReplaceCertificate(X509Utilities.CORDA_ROOT_CA, selfSignCert)
networkRootTrustStore.save(trustStorePath, networkRootTrustPassword)
println("Trust store for distribution to nodes created in $networkRootTrustStore")
X509KeyStore.fromFile(trustStorePath, networkRootTrustPassword, createNew = true).update {
setCertificate(X509Utilities.CORDA_ROOT_CA, rootCert)
}
println("Trust store for distribution to nodes created in $trustStorePath")
println("Root CA keypair and certificate stored in ${rootStoreFile.toAbsolutePath()}.") println("Root CA keypair and certificate stored in ${rootStoreFile.toAbsolutePath()}.")
println(selfSignCert) println(rootCert)
} }
fun generateSigningKeyPairs(keystoreFile: Path, rootStoreFile: Path, rootKeystorePass: String?, rootPrivateKeyPass: String?, keystorePass: String?, caPrivateKeyPass: String?) { fun generateSigningKeyPairs(keystoreFile: Path, rootStoreFile: Path, rootKeystorePass: String?, rootPrivateKeyPass: String?, keystorePass: String?, caPrivateKeyPass: String?) {
@ -66,7 +68,7 @@ fun generateSigningKeyPairs(keystoreFile: Path, rootStoreFile: Path, rootKeystor
// Get password from console if not in config. // Get password from console if not in config.
val rootKeystorePassword = rootKeystorePass ?: readPassword("Root key store password: ") val rootKeystorePassword = rootKeystorePass ?: readPassword("Root key store password: ")
val rootPrivateKeyPassword = rootPrivateKeyPass ?: readPassword("Root private key password: ") val rootPrivateKeyPassword = rootPrivateKeyPass ?: readPassword("Root private key password: ")
val rootKeyStore = loadKeyStore(rootStoreFile, rootKeystorePassword) val rootKeyStore = X509KeyStore.fromFile(rootStoreFile, rootKeystorePassword)
val rootKeyPairAndCert = rootKeyStore.getCertificateAndKeyPair(X509Utilities.CORDA_ROOT_CA, rootPrivateKeyPassword) val rootKeyPairAndCert = rootKeyStore.getCertificateAndKeyPair(X509Utilities.CORDA_ROOT_CA, rootPrivateKeyPassword)
@ -74,10 +76,10 @@ fun generateSigningKeyPairs(keystoreFile: Path, rootStoreFile: Path, rootKeystor
val privateKeyPassword = caPrivateKeyPass ?: readPassword("Private key Password: ") val privateKeyPassword = caPrivateKeyPass ?: readPassword("Private key Password: ")
// Ensure folder exists. // Ensure folder exists.
keystoreFile.parent.createDirectories() keystoreFile.parent.createDirectories()
val keyStore = loadOrCreateKeyStore(keystoreFile, keyStorePassword) val keyStore = X509KeyStore.fromFile(keystoreFile, keyStorePassword, createNew = true)
fun storeCertIfAbsent(alias: String, certificateType: CertificateType, subject: X500Principal, signatureScheme: SignatureScheme) { fun storeCertIfAbsent(alias: String, certificateType: CertificateType, subject: X500Principal, signatureScheme: SignatureScheme) {
if (keyStore.containsAlias(alias)) { if (alias in keyStore) {
println("$alias already exists in keystore:") println("$alias already exists in keystore:")
println(keyStore.getCertificate(alias)) println(keyStore.getCertificate(alias))
return return
@ -91,13 +93,10 @@ fun generateSigningKeyPairs(keystoreFile: Path, rootStoreFile: Path, rootKeystor
subject, subject,
keyPair.public keyPair.public
) )
keyStore.addOrReplaceKey(
alias, keyStore.update {
keyPair.private, setPrivateKey(alias, keyPair.private, listOf(cert, rootKeyPairAndCert.certificate), privateKeyPassword)
privateKeyPassword.toCharArray(), }
arrayOf(cert, rootKeyPairAndCert.certificate)
)
keyStore.save(keystoreFile, keyStorePassword)
println("$certificateType key pair and certificate stored in $keystoreFile.") println("$certificateType key pair and certificate stored in $keystoreFile.")
println(cert) println(cert)
@ -106,12 +105,12 @@ fun generateSigningKeyPairs(keystoreFile: Path, rootStoreFile: Path, rootKeystor
storeCertIfAbsent( storeCertIfAbsent(
DEFAULT_CSR_CERTIFICATE_NAME, DEFAULT_CSR_CERTIFICATE_NAME,
CertificateType.INTERMEDIATE_CA, CertificateType.INTERMEDIATE_CA,
X500Principal("CN=Corda Intermediate CA,$cordaX500Name"), X500Principal("CN=Corda Doorman CA,$CORDA_X500_BASE"),
X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME) X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
storeCertIfAbsent( storeCertIfAbsent(
CORDA_NETWORK_MAP, CORDA_NETWORK_MAP,
CertificateType.NETWORK_MAP, CertificateType.NETWORK_MAP,
X500Principal("CN=Corda Network Map,$cordaX500Name"), X500Principal("CN=Corda Network Map,$CORDA_X500_BASE"),
Crypto.EDDSA_ED25519_SHA512) Crypto.EDDSA_ED25519_SHA512)
} }

View File

@ -15,7 +15,7 @@ import com.r3.corda.networkmanage.hsm.menu.Menu
import com.r3.corda.networkmanage.hsm.persistence.ApprovedCertificateRequestData import com.r3.corda.networkmanage.hsm.persistence.ApprovedCertificateRequestData
import com.r3.corda.networkmanage.hsm.persistence.DBSignedCertificateRequestStorage import com.r3.corda.networkmanage.hsm.persistence.DBSignedCertificateRequestStorage
import com.r3.corda.networkmanage.hsm.signer.HsmCsrSigner import com.r3.corda.networkmanage.hsm.signer.HsmCsrSigner
import com.r3.corda.networkmanage.hsm.signer.HsmNetworkMapSigner import com.r3.corda.networkmanage.hsm.signer.HsmSigner
import com.r3.corda.networkmanage.hsm.utils.mapCryptoServerException import com.r3.corda.networkmanage.hsm.utils.mapCryptoServerException
import net.corda.core.utilities.minutes import net.corda.core.utilities.minutes
import org.apache.logging.log4j.LogManager import org.apache.logging.log4j.LogManager
@ -56,7 +56,7 @@ fun run(parameters: Parameters) {
checkNotNull(dataSourceProperties) checkNotNull(dataSourceProperties)
val database = configureDatabase(dataSourceProperties, databaseConfig) val database = configureDatabase(dataSourceProperties, databaseConfig)
val csrStorage = DBSignedCertificateRequestStorage(database) val csrStorage = DBSignedCertificateRequestStorage(database)
val hsmSigner = HsmNetworkMapSigner( val hsmSigner = HsmSigner(
Authenticator( Authenticator(
AuthMode.KEY_FILE, AuthMode.KEY_FILE,
autoUsername, autoUsername,
@ -123,7 +123,7 @@ fun run(parameters: Parameters) {
} }
private fun startNetworkingMapSigningPolling(networkMapStorage: NetworkMapStorage, private fun startNetworkingMapSigningPolling(networkMapStorage: NetworkMapStorage,
signer: HsmNetworkMapSigner, signer: HsmSigner,
executor: ScheduledExecutorService, executor: ScheduledExecutorService,
signingPeriod: Duration) { signingPeriod: Duration) {
val networkMapSigner = NetworkMapSigner(networkMapStorage, signer) val networkMapSigner = NetworkMapSigner(networkMapStorage, signer)

View File

@ -4,23 +4,21 @@ import CryptoServerCXI.CryptoServerCXI.KEY_ALGO_ECDSA
import CryptoServerCXI.CryptoServerCXI.KeyAttributes import CryptoServerCXI.CryptoServerCXI.KeyAttributes
import CryptoServerJCE.CryptoServerProvider import CryptoServerJCE.CryptoServerProvider
import com.r3.corda.networkmanage.common.utils.CORDA_NETWORK_MAP import com.r3.corda.networkmanage.common.utils.CORDA_NETWORK_MAP
import com.r3.corda.networkmanage.hsm.utils.HsmX509Utilities.cleanEcdsaPublicKey
import com.r3.corda.networkmanage.hsm.utils.HsmX509Utilities.createIntermediateCert import com.r3.corda.networkmanage.hsm.utils.HsmX509Utilities.createIntermediateCert
import com.r3.corda.networkmanage.hsm.utils.HsmX509Utilities.createSelfSignedCACert import com.r3.corda.networkmanage.hsm.utils.HsmX509Utilities.createSelfSignedCert
import com.r3.corda.networkmanage.hsm.utils.HsmX509Utilities.getAndInitializeKeyStore import com.r3.corda.networkmanage.hsm.utils.HsmX509Utilities.getAndInitializeKeyStore
import com.r3.corda.networkmanage.hsm.utils.HsmX509Utilities.getCleanEcdsaKeyPair import com.r3.corda.networkmanage.hsm.utils.HsmX509Utilities.retrieveCertAndKeyPair
import com.r3.corda.networkmanage.hsm.utils.HsmX509Utilities.retrieveKeysAndCertificateChain
import net.corda.core.identity.CordaX500Name import net.corda.core.identity.CordaX500Name
import net.corda.core.internal.div import net.corda.core.internal.div
import net.corda.core.internal.isDirectory import net.corda.core.internal.isDirectory
import net.corda.core.internal.x500Name import net.corda.core.internal.x500Name
import net.corda.core.utilities.contextLogger import net.corda.core.utilities.contextLogger
import net.corda.nodeapi.internal.crypto.CertificateAndKeyPair
import net.corda.nodeapi.internal.crypto.CertificateType.* import net.corda.nodeapi.internal.crypto.CertificateType.*
import net.corda.nodeapi.internal.crypto.X509KeyStore
import net.corda.nodeapi.internal.crypto.X509Utilities.CORDA_INTERMEDIATE_CA import net.corda.nodeapi.internal.crypto.X509Utilities.CORDA_INTERMEDIATE_CA
import net.corda.nodeapi.internal.crypto.X509Utilities.CORDA_ROOT_CA import net.corda.nodeapi.internal.crypto.X509Utilities.CORDA_ROOT_CA
import net.corda.nodeapi.internal.crypto.addOrReplaceCertificate import org.bouncycastle.asn1.x500.X500Name
import net.corda.nodeapi.internal.crypto.loadOrCreateKeyStore
import net.corda.nodeapi.internal.crypto.save
import java.nio.file.Path import java.nio.file.Path
import java.security.Key import java.security.Key
import java.security.KeyPair import java.security.KeyPair
@ -50,10 +48,10 @@ class KeyCertificateGenerator(private val parameters: GeneratorParameters) {
val keyStore = getAndInitializeKeyStore(provider) val keyStore = getAndInitializeKeyStore(provider)
val keyPair = certConfig.generateEcdsaKeyPair(keyName, provider, keyStore) val keyPair = certConfig.generateEcdsaKeyPair(keyName, provider, keyStore)
val certChain = if (rootProvider == null) { val certChain = if (rootProvider == null) {
certConfig.generateRootCert(provider, keyPair, trustStoreDirectory, trustStorePassword) arrayOf(certConfig.generateRootCert(provider, keyPair, trustStoreDirectory, trustStorePassword))
} else { } else {
val rootKeyStore = getAndInitializeKeyStore(rootProvider) val rootKeyStore = getAndInitializeKeyStore(rootProvider)
certConfig.generateIntermediateCert(rootProvider, keyPair, rootKeyStore) certConfig.generateIntermediateCertChain(rootProvider, keyPair, rootKeyStore)
} }
keyStore.addOrReplaceKey(keyName, keyPair.private, null, certChain) keyStore.addOrReplaceKey(keyName, keyPair.private, null, certChain)
logger.info("New certificate and key pair named $keyName have been generated and stored in HSM") logger.info("New certificate and key pair named $keyName have been generated and stored in HSM")
@ -71,43 +69,41 @@ class KeyCertificateGenerator(private val parameters: GeneratorParameters) {
private fun CertificateConfiguration.generateRootCert(provider: CryptoServerProvider, private fun CertificateConfiguration.generateRootCert(provider: CryptoServerProvider,
keyPair: KeyPair, keyPair: KeyPair,
networkRootTrustStoreDirectory: Path, networkRootTrustStoreDirectory: Path,
networkRootTrustStorePassword: String): Array<X509Certificate> { networkRootTrustStorePassword: String): X509Certificate {
val certificate = createSelfSignedCACert(ROOT_CA, val rootCert = createSelfSignedCert(
ROOT_CA,
CordaX500Name.parse(subject).x500Name, CordaX500Name.parse(subject).x500Name,
keyPair, keyPair,
validDays, validDays,
provider, provider,
crlDistributionUrl, crlDistributionUrl,
crlIssuer).certificate crlIssuer?.let { X500Name(it) })
logger.info("Certificate for $subject created.") logger.info("Created root cert:\n$rootCert")
val trustStorePath = networkRootTrustStoreDirectory / "truststore.jks" val trustStorePath = networkRootTrustStoreDirectory / "truststore.jks"
val trustStore = loadOrCreateKeyStore(trustStorePath, networkRootTrustStorePassword) X509KeyStore.fromFile(trustStorePath, networkRootTrustStorePassword, createNew = true).update {
logger.info("Trust store for distribution to nodes created in $trustStore") setCertificate(CORDA_ROOT_CA, rootCert)
trustStore.addOrReplaceCertificate(CORDA_ROOT_CA, certificate) }
logger.info("Certificate $CORDA_ROOT_CA has been added to $trustStore") logger.info("Trust store containing the root for distribution to the nodes created in $trustStorePath")
trustStore.save(trustStorePath, networkRootTrustStorePassword) return rootCert
logger.info("Trust store has been persisted. Ready for distribution.")
return arrayOf(certificate)
} }
private fun CertificateConfiguration.generateIntermediateCert( private fun CertificateConfiguration.generateIntermediateCertChain(
provider: CryptoServerProvider, provider: CryptoServerProvider,
keyPair: KeyPair, keyPair: KeyPair,
rootKeyStore: KeyStore): Array<X509Certificate> { rootKeyStore: KeyStore): Array<X509Certificate> {
logger.info("Retrieving the root key pair.") logger.info("Retrieving the root key pair.")
val rootKeysAndCertChain = retrieveKeysAndCertificateChain(CORDA_ROOT_CA, val rootKeysAndCertChain = retrieveCertAndKeyPair(CORDA_ROOT_CA, rootKeyStore)
rootKeyStore)
val certificateAndKeyPair = createIntermediateCert( val certificateAndKeyPair = createIntermediateCert(
certificateType, certificateType,
CordaX500Name.parse(subject).x500Name, CordaX500Name.parse(subject).x500Name,
CertificateAndKeyPair(rootKeysAndCertChain.certificateChain.first(), rootKeysAndCertChain.keyPair), rootKeysAndCertChain,
keyPair, keyPair,
validDays, validDays,
provider, provider,
crlDistributionUrl, crlDistributionUrl,
crlIssuer) crlIssuer?.let { X500Name(it) })
logger.info("Certificate for $subject created.") logger.info("Certificate for $subject created.")
return arrayOf(certificateAndKeyPair.certificate, *rootKeysAndCertChain.certificateChain) return arrayOf(certificateAndKeyPair.certificate, rootKeysAndCertChain.certificate)
} }
private fun CertificateConfiguration.generateECDSAKey(keyName: String, provider: CryptoServerProvider) { private fun CertificateConfiguration.generateECDSAKey(keyName: String, provider: CryptoServerProvider) {
@ -129,6 +125,6 @@ class KeyCertificateGenerator(private val parameters: GeneratorParameters) {
generateECDSAKey(keyName, provider) generateECDSAKey(keyName, provider)
val privateKey = keyStore.getKey(keyName, null) as PrivateKey val privateKey = keyStore.getKey(keyName, null) as PrivateKey
val publicKey = keyStore.getCertificate(keyName).publicKey val publicKey = keyStore.getCertificate(keyName).publicKey
return getCleanEcdsaKeyPair(publicKey, privateKey) return KeyPair(cleanEcdsaPublicKey(publicKey), privateKey)
} }
} }

View File

@ -3,11 +3,13 @@ package com.r3.corda.networkmanage.hsm.signer
import com.r3.corda.networkmanage.hsm.authentication.Authenticator import com.r3.corda.networkmanage.hsm.authentication.Authenticator
import com.r3.corda.networkmanage.hsm.persistence.ApprovedCertificateRequestData import com.r3.corda.networkmanage.hsm.persistence.ApprovedCertificateRequestData
import com.r3.corda.networkmanage.hsm.persistence.SignedCertificateRequestStorage import com.r3.corda.networkmanage.hsm.persistence.SignedCertificateRequestStorage
import com.r3.corda.networkmanage.hsm.utils.HsmX509Utilities.buildCertPath
import com.r3.corda.networkmanage.hsm.utils.HsmX509Utilities.createClientCertificate import com.r3.corda.networkmanage.hsm.utils.HsmX509Utilities.createClientCertificate
import com.r3.corda.networkmanage.hsm.utils.HsmX509Utilities.getAndInitializeKeyStore import com.r3.corda.networkmanage.hsm.utils.HsmX509Utilities.getAndInitializeKeyStore
import com.r3.corda.networkmanage.hsm.utils.HsmX509Utilities.retrieveCertificateAndKeys import com.r3.corda.networkmanage.hsm.utils.HsmX509Utilities.retrieveCertAndKeyPair
import net.corda.nodeapi.internal.crypto.CertificateType import net.corda.nodeapi.internal.crypto.CertificateType
import net.corda.nodeapi.internal.crypto.X509Utilities
import net.corda.nodeapi.internal.crypto.getX509Certificate
import org.bouncycastle.asn1.x500.X500Name
/** /**
* Encapsulates certificate signing logic * Encapsulates certificate signing logic
@ -33,20 +35,19 @@ class HsmCsrSigner(private val storage: SignedCertificateRequestStorage,
override fun sign(toSign: List<ApprovedCertificateRequestData>) { override fun sign(toSign: List<ApprovedCertificateRequestData>) {
authenticator.connectAndAuthenticate { provider, rootProvider, signers -> authenticator.connectAndAuthenticate { provider, rootProvider, signers ->
val rootKeyStore = getAndInitializeKeyStore(rootProvider!!) val rootKeyStore = getAndInitializeKeyStore(rootProvider!!)
// This should be changed once we allow for more certificates in the chain. Preferably we should use val rootCert = rootKeyStore.getX509Certificate(rootCertAlias)
// keyStore.getCertificateChain(String) and assume entire chain is stored in the HSM (depending on the support).
val rootCert = rootKeyStore.getCertificate(rootCertAlias)
val keyStore = getAndInitializeKeyStore(provider) val keyStore = getAndInitializeKeyStore(provider)
val doormanCertAndKey = retrieveCertificateAndKeys(intermediateCertAlias, keyStore) val doormanCertAndKey = retrieveCertAndKeyPair(intermediateCertAlias, keyStore)
toSign.forEach { toSign.forEach {
it.certPath = buildCertPath(createClientCertificate( val nodeCaCert = createClientCertificate(
CertificateType.NODE_CA, CertificateType.NODE_CA,
doormanCertAndKey, doormanCertAndKey,
it.request, it.request,
validDays, validDays,
provider, provider,
csrCertCrlDistPoint, csrCertCrlDistPoint,
csrCertCrlIssuer), doormanCertAndKey.certificate, rootCert) csrCertCrlIssuer?.let { X500Name(it) })
it.certPath = X509Utilities.buildCertPath(nodeCaCert, doormanCertAndKey.certificate, rootCert)
} }
storage.store(toSign, signers) storage.store(toSign, signers)
println("The following certificates have been signed by $signers:") println("The following certificates have been signed by $signers:")

View File

@ -14,8 +14,7 @@ import java.security.Signature
/** /**
* Signer which connects to a HSM using the given [authenticator] to sign bytes. * Signer which connects to a HSM using the given [authenticator] to sign bytes.
*/ */
// TODO Rename this to HsmSigner class HsmSigner(private val authenticator: Authenticator) : Signer {
class HsmNetworkMapSigner(private val authenticator: Authenticator) : Signer {
/** /**
* Signs given data using [CryptoServerJCE.CryptoServerProvider], which connects to the underlying HSM. * Signs given data using [CryptoServerJCE.CryptoServerProvider], which connects to the underlying HSM.
*/ */

View File

@ -24,8 +24,6 @@ import org.bouncycastle.pkcs.PKCS10CertificationRequest
import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequest import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequest
import java.math.BigInteger import java.math.BigInteger
import java.security.* import java.security.*
import java.security.cert.Certificate
import java.security.cert.CertificateFactory
import java.security.cert.X509Certificate import java.security.cert.X509Certificate
import java.security.spec.X509EncodedKeySpec import java.security.spec.X509EncodedKeySpec
import java.time.Instant import java.time.Instant
@ -34,7 +32,7 @@ import java.util.*
object HsmX509Utilities { object HsmX509Utilities {
val SIGNATURE_ALGORITHM = "SHA256withECDSA" const val SIGNATURE_ALGORITHM = "SHA256withECDSA"
/** /**
* Create a de novo root self-signed X509 v3 CA cert for the specified [KeyPair]. * Create a de novo root self-signed X509 v3 CA cert for the specified [KeyPair].
@ -45,27 +43,26 @@ object HsmX509Utilities {
* @param provider provider to be used during the certificate signing process * @param provider provider to be used during the certificate signing process
* @param crlDistPoint url to the certificate revocation list of this certificate * @param crlDistPoint url to the certificate revocation list of this certificate
* @param crlIssuer issuer of the certificate revocation list of this certificate * @param crlIssuer issuer of the certificate revocation list of this certificate
* @return an instance of [CertificateAndKeyPair] class is returned containing the new root CA Cert and its [KeyPair] for signing downstream certificates. * @return the new root cert.
* Note the generated certificate tree is capped at max depth of 2 to be in line with commercially available certificates * Note the generated certificate tree is capped at max depth of 2 to be in line with commercially available certificates
*/ */
fun createSelfSignedCACert(type: CertificateType, fun createSelfSignedCert(type: CertificateType,
subject: X500Name, subject: X500Name,
keyPair: KeyPair, keyPair: KeyPair,
validDays: Int, validDays: Int,
provider: Provider, provider: Provider,
crlDistPoint: String? = null, crlDistPoint: String? = null,
crlIssuer: String? = null): CertificateAndKeyPair { crlIssuer: X500Name? = null): X509Certificate {
// TODO this needs to be chaneged // TODO this needs to be changed
val serial = BigInteger.valueOf(random63BitValue(provider)) val serial = BigInteger.valueOf(random63BitValue(provider))
val pubKey = keyPair.public
// Ten year certificate validity // Ten year certificate validity
// TODO how do we manage certificate expiry, revocation and loss // TODO how do we manage certificate expiry, revocation and loss
val window = getCertificateValidityWindow(0, validDays) val window = getCertificateValidityWindow(0, validDays)
val keyPurposes = DERSequence(ASN1EncodableVector().apply { type.purposes.forEach { add(it) } }) val keyPurposes = DERSequence(ASN1EncodableVector().apply { type.purposes.forEach { add(it) } })
val builder = JcaX509v3CertificateBuilder(subject, serial, window.first, window.second, subject, pubKey) val builder = JcaX509v3CertificateBuilder(subject, serial, window.first, window.second, subject, keyPair.public)
builder.addExtension(Extension.subjectKeyIdentifier, false, createSubjectKeyIdentifier(pubKey)) builder.addExtension(Extension.subjectKeyIdentifier, false, createSubjectKeyIdentifier(keyPair.public))
builder.addExtension(Extension.basicConstraints, true, BasicConstraints(type.isCA)) builder.addExtension(Extension.basicConstraints, true, BasicConstraints(type.isCA))
builder.addExtension(Extension.keyUsage, false, type.keyUsage) builder.addExtension(Extension.keyUsage, false, type.keyUsage)
builder.addExtension(Extension.extendedKeyUsage, false, keyPurposes) builder.addExtension(Extension.extendedKeyUsage, false, keyPurposes)
@ -77,52 +74,33 @@ object HsmX509Utilities {
val cert = signCertificate(builder, keyPair.private, provider) val cert = signCertificate(builder, keyPair.private, provider)
cert.checkValidity(Date()) cert.checkValidity()
cert.verify(pubKey) cert.verify(keyPair.public)
return CertificateAndKeyPair(cert, KeyPair(pubKey, keyPair.private)) return cert
} }
/** /**
* This is a helper function, which purpose is to workaround a bug in the bouncycastle library * This is a helper function, which purpose is to workaround a bug in the bouncycastle library
* that is associated with the incorrect encoded byte production when the EC algorithm is used with the passed keys. * that is associated with the incorrect encoded byte production when the EC algorithm is used with the passed keys.
* @param publicKey public key * @param publicKey public key
* @param privateKey private key * @return cleaned [PublicKey] instance
* @return cleaned [KeyPair] instance
*/ */
fun getCleanEcdsaKeyPair(publicKey: PublicKey, privateKey: PrivateKey): KeyPair { fun cleanEcdsaPublicKey(publicKey: PublicKey): PublicKey {
val rawPublicKeyBytes = publicKey.encoded return KeyFactory.getInstance("EC").generatePublic(X509EncodedKeySpec(publicKey.encoded))
val kf = KeyFactory.getInstance("EC")
val cleanPublicKey = kf.generatePublic(X509EncodedKeySpec(rawPublicKeyBytes))
return KeyPair(cleanPublicKey, privateKey)
} }
/** /**
* Retrieves a certificate and keys from the given key store. Also, the keys retrieved are cleaned in a sense of the * Retrieves key pair and certificate from the given key store. Also, the keys retrieved are cleaned in a sense of the
* [getCleanEcdsaKeyPair] method. * [cleanEcdsaPublicKey] method.
* @param certificateKeyName certificate and key name (alias) to be used when querying the key store. * @param alias certificate and key name (alias) to be used when querying the key store.
* @param keyStore key store that holds the certificate with its keys. * @param keyStore key store that holds the certificate with its keys.
* @return instance of [CertificateAndKeyPair] holding the retrieved certificate with its keys. * @return instance of [CertificateAndKeyPair] holding the key pair and the certificate.
*/ */
fun retrieveCertificateAndKeys(certificateKeyName: String, keyStore: KeyStore): CertificateAndKeyPair { fun retrieveCertAndKeyPair(alias: String, keyStore: KeyStore): CertificateAndKeyPair {
val privateKey = keyStore.getKey(certificateKeyName, null) as PrivateKey val privateKey = keyStore.getKey(alias, null) as PrivateKey
val publicKey = keyStore.getCertificate(certificateKeyName).publicKey val certificate = keyStore.getX509Certificate(alias)
val certificate = keyStore.getX509Certificate(certificateKeyName) return CertificateAndKeyPair(certificate, KeyPair(cleanEcdsaPublicKey(certificate.publicKey), privateKey))
return CertificateAndKeyPair(certificate, getCleanEcdsaKeyPair(publicKey, privateKey))
}
/**
* Retrieves key pair and certificate chain from the given key store. Also, the keys retrieved are cleaned in a sense of the
* [getCleanEcdsaKeyPair] method.
* @param certificateKeyName certificate and key name (alias) to be used when querying the key store.
* @param keyStore key store that holds the certificate with its keys.
* @return instance of [KeyPairAndCertificateChain] holding the key pair and the certificate chain.
*/
fun retrieveKeysAndCertificateChain(certificateKeyName: String, keyStore: KeyStore): KeyPairAndCertificateChain {
val privateKey = keyStore.getKey(certificateKeyName, null) as PrivateKey
val publicKey = keyStore.getCertificate(certificateKeyName).publicKey
val certificateChain = keyStore.getCertificateChain(certificateKeyName).map { it as X509Certificate }
return KeyPairAndCertificateChain(getCleanEcdsaKeyPair(publicKey, privateKey), certificateChain.toTypedArray())
} }
/** /**
@ -145,7 +123,7 @@ object HsmX509Utilities {
validDays: Int, validDays: Int,
provider: Provider, provider: Provider,
crlDistPoint: String?, crlDistPoint: String?,
crlIssuer: String?): CertificateAndKeyPair { crlIssuer: X500Name?): CertificateAndKeyPair {
val issuer = X509CertificateHolder(certificateAuthority.certificate.encoded).subject val issuer = X509CertificateHolder(certificateAuthority.certificate.encoded).subject
val serial = BigInteger.valueOf(random63BitValue(provider)) val serial = BigInteger.valueOf(random63BitValue(provider))
@ -192,7 +170,7 @@ object HsmX509Utilities {
validDays: Int, validDays: Int,
provider: Provider, provider: Provider,
crlDistPoint: String?, crlDistPoint: String?,
crlIssuer: String?): Certificate { crlIssuer: X500Name?): X509Certificate {
val jcaRequest = JcaPKCS10CertificationRequest(request) val jcaRequest = JcaPKCS10CertificationRequest(request)
// This can be adjusted more to our future needs. // This can be adjusted more to our future needs.
val nameConstraints = NameConstraints(arrayOf(GeneralSubtree(GeneralName(GeneralName.directoryName, CordaX500Name.parse(jcaRequest.subject.toString()).copy(commonName = null).x500Name))), arrayOf()) val nameConstraints = NameConstraints(arrayOf(GeneralSubtree(GeneralName(GeneralName.directoryName, CordaX500Name.parse(jcaRequest.subject.toString()).copy(commonName = null).x500Name))), arrayOf())
@ -249,13 +227,6 @@ object HsmX509Utilities {
return Pair(notBefore, notAfter) return Pair(notBefore, notAfter)
} }
/**
* A utility method for transforming number of certificates into the [CertPath] instance.
* The certificates passed should be ordered starting with the leaf certificate and ending with the root one.
* @param certificates ordered certficates
*/
fun buildCertPath(vararg certificates: Certificate) = CertificateFactory.getInstance("X509").generateCertPath(certificates.asList())
/** /**
* Creates and initializes a key store from the given crypto server provider. * Creates and initializes a key store from the given crypto server provider.
* @param provider crypto server provider to be used for the key store creation * @param provider crypto server provider to be used for the key store creation
@ -312,11 +283,11 @@ object HsmX509Utilities {
return certificateBuilder.build(signer).toJca() return certificateBuilder.build(signer).toJca()
} }
private fun addCrlInfo(builder: X509v3CertificateBuilder, crlDistPoint: String?, crlIssuer: String?) { private fun addCrlInfo(builder: X509v3CertificateBuilder, crlDistPoint: String?, crlIssuer: X500Name?) {
if (crlDistPoint != null) { if (crlDistPoint != null) {
val distPointName = DistributionPointName(GeneralNames(GeneralName(GeneralName.uniformResourceIdentifier, crlDistPoint))) val distPointName = DistributionPointName(GeneralNames(GeneralName(GeneralName.uniformResourceIdentifier, crlDistPoint)))
val crlIssuerGeneralNames = crlIssuer?.let { val crlIssuerGeneralNames = crlIssuer?.let {
GeneralNames(GeneralName(CordaX500Name.parse(crlIssuer).x500Name)) GeneralNames(GeneralName(crlIssuer))
} }
// The second argument is flag that allows you to define what reason of certificate revocation is served by this distribution point see [ReasonFlags]. // The second argument is flag that allows you to define what reason of certificate revocation is served by this distribution point see [ReasonFlags].
// The idea is that you have different revocation per revocation reason. Since we won't go into such a granularity, we can skip that parameter. // The idea is that you have different revocation per revocation reason. Since we won't go into such a granularity, we can skip that parameter.
@ -327,5 +298,3 @@ object HsmX509Utilities {
} }
} }
} }
data class KeyPairAndCertificateChain(val keyPair: KeyPair, val certificateChain: Array<X509Certificate>)

View File

@ -3,14 +3,13 @@ package com.r3.corda.networkmanage.common.persistence
import com.r3.corda.networkmanage.TestBase import com.r3.corda.networkmanage.TestBase
import com.r3.corda.networkmanage.common.persistence.CertificationRequestStorage.Companion.DOORMAN_SIGNATURE import com.r3.corda.networkmanage.common.persistence.CertificationRequestStorage.Companion.DOORMAN_SIGNATURE
import com.r3.corda.networkmanage.common.persistence.entity.CertificateSigningRequestEntity import com.r3.corda.networkmanage.common.persistence.entity.CertificateSigningRequestEntity
import com.r3.corda.networkmanage.common.utils.buildCertPath
import net.corda.core.crypto.Crypto import net.corda.core.crypto.Crypto
import net.corda.core.crypto.SecureHash import net.corda.core.crypto.SecureHash
import net.corda.core.identity.CordaX500Name import net.corda.core.identity.CordaX500Name
import net.corda.nodeapi.internal.crypto.X509Utilities import net.corda.nodeapi.internal.crypto.X509Utilities
import net.corda.nodeapi.internal.persistence.CordaPersistence import net.corda.nodeapi.internal.persistence.CordaPersistence
import net.corda.testing.internal.createDevNodeCaCertPath
import net.corda.nodeapi.internal.persistence.DatabaseConfig import net.corda.nodeapi.internal.persistence.DatabaseConfig
import net.corda.testing.internal.createDevNodeCaCertPath
import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThat
import org.bouncycastle.pkcs.PKCS10CertificationRequest import org.bouncycastle.pkcs.PKCS10CertificationRequest
import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequest import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequest
@ -228,9 +227,8 @@ class PersistentCertificateRequestStorageTest : TestBase() {
private fun generateSignedCertPath(csr: PKCS10CertificationRequest, keyPair: KeyPair): CertPath { private fun generateSignedCertPath(csr: PKCS10CertificationRequest, keyPair: KeyPair): CertPath {
return JcaPKCS10CertificationRequest(csr).run { return JcaPKCS10CertificationRequest(csr).run {
// TODO We need a utility in InternalUtils for converting X500Name -> CordaX500Name
val (rootCa, intermediateCa, nodeCa) = createDevNodeCaCertPath(CordaX500Name.build(X500Principal(subject.encoded)), keyPair) val (rootCa, intermediateCa, nodeCa) = createDevNodeCaCertPath(CordaX500Name.build(X500Principal(subject.encoded)), keyPair)
buildCertPath(nodeCa.certificate, intermediateCa.certificate, rootCa.certificate) X509Utilities.buildCertPath(nodeCa.certificate, intermediateCa.certificate, rootCa.certificate)
} }
} }

View File

@ -1,7 +1,6 @@
package com.r3.corda.networkmanage.common.persistence package com.r3.corda.networkmanage.common.persistence
import com.r3.corda.networkmanage.TestBase import com.r3.corda.networkmanage.TestBase
import com.r3.corda.networkmanage.common.utils.buildCertPath
import com.r3.corda.networkmanage.common.utils.hashString import com.r3.corda.networkmanage.common.utils.hashString
import net.corda.core.crypto.Crypto import net.corda.core.crypto.Crypto
import net.corda.core.crypto.SecureHash import net.corda.core.crypto.SecureHash
@ -71,7 +70,7 @@ class PersistentNodeInfoStorageTest : TestBase() {
requestStorage.putCertificatePath( requestStorage.putCertificatePath(
requestId, requestId,
buildCertPath(nodeCaCert, intermediateCa.certificate, rootCaCert), X509Utilities.buildCertPath(nodeCaCert, intermediateCa.certificate, rootCaCert),
listOf(CertificationRequestStorage.DOORMAN_SIGNATURE)) listOf(CertificationRequestStorage.DOORMAN_SIGNATURE))
val storedCertPath = nodeInfoStorage.getCertificatePath(SecureHash.parse(keyPair.public.hashString())) val storedCertPath = nodeInfoStorage.getCertificatePath(SecureHash.parse(keyPair.public.hashString()))

View File

@ -1,7 +1,6 @@
package com.r3.corda.networkmanage.doorman package com.r3.corda.networkmanage.doorman
import com.atlassian.jira.rest.client.internal.async.AsynchronousJiraRestClientFactory import com.atlassian.jira.rest.client.internal.async.AsynchronousJiraRestClientFactory
import com.r3.corda.networkmanage.common.utils.buildCertPath
import net.corda.core.crypto.Crypto import net.corda.core.crypto.Crypto
import net.corda.core.crypto.SecureHash import net.corda.core.crypto.SecureHash
import net.corda.core.identity.CordaX500Name import net.corda.core.identity.CordaX500Name
@ -10,6 +9,7 @@ import org.junit.Before
import org.junit.Ignore import org.junit.Ignore
import org.junit.Test import org.junit.Test
import java.net.URI import java.net.URI
import javax.security.auth.x500.X500Principal
@Ignore @Ignore
// This is manual test for testing Jira API. // This is manual test for testing Jira API.
@ -41,8 +41,10 @@ class JiraClientTest {
@Test @Test
fun updateSignedRequests() { fun updateSignedRequests() {
val requests = jiraClient.getApprovedRequests() val requests = jiraClient.getApprovedRequests()
val selfSignedCA = X509Utilities.createSelfSignedCACertificate(CordaX500Name("test", "london", "GB").x500Principal, Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)) val selfSignedCaCertPath = X509Utilities.buildCertPath(X509Utilities.createSelfSignedCACertificate(
jiraClient.updateSignedRequests(requests.map { it.requestId to buildCertPath(selfSignedCA) }.toMap()) X500Principal("O=test,L=london,C=GB"),
Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)))
jiraClient.updateSignedRequests(requests.associateBy({ it.requestId }, { selfSignedCaCertPath }))
} }
@Test @Test

View File

@ -29,14 +29,17 @@ class DefaultCsrHandlerTest : TestBase() {
val requestStorage: CertificationRequestStorage = mock { val requestStorage: CertificationRequestStorage = mock {
on { getRequest("New") }.thenReturn(certificateSigningRequest()) on { getRequest("New") }.thenReturn(certificateSigningRequest())
on { getRequest("Signed") }.thenReturn(certificateSigningRequest(status = RequestStatus.SIGNED, certData = certificateData(CertificateStatus.VALID, buildCertPath(cert)))) on { getRequest("Signed") }.thenReturn(certificateSigningRequest(
status = RequestStatus.SIGNED,
certData = certificateData(CertificateStatus.VALID, X509Utilities.buildCertPath(cert))
))
on { getRequest("Rejected") }.thenReturn(certificateSigningRequest(status = RequestStatus.REJECTED, remark = "Random reason")) on { getRequest("Rejected") }.thenReturn(certificateSigningRequest(status = RequestStatus.REJECTED, remark = "Random reason"))
} }
val requestProcessor = DefaultCsrHandler(requestStorage, null) val requestProcessor = DefaultCsrHandler(requestStorage, null)
assertEquals(CertificateResponse.NotReady, requestProcessor.getResponse("random")) assertEquals(CertificateResponse.NotReady, requestProcessor.getResponse("random"))
assertEquals(CertificateResponse.NotReady, requestProcessor.getResponse("New")) assertEquals(CertificateResponse.NotReady, requestProcessor.getResponse("New"))
assertEquals(CertificateResponse.Ready(buildCertPath(cert)), requestProcessor.getResponse("Signed")) assertEquals(CertificateResponse.Ready(X509Utilities.buildCertPath(cert)), requestProcessor.getResponse("Signed"))
assertEquals(CertificateResponse.Unauthorised("Random reason"), requestProcessor.getResponse("Rejected")) assertEquals(CertificateResponse.Unauthorised("Random reason"), requestProcessor.getResponse("Rejected"))
} }

View File

@ -3,7 +3,6 @@ package com.r3.corda.networkmanage.doorman.webservice
import com.nhaarman.mockito_kotlin.* import com.nhaarman.mockito_kotlin.*
import com.r3.corda.networkmanage.TestBase import com.r3.corda.networkmanage.TestBase
import com.r3.corda.networkmanage.common.persistence.CertificateResponse import com.r3.corda.networkmanage.common.persistence.CertificateResponse
import com.r3.corda.networkmanage.common.utils.buildCertPath
import com.r3.corda.networkmanage.doorman.NetworkManagementWebServer import com.r3.corda.networkmanage.doorman.NetworkManagementWebServer
import com.r3.corda.networkmanage.doorman.signer.CsrHandler import com.r3.corda.networkmanage.doorman.signer.CsrHandler
import net.corda.core.crypto.Crypto import net.corda.core.crypto.Crypto
@ -109,7 +108,7 @@ class RegistrationWebServiceTest : TestBase() {
intermediateCa.keyPair, intermediateCa.keyPair,
X500Principal(subject.encoded), X500Principal(subject.encoded),
publicKey) publicKey)
buildCertPath(tlsCert, intermediateCa.certificate, rootCaCert) X509Utilities.buildCertPath(tlsCert, intermediateCa.certificate, rootCaCert)
} }
null null
} }
@ -157,7 +156,7 @@ class RegistrationWebServiceTest : TestBase() {
X500Principal(subject.encoded), X500Principal(subject.encoded),
publicKey, publicKey,
nameConstraints = nameConstraints) nameConstraints = nameConstraints)
buildCertPath(clientCert, intermediateCa.certificate, rootCaCert) X509Utilities.buildCertPath(clientCert, intermediateCa.certificate, rootCaCert)
} }
true true
} }