Reduce use of X500Name bridges (#1483)

* Change to using strings in CordformContext; X500Name is an external API dependency we're trying to avoid, X500Principal rearranges the order of the elements in a way we don't want, and trying to put CordaX500Name into Groovy in the time available is impractical. As such having pre-formatted strings used in the Cordform plugin makes most sense right now.
* Remove uses of CordaX500Name.x500
* Remove old X.500 parsing tools
* Move CordaX500Name.x500 into X500NameUtils
* Move X500NameUtils into internal
This commit is contained in:
Ross Nicoll
2017-09-14 11:56:14 +01:00
committed by GitHub
parent 8f0c0c784b
commit ae2183c8a1
35 changed files with 229 additions and 158 deletions

View File

@ -1,9 +1,7 @@
package net.corda.services.messaging
import net.corda.core.crypto.Crypto
import net.corda.core.internal.copyTo
import net.corda.core.internal.createDirectories
import net.corda.core.internal.exists
import net.corda.core.internal.*
import net.corda.node.utilities.*
import net.corda.nodeapi.ArtemisMessagingComponent.Companion.NODE_USER
import net.corda.nodeapi.ArtemisMessagingComponent.Companion.PEER_USER
@ -20,6 +18,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.X509CertificateHolder
import org.junit.Test
import java.nio.file.Files
@ -98,7 +97,7 @@ class MQSecurityAsNodeTest : MQSecurityTest() {
javaClass.classLoader.getResourceAsStream("net/corda/node/internal/certificates/cordadevcakeys.jks"),
"cordacadevpass")
val rootCACert = caKeyStore.getX509Certificate(X509Utilities.CORDA_ROOT_CA)
val rootCACert = caKeyStore.getX509Certificate(X509Utilities.CORDA_ROOT_CA).toX509CertHolder()
val intermediateCA = caKeyStore.getCertificateAndKeyPair(X509Utilities.CORDA_INTERMEDIATE_CA, "cordacadevkeypass")
val clientKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)

View File

@ -64,7 +64,7 @@ class P2PMessagingTest : NodeBasedTest() {
@Test
fun `communicating with a distributed service which the network map node is part of`() {
ServiceIdentityGenerator.generateToDisk(
listOf(DUMMY_MAP.name, SERVICE_2_NAME).map { baseDirectory(it.x500Name) },
listOf(DUMMY_MAP.name, SERVICE_2_NAME).map { baseDirectory(it) },
RaftValidatingNotaryService.type.id,
DISTRIBUTED_SERVICE_NAME)

View File

@ -30,7 +30,8 @@ class P2PSecurityTest : NodeBasedTest() {
@Test
fun `incorrect legal name for the network map service config`() {
val incorrectNetworkMapName = getX500Name(O = "NetworkMap-${random63BitValue()}", L = "London", C = "GB")
val incorrectNetworkMapName = CordaX500Name(organisation = "NetworkMap-${random63BitValue()}",
locality = "London", country = "GB")
val node = startNode(BOB.name, configOverrides = mapOf(
"networkMapService" to mapOf(
"address" to networkMapNode.internals.configuration.p2pAddress.toString(),
@ -57,7 +58,7 @@ class P2PSecurityTest : NodeBasedTest() {
private fun startSimpleNode(legalName: CordaX500Name,
trustRoot: X509Certificate): SimpleNode {
val config = testNodeConfiguration(
baseDirectory = baseDirectory(legalName.x500Name),
baseDirectory = baseDirectory(legalName),
myLegalName = legalName).also {
whenever(it.networkMapService).thenReturn(NetworkMapInfo(networkMapNode.internals.configuration.p2pAddress, networkMapNode.info.legalIdentity.name))
}

View File

@ -153,7 +153,7 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
protected val myLegalName: CordaX500Name by lazy {
val cert = loadKeyStore(configuration.nodeKeystore, configuration.keyStorePassword).getX509Certificate(X509Utilities.CORDA_CLIENT_CA)
CordaX500Name.build(cert.subject).copy(commonName = null)
CordaX500Name.build(cert.subjectX500Principal).copy(commonName = null)
}
open val pluginRegistries: List<CordaPluginRegistry> by lazy {
@ -631,7 +631,11 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
}
}
val subject = CordaX500Name.build(certificates[0].toX509CertHolder().subject)
val nodeCertificate: X509Certificate = if (certificates[0] is X509Certificate)
certificates[0] as X509Certificate
else
throw ConfigurationException("Node certificate must be an X.509 certificate")
val subject: CordaX500Name? = CordaX500Name.build(nodeCertificate.subjectX500Principal)
if (subject != name)
throw ConfigurationException("The name for $id doesn't match what's in the key store: $name vs $subject")
@ -681,7 +685,7 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
val trustStore = KeyStoreWrapper(configuration.trustStoreFile, configuration.trustStorePassword)
val caKeyStore = KeyStoreWrapper(configuration.nodeKeystore, configuration.keyStorePassword)
makeIdentityService(
trustStore.getX509Certificate(X509Utilities.CORDA_ROOT_CA).cert,
trustStore.getX509Certificate(X509Utilities.CORDA_ROOT_CA),
caKeyStore.certificateAndKeyPair(X509Utilities.CORDA_CLIENT_CA),
info.legalIdentityAndCert)
}

View File

@ -7,10 +7,7 @@ import com.typesafe.config.ConfigRenderOptions
import net.corda.core.crypto.Crypto
import net.corda.core.crypto.SignatureScheme
import net.corda.core.identity.CordaX500Name
import net.corda.core.internal.copyTo
import net.corda.core.internal.createDirectories
import net.corda.core.internal.div
import net.corda.core.internal.exists
import net.corda.core.internal.*
import net.corda.core.utilities.loggerFor
import net.corda.node.utilities.*
import net.corda.nodeapi.config.SSLConfiguration
@ -82,7 +79,7 @@ fun createKeystoreForCordaNode(sslKeyStorePath: Path,
legalName: CordaX500Name,
signatureScheme: SignatureScheme = X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME) {
val rootCACert = caKeyStore.getX509Certificate(X509Utilities.CORDA_ROOT_CA)
val rootCACert = caKeyStore.getX509Certificate(X509Utilities.CORDA_ROOT_CA).toX509CertHolder()
val (intermediateCACert, intermediateCAKeyPair) = caKeyStore.getCertificateAndKeyPair(X509Utilities.CORDA_INTERMEDIATE_CA, caKeyPassword)
val clientKey = Crypto.generateKeyPair(signatureScheme)
@ -92,12 +89,12 @@ fun createKeystoreForCordaNode(sslKeyStorePath: Path,
val clientCACert = X509Utilities.createCertificate(CertificateType.INTERMEDIATE_CA,
intermediateCACert,
intermediateCAKeyPair,
clientName.copy(commonName = X509Utilities.CORDA_CLIENT_CA_CN).x500Name,
clientName.copy(commonName = X509Utilities.CORDA_CLIENT_CA_CN),
clientKey.public,
nameConstraints = nameConstraints)
val tlsKey = Crypto.generateKeyPair(signatureScheme)
val clientTLSCert = X509Utilities.createCertificate(CertificateType.TLS, clientCACert, clientKey, clientName.x500Name, tlsKey.public)
val clientTLSCert = X509Utilities.createCertificate(CertificateType.TLS, clientCACert, clientKey, clientName, tlsKey.public)
val keyPass = keyPassword.toCharArray()

View File

@ -106,8 +106,8 @@ class InMemoryIdentityService(identities: Iterable<PartyAndCertificate> = emptyS
val results = LinkedHashSet<Party>()
for ((x500name, partyAndCertificate) in principalToParties) {
val party = partyAndCertificate.party
for (rdn in x500name.x500Name.rdNs) {
val component = rdn.first.value.toString()
val components = listOf(x500name.commonName, x500name.organisationUnit, x500name.organisation, x500name.locality, x500name.state, x500name.country).filterNotNull()
components.forEach { component ->
if (exactMatch && component == query) {
results += party
} else if (!exactMatch) {

View File

@ -164,8 +164,8 @@ class PersistentIdentityService(identities: Iterable<PartyAndCertificate> = empt
val results = LinkedHashSet<Party>()
for ((x500name, partyId) in principalToParties.allPersisted()) {
val party = keyToParties[partyId]!!.party
for (rdn in x500name.x500Name.rdNs) {
val component = rdn.first.value.toString()
val components = listOf(x500name.commonName, x500name.organisationUnit, x500name.organisation, x500name.locality, x500name.state, x500name.country).filterNotNull()
components.forEach { component ->
if (exactMatch && component == query) {
results += party
} else if (!exactMatch) {

View File

@ -35,7 +35,7 @@ fun freshCertificate(identityService: IdentityService,
val issuerCertificate = issuer.certificate
val window = X509Utilities.getCertificateValidityWindow(Duration.ZERO, 3650.days, issuerCertificate)
val ourCertificate = X509Utilities.createCertificate(CertificateType.IDENTITY, issuerCertificate.subject,
issuerSigner, issuer.name.x500Name, subjectPublicKey, window)
issuerSigner, issuer.name, subjectPublicKey, window)
val certFactory = CertificateFactory.getInstance("X509")
val ourCertPath = certFactory.generateCertPath(listOf(ourCertificate.cert) + issuer.certPath.certificates)
val anonymisedIdentity = PartyAndCertificate(ourCertPath)

View File

@ -11,7 +11,6 @@ import net.corda.core.internal.ThreadBox
import net.corda.core.internal.concurrent.openFuture
import net.corda.core.internal.div
import net.corda.core.internal.noneOrSingle
import net.corda.core.internal.toX509CertHolder
import net.corda.core.node.NodeInfo
import net.corda.core.node.services.NetworkMapCache
import net.corda.core.node.services.NetworkMapCache.MapChange
@ -57,6 +56,7 @@ import java.math.BigInteger
import java.security.KeyStore
import java.security.KeyStoreException
import java.security.Principal
import java.security.cert.X509Certificate
import java.util.*
import java.util.concurrent.Executor
import java.util.concurrent.ScheduledExecutorService
@ -71,8 +71,8 @@ import javax.security.auth.login.AppConfigurationEntry.LoginModuleControlFlag.RE
import javax.security.auth.login.FailedLoginException
import javax.security.auth.login.LoginException
import javax.security.auth.spi.LoginModule
import javax.security.auth.x500.X500Principal
import javax.security.cert.CertificateException
import javax.security.cert.X509Certificate
// TODO: Verify that nobody can connect to us and fiddle with our config over the socket due to the secman.
// TODO: Implement a discovery engine that can trigger builds of new connections when another node registers? (later)
@ -506,13 +506,12 @@ private class VerifyingNettyConnector(configuration: MutableMap<String, Any>,
"misconfiguration by the remote peer or an SSL man-in-the-middle attack!"
}
// Make sure certificate has the same name.
val peerCertificate = session.peerCertificateChain[0].toX509CertHolder()
val peerCertificateName = CordaX500Name.build(peerCertificate.subject)
val peerCertificateName = CordaX500Name.build(X500Principal(session.peerCertificateChain[0].subjectDN.name))
require(peerCertificateName == expectedLegalName) {
"Peer has wrong subject name in the certificate - expected $expectedLegalName but got $peerCertificateName. This is either a fatal " +
"misconfiguration by the remote peer or an SSL man-in-the-middle attack!"
}
X509Utilities.validateCertificateChain(session.localCertificates.last().toX509CertHolder(), *session.peerCertificates)
X509Utilities.validateCertificateChain(session.localCertificates.last() as java.security.cert.X509Certificate, *session.peerCertificates)
server.onTcpConnection(peerLegalName)
} catch (e: IllegalArgumentException) {
connection.close()
@ -528,7 +527,7 @@ sealed class CertificateChainCheckPolicy {
@FunctionalInterface
interface Check {
fun checkCertificateChain(theirChain: Array<X509Certificate>)
fun checkCertificateChain(theirChain: Array<javax.security.cert.X509Certificate>)
}
abstract fun createCheck(keyStore: KeyStore, trustStore: KeyStore): Check
@ -536,7 +535,7 @@ sealed class CertificateChainCheckPolicy {
object Any : CertificateChainCheckPolicy() {
override fun createCheck(keyStore: KeyStore, trustStore: KeyStore): Check {
return object : Check {
override fun checkCertificateChain(theirChain: Array<X509Certificate>) {
override fun checkCertificateChain(theirChain: Array<javax.security.cert.X509Certificate>) {
}
}
}
@ -546,7 +545,7 @@ sealed class CertificateChainCheckPolicy {
override fun createCheck(keyStore: KeyStore, trustStore: KeyStore): Check {
val rootPublicKey = trustStore.getCertificate(CORDA_ROOT_CA).publicKey
return object : Check {
override fun checkCertificateChain(theirChain: Array<X509Certificate>) {
override fun checkCertificateChain(theirChain: Array<javax.security.cert.X509Certificate>) {
val theirRoot = theirChain.last().publicKey
if (rootPublicKey != theirRoot) {
throw CertificateException("Root certificate mismatch, their root = $theirRoot")
@ -560,7 +559,7 @@ sealed class CertificateChainCheckPolicy {
override fun createCheck(keyStore: KeyStore, trustStore: KeyStore): Check {
val ourPublicKey = keyStore.getCertificate(CORDA_CLIENT_TLS).publicKey
return object : Check {
override fun checkCertificateChain(theirChain: Array<X509Certificate>) {
override fun checkCertificateChain(theirChain: Array<javax.security.cert.X509Certificate>) {
val theirLeaf = theirChain.first().publicKey
if (ourPublicKey != theirLeaf) {
throw CertificateException("Leaf certificate mismatch, their leaf = $theirLeaf")
@ -574,7 +573,7 @@ sealed class CertificateChainCheckPolicy {
override fun createCheck(keyStore: KeyStore, trustStore: KeyStore): Check {
val trustedPublicKeys = trustedAliases.map { trustStore.getCertificate(it).publicKey }.toSet()
return object : Check {
override fun checkCertificateChain(theirChain: Array<X509Certificate>) {
override fun checkCertificateChain(theirChain: Array<javax.security.cert.X509Certificate>) {
if (!theirChain.any { it.publicKey in trustedPublicKeys }) {
throw CertificateException("Their certificate chain contained none of the trusted ones")
}
@ -664,19 +663,19 @@ class NodeLoginModule : LoginModule {
}
}
private fun authenticateNode(certificates: Array<X509Certificate>): String {
private fun authenticateNode(certificates: Array<javax.security.cert.X509Certificate>): String {
nodeCertCheck.checkCertificateChain(certificates)
principals += RolePrincipal(NODE_ROLE)
return certificates.first().subjectDN.name
}
private fun authenticateVerifier(certificates: Array<X509Certificate>): String {
private fun authenticateVerifier(certificates: Array<javax.security.cert.X509Certificate>): String {
verifierCertCheck.checkCertificateChain(certificates)
principals += RolePrincipal(VERIFIER_ROLE)
return certificates.first().subjectDN.name
}
private fun authenticatePeer(certificates: Array<X509Certificate>): String {
private fun authenticatePeer(certificates: Array<javax.security.cert.X509Certificate>): String {
peerCertCheck.checkCertificateChain(certificates)
principals += RolePrincipal(PEER_ROLE)
return certificates.first().subjectDN.name
@ -694,7 +693,7 @@ class NodeLoginModule : LoginModule {
return username
}
private fun determineUserRole(certificates: Array<X509Certificate>?, username: String): String? {
private fun determineUserRole(certificates: Array<javax.security.cert.X509Certificate>?, username: String): String? {
fun requireTls() = require(certificates != null) { "No TLS?" }
return when (username) {
PEER_USER -> {

View File

@ -48,6 +48,7 @@ import javax.persistence.Column
import javax.persistence.Entity
import javax.persistence.Id
import javax.persistence.Lob
import javax.security.auth.x500.X500Principal
// TODO: Stop the wallet explorer and other clients from using this class and get rid of persistentInbox
@ -247,8 +248,8 @@ class NodeMessagingClient(override val config: NodeConfiguration,
}
}, {})
val myLegalName = loadKeyStore(config.sslKeystore, config.keyStorePassword).getX509Certificate(X509Utilities.CORDA_CLIENT_TLS).subject
rpcServer = RPCServer(rpcOps, NODE_USER, NODE_USER, locator, userService, CordaX500Name.build(myLegalName))
val myCert = loadKeyStore(config.sslKeystore, config.keyStorePassword).getX509Certificate(X509Utilities.CORDA_CLIENT_TLS)
rpcServer = RPCServer(rpcOps, NODE_USER, NODE_USER, locator, userService, CordaX500Name.build(myCert.subjectX500Principal))
fun checkVerifierCount() {
if (session.queueQuery(SimpleString(VERIFICATION_REQUESTS_QUEUE_NAME)).consumerCount == 0) {

View File

@ -16,6 +16,7 @@ import java.security.*
import java.security.cert.CertPath
import java.security.cert.Certificate
import java.security.cert.CertificateFactory
import java.security.cert.X509Certificate
val KEYSTORE_TYPE = "JKS"
@ -136,7 +137,7 @@ fun KeyStore.getKeyPair(alias: String, keyPassword: String): KeyPair = getCertif
* @param keyPassword The password for the PrivateKey (not the store access password).
*/
fun KeyStore.getCertificateAndKeyPair(alias: String, keyPassword: String): CertificateAndKeyPair {
val cert = getX509Certificate(alias)
val cert = getX509Certificate(alias).toX509CertHolder()
val publicKey = Crypto.toSupportedPublicKey(cert.subjectPublicKeyInfo)
return CertificateAndKeyPair(cert, KeyPair(publicKey, getSupportedKey(alias, keyPassword)))
}
@ -146,9 +147,9 @@ fun KeyStore.getCertificateAndKeyPair(alias: String, keyPassword: String): Certi
* @param alias The name to lookup the Key and Certificate chain from.
* @return The X509Certificate found in the KeyStore under the specified alias.
*/
fun KeyStore.getX509Certificate(alias: String): X509CertificateHolder {
val certificate = getCertificate(alias) ?: throw IllegalArgumentException("No certificate under alias \"$alias\"")
return certificate.toX509CertHolder()
fun KeyStore.getX509Certificate(alias: String): X509Certificate {
val certificate = getCertificate(alias) ?: throw IllegalArgumentException("No certificate under alias \"$alias\".")
return certificate as? X509Certificate ?: throw IllegalArgumentException("Certificate under alias \"$alias\" is not an X.509 certificate.")
}
/**
@ -179,7 +180,7 @@ class KeyStoreWrapper(private val storePath: Path, private val storePassword: St
// Assume key password = store password.
val clientCA = certificateAndKeyPair(X509Utilities.CORDA_CLIENT_CA)
// Create new keys and store in keystore.
val cert = X509Utilities.createCertificate(CertificateType.IDENTITY, clientCA.certificate, clientCA.keyPair, serviceName.x500Name, pubKey)
val cert = X509Utilities.createCertificate(CertificateType.IDENTITY, clientCA.certificate, clientCA.keyPair, serviceName, pubKey)
val certPath = CertificateFactory.getInstance("X509").generateCertPath(listOf(cert.cert) + clientCertPath)
require(certPath.certificates.isNotEmpty()) { "Certificate path cannot be empty" }
// TODO: X509Utilities.validateCertificateChain()

View File

@ -4,6 +4,7 @@ import net.corda.core.crypto.Crypto
import net.corda.core.crypto.SignatureScheme
import net.corda.core.crypto.random63BitValue
import net.corda.core.identity.CordaX500Name
import net.corda.core.internal.x500Name
import net.corda.core.utilities.cert
import net.corda.core.utilities.days
import net.corda.core.utilities.millis
@ -89,37 +90,43 @@ object X509Utilities {
* Create a de novo root self-signed X509 v3 CA cert.
*/
@JvmStatic
fun createSelfSignedCACertificate(subject: X500Name, keyPair: KeyPair, validityWindow: Pair<Duration, Duration> = DEFAULT_VALIDITY_WINDOW): X509CertificateHolder {
fun createSelfSignedCACertificate(subject: CordaX500Name, keyPair: KeyPair, validityWindow: Pair<Duration, Duration> = DEFAULT_VALIDITY_WINDOW): X509CertificateHolder {
val window = getCertificateValidityWindow(validityWindow.first, validityWindow.second)
return createCertificate(CertificateType.ROOT_CA, subject, keyPair, subject, keyPair.public, window)
return createCertificate(CertificateType.ROOT_CA, subject.x500Name, keyPair, subject.x500Name, keyPair.public, window)
}
/**
* Create a X509 v3 cert.
* Create a X509 v3 certificate for use as a CA or for TLS. This does not require a [CordaX500Name] because the
* constraints are inappropriate for TLS/CA usage, however as a result this is unsuitable for Corda identity
* certificate generation.
*
* @param issuerCertificate The Public certificate of the root CA above this used to sign it.
* @param issuerKeyPair The KeyPair of the root CA above this used to sign it.
* @param subject subject of the generated certificate.
* @param subjectPublicKey subject 's public key.
* @param subjectPublicKey subject's public key.
* @param validityWindow The certificate's validity window. Default to [DEFAULT_VALIDITY_WINDOW] if not provided.
* @return A data class is returned containing the new intermediate CA Cert and its KeyPair for signing downstream certificates.
* Note the generated certificate tree is capped at max depth of 1 below this to be in line with commercially available certificates.
*/
@JvmStatic
fun createCertificate(certificateType: CertificateType,
issuerCertificate: X509CertificateHolder, issuerKeyPair: KeyPair,
subject: CordaX500Name, subjectPublicKey: PublicKey,
issuerCertificate: X509CertificateHolder,
issuerKeyPair: KeyPair,
subject: CordaX500Name,
subjectPublicKey: PublicKey,
validityWindow: Pair<Duration, Duration> = DEFAULT_VALIDITY_WINDOW,
nameConstraints: NameConstraints? = null): X509CertificateHolder {
val window = getCertificateValidityWindow(validityWindow.first, validityWindow.second, issuerCertificate)
return createCertificate(certificateType, issuerCertificate.subject, issuerKeyPair, subject.x500Name, subjectPublicKey, window, nameConstraints)
}
nameConstraints: NameConstraints? = null): X509CertificateHolder
= createCertificate(certificateType, issuerCertificate, issuerKeyPair, subject.x500Name, subjectPublicKey, validityWindow, nameConstraints)
/**
* Create a X509 v3 cert.
* Create a X509 v3 certificate for use as a CA or for TLS. This does not require a [CordaX500Name] because the
* constraints are inappropriate for TLS/CA usage, however as a result this is unsuitable for Corda identity
* certificate generation.
*
* @param issuerCertificate The Public certificate of the root CA above this used to sign it.
* @param issuerKeyPair The KeyPair of the root CA above this used to sign it.
* @param subject subject of the generated certificate.
* @param subjectPublicKey subject 's public key.
* @param subjectPublicKey subject's public key.
* @param validityWindow The certificate's validity window. Default to [DEFAULT_VALIDITY_WINDOW] if not provided.
* @return A data class is returned containing the new intermediate CA Cert and its KeyPair for signing downstream certificates.
* Note the generated certificate tree is capped at max depth of 1 below this to be in line with commercially available certificates.
@ -137,10 +144,10 @@ object X509Utilities {
}
@Throws(CertPathValidatorException::class)
fun validateCertificateChain(trustedRoot: X509CertificateHolder, vararg certificates: Certificate) {
fun validateCertificateChain(trustedRoot: X509Certificate, vararg certificates: Certificate) {
require(certificates.isNotEmpty()) { "Certificate path must contain at least one certificate" }
val certFactory = CertificateFactory.getInstance("X509")
val params = PKIXParameters(setOf(TrustAnchor(trustedRoot.cert, null)))
val params = PKIXParameters(setOf(TrustAnchor(trustedRoot, null)))
params.isRevocationEnabled = false
val certPath = certFactory.generateCertPath(certificates.toList())
val pathValidator = CertPathValidator.getInstance("PKIX")
@ -185,16 +192,37 @@ object X509Utilities {
* @param validityWindow the time period the certificate is valid for.
* @param nameConstraints any name constraints to impose on certificates signed by the generated certificate.
*/
fun createCertificate(certificateType: CertificateType, issuer: X500Name,
subject: X500Name, subjectPublicKey: PublicKey,
fun createCertificate(certificateType: CertificateType,
issuer: CordaX500Name,
subject: CordaX500Name,
subjectPublicKey: PublicKey,
validityWindow: Pair<Date, Date>,
nameConstraints: NameConstraints? = null): X509v3CertificateBuilder {
return createCertificate(certificateType, issuer.x500Name, subject.x500Name, subjectPublicKey, validityWindow, nameConstraints)
}
/**
* Build a partial X.509 certificate ready for signing.
*
* @param issuer name of the issuing entity.
* @param subject name of the certificate subject.
* @param subjectPublicKey public key of the certificate subject.
* @param validityWindow the time period the certificate is valid for.
* @param nameConstraints any name constraints to impose on certificates signed by the generated certificate.
*/
internal fun createCertificate(certificateType: CertificateType,
issuer: X500Name,
subject: X500Name,
subjectPublicKey: PublicKey,
validityWindow: Pair<Date, Date>,
nameConstraints: NameConstraints? = null): X509v3CertificateBuilder {
val serial = BigInteger.valueOf(random63BitValue())
val keyPurposes = DERSequence(ASN1EncodableVector().apply { certificateType.purposes.forEach { add(it) } })
val subjectPublicKeyInfo = SubjectPublicKeyInfo.getInstance(ASN1Sequence.getInstance(subjectPublicKey.encoded))
val builder = JcaX509v3CertificateBuilder(issuer, serial, validityWindow.first, validityWindow.second, subject, subjectPublicKey)
val builder = JcaX509v3CertificateBuilder(issuer, serial, validityWindow.first, validityWindow.second,
subject, subjectPublicKey)
.addExtension(Extension.subjectKeyIdentifier, false, BcX509ExtensionUtils().createSubjectKeyIdentifier(subjectPublicKeyInfo))
.addExtension(Extension.basicConstraints, certificateType.isCA, BasicConstraints(certificateType.isCA))
.addExtension(Extension.keyUsage, false, certificateType.keyUsage)
@ -216,11 +244,13 @@ object X509Utilities {
* @param validityWindow the time period the certificate is valid for.
* @param nameConstraints any name constraints to impose on certificates signed by the generated certificate.
*/
fun createCertificate(certificateType: CertificateType, issuer: X500Name, issuerSigner: ContentSigner,
subject: X500Name, subjectPublicKey: PublicKey,
validityWindow: Pair<Date, Date>,
nameConstraints: NameConstraints? = null): X509CertificateHolder {
val builder = createCertificate(certificateType, issuer, subject, subjectPublicKey, validityWindow, nameConstraints)
internal fun createCertificate(certificateType: CertificateType,
issuer: X500Name,
issuerSigner: ContentSigner,
subject: CordaX500Name, subjectPublicKey: PublicKey,
validityWindow: Pair<Date, Date>,
nameConstraints: NameConstraints? = null): X509CertificateHolder {
val builder = createCertificate(certificateType, issuer, subject.x500Name, subjectPublicKey, validityWindow, nameConstraints)
return builder.build(issuerSigner).apply {
require(isValidOn(Date()))
}
@ -236,7 +266,7 @@ object X509Utilities {
* @param validityWindow the time period the certificate is valid for.
* @param nameConstraints any name constraints to impose on certificates signed by the generated certificate.
*/
fun createCertificate(certificateType: CertificateType, issuer: X500Name, issuerKeyPair: KeyPair,
internal fun createCertificate(certificateType: CertificateType, issuer: X500Name, issuerKeyPair: KeyPair,
subject: X500Name, subjectPublicKey: PublicKey,
validityWindow: Pair<Date, Date>,
nameConstraints: NameConstraints? = null): X509CertificateHolder {
@ -255,12 +285,12 @@ object X509Utilities {
/**
* Create certificate signing request using provided information.
*/
fun createCertificateSigningRequest(subject: X500Name, email: String, keyPair: KeyPair, signatureScheme: SignatureScheme): PKCS10CertificationRequest {
internal fun createCertificateSigningRequest(subject: CordaX500Name, email: String, keyPair: KeyPair, signatureScheme: SignatureScheme): PKCS10CertificationRequest {
val signer = ContentSignerBuilder.build(signatureScheme, keyPair.private, Crypto.findProvider(signatureScheme.providerName))
return JcaPKCS10CertificationRequestBuilder(subject, keyPair.public).addAttribute(BCStyle.E, DERUTF8String(email)).build(signer)
return JcaPKCS10CertificationRequestBuilder(subject.x500Name, keyPair.public).addAttribute(BCStyle.E, DERUTF8String(email)).build(signer)
}
fun createCertificateSigningRequest(subject: X500Name, email: String, keyPair: KeyPair) = createCertificateSigningRequest(subject, email, keyPair, DEFAULT_TLS_SIGNATURE_SCHEME)
fun createCertificateSigningRequest(subject: CordaX500Name, email: String, keyPair: KeyPair) = createCertificateSigningRequest(subject, email, keyPair, DEFAULT_TLS_SIGNATURE_SCHEME)
}

View File

@ -1,8 +1,8 @@
package net.corda.node.utilities.registration
import net.corda.core.crypto.Crypto
import net.corda.core.utilities.cert
import net.corda.core.internal.*
import net.corda.core.utilities.cert
import net.corda.core.utilities.seconds
import net.corda.node.services.config.NodeConfiguration
import net.corda.node.utilities.*
@ -51,7 +51,7 @@ class NetworkRegistrationHelper(private val config: NodeConfiguration, private v
// We use the self sign certificate to store the key temporarily in the keystore while waiting for the request approval.
if (!caKeyStore.containsAlias(SELF_SIGNED_PRIVATE_KEY)) {
val keyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
val selfSignCert = X509Utilities.createSelfSignedCACertificate(config.myLegalName.x500Name, keyPair)
val selfSignCert = X509Utilities.createSelfSignedCACertificate(config.myLegalName, keyPair)
// Save to the key store.
caKeyStore.addOrReplaceKey(SELF_SIGNED_PRIVATE_KEY, keyPair.private, privateKeyPassword.toCharArray(),
arrayOf(selfSignCert))
@ -84,7 +84,7 @@ class NetworkRegistrationHelper(private val config: NodeConfiguration, private v
println("Generating SSL certificate for node messaging service.")
val sslKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
val caCert = caKeyStore.getX509Certificate(CORDA_CLIENT_CA)
val caCert = caKeyStore.getX509Certificate(CORDA_CLIENT_CA).toX509CertHolder()
val sslCert = X509Utilities.createCertificate(CertificateType.TLS, caCert, keyPair, caCert.subject, sslKey.public)
val sslKeyStore = loadOrCreateKeyStore(config.sslKeystore, keystorePassword)
sslKeyStore.addOrReplaceKey(CORDA_CLIENT_TLS, sslKey.private, privateKeyPassword.toCharArray(),
@ -124,7 +124,7 @@ class NetworkRegistrationHelper(private val config: NodeConfiguration, private v
private fun submitOrResumeCertificateSigningRequest(keyPair: KeyPair): String {
// Retrieve request id from file if exists, else post a request to server.
return if (!requestIdStore.exists()) {
val request = X509Utilities.createCertificateSigningRequest(config.myLegalName.x500Name, config.emailAddress, keyPair)
val request = X509Utilities.createCertificateSigningRequest(config.myLegalName, config.emailAddress, keyPair)
val writer = StringWriter()
JcaPEMWriter(writer).use {
it.writeObject(PemObject("CERTIFICATE REQUEST", request.encoded))

View File

@ -7,14 +7,15 @@ import net.corda.core.identity.CordaX500Name
import net.corda.core.identity.Party
import net.corda.core.identity.PartyAndCertificate
import net.corda.core.node.services.UnknownAnonymousPartyException
import net.corda.node.utilities.CertificateAndKeyPair
import net.corda.core.utilities.cert
import net.corda.node.services.identity.InMemoryIdentityService
import net.corda.node.utilities.CertificateAndKeyPair
import net.corda.node.utilities.CertificateType
import net.corda.node.utilities.X509Utilities
import net.corda.testing.*
import org.junit.Test
import java.security.cert.CertificateFactory
import javax.security.auth.x500.X500Principal
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
import kotlin.test.assertNull
@ -86,7 +87,7 @@ class InMemoryIdentityServiceTests {
fun `assert unknown anonymous key is unrecognised`() {
withTestSerialization {
val rootKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
val rootCert = X509Utilities.createSelfSignedCACertificate(ALICE.name.x500Name, rootKey)
val rootCert = X509Utilities.createSelfSignedCACertificate(ALICE.name, rootKey)
val txKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
val service = InMemoryIdentityService(trustRoot = DUMMY_CA.certificate)
// TODO: Generate certificate with an EdDSA key rather than ECDSA
@ -151,7 +152,7 @@ class InMemoryIdentityServiceTests {
assertFailsWith<IllegalArgumentException> {
val owningKey = Crypto.decodePublicKey(trustRoot.certificate.subjectPublicKeyInfo.encoded)
val subject = CordaX500Name.build(trustRoot.certificate.subject)
val subject = CordaX500Name.build(X500Principal(trustRoot.certificate.subject.encoded))
service.assertOwnership(Party(subject, owningKey), anonymousAlice.party.anonymise())
}
}
@ -162,7 +163,7 @@ class InMemoryIdentityServiceTests {
val issuerKeyPair = generateKeyPair()
val issuer = getTestPartyAndCertificate(x500Name, issuerKeyPair.public, ca)
val txKey = Crypto.generateKeyPair()
val txCert = X509Utilities.createCertificate(CertificateType.IDENTITY, issuer.certificate, issuerKeyPair, x500Name.x500Name, txKey.public)
val txCert = X509Utilities.createCertificate(CertificateType.IDENTITY, issuer.certificate, issuerKeyPair, x500Name, txKey.public)
val txCertPath = certFactory.generateCertPath(listOf(txCert.cert) + issuer.certPath.certificates)
return Pair(issuer, PartyAndCertificate(txCertPath))
}

View File

@ -8,9 +8,9 @@ import net.corda.core.identity.Party
import net.corda.core.identity.PartyAndCertificate
import net.corda.core.node.services.IdentityService
import net.corda.core.node.services.UnknownAnonymousPartyException
import net.corda.node.utilities.CertificateAndKeyPair
import net.corda.core.utilities.cert
import net.corda.node.services.identity.PersistentIdentityService
import net.corda.node.utilities.CertificateAndKeyPair
import net.corda.node.utilities.CertificateType
import net.corda.node.utilities.CordaPersistence
import net.corda.node.utilities.X509Utilities
@ -20,6 +20,7 @@ import org.junit.After
import org.junit.Before
import org.junit.Test
import java.security.cert.CertificateFactory
import javax.security.auth.x500.X500Principal
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
import kotlin.test.assertNull
@ -131,7 +132,7 @@ class PersistentIdentityServiceTests {
fun `assert unknown anonymous key is unrecognised`() {
withTestSerialization {
val rootKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
val rootCert = X509Utilities.createSelfSignedCACertificate(ALICE.name.x500Name, rootKey)
val rootCert = X509Utilities.createSelfSignedCACertificate(ALICE.name, rootKey)
val txKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_IDENTITY_SIGNATURE_SCHEME)
val identity = Party(rootCert)
val txIdentity = AnonymousParty(txKey.public)
@ -213,7 +214,7 @@ class PersistentIdentityServiceTests {
assertFailsWith<IllegalArgumentException> {
val owningKey = Crypto.decodePublicKey(trustRoot.certificate.subjectPublicKeyInfo.encoded)
database.transaction {
val subject = CordaX500Name.build(trustRoot.certificate.subject)
val subject = CordaX500Name.build(X500Principal(trustRoot.certificate.subject.encoded))
identityService.assertOwnership(Party(subject, owningKey), anonymousAlice.party.anonymise())
}
}
@ -261,7 +262,7 @@ class PersistentIdentityServiceTests {
val issuerKeyPair = generateKeyPair()
val issuer = getTestPartyAndCertificate(x500Name, issuerKeyPair.public, ca)
val txKey = Crypto.generateKeyPair()
val txCert = X509Utilities.createCertificate(CertificateType.IDENTITY, issuer.certificate, issuerKeyPair, x500Name.x500Name, txKey.public)
val txCert = X509Utilities.createCertificate(CertificateType.IDENTITY, issuer.certificate, issuerKeyPair, x500Name, txKey.public)
val txCertPath = certFactory.generateCertPath(listOf(txCert.cert) + issuer.certPath.certificates)
return Pair(issuer, PartyAndCertificate(txCertPath))
}

View File

@ -3,8 +3,10 @@ package net.corda.node.utilities
import net.corda.core.crypto.Crypto
import net.corda.core.crypto.Crypto.EDDSA_ED25519_SHA512
import net.corda.core.crypto.Crypto.generateKeyPair
import net.corda.core.identity.CordaX500Name
import net.corda.core.internal.div
import net.corda.core.internal.toTypedArray
import net.corda.core.internal.x500Name
import net.corda.core.serialization.SerializationContext
import net.corda.core.serialization.deserialize
import net.corda.core.serialization.serialize
@ -15,7 +17,10 @@ import net.corda.nodeapi.internal.serialization.AllWhitelist
import net.corda.nodeapi.internal.serialization.KryoHeaderV0_1
import net.corda.nodeapi.internal.serialization.SerializationContextImpl
import net.corda.nodeapi.internal.serialization.SerializationFactoryImpl
import net.corda.testing.*
import net.corda.testing.ALICE
import net.corda.testing.BOB
import net.corda.testing.BOB_PUBKEY
import net.corda.testing.MEGA_CORP
import org.bouncycastle.asn1.x500.X500Name
import org.bouncycastle.asn1.x509.BasicConstraints
import org.bouncycastle.asn1.x509.Extension
@ -44,6 +49,7 @@ import javax.net.ssl.*
import kotlin.concurrent.thread
import kotlin.test.*
class X509UtilitiesTest {
@Rule
@JvmField
@ -52,8 +58,8 @@ class X509UtilitiesTest {
@Test
fun `create valid self-signed CA certificate`() {
val caKey = generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
val caCert = X509Utilities.createSelfSignedCACertificate(getX500Name(CN = "Test Cert", O = "R3 Ltd", L = "London", C = "GB"), caKey)
assertEquals(X500Name("CN=Test Cert,O=R3 Ltd,L=London,C=GB"), caCert.subject)
val caCert = X509Utilities.createSelfSignedCACertificate(CordaX500Name(commonName = "Test Cert", organisation = "R3 Ltd", locality = "London", country = "GB"), caKey)
assertEquals(X500Name("CN=Test Cert,O=R3 Ltd,L=London,C=GB"), caCert.subject) // using our subject common name
assertEquals(caCert.issuer, caCert.subject) //self-signed
caCert.isValidOn(Date()) // throws on verification problems
caCert.isSignatureValid(JcaContentVerifierProviderBuilder().build(caKey.public)) // throws on verification problems
@ -67,7 +73,7 @@ class X509UtilitiesTest {
fun `load and save a PEM file certificate`() {
val tmpCertificateFile = tempFile("cacert.pem")
val caKey = generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
val caCert = X509Utilities.createSelfSignedCACertificate(getX500Name(CN = "Test Cert", O = "R3 Ltd", L = "London", C = "GB"), caKey)
val caCert = X509Utilities.createSelfSignedCACertificate(CordaX500Name(commonName = "Test Cert", organisation = "R3 Ltd", locality = "London", country = "GB"), caKey)
X509Utilities.saveCertificateAsPEMFile(caCert, tmpCertificateFile)
val readCertificate = X509Utilities.loadCertificateFromPEMFile(tmpCertificateFile)
assertEquals(caCert, readCertificate)
@ -76,11 +82,11 @@ class X509UtilitiesTest {
@Test
fun `create valid server certificate chain`() {
val caKey = generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
val caCert = X509Utilities.createSelfSignedCACertificate(getX500Name(CN = "Test CA Cert", O = "R3 Ltd", L = "London", C = "GB"), caKey)
val subject = getX500Name(CN = "Server Cert", O = "R3 Ltd", L = "London", C = "GB")
val caCert = X509Utilities.createSelfSignedCACertificate(CordaX500Name(commonName = "Test CA Cert", organisation = "R3 Ltd", locality = "London", country = "GB"), caKey)
val subject = CordaX500Name(commonName = "Server Cert", organisation = "R3 Ltd", locality = "London", country = "GB")
val keyPair = generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
val serverCert = X509Utilities.createCertificate(CertificateType.TLS, caCert, caKey, subject, keyPair.public)
assertTrue { serverCert.subject.toString().contains("CN=Server Cert") } // using our subject common name
assertEquals(X500Name("C=GB,L=London,O=R3 Ltd,CN=Server Cert"), serverCert.subject) // using our subject common name
assertEquals(caCert.issuer, serverCert.issuer) // Issued by our CA cert
serverCert.isValidOn(Date()) // throws on verification problems
serverCert.isSignatureValid(JcaContentVerifierProviderBuilder().build(caKey.public)) // throws on verification problems
@ -95,7 +101,8 @@ class X509UtilitiesTest {
val tmpKeyStore = tempFile("keystore.jks")
val keyPair = generateKeyPair(EDDSA_ED25519_SHA512)
val selfSignCert = X509Utilities.createSelfSignedCACertificate(X500Name("CN=Test"), keyPair)
val testName = CordaX500Name(commonName = "Test", organisation = "R3 Ltd", locality = "London", country = "GB")
val selfSignCert = X509Utilities.createSelfSignedCACertificate(testName, keyPair)
assertTrue(Arrays.equals(selfSignCert.subjectPublicKeyInfo.encoded, keyPair.public.encoded))
@ -120,7 +127,8 @@ class X509UtilitiesTest {
fun `signing EdDSA key with EcDSA certificate`() {
val tmpKeyStore = tempFile("keystore.jks")
val ecDSAKey = generateKeyPair(Crypto.ECDSA_SECP256R1_SHA256)
val ecDSACert = X509Utilities.createSelfSignedCACertificate(X500Name("CN=Test"), ecDSAKey)
val testName = CordaX500Name(commonName = "Test", organisation = "R3 Ltd", locality = "London", country = "GB")
val ecDSACert = X509Utilities.createSelfSignedCACertificate(testName, ecDSAKey)
val edDSAKeypair = generateKeyPair(EDDSA_ED25519_SHA512)
val edDSACert = X509Utilities.createCertificate(CertificateType.TLS, ecDSACert, ecDSAKey, X500Name("CN=TestEdDSA"), edDSAKeypair.public)
@ -311,8 +319,7 @@ class X509UtilitiesTest {
// Double check hostname manually
val peerChain = clientSocket.session.peerCertificates
val peerX500Principal = (peerChain[0] as X509Certificate).subjectX500Principal
val x500name = X500Name(peerX500Principal.name)
assertEquals(MEGA_CORP.name.x500Name, x500name)
assertEquals(MEGA_CORP.name.x500Principal, peerX500Principal)
X509Utilities.validateCertificateChain(trustStore.getX509Certificate(X509Utilities.CORDA_ROOT_CA), *peerChain)
val output = DataOutputStream(clientSocket.outputStream)
output.writeUTF("Hello World")
@ -353,10 +360,10 @@ class X509UtilitiesTest {
trustStorePassword: String
): KeyStore {
val rootCAKey = generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
val rootCACert = X509Utilities.createSelfSignedCACertificate(getX500Name(CN = "Corda Node Root CA", O = "R3CEV", L = "London", C = "GB"), rootCAKey)
val rootCACert = X509Utilities.createSelfSignedCACertificate(CordaX500Name(commonName = "Corda Node Root CA", organisation = "R3CEV", locality = "London", country = "GB"), rootCAKey)
val intermediateCAKeyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
val intermediateCACert = X509Utilities.createCertificate(CertificateType.INTERMEDIATE_CA, rootCACert, rootCAKey, getX500Name(CN = "Corda Node Intermediate CA", O = "R3CEV", L = "London", C = "GB"), intermediateCAKeyPair.public)
val intermediateCACert = X509Utilities.createCertificate(CertificateType.INTERMEDIATE_CA, rootCACert, rootCAKey, CordaX500Name(commonName = "Corda Node Intermediate CA", organisation = "R3CEV", locality = "London", country = "GB"), intermediateCAKeyPair.public)
val keyPass = keyPassword.toCharArray()
val keyStore = loadOrCreateKeyStore(keyStoreFilePath, storePassword)
@ -383,7 +390,8 @@ class X509UtilitiesTest {
@Test
fun `Get correct private key type from Keystore`() {
val keyPair = generateKeyPair(Crypto.ECDSA_SECP256R1_SHA256)
val selfSignCert = X509Utilities.createSelfSignedCACertificate(X500Name("CN=Test"), keyPair)
val testName = CordaX500Name(commonName = "Test", organisation = "R3 Ltd", locality = "London", country = "GB")
val selfSignCert = X509Utilities.createSelfSignedCACertificate(testName, keyPair)
val keyStore = loadOrCreateKeyStore(tempFile("testKeystore.jks"), "keystorepassword")
keyStore.setKeyEntry("Key", keyPair.private, "keypassword".toCharArray(), arrayOf(selfSignCert.cert))
@ -403,7 +411,7 @@ class X509UtilitiesTest {
emptyMap(),
true,
SerializationContext.UseCase.P2P)
val expected: X509CertificateHolder = X509Utilities.createSelfSignedCACertificate(ALICE.name.x500Name, Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME))
val expected: X509CertificateHolder = X509Utilities.createSelfSignedCACertificate(ALICE.name, Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME))
val serialized = expected.serialize(factory, context).bytes
val actual: X509CertificateHolder = serialized.deserialize(factory, context)
assertEquals(expected, actual)
@ -420,7 +428,7 @@ class X509UtilitiesTest {
SerializationContext.UseCase.P2P)
val certFactory = CertificateFactory.getInstance("X509")
val rootCAKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
val rootCACert = X509Utilities.createSelfSignedCACertificate(ALICE.name.x500Name, rootCAKey)
val rootCACert = X509Utilities.createSelfSignedCACertificate(ALICE.name, rootCAKey)
val certificate = X509Utilities.createCertificate(CertificateType.TLS, rootCACert, rootCAKey, BOB.name.x500Name, BOB_PUBKEY)
val expected = certFactory.generateCertPath(listOf(certificate.cert, rootCACert.cert))
val serialized = expected.serialize(factory, context).bytes

View File

@ -5,16 +5,18 @@ import com.nhaarman.mockito_kotlin.eq
import com.nhaarman.mockito_kotlin.mock
import net.corda.core.crypto.Crypto
import net.corda.core.crypto.SecureHash
import net.corda.core.identity.CordaX500Name
import net.corda.core.internal.exists
import net.corda.core.internal.toTypedArray
import net.corda.core.internal.toX509CertHolder
import net.corda.core.utilities.cert
import net.corda.core.utilities.commonName
import net.corda.node.utilities.X509Utilities
import net.corda.node.utilities.loadKeyStore
import net.corda.testing.ALICE
import net.corda.testing.getX500Name
import net.corda.testing.testNodeConfiguration
import org.bouncycastle.asn1.x500.X500Name
import org.bouncycastle.asn1.x500.style.BCStyle
import org.junit.Rule
import org.junit.Test
import org.junit.rules.TemporaryFolder
@ -22,6 +24,8 @@ import kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertTrue
val X500Name.commonName: String? get() = getRDNs(BCStyle.CN).firstOrNull()?.first?.value?.toString()
class NetworkRegistrationHelperTest {
@Rule
@JvmField
@ -34,7 +38,7 @@ class NetworkRegistrationHelperTest {
val identities = listOf("CORDA_CLIENT_CA",
"CORDA_INTERMEDIATE_CA",
"CORDA_ROOT_CA")
.map { getX500Name(CN = it, O = "R3 Ltd", L = "London", C = "GB") }
.map { CordaX500Name(commonName = it, organisation = "R3 Ltd", locality = "London", country = "GB") }
val certs = identities.stream().map { X509Utilities.createSelfSignedCACertificate(it, Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)) }
.map { it.cert }.toTypedArray()