mirror of
https://github.com/corda/corda.git
synced 2025-05-03 09:12:55 +00:00
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:
parent
8f0c0c784b
commit
ae2183c8a1
@ -7,7 +7,6 @@ import net.corda.core.messaging.CordaRPCOps;
|
|||||||
import net.corda.core.messaging.FlowHandle;
|
import net.corda.core.messaging.FlowHandle;
|
||||||
import net.corda.core.node.NodeInfo;
|
import net.corda.core.node.NodeInfo;
|
||||||
import net.corda.core.utilities.OpaqueBytes;
|
import net.corda.core.utilities.OpaqueBytes;
|
||||||
import net.corda.core.utilities.X500NameUtils;
|
|
||||||
import net.corda.finance.flows.AbstractCashFlow;
|
import net.corda.finance.flows.AbstractCashFlow;
|
||||||
import net.corda.finance.flows.CashIssueFlow;
|
import net.corda.finance.flows.CashIssueFlow;
|
||||||
import net.corda.nodeapi.User;
|
import net.corda.nodeapi.User;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
gradlePluginsVersion=0.16.2
|
gradlePluginsVersion=0.16.3
|
||||||
kotlinVersion=1.1.4
|
kotlinVersion=1.1.4
|
||||||
guavaVersion=21.0
|
guavaVersion=21.0
|
||||||
bouncycastleVersion=1.57
|
bouncycastleVersion=1.57
|
||||||
|
@ -2,13 +2,15 @@ package net.corda.core.identity
|
|||||||
|
|
||||||
import net.corda.core.internal.LegalNameValidator
|
import net.corda.core.internal.LegalNameValidator
|
||||||
import net.corda.core.internal.countryCodes
|
import net.corda.core.internal.countryCodes
|
||||||
|
import net.corda.core.internal.x500Name
|
||||||
import net.corda.core.serialization.CordaSerializable
|
import net.corda.core.serialization.CordaSerializable
|
||||||
import org.bouncycastle.asn1.ASN1Encodable
|
import org.bouncycastle.asn1.ASN1Encodable
|
||||||
import org.bouncycastle.asn1.ASN1ObjectIdentifier
|
import org.bouncycastle.asn1.ASN1ObjectIdentifier
|
||||||
import org.bouncycastle.asn1.x500.AttributeTypeAndValue
|
import org.bouncycastle.asn1.x500.AttributeTypeAndValue
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
import org.bouncycastle.asn1.x500.X500Name
|
||||||
import org.bouncycastle.asn1.x500.X500NameBuilder
|
|
||||||
import org.bouncycastle.asn1.x500.style.BCStyle
|
import org.bouncycastle.asn1.x500.style.BCStyle
|
||||||
|
import java.security.Principal
|
||||||
|
import javax.security.auth.x500.X500Principal
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* X.500 distinguished name data type customised to how Corda uses names. This restricts the attributes to those Corda
|
* X.500 distinguished name data type customised to how Corda uses names. This restricts the attributes to those Corda
|
||||||
@ -56,11 +58,15 @@ data class CordaX500Name(val commonName: String?,
|
|||||||
require(locality.length < MAX_LENGTH_LOCALITY) { "Locality attribute (L) must contain less then $MAX_LENGTH_LOCALITY characters." }
|
require(locality.length < MAX_LENGTH_LOCALITY) { "Locality attribute (L) must contain less then $MAX_LENGTH_LOCALITY characters." }
|
||||||
|
|
||||||
state?.let { require(it.length < MAX_LENGTH_STATE) { "State attribute (ST) must contain less then $MAX_LENGTH_STATE characters." } }
|
state?.let { require(it.length < MAX_LENGTH_STATE) { "State attribute (ST) must contain less then $MAX_LENGTH_STATE characters." } }
|
||||||
organisationUnit?.let { require(it.length < MAX_LENGTH_ORGANISATION_UNIT) {
|
organisationUnit?.let {
|
||||||
"Organisation Unit attribute (OU) must contain less then $MAX_LENGTH_ORGANISATION_UNIT characters." }
|
require(it.length < MAX_LENGTH_ORGANISATION_UNIT) {
|
||||||
|
"Organisation Unit attribute (OU) must contain less then $MAX_LENGTH_ORGANISATION_UNIT characters."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
commonName?.let {
|
||||||
|
require(it.length < MAX_LENGTH_COMMON_NAME) {
|
||||||
|
"Common Name attribute (CN) must contain less then $MAX_LENGTH_COMMON_NAME characters."
|
||||||
}
|
}
|
||||||
commonName?.let { require(it.length < MAX_LENGTH_COMMON_NAME) {
|
|
||||||
"Common Name attribute (CN) must contain less then $MAX_LENGTH_COMMON_NAME characters." }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,7 +80,8 @@ data class CordaX500Name(val commonName: String?,
|
|||||||
private val supportedAttributes = setOf(BCStyle.O, BCStyle.C, BCStyle.L, BCStyle.CN, BCStyle.ST, BCStyle.OU)
|
private val supportedAttributes = setOf(BCStyle.O, BCStyle.C, BCStyle.L, BCStyle.CN, BCStyle.ST, BCStyle.OU)
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun build(x500Name: X500Name) : CordaX500Name {
|
fun build(principal: X500Principal) : CordaX500Name {
|
||||||
|
val x500Name = X500Name.getInstance(principal.encoded)
|
||||||
val attrsMap: Map<ASN1ObjectIdentifier, ASN1Encodable> = x500Name.rdNs
|
val attrsMap: Map<ASN1ObjectIdentifier, ASN1Encodable> = x500Name.rdNs
|
||||||
.flatMap { it.typesAndValues.asList() }
|
.flatMap { it.typesAndValues.asList() }
|
||||||
.groupBy(AttributeTypeAndValue::getType, AttributeTypeAndValue::getValue)
|
.groupBy(AttributeTypeAndValue::getType, AttributeTypeAndValue::getValue)
|
||||||
@ -99,31 +106,26 @@ data class CordaX500Name(val commonName: String?,
|
|||||||
val C = attrsMap[BCStyle.C]?.toString() ?: throw IllegalArgumentException("Corda X.500 names must include an C attribute")
|
val C = attrsMap[BCStyle.C]?.toString() ?: throw IllegalArgumentException("Corda X.500 names must include an C attribute")
|
||||||
return CordaX500Name(CN, OU, O, L, ST, C)
|
return CordaX500Name(CN, OU, O, L, ST, C)
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun parse(name: String) : CordaX500Name = build(X500Name(name))
|
fun parse(name: String) : CordaX500Name = build(X500Principal(name))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transient
|
@Transient
|
||||||
private var x500Cache: X500Name? = null
|
private var x500Cache: X500Name? = null
|
||||||
|
|
||||||
override fun toString(): String = x500Name.toString()
|
val x500Principal: X500Principal
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the underlying X.500 name from this Corda-safe X.500 name. These are guaranteed to have a consistent
|
|
||||||
* ordering, such that their `toString()` function returns the same value every time for the same [CordaX500Name].
|
|
||||||
*/
|
|
||||||
val x500Name: X500Name
|
|
||||||
get() {
|
get() {
|
||||||
if (x500Cache == null) {
|
if (x500Cache == null) {
|
||||||
x500Cache = X500NameBuilder(BCStyle.INSTANCE).apply {
|
x500Cache = this.x500Name
|
||||||
addRDN(BCStyle.C, country)
|
|
||||||
state?.let { addRDN(BCStyle.ST, it) }
|
|
||||||
addRDN(BCStyle.L, locality)
|
|
||||||
addRDN(BCStyle.O, organisation)
|
|
||||||
organisationUnit?.let { addRDN(BCStyle.OU, it) }
|
|
||||||
commonName?.let { addRDN(BCStyle.CN, it) }
|
|
||||||
}.build()
|
|
||||||
}
|
}
|
||||||
return x500Cache!!
|
return X500Principal(x500Cache!!.encoded)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
if (x500Cache == null) {
|
||||||
|
x500Cache = this.x500Name
|
||||||
|
}
|
||||||
|
return x500Cache.toString()
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -6,6 +6,8 @@ import net.corda.core.crypto.Crypto
|
|||||||
import net.corda.core.utilities.OpaqueBytes
|
import net.corda.core.utilities.OpaqueBytes
|
||||||
import org.bouncycastle.cert.X509CertificateHolder
|
import org.bouncycastle.cert.X509CertificateHolder
|
||||||
import java.security.PublicKey
|
import java.security.PublicKey
|
||||||
|
import java.security.cert.X509Certificate
|
||||||
|
import javax.security.auth.x500.X500Principal
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The [Party] class represents an entity on the network, which is typically identified by a legal [name] and public key
|
* The [Party] class represents an entity on the network, which is typically identified by a legal [name] and public key
|
||||||
@ -27,7 +29,8 @@ import java.security.PublicKey
|
|||||||
* @see CompositeKey
|
* @see CompositeKey
|
||||||
*/
|
*/
|
||||||
class Party(val name: CordaX500Name, owningKey: PublicKey) : AbstractParty(owningKey) {
|
class Party(val name: CordaX500Name, owningKey: PublicKey) : AbstractParty(owningKey) {
|
||||||
constructor(certificate: X509CertificateHolder) : this(CordaX500Name.build(certificate.subject), Crypto.toSupportedPublicKey(certificate.subjectPublicKeyInfo))
|
constructor(certificate: X509Certificate) : this(CordaX500Name.build(certificate.subjectX500Principal), Crypto.toSupportedPublicKey(certificate.publicKey))
|
||||||
|
constructor(certificate: X509CertificateHolder) : this(CordaX500Name.build(X500Principal(certificate.subject.encoded)), Crypto.toSupportedPublicKey(certificate.subjectPublicKeyInfo))
|
||||||
override fun nameOrNull(): CordaX500Name = name
|
override fun nameOrNull(): CordaX500Name = name
|
||||||
fun anonymise(): AnonymousParty = AnonymousParty(owningKey)
|
fun anonymise(): AnonymousParty = AnonymousParty(owningKey)
|
||||||
override fun ref(bytes: OpaqueBytes): PartyAndReference = PartyAndReference(this, bytes)
|
override fun ref(bytes: OpaqueBytes): PartyAndReference = PartyAndReference(this, bytes)
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
@file:JvmName("X500NameUtils")
|
@file:JvmName("X500NameUtils")
|
||||||
|
|
||||||
package net.corda.core.utilities
|
package net.corda.core.internal
|
||||||
|
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import org.bouncycastle.asn1.ASN1ObjectIdentifier
|
import org.bouncycastle.asn1.ASN1ObjectIdentifier
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
import org.bouncycastle.asn1.x500.X500Name
|
||||||
|
import org.bouncycastle.asn1.x500.X500NameBuilder
|
||||||
import org.bouncycastle.asn1.x500.style.BCStyle
|
import org.bouncycastle.asn1.x500.style.BCStyle
|
||||||
|
|
||||||
val X500Name.commonName: String? get() = getRDNValueString(BCStyle.CN)
|
val X500Name.commonName: String? get() = getRDNValueString(BCStyle.CN)
|
||||||
@ -13,3 +15,20 @@ val X500Name.locality: String get() = getRDNValueString(BCStyle.L) ?: throw Ille
|
|||||||
val X500Name.country: String get() = getRDNValueString(BCStyle.C) ?: throw IllegalArgumentException("Malformed X500 name, country attribute (C) cannot be empty.")
|
val X500Name.country: String get() = getRDNValueString(BCStyle.C) ?: throw IllegalArgumentException("Malformed X500 name, country attribute (C) cannot be empty.")
|
||||||
|
|
||||||
private fun X500Name.getRDNValueString(identifier: ASN1ObjectIdentifier): String? = getRDNs(identifier).firstOrNull()?.first?.value?.toString()
|
private fun X500Name.getRDNValueString(identifier: ASN1ObjectIdentifier): String? = getRDNs(identifier).firstOrNull()?.first?.value?.toString()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the underlying X.500 name from this Corda-safe X.500 name. These are guaranteed to have a consistent
|
||||||
|
* ordering, such that their `toString()` function returns the same value every time for the same [CordaX500Name].
|
||||||
|
*/
|
||||||
|
val CordaX500Name.x500Name: X500Name
|
||||||
|
get() {
|
||||||
|
return X500NameBuilder(BCStyle.INSTANCE).apply {
|
||||||
|
addRDN(BCStyle.C, country)
|
||||||
|
state?.let { addRDN(BCStyle.ST, it) }
|
||||||
|
addRDN(BCStyle.L, locality)
|
||||||
|
addRDN(BCStyle.O, organisation)
|
||||||
|
organisationUnit?.let { addRDN(BCStyle.OU, it) }
|
||||||
|
commonName?.let { addRDN(BCStyle.CN, it) }
|
||||||
|
}.build()
|
||||||
|
}
|
@ -2,6 +2,7 @@ package net.corda.core.crypto
|
|||||||
|
|
||||||
import net.corda.core.crypto.CompositeKey.NodeAndWeight
|
import net.corda.core.crypto.CompositeKey.NodeAndWeight
|
||||||
import net.corda.core.crypto.composite.CompositeSignaturesWithKeys
|
import net.corda.core.crypto.composite.CompositeSignaturesWithKeys
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.internal.declaredField
|
import net.corda.core.internal.declaredField
|
||||||
import net.corda.core.internal.div
|
import net.corda.core.internal.div
|
||||||
import net.corda.core.serialization.serialize
|
import net.corda.core.serialization.serialize
|
||||||
@ -331,10 +332,11 @@ class CompositeKeyTests : TestDependencyInjectionBase() {
|
|||||||
|
|
||||||
// Create self sign CA.
|
// Create self sign CA.
|
||||||
val caKeyPair = Crypto.generateKeyPair()
|
val caKeyPair = Crypto.generateKeyPair()
|
||||||
val ca = X509Utilities.createSelfSignedCACertificate(getX500Name(CN = "Test CA", O = "R3 Ltd", L = "London", C = "GB"), caKeyPair)
|
val caName = CordaX500Name(commonName = "Test CA", organisation = "R3 Ltd", locality = "London", country = "GB")
|
||||||
|
val ca = X509Utilities.createSelfSignedCACertificate(caName, caKeyPair)
|
||||||
|
|
||||||
// Sign the composite key with the self sign CA.
|
// Sign the composite key with the self sign CA.
|
||||||
val compositeKeyCert = X509Utilities.createCertificate(CertificateType.IDENTITY, ca, caKeyPair, getX500Name(CN = "CompositeKey", O = "R3 Ltd", L = "London", C = "GB"), compositeKey)
|
val compositeKeyCert = X509Utilities.createCertificate(CertificateType.IDENTITY, ca, caKeyPair, caName.copy(commonName = "CompositeKey"), compositeKey)
|
||||||
|
|
||||||
// Store certificate to keystore.
|
// Store certificate to keystore.
|
||||||
val keystorePath = tempFolder.root.toPath() / "keystore.jks"
|
val keystorePath = tempFolder.root.toPath() / "keystore.jks"
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package net.corda.core.crypto
|
package net.corda.core.crypto
|
||||||
|
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.internal.toTypedArray
|
import net.corda.core.internal.toTypedArray
|
||||||
import net.corda.core.utilities.cert
|
import net.corda.core.utilities.cert
|
||||||
import net.corda.node.utilities.*
|
import net.corda.node.utilities.*
|
||||||
@ -20,13 +21,13 @@ class X509NameConstraintsTest {
|
|||||||
|
|
||||||
private fun makeKeyStores(subjectName: X500Name, nameConstraints: NameConstraints): Pair<KeyStore, KeyStore> {
|
private fun makeKeyStores(subjectName: X500Name, nameConstraints: NameConstraints): Pair<KeyStore, KeyStore> {
|
||||||
val rootKeys = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
val rootKeys = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
||||||
val rootCACert = X509Utilities.createSelfSignedCACertificate(getX500Name(CN = "Corda Root CA", O = "R3CEV", L = "London", C = "GB"), rootKeys)
|
val rootCACert = X509Utilities.createSelfSignedCACertificate(CordaX500Name(commonName = "Corda Root CA", organisation = "R3 Ltd", locality= "London", country = "GB"), rootKeys)
|
||||||
|
|
||||||
val intermediateCAKeyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
val intermediateCAKeyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
||||||
val intermediateCACert = X509Utilities.createCertificate(CertificateType.INTERMEDIATE_CA, rootCACert, rootKeys, getX500Name(CN = "Corda Intermediate CA", O = "R3CEV", L = "London", C = "GB"), intermediateCAKeyPair.public)
|
val intermediateCACert = X509Utilities.createCertificate(CertificateType.INTERMEDIATE_CA, rootCACert, rootKeys, CordaX500Name(commonName = "Corda Intermediate CA", organisation = "R3 Ltd", locality = "London", country = "GB"), intermediateCAKeyPair.public)
|
||||||
|
|
||||||
val clientCAKeyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
val clientCAKeyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
||||||
val clientCACert = X509Utilities.createCertificate(CertificateType.INTERMEDIATE_CA, intermediateCACert, intermediateCAKeyPair, getX500Name(CN = "Corda Client CA", O = "R3CEV", L = "London", C = "GB"), clientCAKeyPair.public, nameConstraints = nameConstraints)
|
val clientCACert = X509Utilities.createCertificate(CertificateType.INTERMEDIATE_CA, intermediateCACert, intermediateCAKeyPair, CordaX500Name(commonName = "Corda Client CA", organisation = "R3 Ltd", locality = "London", country = "GB"), clientCAKeyPair.public, nameConstraints = nameConstraints)
|
||||||
|
|
||||||
val keyPass = "password"
|
val keyPass = "password"
|
||||||
val trustStore = KeyStore.getInstance(KEYSTORE_TYPE)
|
val trustStore = KeyStore.getInstance(KEYSTORE_TYPE)
|
||||||
|
@ -4,5 +4,5 @@ import org.bouncycastle.asn1.x500.X500Name;
|
|||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
|
||||||
public interface CordformContext {
|
public interface CordformContext {
|
||||||
Path baseDirectory(X500Name nodeName);
|
Path baseDirectory(String nodeName);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package net.corda.cordform;
|
package net.corda.cordform;
|
||||||
|
|
||||||
import org.bouncycastle.asn1.x500.X500Name;
|
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
@ -8,9 +7,9 @@ import java.util.function.Consumer;
|
|||||||
public abstract class CordformDefinition {
|
public abstract class CordformDefinition {
|
||||||
public final Path driverDirectory;
|
public final Path driverDirectory;
|
||||||
public final ArrayList<Consumer<? super CordformNode>> nodeConfigurers = new ArrayList<>();
|
public final ArrayList<Consumer<? super CordformNode>> nodeConfigurers = new ArrayList<>();
|
||||||
public final X500Name networkMapNodeName;
|
public final String networkMapNodeName;
|
||||||
|
|
||||||
public CordformDefinition(Path driverDirectory, X500Name networkMapNodeName) {
|
public CordformDefinition(Path driverDirectory, String networkMapNodeName) {
|
||||||
this.driverDirectory = driverDirectory;
|
this.driverDirectory = driverDirectory;
|
||||||
this.networkMapNodeName = networkMapNodeName;
|
this.networkMapNodeName = networkMapNodeName;
|
||||||
}
|
}
|
||||||
|
@ -120,8 +120,8 @@ class Cordform extends DefaultTask {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
cd.setup new CordformContext() {
|
cd.setup new CordformContext() {
|
||||||
Path baseDirectory(X500Name nodeName) {
|
Path baseDirectory(String nodeName) {
|
||||||
project.projectDir.toPath().resolve(getNodeByName(nodeName.toString()).nodeDir.toPath())
|
project.projectDir.toPath().resolve(getNodeByName(nodeName).nodeDir.toPath())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
package net.corda.services.messaging
|
package net.corda.services.messaging
|
||||||
|
|
||||||
import net.corda.core.crypto.Crypto
|
import net.corda.core.crypto.Crypto
|
||||||
import net.corda.core.internal.copyTo
|
import net.corda.core.internal.*
|
||||||
import net.corda.core.internal.createDirectories
|
|
||||||
import net.corda.core.internal.exists
|
|
||||||
import net.corda.node.utilities.*
|
import net.corda.node.utilities.*
|
||||||
import net.corda.nodeapi.ArtemisMessagingComponent.Companion.NODE_USER
|
import net.corda.nodeapi.ArtemisMessagingComponent.Companion.NODE_USER
|
||||||
import net.corda.nodeapi.ArtemisMessagingComponent.Companion.PEER_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.GeneralName
|
||||||
import org.bouncycastle.asn1.x509.GeneralSubtree
|
import org.bouncycastle.asn1.x509.GeneralSubtree
|
||||||
import org.bouncycastle.asn1.x509.NameConstraints
|
import org.bouncycastle.asn1.x509.NameConstraints
|
||||||
|
import org.bouncycastle.cert.X509CertificateHolder
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.nio.file.Files
|
import java.nio.file.Files
|
||||||
|
|
||||||
@ -98,7 +97,7 @@ class MQSecurityAsNodeTest : MQSecurityTest() {
|
|||||||
javaClass.classLoader.getResourceAsStream("net/corda/node/internal/certificates/cordadevcakeys.jks"),
|
javaClass.classLoader.getResourceAsStream("net/corda/node/internal/certificates/cordadevcakeys.jks"),
|
||||||
"cordacadevpass")
|
"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 intermediateCA = caKeyStore.getCertificateAndKeyPair(X509Utilities.CORDA_INTERMEDIATE_CA, "cordacadevkeypass")
|
||||||
val clientKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
val clientKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ class P2PMessagingTest : NodeBasedTest() {
|
|||||||
@Test
|
@Test
|
||||||
fun `communicating with a distributed service which the network map node is part of`() {
|
fun `communicating with a distributed service which the network map node is part of`() {
|
||||||
ServiceIdentityGenerator.generateToDisk(
|
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,
|
RaftValidatingNotaryService.type.id,
|
||||||
DISTRIBUTED_SERVICE_NAME)
|
DISTRIBUTED_SERVICE_NAME)
|
||||||
|
|
||||||
|
@ -30,7 +30,8 @@ class P2PSecurityTest : NodeBasedTest() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `incorrect legal name for the network map service config`() {
|
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(
|
val node = startNode(BOB.name, configOverrides = mapOf(
|
||||||
"networkMapService" to mapOf(
|
"networkMapService" to mapOf(
|
||||||
"address" to networkMapNode.internals.configuration.p2pAddress.toString(),
|
"address" to networkMapNode.internals.configuration.p2pAddress.toString(),
|
||||||
@ -57,7 +58,7 @@ class P2PSecurityTest : NodeBasedTest() {
|
|||||||
private fun startSimpleNode(legalName: CordaX500Name,
|
private fun startSimpleNode(legalName: CordaX500Name,
|
||||||
trustRoot: X509Certificate): SimpleNode {
|
trustRoot: X509Certificate): SimpleNode {
|
||||||
val config = testNodeConfiguration(
|
val config = testNodeConfiguration(
|
||||||
baseDirectory = baseDirectory(legalName.x500Name),
|
baseDirectory = baseDirectory(legalName),
|
||||||
myLegalName = legalName).also {
|
myLegalName = legalName).also {
|
||||||
whenever(it.networkMapService).thenReturn(NetworkMapInfo(networkMapNode.internals.configuration.p2pAddress, networkMapNode.info.legalIdentity.name))
|
whenever(it.networkMapService).thenReturn(NetworkMapInfo(networkMapNode.internals.configuration.p2pAddress, networkMapNode.info.legalIdentity.name))
|
||||||
}
|
}
|
||||||
|
@ -153,7 +153,7 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
|
|||||||
|
|
||||||
protected val myLegalName: CordaX500Name by lazy {
|
protected val myLegalName: CordaX500Name by lazy {
|
||||||
val cert = loadKeyStore(configuration.nodeKeystore, configuration.keyStorePassword).getX509Certificate(X509Utilities.CORDA_CLIENT_CA)
|
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 {
|
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)
|
if (subject != name)
|
||||||
throw ConfigurationException("The name for $id doesn't match what's in the key store: $name vs $subject")
|
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 trustStore = KeyStoreWrapper(configuration.trustStoreFile, configuration.trustStorePassword)
|
||||||
val caKeyStore = KeyStoreWrapper(configuration.nodeKeystore, configuration.keyStorePassword)
|
val caKeyStore = KeyStoreWrapper(configuration.nodeKeystore, configuration.keyStorePassword)
|
||||||
makeIdentityService(
|
makeIdentityService(
|
||||||
trustStore.getX509Certificate(X509Utilities.CORDA_ROOT_CA).cert,
|
trustStore.getX509Certificate(X509Utilities.CORDA_ROOT_CA),
|
||||||
caKeyStore.certificateAndKeyPair(X509Utilities.CORDA_CLIENT_CA),
|
caKeyStore.certificateAndKeyPair(X509Utilities.CORDA_CLIENT_CA),
|
||||||
info.legalIdentityAndCert)
|
info.legalIdentityAndCert)
|
||||||
}
|
}
|
||||||
|
@ -7,10 +7,7 @@ import com.typesafe.config.ConfigRenderOptions
|
|||||||
import net.corda.core.crypto.Crypto
|
import net.corda.core.crypto.Crypto
|
||||||
import net.corda.core.crypto.SignatureScheme
|
import net.corda.core.crypto.SignatureScheme
|
||||||
import net.corda.core.identity.CordaX500Name
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.internal.copyTo
|
import net.corda.core.internal.*
|
||||||
import net.corda.core.internal.createDirectories
|
|
||||||
import net.corda.core.internal.div
|
|
||||||
import net.corda.core.internal.exists
|
|
||||||
import net.corda.core.utilities.loggerFor
|
import net.corda.core.utilities.loggerFor
|
||||||
import net.corda.node.utilities.*
|
import net.corda.node.utilities.*
|
||||||
import net.corda.nodeapi.config.SSLConfiguration
|
import net.corda.nodeapi.config.SSLConfiguration
|
||||||
@ -82,7 +79,7 @@ fun createKeystoreForCordaNode(sslKeyStorePath: Path,
|
|||||||
legalName: CordaX500Name,
|
legalName: CordaX500Name,
|
||||||
signatureScheme: SignatureScheme = X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME) {
|
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 (intermediateCACert, intermediateCAKeyPair) = caKeyStore.getCertificateAndKeyPair(X509Utilities.CORDA_INTERMEDIATE_CA, caKeyPassword)
|
||||||
|
|
||||||
val clientKey = Crypto.generateKeyPair(signatureScheme)
|
val clientKey = Crypto.generateKeyPair(signatureScheme)
|
||||||
@ -92,12 +89,12 @@ fun createKeystoreForCordaNode(sslKeyStorePath: Path,
|
|||||||
val clientCACert = X509Utilities.createCertificate(CertificateType.INTERMEDIATE_CA,
|
val clientCACert = X509Utilities.createCertificate(CertificateType.INTERMEDIATE_CA,
|
||||||
intermediateCACert,
|
intermediateCACert,
|
||||||
intermediateCAKeyPair,
|
intermediateCAKeyPair,
|
||||||
clientName.copy(commonName = X509Utilities.CORDA_CLIENT_CA_CN).x500Name,
|
clientName.copy(commonName = X509Utilities.CORDA_CLIENT_CA_CN),
|
||||||
clientKey.public,
|
clientKey.public,
|
||||||
nameConstraints = nameConstraints)
|
nameConstraints = nameConstraints)
|
||||||
|
|
||||||
val tlsKey = Crypto.generateKeyPair(signatureScheme)
|
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()
|
val keyPass = keyPassword.toCharArray()
|
||||||
|
|
||||||
|
@ -106,8 +106,8 @@ class InMemoryIdentityService(identities: Iterable<PartyAndCertificate> = emptyS
|
|||||||
val results = LinkedHashSet<Party>()
|
val results = LinkedHashSet<Party>()
|
||||||
for ((x500name, partyAndCertificate) in principalToParties) {
|
for ((x500name, partyAndCertificate) in principalToParties) {
|
||||||
val party = partyAndCertificate.party
|
val party = partyAndCertificate.party
|
||||||
for (rdn in x500name.x500Name.rdNs) {
|
val components = listOf(x500name.commonName, x500name.organisationUnit, x500name.organisation, x500name.locality, x500name.state, x500name.country).filterNotNull()
|
||||||
val component = rdn.first.value.toString()
|
components.forEach { component ->
|
||||||
if (exactMatch && component == query) {
|
if (exactMatch && component == query) {
|
||||||
results += party
|
results += party
|
||||||
} else if (!exactMatch) {
|
} else if (!exactMatch) {
|
||||||
|
@ -164,8 +164,8 @@ class PersistentIdentityService(identities: Iterable<PartyAndCertificate> = empt
|
|||||||
val results = LinkedHashSet<Party>()
|
val results = LinkedHashSet<Party>()
|
||||||
for ((x500name, partyId) in principalToParties.allPersisted()) {
|
for ((x500name, partyId) in principalToParties.allPersisted()) {
|
||||||
val party = keyToParties[partyId]!!.party
|
val party = keyToParties[partyId]!!.party
|
||||||
for (rdn in x500name.x500Name.rdNs) {
|
val components = listOf(x500name.commonName, x500name.organisationUnit, x500name.organisation, x500name.locality, x500name.state, x500name.country).filterNotNull()
|
||||||
val component = rdn.first.value.toString()
|
components.forEach { component ->
|
||||||
if (exactMatch && component == query) {
|
if (exactMatch && component == query) {
|
||||||
results += party
|
results += party
|
||||||
} else if (!exactMatch) {
|
} else if (!exactMatch) {
|
||||||
|
@ -35,7 +35,7 @@ fun freshCertificate(identityService: IdentityService,
|
|||||||
val issuerCertificate = issuer.certificate
|
val issuerCertificate = issuer.certificate
|
||||||
val window = X509Utilities.getCertificateValidityWindow(Duration.ZERO, 3650.days, issuerCertificate)
|
val window = X509Utilities.getCertificateValidityWindow(Duration.ZERO, 3650.days, issuerCertificate)
|
||||||
val ourCertificate = X509Utilities.createCertificate(CertificateType.IDENTITY, issuerCertificate.subject,
|
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 certFactory = CertificateFactory.getInstance("X509")
|
||||||
val ourCertPath = certFactory.generateCertPath(listOf(ourCertificate.cert) + issuer.certPath.certificates)
|
val ourCertPath = certFactory.generateCertPath(listOf(ourCertificate.cert) + issuer.certPath.certificates)
|
||||||
val anonymisedIdentity = PartyAndCertificate(ourCertPath)
|
val anonymisedIdentity = PartyAndCertificate(ourCertPath)
|
||||||
|
@ -11,7 +11,6 @@ import net.corda.core.internal.ThreadBox
|
|||||||
import net.corda.core.internal.concurrent.openFuture
|
import net.corda.core.internal.concurrent.openFuture
|
||||||
import net.corda.core.internal.div
|
import net.corda.core.internal.div
|
||||||
import net.corda.core.internal.noneOrSingle
|
import net.corda.core.internal.noneOrSingle
|
||||||
import net.corda.core.internal.toX509CertHolder
|
|
||||||
import net.corda.core.node.NodeInfo
|
import net.corda.core.node.NodeInfo
|
||||||
import net.corda.core.node.services.NetworkMapCache
|
import net.corda.core.node.services.NetworkMapCache
|
||||||
import net.corda.core.node.services.NetworkMapCache.MapChange
|
import net.corda.core.node.services.NetworkMapCache.MapChange
|
||||||
@ -57,6 +56,7 @@ import java.math.BigInteger
|
|||||||
import java.security.KeyStore
|
import java.security.KeyStore
|
||||||
import java.security.KeyStoreException
|
import java.security.KeyStoreException
|
||||||
import java.security.Principal
|
import java.security.Principal
|
||||||
|
import java.security.cert.X509Certificate
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.concurrent.Executor
|
import java.util.concurrent.Executor
|
||||||
import java.util.concurrent.ScheduledExecutorService
|
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.FailedLoginException
|
||||||
import javax.security.auth.login.LoginException
|
import javax.security.auth.login.LoginException
|
||||||
import javax.security.auth.spi.LoginModule
|
import javax.security.auth.spi.LoginModule
|
||||||
|
import javax.security.auth.x500.X500Principal
|
||||||
import javax.security.cert.CertificateException
|
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: 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)
|
// 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!"
|
"misconfiguration by the remote peer or an SSL man-in-the-middle attack!"
|
||||||
}
|
}
|
||||||
// Make sure certificate has the same name.
|
// Make sure certificate has the same name.
|
||||||
val peerCertificate = session.peerCertificateChain[0].toX509CertHolder()
|
val peerCertificateName = CordaX500Name.build(X500Principal(session.peerCertificateChain[0].subjectDN.name))
|
||||||
val peerCertificateName = CordaX500Name.build(peerCertificate.subject)
|
|
||||||
require(peerCertificateName == expectedLegalName) {
|
require(peerCertificateName == expectedLegalName) {
|
||||||
"Peer has wrong subject name in the certificate - expected $expectedLegalName but got $peerCertificateName. This is either a fatal " +
|
"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!"
|
"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)
|
server.onTcpConnection(peerLegalName)
|
||||||
} catch (e: IllegalArgumentException) {
|
} catch (e: IllegalArgumentException) {
|
||||||
connection.close()
|
connection.close()
|
||||||
@ -528,7 +527,7 @@ sealed class CertificateChainCheckPolicy {
|
|||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
interface Check {
|
interface Check {
|
||||||
fun checkCertificateChain(theirChain: Array<X509Certificate>)
|
fun checkCertificateChain(theirChain: Array<javax.security.cert.X509Certificate>)
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract fun createCheck(keyStore: KeyStore, trustStore: KeyStore): Check
|
abstract fun createCheck(keyStore: KeyStore, trustStore: KeyStore): Check
|
||||||
@ -536,7 +535,7 @@ sealed class CertificateChainCheckPolicy {
|
|||||||
object Any : CertificateChainCheckPolicy() {
|
object Any : CertificateChainCheckPolicy() {
|
||||||
override fun createCheck(keyStore: KeyStore, trustStore: KeyStore): Check {
|
override fun createCheck(keyStore: KeyStore, trustStore: KeyStore): Check {
|
||||||
return object : 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 {
|
override fun createCheck(keyStore: KeyStore, trustStore: KeyStore): Check {
|
||||||
val rootPublicKey = trustStore.getCertificate(CORDA_ROOT_CA).publicKey
|
val rootPublicKey = trustStore.getCertificate(CORDA_ROOT_CA).publicKey
|
||||||
return object : Check {
|
return object : Check {
|
||||||
override fun checkCertificateChain(theirChain: Array<X509Certificate>) {
|
override fun checkCertificateChain(theirChain: Array<javax.security.cert.X509Certificate>) {
|
||||||
val theirRoot = theirChain.last().publicKey
|
val theirRoot = theirChain.last().publicKey
|
||||||
if (rootPublicKey != theirRoot) {
|
if (rootPublicKey != theirRoot) {
|
||||||
throw CertificateException("Root certificate mismatch, their root = $theirRoot")
|
throw CertificateException("Root certificate mismatch, their root = $theirRoot")
|
||||||
@ -560,7 +559,7 @@ sealed class CertificateChainCheckPolicy {
|
|||||||
override fun createCheck(keyStore: KeyStore, trustStore: KeyStore): Check {
|
override fun createCheck(keyStore: KeyStore, trustStore: KeyStore): Check {
|
||||||
val ourPublicKey = keyStore.getCertificate(CORDA_CLIENT_TLS).publicKey
|
val ourPublicKey = keyStore.getCertificate(CORDA_CLIENT_TLS).publicKey
|
||||||
return object : Check {
|
return object : Check {
|
||||||
override fun checkCertificateChain(theirChain: Array<X509Certificate>) {
|
override fun checkCertificateChain(theirChain: Array<javax.security.cert.X509Certificate>) {
|
||||||
val theirLeaf = theirChain.first().publicKey
|
val theirLeaf = theirChain.first().publicKey
|
||||||
if (ourPublicKey != theirLeaf) {
|
if (ourPublicKey != theirLeaf) {
|
||||||
throw CertificateException("Leaf certificate mismatch, their leaf = $theirLeaf")
|
throw CertificateException("Leaf certificate mismatch, their leaf = $theirLeaf")
|
||||||
@ -574,7 +573,7 @@ sealed class CertificateChainCheckPolicy {
|
|||||||
override fun createCheck(keyStore: KeyStore, trustStore: KeyStore): Check {
|
override fun createCheck(keyStore: KeyStore, trustStore: KeyStore): Check {
|
||||||
val trustedPublicKeys = trustedAliases.map { trustStore.getCertificate(it).publicKey }.toSet()
|
val trustedPublicKeys = trustedAliases.map { trustStore.getCertificate(it).publicKey }.toSet()
|
||||||
return object : Check {
|
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 }) {
|
if (!theirChain.any { it.publicKey in trustedPublicKeys }) {
|
||||||
throw CertificateException("Their certificate chain contained none of the trusted ones")
|
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)
|
nodeCertCheck.checkCertificateChain(certificates)
|
||||||
principals += RolePrincipal(NODE_ROLE)
|
principals += RolePrincipal(NODE_ROLE)
|
||||||
return certificates.first().subjectDN.name
|
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)
|
verifierCertCheck.checkCertificateChain(certificates)
|
||||||
principals += RolePrincipal(VERIFIER_ROLE)
|
principals += RolePrincipal(VERIFIER_ROLE)
|
||||||
return certificates.first().subjectDN.name
|
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)
|
peerCertCheck.checkCertificateChain(certificates)
|
||||||
principals += RolePrincipal(PEER_ROLE)
|
principals += RolePrincipal(PEER_ROLE)
|
||||||
return certificates.first().subjectDN.name
|
return certificates.first().subjectDN.name
|
||||||
@ -694,7 +693,7 @@ class NodeLoginModule : LoginModule {
|
|||||||
return username
|
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?" }
|
fun requireTls() = require(certificates != null) { "No TLS?" }
|
||||||
return when (username) {
|
return when (username) {
|
||||||
PEER_USER -> {
|
PEER_USER -> {
|
||||||
|
@ -48,6 +48,7 @@ import javax.persistence.Column
|
|||||||
import javax.persistence.Entity
|
import javax.persistence.Entity
|
||||||
import javax.persistence.Id
|
import javax.persistence.Id
|
||||||
import javax.persistence.Lob
|
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
|
// 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
|
val myCert = loadKeyStore(config.sslKeystore, config.keyStorePassword).getX509Certificate(X509Utilities.CORDA_CLIENT_TLS)
|
||||||
rpcServer = RPCServer(rpcOps, NODE_USER, NODE_USER, locator, userService, CordaX500Name.build(myLegalName))
|
rpcServer = RPCServer(rpcOps, NODE_USER, NODE_USER, locator, userService, CordaX500Name.build(myCert.subjectX500Principal))
|
||||||
|
|
||||||
fun checkVerifierCount() {
|
fun checkVerifierCount() {
|
||||||
if (session.queueQuery(SimpleString(VERIFICATION_REQUESTS_QUEUE_NAME)).consumerCount == 0) {
|
if (session.queueQuery(SimpleString(VERIFICATION_REQUESTS_QUEUE_NAME)).consumerCount == 0) {
|
||||||
|
@ -16,6 +16,7 @@ import java.security.*
|
|||||||
import java.security.cert.CertPath
|
import java.security.cert.CertPath
|
||||||
import java.security.cert.Certificate
|
import java.security.cert.Certificate
|
||||||
import java.security.cert.CertificateFactory
|
import java.security.cert.CertificateFactory
|
||||||
|
import java.security.cert.X509Certificate
|
||||||
|
|
||||||
val KEYSTORE_TYPE = "JKS"
|
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).
|
* @param keyPassword The password for the PrivateKey (not the store access password).
|
||||||
*/
|
*/
|
||||||
fun KeyStore.getCertificateAndKeyPair(alias: String, keyPassword: String): CertificateAndKeyPair {
|
fun KeyStore.getCertificateAndKeyPair(alias: String, keyPassword: String): CertificateAndKeyPair {
|
||||||
val cert = getX509Certificate(alias)
|
val cert = getX509Certificate(alias).toX509CertHolder()
|
||||||
val publicKey = Crypto.toSupportedPublicKey(cert.subjectPublicKeyInfo)
|
val publicKey = Crypto.toSupportedPublicKey(cert.subjectPublicKeyInfo)
|
||||||
return CertificateAndKeyPair(cert, KeyPair(publicKey, getSupportedKey(alias, keyPassword)))
|
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.
|
* @param alias The name to lookup the Key and Certificate chain from.
|
||||||
* @return The X509Certificate found in the KeyStore under the specified alias.
|
* @return The X509Certificate found in the KeyStore under the specified alias.
|
||||||
*/
|
*/
|
||||||
fun KeyStore.getX509Certificate(alias: String): X509CertificateHolder {
|
fun KeyStore.getX509Certificate(alias: String): X509Certificate {
|
||||||
val certificate = getCertificate(alias) ?: throw IllegalArgumentException("No certificate under alias \"$alias\"")
|
val certificate = getCertificate(alias) ?: throw IllegalArgumentException("No certificate under alias \"$alias\".")
|
||||||
return certificate.toX509CertHolder()
|
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.
|
// Assume key password = store password.
|
||||||
val clientCA = certificateAndKeyPair(X509Utilities.CORDA_CLIENT_CA)
|
val clientCA = certificateAndKeyPair(X509Utilities.CORDA_CLIENT_CA)
|
||||||
// Create new keys and store in keystore.
|
// 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)
|
val certPath = CertificateFactory.getInstance("X509").generateCertPath(listOf(cert.cert) + clientCertPath)
|
||||||
require(certPath.certificates.isNotEmpty()) { "Certificate path cannot be empty" }
|
require(certPath.certificates.isNotEmpty()) { "Certificate path cannot be empty" }
|
||||||
// TODO: X509Utilities.validateCertificateChain()
|
// TODO: X509Utilities.validateCertificateChain()
|
||||||
|
@ -4,6 +4,7 @@ import net.corda.core.crypto.Crypto
|
|||||||
import net.corda.core.crypto.SignatureScheme
|
import net.corda.core.crypto.SignatureScheme
|
||||||
import net.corda.core.crypto.random63BitValue
|
import net.corda.core.crypto.random63BitValue
|
||||||
import net.corda.core.identity.CordaX500Name
|
import net.corda.core.identity.CordaX500Name
|
||||||
|
import net.corda.core.internal.x500Name
|
||||||
import net.corda.core.utilities.cert
|
import net.corda.core.utilities.cert
|
||||||
import net.corda.core.utilities.days
|
import net.corda.core.utilities.days
|
||||||
import net.corda.core.utilities.millis
|
import net.corda.core.utilities.millis
|
||||||
@ -89,13 +90,16 @@ object X509Utilities {
|
|||||||
* Create a de novo root self-signed X509 v3 CA cert.
|
* Create a de novo root self-signed X509 v3 CA cert.
|
||||||
*/
|
*/
|
||||||
@JvmStatic
|
@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)
|
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 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 issuerKeyPair The KeyPair of the root CA above this used to sign it.
|
||||||
* @param subject subject of the generated certificate.
|
* @param subject subject of the generated certificate.
|
||||||
@ -106,16 +110,19 @@ object X509Utilities {
|
|||||||
*/
|
*/
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun createCertificate(certificateType: CertificateType,
|
fun createCertificate(certificateType: CertificateType,
|
||||||
issuerCertificate: X509CertificateHolder, issuerKeyPair: KeyPair,
|
issuerCertificate: X509CertificateHolder,
|
||||||
subject: CordaX500Name, subjectPublicKey: PublicKey,
|
issuerKeyPair: KeyPair,
|
||||||
|
subject: CordaX500Name,
|
||||||
|
subjectPublicKey: PublicKey,
|
||||||
validityWindow: Pair<Duration, Duration> = DEFAULT_VALIDITY_WINDOW,
|
validityWindow: Pair<Duration, Duration> = DEFAULT_VALIDITY_WINDOW,
|
||||||
nameConstraints: NameConstraints? = null): X509CertificateHolder {
|
nameConstraints: NameConstraints? = null): X509CertificateHolder
|
||||||
val window = getCertificateValidityWindow(validityWindow.first, validityWindow.second, issuerCertificate)
|
= createCertificate(certificateType, issuerCertificate, issuerKeyPair, subject.x500Name, subjectPublicKey, validityWindow, nameConstraints)
|
||||||
return createCertificate(certificateType, issuerCertificate.subject, issuerKeyPair, subject.x500Name, subjectPublicKey, window, 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 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 issuerKeyPair The KeyPair of the root CA above this used to sign it.
|
||||||
* @param subject subject of the generated certificate.
|
* @param subject subject of the generated certificate.
|
||||||
@ -137,10 +144,10 @@ object X509Utilities {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Throws(CertPathValidatorException::class)
|
@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" }
|
require(certificates.isNotEmpty()) { "Certificate path must contain at least one certificate" }
|
||||||
val certFactory = CertificateFactory.getInstance("X509")
|
val certFactory = CertificateFactory.getInstance("X509")
|
||||||
val params = PKIXParameters(setOf(TrustAnchor(trustedRoot.cert, null)))
|
val params = PKIXParameters(setOf(TrustAnchor(trustedRoot, null)))
|
||||||
params.isRevocationEnabled = false
|
params.isRevocationEnabled = false
|
||||||
val certPath = certFactory.generateCertPath(certificates.toList())
|
val certPath = certFactory.generateCertPath(certificates.toList())
|
||||||
val pathValidator = CertPathValidator.getInstance("PKIX")
|
val pathValidator = CertPathValidator.getInstance("PKIX")
|
||||||
@ -185,8 +192,28 @@ object X509Utilities {
|
|||||||
* @param validityWindow the time period the certificate is valid for.
|
* @param validityWindow the time period the certificate is valid for.
|
||||||
* @param nameConstraints any name constraints to impose on certificates signed by the generated certificate.
|
* @param nameConstraints any name constraints to impose on certificates signed by the generated certificate.
|
||||||
*/
|
*/
|
||||||
fun createCertificate(certificateType: CertificateType, issuer: X500Name,
|
fun createCertificate(certificateType: CertificateType,
|
||||||
subject: X500Name, subjectPublicKey: PublicKey,
|
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>,
|
validityWindow: Pair<Date, Date>,
|
||||||
nameConstraints: NameConstraints? = null): X509v3CertificateBuilder {
|
nameConstraints: NameConstraints? = null): X509v3CertificateBuilder {
|
||||||
|
|
||||||
@ -194,7 +221,8 @@ object X509Utilities {
|
|||||||
val keyPurposes = DERSequence(ASN1EncodableVector().apply { certificateType.purposes.forEach { add(it) } })
|
val keyPurposes = DERSequence(ASN1EncodableVector().apply { certificateType.purposes.forEach { add(it) } })
|
||||||
val subjectPublicKeyInfo = SubjectPublicKeyInfo.getInstance(ASN1Sequence.getInstance(subjectPublicKey.encoded))
|
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.subjectKeyIdentifier, false, BcX509ExtensionUtils().createSubjectKeyIdentifier(subjectPublicKeyInfo))
|
||||||
.addExtension(Extension.basicConstraints, certificateType.isCA, BasicConstraints(certificateType.isCA))
|
.addExtension(Extension.basicConstraints, certificateType.isCA, BasicConstraints(certificateType.isCA))
|
||||||
.addExtension(Extension.keyUsage, false, certificateType.keyUsage)
|
.addExtension(Extension.keyUsage, false, certificateType.keyUsage)
|
||||||
@ -216,11 +244,13 @@ object X509Utilities {
|
|||||||
* @param validityWindow the time period the certificate is valid for.
|
* @param validityWindow the time period the certificate is valid for.
|
||||||
* @param nameConstraints any name constraints to impose on certificates signed by the generated certificate.
|
* @param nameConstraints any name constraints to impose on certificates signed by the generated certificate.
|
||||||
*/
|
*/
|
||||||
fun createCertificate(certificateType: CertificateType, issuer: X500Name, issuerSigner: ContentSigner,
|
internal fun createCertificate(certificateType: CertificateType,
|
||||||
subject: X500Name, subjectPublicKey: PublicKey,
|
issuer: X500Name,
|
||||||
|
issuerSigner: ContentSigner,
|
||||||
|
subject: CordaX500Name, subjectPublicKey: PublicKey,
|
||||||
validityWindow: Pair<Date, Date>,
|
validityWindow: Pair<Date, Date>,
|
||||||
nameConstraints: NameConstraints? = null): X509CertificateHolder {
|
nameConstraints: NameConstraints? = null): X509CertificateHolder {
|
||||||
val builder = createCertificate(certificateType, issuer, subject, subjectPublicKey, validityWindow, nameConstraints)
|
val builder = createCertificate(certificateType, issuer, subject.x500Name, subjectPublicKey, validityWindow, nameConstraints)
|
||||||
return builder.build(issuerSigner).apply {
|
return builder.build(issuerSigner).apply {
|
||||||
require(isValidOn(Date()))
|
require(isValidOn(Date()))
|
||||||
}
|
}
|
||||||
@ -236,7 +266,7 @@ object X509Utilities {
|
|||||||
* @param validityWindow the time period the certificate is valid for.
|
* @param validityWindow the time period the certificate is valid for.
|
||||||
* @param nameConstraints any name constraints to impose on certificates signed by the generated certificate.
|
* @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,
|
subject: X500Name, subjectPublicKey: PublicKey,
|
||||||
validityWindow: Pair<Date, Date>,
|
validityWindow: Pair<Date, Date>,
|
||||||
nameConstraints: NameConstraints? = null): X509CertificateHolder {
|
nameConstraints: NameConstraints? = null): X509CertificateHolder {
|
||||||
@ -255,12 +285,12 @@ object X509Utilities {
|
|||||||
/**
|
/**
|
||||||
* Create certificate signing request using provided information.
|
* 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))
|
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package net.corda.node.utilities.registration
|
package net.corda.node.utilities.registration
|
||||||
|
|
||||||
import net.corda.core.crypto.Crypto
|
import net.corda.core.crypto.Crypto
|
||||||
import net.corda.core.utilities.cert
|
|
||||||
import net.corda.core.internal.*
|
import net.corda.core.internal.*
|
||||||
|
import net.corda.core.utilities.cert
|
||||||
import net.corda.core.utilities.seconds
|
import net.corda.core.utilities.seconds
|
||||||
import net.corda.node.services.config.NodeConfiguration
|
import net.corda.node.services.config.NodeConfiguration
|
||||||
import net.corda.node.utilities.*
|
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.
|
// 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)) {
|
if (!caKeyStore.containsAlias(SELF_SIGNED_PRIVATE_KEY)) {
|
||||||
val keyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
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.
|
// Save to the key store.
|
||||||
caKeyStore.addOrReplaceKey(SELF_SIGNED_PRIVATE_KEY, keyPair.private, privateKeyPassword.toCharArray(),
|
caKeyStore.addOrReplaceKey(SELF_SIGNED_PRIVATE_KEY, keyPair.private, privateKeyPassword.toCharArray(),
|
||||||
arrayOf(selfSignCert))
|
arrayOf(selfSignCert))
|
||||||
@ -84,7 +84,7 @@ class NetworkRegistrationHelper(private val config: NodeConfiguration, private v
|
|||||||
|
|
||||||
println("Generating SSL certificate for node messaging service.")
|
println("Generating SSL certificate for node messaging service.")
|
||||||
val sslKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
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 sslCert = X509Utilities.createCertificate(CertificateType.TLS, caCert, keyPair, caCert.subject, sslKey.public)
|
||||||
val sslKeyStore = loadOrCreateKeyStore(config.sslKeystore, keystorePassword)
|
val sslKeyStore = loadOrCreateKeyStore(config.sslKeystore, keystorePassword)
|
||||||
sslKeyStore.addOrReplaceKey(CORDA_CLIENT_TLS, sslKey.private, privateKeyPassword.toCharArray(),
|
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 {
|
private fun submitOrResumeCertificateSigningRequest(keyPair: KeyPair): String {
|
||||||
// Retrieve request id from file if exists, else post a request to server.
|
// Retrieve request id from file if exists, else post a request to server.
|
||||||
return if (!requestIdStore.exists()) {
|
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()
|
val writer = StringWriter()
|
||||||
JcaPEMWriter(writer).use {
|
JcaPEMWriter(writer).use {
|
||||||
it.writeObject(PemObject("CERTIFICATE REQUEST", request.encoded))
|
it.writeObject(PemObject("CERTIFICATE REQUEST", request.encoded))
|
||||||
|
@ -7,14 +7,15 @@ import net.corda.core.identity.CordaX500Name
|
|||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.identity.PartyAndCertificate
|
import net.corda.core.identity.PartyAndCertificate
|
||||||
import net.corda.core.node.services.UnknownAnonymousPartyException
|
import net.corda.core.node.services.UnknownAnonymousPartyException
|
||||||
import net.corda.node.utilities.CertificateAndKeyPair
|
|
||||||
import net.corda.core.utilities.cert
|
import net.corda.core.utilities.cert
|
||||||
import net.corda.node.services.identity.InMemoryIdentityService
|
import net.corda.node.services.identity.InMemoryIdentityService
|
||||||
|
import net.corda.node.utilities.CertificateAndKeyPair
|
||||||
import net.corda.node.utilities.CertificateType
|
import net.corda.node.utilities.CertificateType
|
||||||
import net.corda.node.utilities.X509Utilities
|
import net.corda.node.utilities.X509Utilities
|
||||||
import net.corda.testing.*
|
import net.corda.testing.*
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.security.cert.CertificateFactory
|
import java.security.cert.CertificateFactory
|
||||||
|
import javax.security.auth.x500.X500Principal
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
import kotlin.test.assertFailsWith
|
import kotlin.test.assertFailsWith
|
||||||
import kotlin.test.assertNull
|
import kotlin.test.assertNull
|
||||||
@ -86,7 +87,7 @@ class InMemoryIdentityServiceTests {
|
|||||||
fun `assert unknown anonymous key is unrecognised`() {
|
fun `assert unknown anonymous key is unrecognised`() {
|
||||||
withTestSerialization {
|
withTestSerialization {
|
||||||
val rootKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
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 txKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
||||||
val service = InMemoryIdentityService(trustRoot = DUMMY_CA.certificate)
|
val service = InMemoryIdentityService(trustRoot = DUMMY_CA.certificate)
|
||||||
// TODO: Generate certificate with an EdDSA key rather than ECDSA
|
// TODO: Generate certificate with an EdDSA key rather than ECDSA
|
||||||
@ -151,7 +152,7 @@ class InMemoryIdentityServiceTests {
|
|||||||
|
|
||||||
assertFailsWith<IllegalArgumentException> {
|
assertFailsWith<IllegalArgumentException> {
|
||||||
val owningKey = Crypto.decodePublicKey(trustRoot.certificate.subjectPublicKeyInfo.encoded)
|
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())
|
service.assertOwnership(Party(subject, owningKey), anonymousAlice.party.anonymise())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -162,7 +163,7 @@ class InMemoryIdentityServiceTests {
|
|||||||
val issuerKeyPair = generateKeyPair()
|
val issuerKeyPair = generateKeyPair()
|
||||||
val issuer = getTestPartyAndCertificate(x500Name, issuerKeyPair.public, ca)
|
val issuer = getTestPartyAndCertificate(x500Name, issuerKeyPair.public, ca)
|
||||||
val txKey = Crypto.generateKeyPair()
|
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)
|
val txCertPath = certFactory.generateCertPath(listOf(txCert.cert) + issuer.certPath.certificates)
|
||||||
return Pair(issuer, PartyAndCertificate(txCertPath))
|
return Pair(issuer, PartyAndCertificate(txCertPath))
|
||||||
}
|
}
|
||||||
|
@ -8,9 +8,9 @@ import net.corda.core.identity.Party
|
|||||||
import net.corda.core.identity.PartyAndCertificate
|
import net.corda.core.identity.PartyAndCertificate
|
||||||
import net.corda.core.node.services.IdentityService
|
import net.corda.core.node.services.IdentityService
|
||||||
import net.corda.core.node.services.UnknownAnonymousPartyException
|
import net.corda.core.node.services.UnknownAnonymousPartyException
|
||||||
import net.corda.node.utilities.CertificateAndKeyPair
|
|
||||||
import net.corda.core.utilities.cert
|
import net.corda.core.utilities.cert
|
||||||
import net.corda.node.services.identity.PersistentIdentityService
|
import net.corda.node.services.identity.PersistentIdentityService
|
||||||
|
import net.corda.node.utilities.CertificateAndKeyPair
|
||||||
import net.corda.node.utilities.CertificateType
|
import net.corda.node.utilities.CertificateType
|
||||||
import net.corda.node.utilities.CordaPersistence
|
import net.corda.node.utilities.CordaPersistence
|
||||||
import net.corda.node.utilities.X509Utilities
|
import net.corda.node.utilities.X509Utilities
|
||||||
@ -20,6 +20,7 @@ import org.junit.After
|
|||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.security.cert.CertificateFactory
|
import java.security.cert.CertificateFactory
|
||||||
|
import javax.security.auth.x500.X500Principal
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
import kotlin.test.assertFailsWith
|
import kotlin.test.assertFailsWith
|
||||||
import kotlin.test.assertNull
|
import kotlin.test.assertNull
|
||||||
@ -131,7 +132,7 @@ class PersistentIdentityServiceTests {
|
|||||||
fun `assert unknown anonymous key is unrecognised`() {
|
fun `assert unknown anonymous key is unrecognised`() {
|
||||||
withTestSerialization {
|
withTestSerialization {
|
||||||
val rootKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
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 txKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_IDENTITY_SIGNATURE_SCHEME)
|
||||||
val identity = Party(rootCert)
|
val identity = Party(rootCert)
|
||||||
val txIdentity = AnonymousParty(txKey.public)
|
val txIdentity = AnonymousParty(txKey.public)
|
||||||
@ -213,7 +214,7 @@ class PersistentIdentityServiceTests {
|
|||||||
assertFailsWith<IllegalArgumentException> {
|
assertFailsWith<IllegalArgumentException> {
|
||||||
val owningKey = Crypto.decodePublicKey(trustRoot.certificate.subjectPublicKeyInfo.encoded)
|
val owningKey = Crypto.decodePublicKey(trustRoot.certificate.subjectPublicKeyInfo.encoded)
|
||||||
database.transaction {
|
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())
|
identityService.assertOwnership(Party(subject, owningKey), anonymousAlice.party.anonymise())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -261,7 +262,7 @@ class PersistentIdentityServiceTests {
|
|||||||
val issuerKeyPair = generateKeyPair()
|
val issuerKeyPair = generateKeyPair()
|
||||||
val issuer = getTestPartyAndCertificate(x500Name, issuerKeyPair.public, ca)
|
val issuer = getTestPartyAndCertificate(x500Name, issuerKeyPair.public, ca)
|
||||||
val txKey = Crypto.generateKeyPair()
|
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)
|
val txCertPath = certFactory.generateCertPath(listOf(txCert.cert) + issuer.certPath.certificates)
|
||||||
return Pair(issuer, PartyAndCertificate(txCertPath))
|
return Pair(issuer, PartyAndCertificate(txCertPath))
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,10 @@ package net.corda.node.utilities
|
|||||||
import net.corda.core.crypto.Crypto
|
import net.corda.core.crypto.Crypto
|
||||||
import net.corda.core.crypto.Crypto.EDDSA_ED25519_SHA512
|
import net.corda.core.crypto.Crypto.EDDSA_ED25519_SHA512
|
||||||
import net.corda.core.crypto.Crypto.generateKeyPair
|
import net.corda.core.crypto.Crypto.generateKeyPair
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.internal.div
|
import net.corda.core.internal.div
|
||||||
import net.corda.core.internal.toTypedArray
|
import net.corda.core.internal.toTypedArray
|
||||||
|
import net.corda.core.internal.x500Name
|
||||||
import net.corda.core.serialization.SerializationContext
|
import net.corda.core.serialization.SerializationContext
|
||||||
import net.corda.core.serialization.deserialize
|
import net.corda.core.serialization.deserialize
|
||||||
import net.corda.core.serialization.serialize
|
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.KryoHeaderV0_1
|
||||||
import net.corda.nodeapi.internal.serialization.SerializationContextImpl
|
import net.corda.nodeapi.internal.serialization.SerializationContextImpl
|
||||||
import net.corda.nodeapi.internal.serialization.SerializationFactoryImpl
|
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.x500.X500Name
|
||||||
import org.bouncycastle.asn1.x509.BasicConstraints
|
import org.bouncycastle.asn1.x509.BasicConstraints
|
||||||
import org.bouncycastle.asn1.x509.Extension
|
import org.bouncycastle.asn1.x509.Extension
|
||||||
@ -44,6 +49,7 @@ import javax.net.ssl.*
|
|||||||
import kotlin.concurrent.thread
|
import kotlin.concurrent.thread
|
||||||
import kotlin.test.*
|
import kotlin.test.*
|
||||||
|
|
||||||
|
|
||||||
class X509UtilitiesTest {
|
class X509UtilitiesTest {
|
||||||
@Rule
|
@Rule
|
||||||
@JvmField
|
@JvmField
|
||||||
@ -52,8 +58,8 @@ class X509UtilitiesTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `create valid self-signed CA certificate`() {
|
fun `create valid self-signed CA certificate`() {
|
||||||
val caKey = generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
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)
|
||||||
assertEquals(X500Name("CN=Test Cert,O=R3 Ltd,L=London,C=GB"), caCert.subject)
|
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
|
assertEquals(caCert.issuer, caCert.subject) //self-signed
|
||||||
caCert.isValidOn(Date()) // throws on verification problems
|
caCert.isValidOn(Date()) // throws on verification problems
|
||||||
caCert.isSignatureValid(JcaContentVerifierProviderBuilder().build(caKey.public)) // 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`() {
|
fun `load and save a PEM file certificate`() {
|
||||||
val tmpCertificateFile = tempFile("cacert.pem")
|
val tmpCertificateFile = tempFile("cacert.pem")
|
||||||
val caKey = generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
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)
|
X509Utilities.saveCertificateAsPEMFile(caCert, tmpCertificateFile)
|
||||||
val readCertificate = X509Utilities.loadCertificateFromPEMFile(tmpCertificateFile)
|
val readCertificate = X509Utilities.loadCertificateFromPEMFile(tmpCertificateFile)
|
||||||
assertEquals(caCert, readCertificate)
|
assertEquals(caCert, readCertificate)
|
||||||
@ -76,11 +82,11 @@ class X509UtilitiesTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `create valid server certificate chain`() {
|
fun `create valid server certificate chain`() {
|
||||||
val caKey = generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
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 caCert = X509Utilities.createSelfSignedCACertificate(CordaX500Name(commonName = "Test CA Cert", organisation = "R3 Ltd", locality = "London", country = "GB"), caKey)
|
||||||
val subject = getX500Name(CN = "Server Cert", O = "R3 Ltd", L = "London", C = "GB")
|
val subject = CordaX500Name(commonName = "Server Cert", organisation = "R3 Ltd", locality = "London", country = "GB")
|
||||||
val keyPair = generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
val keyPair = generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
||||||
val serverCert = X509Utilities.createCertificate(CertificateType.TLS, caCert, caKey, subject, keyPair.public)
|
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
|
assertEquals(caCert.issuer, serverCert.issuer) // Issued by our CA cert
|
||||||
serverCert.isValidOn(Date()) // throws on verification problems
|
serverCert.isValidOn(Date()) // throws on verification problems
|
||||||
serverCert.isSignatureValid(JcaContentVerifierProviderBuilder().build(caKey.public)) // 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 tmpKeyStore = tempFile("keystore.jks")
|
||||||
|
|
||||||
val keyPair = generateKeyPair(EDDSA_ED25519_SHA512)
|
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))
|
assertTrue(Arrays.equals(selfSignCert.subjectPublicKeyInfo.encoded, keyPair.public.encoded))
|
||||||
|
|
||||||
@ -120,7 +127,8 @@ class X509UtilitiesTest {
|
|||||||
fun `signing EdDSA key with EcDSA certificate`() {
|
fun `signing EdDSA key with EcDSA certificate`() {
|
||||||
val tmpKeyStore = tempFile("keystore.jks")
|
val tmpKeyStore = tempFile("keystore.jks")
|
||||||
val ecDSAKey = generateKeyPair(Crypto.ECDSA_SECP256R1_SHA256)
|
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 edDSAKeypair = generateKeyPair(EDDSA_ED25519_SHA512)
|
||||||
val edDSACert = X509Utilities.createCertificate(CertificateType.TLS, ecDSACert, ecDSAKey, X500Name("CN=TestEdDSA"), edDSAKeypair.public)
|
val edDSACert = X509Utilities.createCertificate(CertificateType.TLS, ecDSACert, ecDSAKey, X500Name("CN=TestEdDSA"), edDSAKeypair.public)
|
||||||
|
|
||||||
@ -311,8 +319,7 @@ class X509UtilitiesTest {
|
|||||||
// Double check hostname manually
|
// Double check hostname manually
|
||||||
val peerChain = clientSocket.session.peerCertificates
|
val peerChain = clientSocket.session.peerCertificates
|
||||||
val peerX500Principal = (peerChain[0] as X509Certificate).subjectX500Principal
|
val peerX500Principal = (peerChain[0] as X509Certificate).subjectX500Principal
|
||||||
val x500name = X500Name(peerX500Principal.name)
|
assertEquals(MEGA_CORP.name.x500Principal, peerX500Principal)
|
||||||
assertEquals(MEGA_CORP.name.x500Name, x500name)
|
|
||||||
X509Utilities.validateCertificateChain(trustStore.getX509Certificate(X509Utilities.CORDA_ROOT_CA), *peerChain)
|
X509Utilities.validateCertificateChain(trustStore.getX509Certificate(X509Utilities.CORDA_ROOT_CA), *peerChain)
|
||||||
val output = DataOutputStream(clientSocket.outputStream)
|
val output = DataOutputStream(clientSocket.outputStream)
|
||||||
output.writeUTF("Hello World")
|
output.writeUTF("Hello World")
|
||||||
@ -353,10 +360,10 @@ class X509UtilitiesTest {
|
|||||||
trustStorePassword: String
|
trustStorePassword: String
|
||||||
): KeyStore {
|
): KeyStore {
|
||||||
val rootCAKey = generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
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 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 keyPass = keyPassword.toCharArray()
|
||||||
val keyStore = loadOrCreateKeyStore(keyStoreFilePath, storePassword)
|
val keyStore = loadOrCreateKeyStore(keyStoreFilePath, storePassword)
|
||||||
@ -383,7 +390,8 @@ class X509UtilitiesTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `Get correct private key type from Keystore`() {
|
fun `Get correct private key type from Keystore`() {
|
||||||
val keyPair = generateKeyPair(Crypto.ECDSA_SECP256R1_SHA256)
|
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")
|
val keyStore = loadOrCreateKeyStore(tempFile("testKeystore.jks"), "keystorepassword")
|
||||||
keyStore.setKeyEntry("Key", keyPair.private, "keypassword".toCharArray(), arrayOf(selfSignCert.cert))
|
keyStore.setKeyEntry("Key", keyPair.private, "keypassword".toCharArray(), arrayOf(selfSignCert.cert))
|
||||||
|
|
||||||
@ -403,7 +411,7 @@ class X509UtilitiesTest {
|
|||||||
emptyMap(),
|
emptyMap(),
|
||||||
true,
|
true,
|
||||||
SerializationContext.UseCase.P2P)
|
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 serialized = expected.serialize(factory, context).bytes
|
||||||
val actual: X509CertificateHolder = serialized.deserialize(factory, context)
|
val actual: X509CertificateHolder = serialized.deserialize(factory, context)
|
||||||
assertEquals(expected, actual)
|
assertEquals(expected, actual)
|
||||||
@ -420,7 +428,7 @@ class X509UtilitiesTest {
|
|||||||
SerializationContext.UseCase.P2P)
|
SerializationContext.UseCase.P2P)
|
||||||
val certFactory = CertificateFactory.getInstance("X509")
|
val certFactory = CertificateFactory.getInstance("X509")
|
||||||
val rootCAKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
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 certificate = X509Utilities.createCertificate(CertificateType.TLS, rootCACert, rootCAKey, BOB.name.x500Name, BOB_PUBKEY)
|
||||||
val expected = certFactory.generateCertPath(listOf(certificate.cert, rootCACert.cert))
|
val expected = certFactory.generateCertPath(listOf(certificate.cert, rootCACert.cert))
|
||||||
val serialized = expected.serialize(factory, context).bytes
|
val serialized = expected.serialize(factory, context).bytes
|
||||||
|
@ -5,16 +5,18 @@ import com.nhaarman.mockito_kotlin.eq
|
|||||||
import com.nhaarman.mockito_kotlin.mock
|
import com.nhaarman.mockito_kotlin.mock
|
||||||
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.internal.exists
|
import net.corda.core.internal.exists
|
||||||
import net.corda.core.internal.toTypedArray
|
import net.corda.core.internal.toTypedArray
|
||||||
import net.corda.core.internal.toX509CertHolder
|
import net.corda.core.internal.toX509CertHolder
|
||||||
import net.corda.core.utilities.cert
|
import net.corda.core.utilities.cert
|
||||||
import net.corda.core.utilities.commonName
|
|
||||||
import net.corda.node.utilities.X509Utilities
|
import net.corda.node.utilities.X509Utilities
|
||||||
import net.corda.node.utilities.loadKeyStore
|
import net.corda.node.utilities.loadKeyStore
|
||||||
import net.corda.testing.ALICE
|
import net.corda.testing.ALICE
|
||||||
import net.corda.testing.getX500Name
|
import net.corda.testing.getX500Name
|
||||||
import net.corda.testing.testNodeConfiguration
|
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.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.rules.TemporaryFolder
|
import org.junit.rules.TemporaryFolder
|
||||||
@ -22,6 +24,8 @@ import kotlin.test.assertEquals
|
|||||||
import kotlin.test.assertFalse
|
import kotlin.test.assertFalse
|
||||||
import kotlin.test.assertTrue
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
|
val X500Name.commonName: String? get() = getRDNs(BCStyle.CN).firstOrNull()?.first?.value?.toString()
|
||||||
|
|
||||||
class NetworkRegistrationHelperTest {
|
class NetworkRegistrationHelperTest {
|
||||||
@Rule
|
@Rule
|
||||||
@JvmField
|
@JvmField
|
||||||
@ -34,7 +38,7 @@ class NetworkRegistrationHelperTest {
|
|||||||
val identities = listOf("CORDA_CLIENT_CA",
|
val identities = listOf("CORDA_CLIENT_CA",
|
||||||
"CORDA_INTERMEDIATE_CA",
|
"CORDA_INTERMEDIATE_CA",
|
||||||
"CORDA_ROOT_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)) }
|
val certs = identities.stream().map { X509Utilities.createSelfSignedCACertificate(it, Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)) }
|
||||||
.map { it.cert }.toTypedArray()
|
.map { it.cert }.toTypedArray()
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ fun main(args: Array<String>) = BFTNotaryCordform.runNodes()
|
|||||||
private val clusterSize = 4 // Minimum size that tolerates a faulty replica.
|
private val clusterSize = 4 // Minimum size that tolerates a faulty replica.
|
||||||
private val notaryNames = createNotaryNames(clusterSize)
|
private val notaryNames = createNotaryNames(clusterSize)
|
||||||
|
|
||||||
object BFTNotaryCordform : CordformDefinition("build" / "notary-demo-nodes", notaryNames[0].x500Name) {
|
object BFTNotaryCordform : CordformDefinition("build" / "notary-demo-nodes", notaryNames[0].toString()) {
|
||||||
private val clusterName = CordaX500Name(organisation = "BFT", locality = "Zurich", country = "CH")
|
private val clusterName = CordaX500Name(organisation = "BFT", locality = "Zurich", country = "CH")
|
||||||
private val advertisedService = ServiceInfo(BFTNonValidatingNotaryService.type, clusterName)
|
private val advertisedService = ServiceInfo(BFTNonValidatingNotaryService.type, clusterName)
|
||||||
|
|
||||||
@ -65,6 +65,6 @@ object BFTNotaryCordform : CordformDefinition("build" / "notary-demo-nodes", not
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun setup(context: CordformContext) {
|
override fun setup(context: CordformContext) {
|
||||||
ServiceIdentityGenerator.generateToDisk(notaryNames.map { context.baseDirectory(it.x500Name) }, advertisedService.type.id, clusterName, minCorrectReplicas(clusterSize))
|
ServiceIdentityGenerator.generateToDisk(notaryNames.map(CordaX500Name::toString).map(context::baseDirectory), advertisedService.type.id, clusterName, minCorrectReplicas(clusterSize))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ internal fun createNotaryNames(clusterSize: Int) = (0 until clusterSize).map { C
|
|||||||
|
|
||||||
private val notaryNames = createNotaryNames(3)
|
private val notaryNames = createNotaryNames(3)
|
||||||
|
|
||||||
object RaftNotaryCordform : CordformDefinition("build" / "notary-demo-nodes", notaryNames[0].x500Name) {
|
object RaftNotaryCordform : CordformDefinition("build" / "notary-demo-nodes", notaryNames[0].toString()) {
|
||||||
private val clusterName = CordaX500Name(organisation = "Raft", locality = "Zurich", country = "CH")
|
private val clusterName = CordaX500Name(organisation = "Raft", locality = "Zurich", country = "CH")
|
||||||
private val advertisedService = ServiceInfo(RaftValidatingNotaryService.type, clusterName)
|
private val advertisedService = ServiceInfo(RaftValidatingNotaryService.type, clusterName)
|
||||||
|
|
||||||
@ -62,6 +62,6 @@ object RaftNotaryCordform : CordformDefinition("build" / "notary-demo-nodes", no
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun setup(context: CordformContext) {
|
override fun setup(context: CordformContext) {
|
||||||
ServiceIdentityGenerator.generateToDisk(notaryNames.map { context.baseDirectory(it.x500Name) }, advertisedService.type.id, clusterName)
|
ServiceIdentityGenerator.generateToDisk(notaryNames.map(CordaX500Name::toString).map(context::baseDirectory), advertisedService.type.id, clusterName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ fun main(args: Array<String>) = SingleNotaryCordform.runNodes()
|
|||||||
|
|
||||||
val notaryDemoUser = User("demou", "demop", setOf(startFlowPermission<DummyIssueAndMove>(), startFlowPermission<RPCStartableNotaryFlowClient>()))
|
val notaryDemoUser = User("demou", "demop", setOf(startFlowPermission<DummyIssueAndMove>(), startFlowPermission<RPCStartableNotaryFlowClient>()))
|
||||||
|
|
||||||
object SingleNotaryCordform : CordformDefinition("build" / "notary-demo-nodes", DUMMY_NOTARY.name.x500Name) {
|
object SingleNotaryCordform : CordformDefinition("build" / "notary-demo-nodes", DUMMY_NOTARY.name.toString()) {
|
||||||
init {
|
init {
|
||||||
node {
|
node {
|
||||||
name(ALICE.name)
|
name(ALICE.name)
|
||||||
|
@ -6,6 +6,7 @@ import net.corda.core.identity.CordaX500Name
|
|||||||
import net.corda.testing.driver.NetworkMapStartStrategy
|
import net.corda.testing.driver.NetworkMapStartStrategy
|
||||||
import net.corda.testing.driver.PortAllocation
|
import net.corda.testing.driver.PortAllocation
|
||||||
import net.corda.testing.driver.driver
|
import net.corda.testing.driver.driver
|
||||||
|
import javax.security.auth.x500.X500Principal
|
||||||
|
|
||||||
fun CordformDefinition.clean() {
|
fun CordformDefinition.clean() {
|
||||||
System.err.println("Deleting: $driverDirectory")
|
System.err.println("Deleting: $driverDirectory")
|
||||||
@ -18,7 +19,7 @@ fun CordformDefinition.clean() {
|
|||||||
fun CordformDefinition.runNodes() = driver(
|
fun CordformDefinition.runNodes() = driver(
|
||||||
isDebug = true,
|
isDebug = true,
|
||||||
driverDirectory = driverDirectory,
|
driverDirectory = driverDirectory,
|
||||||
networkMapStartStrategy = NetworkMapStartStrategy.Nominated(CordaX500Name.build(networkMapNodeName)),
|
networkMapStartStrategy = NetworkMapStartStrategy.Nominated(CordaX500Name.parse(networkMapNodeName)),
|
||||||
portAllocation = PortAllocation.Incremental(10001)
|
portAllocation = PortAllocation.Incremental(10001)
|
||||||
) {
|
) {
|
||||||
setup(this)
|
setup(this)
|
||||||
|
@ -38,7 +38,6 @@ import net.corda.testing.*
|
|||||||
import net.corda.testing.node.MockServices.Companion.MOCK_VERSION_INFO
|
import net.corda.testing.node.MockServices.Companion.MOCK_VERSION_INFO
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import org.slf4j.Logger
|
import org.slf4j.Logger
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.net.*
|
import java.net.*
|
||||||
@ -681,7 +680,7 @@ class DriverDSL(
|
|||||||
override fun getConfig() = configOf("p2pAddress" to p2pAddress.toString())
|
override fun getConfig() = configOf("p2pAddress" to p2pAddress.toString())
|
||||||
}))
|
}))
|
||||||
val config = ConfigHelper.loadConfig(
|
val config = ConfigHelper.loadConfig(
|
||||||
baseDirectory = baseDirectory(name.x500Name),
|
baseDirectory = baseDirectory(name),
|
||||||
allowMissingConfig = true,
|
allowMissingConfig = true,
|
||||||
configOverrides = configOf(
|
configOverrides = configOf(
|
||||||
"myLegalName" to name.toString(),
|
"myLegalName" to name.toString(),
|
||||||
@ -706,7 +705,7 @@ class DriverDSL(
|
|||||||
val name = CordaX500Name.parse(node.name)
|
val name = CordaX500Name.parse(node.name)
|
||||||
|
|
||||||
val config = ConfigHelper.loadConfig(
|
val config = ConfigHelper.loadConfig(
|
||||||
baseDirectory = baseDirectory(name.x500Name),
|
baseDirectory = baseDirectory(name),
|
||||||
allowMissingConfig = true,
|
allowMissingConfig = true,
|
||||||
configOverrides = node.config + mapOf(
|
configOverrides = node.config + mapOf(
|
||||||
"extraAdvertisedServiceIds" to node.advertisedServices,
|
"extraAdvertisedServiceIds" to node.advertisedServices,
|
||||||
@ -728,7 +727,7 @@ class DriverDSL(
|
|||||||
startInSameProcess: Boolean?
|
startInSameProcess: Boolean?
|
||||||
): CordaFuture<Pair<Party, List<NodeHandle>>> {
|
): CordaFuture<Pair<Party, List<NodeHandle>>> {
|
||||||
val nodeNames = (0 until clusterSize).map { CordaX500Name(organisation = "Notary Service $it", locality = "Zurich", country = "CH") }
|
val nodeNames = (0 until clusterSize).map { CordaX500Name(organisation = "Notary Service $it", locality = "Zurich", country = "CH") }
|
||||||
val paths = nodeNames.map { baseDirectory(it.x500Name) }
|
val paths = nodeNames.map { baseDirectory(it) }
|
||||||
ServiceIdentityGenerator.generateToDisk(paths, type.id, notaryName)
|
ServiceIdentityGenerator.generateToDisk(paths, type.id, notaryName)
|
||||||
val advertisedServices = setOf(ServiceInfo(type, notaryName))
|
val advertisedServices = setOf(ServiceInfo(type, notaryName))
|
||||||
val notaryClusterAddress = portAllocation.nextHostAndPort()
|
val notaryClusterAddress = portAllocation.nextHostAndPort()
|
||||||
@ -793,16 +792,19 @@ class DriverDSL(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun baseDirectory(nodeName: X500Name): Path {
|
fun baseDirectory(nodeName: CordaX500Name): Path {
|
||||||
val nodeDirectoryName = String(nodeName.organisation.filter { !it.isWhitespace() }.toCharArray())
|
val nodeDirectoryName = String(nodeName.organisation.filter { !it.isWhitespace() }.toCharArray())
|
||||||
return driverDirectory / nodeDirectoryName
|
return driverDirectory / nodeDirectoryName
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun baseDirectory(nodeName: String): Path = baseDirectory(CordaX500Name.parse(nodeName))
|
||||||
|
|
||||||
override fun startDedicatedNetworkMapService(startInProcess: Boolean?): CordaFuture<NodeHandle> {
|
override fun startDedicatedNetworkMapService(startInProcess: Boolean?): CordaFuture<NodeHandle> {
|
||||||
val webAddress = portAllocation.nextHostAndPort()
|
val webAddress = portAllocation.nextHostAndPort()
|
||||||
val networkMapLegalName = networkMapStartStrategy.legalName
|
val networkMapLegalName = networkMapStartStrategy.legalName
|
||||||
val config = ConfigHelper.loadConfig(
|
val config = ConfigHelper.loadConfig(
|
||||||
baseDirectory = baseDirectory(networkMapLegalName.x500Name),
|
baseDirectory = baseDirectory(networkMapLegalName),
|
||||||
allowMissingConfig = true,
|
allowMissingConfig = true,
|
||||||
configOverrides = configOf(
|
configOverrides = configOf(
|
||||||
"myLegalName" to networkMapLegalName.toString(),
|
"myLegalName" to networkMapLegalName.toString(),
|
||||||
|
@ -8,7 +8,6 @@ import net.corda.core.internal.div
|
|||||||
import net.corda.core.node.services.ServiceInfo
|
import net.corda.core.node.services.ServiceInfo
|
||||||
import net.corda.core.node.services.ServiceType
|
import net.corda.core.node.services.ServiceType
|
||||||
import net.corda.core.utilities.getOrThrow
|
import net.corda.core.utilities.getOrThrow
|
||||||
import net.corda.core.utilities.organisation
|
|
||||||
import net.corda.node.internal.Node
|
import net.corda.node.internal.Node
|
||||||
import net.corda.node.internal.StartedNode
|
import net.corda.node.internal.StartedNode
|
||||||
import net.corda.node.services.config.ConfigHelper
|
import net.corda.node.services.config.ConfigHelper
|
||||||
@ -24,10 +23,8 @@ import net.corda.testing.DUMMY_MAP
|
|||||||
import net.corda.testing.TestDependencyInjectionBase
|
import net.corda.testing.TestDependencyInjectionBase
|
||||||
import net.corda.testing.driver.addressMustNotBeBoundFuture
|
import net.corda.testing.driver.addressMustNotBeBoundFuture
|
||||||
import net.corda.testing.getFreeLocalPorts
|
import net.corda.testing.getFreeLocalPorts
|
||||||
import net.corda.testing.getX500Name
|
|
||||||
import net.corda.testing.node.MockServices.Companion.MOCK_VERSION_INFO
|
import net.corda.testing.node.MockServices.Companion.MOCK_VERSION_INFO
|
||||||
import org.apache.logging.log4j.Level
|
import org.apache.logging.log4j.Level
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.rules.TemporaryFolder
|
import org.junit.rules.TemporaryFolder
|
||||||
@ -135,7 +132,7 @@ abstract class NodeBasedTest : TestDependencyInjectionBase() {
|
|||||||
clusterSize: Int,
|
clusterSize: Int,
|
||||||
serviceType: ServiceType = RaftValidatingNotaryService.type): CordaFuture<List<StartedNode<Node>>> {
|
serviceType: ServiceType = RaftValidatingNotaryService.type): CordaFuture<List<StartedNode<Node>>> {
|
||||||
ServiceIdentityGenerator.generateToDisk(
|
ServiceIdentityGenerator.generateToDisk(
|
||||||
(0 until clusterSize).map { baseDirectory(getX500Name(O = "${notaryName.organisation}-$it", L = notaryName.locality, C = notaryName.country)) },
|
(0 until clusterSize).map { baseDirectory(notaryName.copy(organisation = "${notaryName.organisation}-$it")) },
|
||||||
serviceType.id,
|
serviceType.id,
|
||||||
notaryName)
|
notaryName)
|
||||||
|
|
||||||
@ -163,7 +160,7 @@ abstract class NodeBasedTest : TestDependencyInjectionBase() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun baseDirectory(legalName: X500Name) = tempFolder.root.toPath() / legalName.organisation.replace(WHITESPACE, "")
|
protected fun baseDirectory(legalName: CordaX500Name) = tempFolder.root.toPath() / legalName.organisation.replace(WHITESPACE, "")
|
||||||
|
|
||||||
private fun startNodeInternal(legalName: CordaX500Name,
|
private fun startNodeInternal(legalName: CordaX500Name,
|
||||||
platformVersion: Int,
|
platformVersion: Int,
|
||||||
@ -171,7 +168,7 @@ abstract class NodeBasedTest : TestDependencyInjectionBase() {
|
|||||||
rpcUsers: List<User>,
|
rpcUsers: List<User>,
|
||||||
configOverrides: Map<String, Any>,
|
configOverrides: Map<String, Any>,
|
||||||
noNetworkMap: Boolean = false): StartedNode<Node> {
|
noNetworkMap: Boolean = false): StartedNode<Node> {
|
||||||
val baseDirectory = baseDirectory(legalName.x500Name).createDirectories()
|
val baseDirectory = baseDirectory(legalName).createDirectories()
|
||||||
val localPort = getFreeLocalPorts("localhost", 2)
|
val localPort = getFreeLocalPorts("localhost", 2)
|
||||||
val p2pAddress = configOverrides["p2pAddress"] ?: localPort[0].toString()
|
val p2pAddress = configOverrides["p2pAddress"] ?: localPort[0].toString()
|
||||||
val config = ConfigHelper.loadConfig(
|
val config = ConfigHelper.loadConfig(
|
||||||
|
@ -128,7 +128,7 @@ fun configureTestSSL(legalName: CordaX500Name = MEGA_CORP.name): SSLConfiguratio
|
|||||||
|
|
||||||
fun getTestPartyAndCertificate(party: Party, trustRoot: CertificateAndKeyPair = DUMMY_CA): PartyAndCertificate {
|
fun getTestPartyAndCertificate(party: Party, trustRoot: CertificateAndKeyPair = DUMMY_CA): PartyAndCertificate {
|
||||||
val certFactory = CertificateFactory.getInstance("X509")
|
val certFactory = CertificateFactory.getInstance("X509")
|
||||||
val certHolder = X509Utilities.createCertificate(CertificateType.IDENTITY, trustRoot.certificate, trustRoot.keyPair, party.name.x500Name, party.owningKey)
|
val certHolder = X509Utilities.createCertificate(CertificateType.IDENTITY, trustRoot.certificate, trustRoot.keyPair, party.name, party.owningKey)
|
||||||
val certPath = certFactory.generateCertPath(listOf(certHolder.cert, trustRoot.certificate.cert))
|
val certPath = certFactory.generateCertPath(listOf(certHolder.cert, trustRoot.certificate.cert))
|
||||||
return PartyAndCertificate(certPath)
|
return PartyAndCertificate(certPath)
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,7 @@ val DUMMY_REGULATOR: Party get() = Party(CordaX500Name(organisation = "Regulator
|
|||||||
val DUMMY_CA_KEY: KeyPair by lazy { entropyToKeyPair(BigInteger.valueOf(110)) }
|
val DUMMY_CA_KEY: KeyPair by lazy { entropyToKeyPair(BigInteger.valueOf(110)) }
|
||||||
val DUMMY_CA: CertificateAndKeyPair by lazy {
|
val DUMMY_CA: CertificateAndKeyPair by lazy {
|
||||||
// TODO: Should be identity scheme
|
// TODO: Should be identity scheme
|
||||||
val cert = X509Utilities.createSelfSignedCACertificate(getX500Name(CN = "Dummy CA", OU = "Corda", O = "R3 Ltd", L = "London", C = "GB"), DUMMY_CA_KEY)
|
val cert = X509Utilities.createSelfSignedCACertificate(CordaX500Name(commonName = "Dummy CA", organisationUnit = "Corda", organisation = "R3 Ltd", locality = "London", state = null, country = "GB"), DUMMY_CA_KEY)
|
||||||
CertificateAndKeyPair(cert, DUMMY_CA_KEY)
|
CertificateAndKeyPair(cert, DUMMY_CA_KEY)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user