mirror of
https://github.com/corda/corda.git
synced 2025-06-17 14:48:16 +00:00
Replace X509Certificate with X509CertificateHolder
Replace X509Certificate with X509CertificateHolder for consistency in implementation of how X.509 certificates are managed. Using the Java standard class entails the actual implementing class being one of several options depending how a certificate is built, which makes serialization/deserialization with Kryo inconsistent as some of these forms cannot be directly built from outside restricted classes.
This commit is contained in:
@ -19,6 +19,7 @@ import org.assertj.core.api.Assertions.assertThatExceptionOfType
|
||||
import org.bouncycastle.asn1.x509.GeneralName
|
||||
import org.bouncycastle.asn1.x509.GeneralSubtree
|
||||
import org.bouncycastle.asn1.x509.NameConstraints
|
||||
import org.bouncycastle.cert.path.CertPath
|
||||
import org.junit.Test
|
||||
import java.nio.file.Files
|
||||
|
||||
@ -111,7 +112,7 @@ class MQSecurityAsNodeTest : MQSecurityTest() {
|
||||
X509Utilities.CORDA_CLIENT_CA,
|
||||
clientKey.private,
|
||||
keyPass,
|
||||
arrayOf(clientCACert, intermediateCA.certificate, rootCACert))
|
||||
CertPath(arrayOf(clientCACert, intermediateCA.certificate, rootCACert)))
|
||||
clientCAKeystore.save(nodeKeystore, keyStorePassword)
|
||||
|
||||
val tlsKeystore = KeyStoreUtilities.loadOrCreateKeyStore(sslKeystore, keyStorePassword)
|
||||
@ -119,7 +120,7 @@ class MQSecurityAsNodeTest : MQSecurityTest() {
|
||||
X509Utilities.CORDA_CLIENT_TLS,
|
||||
tlsKey.private,
|
||||
keyPass,
|
||||
arrayOf(clientTLSCert, clientCACert, intermediateCA.certificate, rootCACert))
|
||||
CertPath(arrayOf(clientTLSCert, clientCACert, intermediateCA.certificate, rootCACert)))
|
||||
tlsKeystore.save(sslKeystore, keyStorePassword)
|
||||
}
|
||||
}
|
||||
|
@ -57,6 +57,7 @@ import net.corda.node.utilities.transaction
|
||||
import org.apache.activemq.artemis.utils.ReusableLatch
|
||||
import org.bouncycastle.asn1.x500.X500Name
|
||||
import org.bouncycastle.cert.X509CertificateHolder
|
||||
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter
|
||||
import org.jetbrains.exposed.sql.Database
|
||||
import org.slf4j.Logger
|
||||
import java.io.IOException
|
||||
@ -671,8 +672,10 @@ private class KeyStoreWrapper(private val storePath: Path, private val storePass
|
||||
|
||||
fun save(serviceName: X500Name, privateKeyAlias: String, keyPair: KeyPair) {
|
||||
val clientCA = keyStore.getCertificateAndKeyPair(X509Utilities.CORDA_CLIENT_CA, storePassword)
|
||||
val converter = JcaX509CertificateConverter()
|
||||
val cert = X509Utilities.createCertificate(CertificateType.IDENTITY, clientCA.certificate, clientCA.keyPair, serviceName, keyPair.public)
|
||||
keyStore.addOrReplaceKey(privateKeyAlias, keyPair.private, storePassword.toCharArray(), arrayOf(cert, *keyStore.getCertificateChain(X509Utilities.CORDA_CLIENT_CA)))
|
||||
keyStore.addOrReplaceKey(privateKeyAlias, keyPair.private, storePassword.toCharArray(),
|
||||
arrayOf(converter.getCertificate(cert), *keyStore.getCertificateChain(X509Utilities.CORDA_CLIENT_CA)))
|
||||
keyStore.save(storePath, storePassword)
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,8 @@ import net.corda.core.serialization.SingletonSerializeAsToken
|
||||
import net.corda.core.utilities.loggerFor
|
||||
import net.corda.core.utilities.trace
|
||||
import org.bouncycastle.asn1.x500.X500Name
|
||||
import org.bouncycastle.cert.X509CertificateHolder
|
||||
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter
|
||||
import java.security.InvalidAlgorithmParameterException
|
||||
import java.security.PublicKey
|
||||
import java.security.cert.*
|
||||
@ -82,8 +84,9 @@ class InMemoryIdentityService(identities: Iterable<Party> = emptySet(),
|
||||
override fun pathForAnonymous(anonymousParty: AnonymousParty): CertPath? = partyToPath[anonymousParty]
|
||||
|
||||
@Throws(CertificateExpiredException::class, CertificateNotYetValidException::class, InvalidAlgorithmParameterException::class)
|
||||
override fun registerPath(trustedRoot: X509Certificate, anonymousParty: AnonymousParty, path: CertPath) {
|
||||
val expectedTrustAnchor = TrustAnchor(trustedRoot, null)
|
||||
override fun registerPath(trustedRoot: X509CertificateHolder, anonymousParty: AnonymousParty, path: CertPath) {
|
||||
val converter = JcaX509CertificateConverter()
|
||||
val expectedTrustAnchor = TrustAnchor(converter.getCertificate(trustedRoot), null)
|
||||
require(path.certificates.isNotEmpty()) { "Certificate path must contain at least one certificate" }
|
||||
val target = path.certificates.last() as X509Certificate
|
||||
require(target.publicKey == anonymousParty.owningKey) { "Certificate path must end with anonymous party's public key" }
|
||||
|
@ -9,11 +9,12 @@ import net.corda.core.identity.Party
|
||||
import net.corda.core.node.services.IdentityService
|
||||
import net.corda.core.node.services.KeyManagementService
|
||||
import net.corda.core.serialization.SingletonSerializeAsToken
|
||||
import org.bouncycastle.cert.X509CertificateHolder
|
||||
import org.bouncycastle.operator.ContentSigner
|
||||
import java.security.KeyPair
|
||||
import java.security.PrivateKey
|
||||
import java.security.PublicKey
|
||||
import java.security.cert.CertPath
|
||||
import java.security.cert.X509Certificate
|
||||
import java.util.*
|
||||
import javax.annotation.concurrent.ThreadSafe
|
||||
|
||||
@ -56,7 +57,7 @@ class E2ETestKeyManagementService(val identityService: IdentityService,
|
||||
return keyPair.public
|
||||
}
|
||||
|
||||
override fun freshKeyAndCert(identity: Party, revocationEnabled: Boolean): Pair<X509Certificate, CertPath> = freshKeyAndCert(this, identityService, identity, revocationEnabled)
|
||||
override fun freshKeyAndCert(identity: Party, revocationEnabled: Boolean): Pair<X509CertificateHolder, CertPath> = freshKeyAndCert(this, identityService, identity, revocationEnabled)
|
||||
|
||||
private fun getSigningKeyPair(publicKey: PublicKey): KeyPair {
|
||||
return mutex.locked {
|
||||
|
@ -1,12 +1,17 @@
|
||||
package net.corda.node.services.keys
|
||||
|
||||
import net.corda.core.crypto.CertificateType
|
||||
import net.corda.core.crypto.ContentSignerBuilder
|
||||
import net.corda.core.crypto.Crypto
|
||||
import net.corda.core.crypto.X509Utilities
|
||||
import net.corda.core.identity.AnonymousParty
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.node.services.IdentityService
|
||||
import net.corda.core.node.services.KeyManagementService
|
||||
import org.bouncycastle.cert.X509CertificateHolder
|
||||
import org.bouncycastle.operator.ContentSigner
|
||||
import java.security.KeyPair
|
||||
import java.security.Security
|
||||
import java.security.cert.CertPath
|
||||
import java.security.cert.X509Certificate
|
||||
|
||||
@ -23,7 +28,7 @@ import java.security.cert.X509Certificate
|
||||
fun freshKeyAndCert(keyManagementService: KeyManagementService,
|
||||
identityService: IdentityService,
|
||||
identity: Party,
|
||||
revocationEnabled: Boolean = false): Pair<X509Certificate, CertPath> {
|
||||
revocationEnabled: Boolean = false): Pair<X509CertificateHolder, CertPath> {
|
||||
val ourPublicKey = keyManagementService.freshKey()
|
||||
// FIXME: Use the actual certificate for the identity the flow is presenting themselves as
|
||||
val issuerKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_IDENTITY_SIGNATURE_SCHEME)
|
||||
|
@ -10,13 +10,14 @@ import net.corda.core.node.services.IdentityService
|
||||
import net.corda.core.node.services.KeyManagementService
|
||||
import net.corda.core.serialization.SingletonSerializeAsToken
|
||||
import net.corda.node.utilities.*
|
||||
import org.bouncycastle.cert.X509CertificateHolder
|
||||
import org.bouncycastle.operator.ContentSigner
|
||||
import org.jetbrains.exposed.sql.ResultRow
|
||||
import org.jetbrains.exposed.sql.statements.InsertStatement
|
||||
import java.security.KeyPair
|
||||
import java.security.PrivateKey
|
||||
import java.security.PublicKey
|
||||
import java.security.cert.CertPath
|
||||
import java.security.cert.X509Certificate
|
||||
|
||||
/**
|
||||
* A persistent re-implementation of [E2ETestKeyManagementService] to support node re-start.
|
||||
@ -66,8 +67,7 @@ class PersistentKeyManagementService(val identityService: IdentityService,
|
||||
}
|
||||
return keyPair.public
|
||||
}
|
||||
|
||||
override fun freshKeyAndCert(identity: Party, revocationEnabled: Boolean): Pair<X509Certificate, CertPath> = freshKeyAndCert(this, identityService, identity, revocationEnabled)
|
||||
override fun freshKeyAndCert(identity: Party, revocationEnabled: Boolean): Pair<X509CertificateHolder, CertPath> = freshKeyAndCert(this, identityService, identity, revocationEnabled)
|
||||
|
||||
private fun getSigningKeyPair(publicKey: PublicKey): KeyPair {
|
||||
return mutex.locked {
|
||||
|
@ -263,10 +263,9 @@ class ArtemisMessagingServer(override val config: NodeConfiguration,
|
||||
val trustStore = KeyStoreUtilities.loadKeyStore(config.trustStoreFile, config.trustStorePassword)
|
||||
val ourCertificate = keyStore.getX509Certificate(CORDA_CLIENT_TLS)
|
||||
|
||||
val ourSubjectDN = X500Name(ourCertificate.subjectDN.name)
|
||||
// This is a sanity check and should not fail unless things have been misconfigured
|
||||
require(ourSubjectDN == config.myLegalName) {
|
||||
"Legal name does not match with our subject CN: $ourSubjectDN"
|
||||
require(ourCertificate.subject == config.myLegalName) {
|
||||
"Legal name does not match with our subject CN: ${ourCertificate.subject}"
|
||||
}
|
||||
val defaultCertPolicies = mapOf(
|
||||
PEER_ROLE to CertificateChainCheckPolicy.RootMustMatch,
|
||||
@ -510,7 +509,7 @@ private class VerifyingNettyConnector(configuration: MutableMap<String, Any>,
|
||||
"Peer has wrong subject name in the certificate - expected $expectedLegalName but got ${peerCertificate.subject}. This is either a fatal " +
|
||||
"misconfiguration by the remote peer or an SSL man-in-the-middle attack!"
|
||||
}
|
||||
X509Utilities.validateCertificateChain(X509CertImpl(session.localCertificates.last().encoded), *session.peerCertificates)
|
||||
X509Utilities.validateCertificateChain(X509CertificateHolder(session.localCertificates.last().encoded), *session.peerCertificates)
|
||||
server.onTcpConnection(peerLegalName)
|
||||
} catch (e: IllegalArgumentException) {
|
||||
connection.close()
|
||||
|
@ -2,7 +2,9 @@ package net.corda.node.services.network
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting
|
||||
import net.corda.core.ThreadBox
|
||||
import net.corda.core.crypto.*
|
||||
import net.corda.core.crypto.DigitalSignature
|
||||
import net.corda.core.crypto.SignedData
|
||||
import net.corda.core.crypto.isFulfilledBy
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.messaging.MessageRecipients
|
||||
import net.corda.core.messaging.SingleMessageRecipient
|
||||
|
@ -6,6 +6,8 @@ import net.corda.core.crypto.X509Utilities.CORDA_CLIENT_CA
|
||||
import net.corda.core.crypto.X509Utilities.CORDA_CLIENT_TLS
|
||||
import net.corda.core.crypto.X509Utilities.CORDA_ROOT_CA
|
||||
import net.corda.node.services.config.NodeConfiguration
|
||||
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter
|
||||
import org.bouncycastle.cert.path.CertPath
|
||||
import org.bouncycastle.openssl.jcajce.JcaPEMWriter
|
||||
import org.bouncycastle.util.io.pem.PemObject
|
||||
import java.io.StringWriter
|
||||
@ -40,7 +42,8 @@ class NetworkRegistrationHelper(val config: NodeConfiguration, val certService:
|
||||
val keyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
||||
val selfSignCert = X509Utilities.createSelfSignedCACertificate(config.myLegalName, keyPair)
|
||||
// Save to the key store.
|
||||
caKeyStore.addOrReplaceKey(SELF_SIGNED_PRIVATE_KEY, keyPair.private, privateKeyPassword.toCharArray(), arrayOf(selfSignCert))
|
||||
caKeyStore.addOrReplaceKey(SELF_SIGNED_PRIVATE_KEY, keyPair.private, privateKeyPassword.toCharArray(),
|
||||
CertPath(arrayOf(selfSignCert)))
|
||||
caKeyStore.save(config.nodeKeystore, keystorePassword)
|
||||
}
|
||||
val keyPair = caKeyStore.getKeyPair(SELF_SIGNED_PRIVATE_KEY, privateKeyPassword)
|
||||
@ -69,11 +72,13 @@ class NetworkRegistrationHelper(val config: NodeConfiguration, val certService:
|
||||
println("Node private key and certificate stored in ${config.nodeKeystore}.")
|
||||
|
||||
println("Generating SSL certificate for node messaging service.")
|
||||
val converter = JcaX509CertificateConverter()
|
||||
val sslKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
||||
val caCert = caKeyStore.getX509Certificate(CORDA_CLIENT_CA)
|
||||
val sslCert = X509Utilities.createCertificate(CertificateType.TLS, caCert, keyPair, caCert.subject, sslKey.public)
|
||||
val sslKeyStore = KeyStoreUtilities.loadOrCreateKeyStore(config.sslKeystore, keystorePassword)
|
||||
sslKeyStore.addOrReplaceKey(CORDA_CLIENT_TLS, sslKey.private, privateKeyPassword.toCharArray(), arrayOf(sslCert, *certificates))
|
||||
sslKeyStore.addOrReplaceKey(CORDA_CLIENT_TLS, sslKey.private, privateKeyPassword.toCharArray(),
|
||||
arrayOf(converter.getCertificate(sslCert), *certificates))
|
||||
sslKeyStore.save(config.sslKeystore, config.keyStorePassword)
|
||||
println("SSL private key and certificate stored in ${config.sslKeystore}.")
|
||||
// All done, clean up temp files.
|
||||
|
@ -5,10 +5,12 @@ import com.nhaarman.mockito_kotlin.eq
|
||||
import com.nhaarman.mockito_kotlin.mock
|
||||
import net.corda.core.crypto.*
|
||||
import net.corda.core.exists
|
||||
import net.corda.core.mapToArray
|
||||
import net.corda.core.utilities.ALICE
|
||||
import net.corda.testing.TestNodeConfiguration
|
||||
import net.corda.testing.getTestX509Name
|
||||
import org.bouncycastle.cert.X509CertificateHolder
|
||||
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.rules.TemporaryFolder
|
||||
@ -29,8 +31,9 @@ class NetworkRegistrationHelperTest {
|
||||
"CORDA_INTERMEDIATE_CA",
|
||||
"CORDA_ROOT_CA")
|
||||
.map { getTestX509Name(it) }
|
||||
val converter = JcaX509CertificateConverter()
|
||||
val certs = identities.map { X509Utilities.createSelfSignedCACertificate(it, Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)) }
|
||||
.toTypedArray()
|
||||
.mapToArray(converter::getCertificate)
|
||||
|
||||
val certService: NetworkRegistrationService = mock {
|
||||
on { submitRequest(any()) }.then { id }
|
||||
|
Reference in New Issue
Block a user