mirror of
https://github.com/corda/corda.git
synced 2025-02-01 08:48:09 +00:00
Validating the entire cert path in node registration, rather just checking the root cert. (#2298)
Also reduced duplicate code when creating the node CA cert path for testing, and renamed IdentityGenerator to DevIdentityGenerator.
This commit is contained in:
parent
39d25958e2
commit
4a2f157118
@ -1,9 +1,9 @@
|
||||
package net.corda.core.crypto
|
||||
|
||||
import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.internal.toTypedArray
|
||||
import net.corda.core.internal.cert
|
||||
import net.corda.nodeapi.internal.crypto.*
|
||||
import net.corda.testing.internal.createDevIntermediateCaCertPath
|
||||
import org.bouncycastle.asn1.x500.X500Name
|
||||
import org.bouncycastle.asn1.x509.GeneralName
|
||||
import org.bouncycastle.asn1.x509.GeneralSubtree
|
||||
@ -11,35 +11,40 @@ import org.bouncycastle.asn1.x509.NameConstraints
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider
|
||||
import org.junit.Test
|
||||
import java.security.KeyStore
|
||||
import java.security.cert.*
|
||||
import java.util.stream.Stream
|
||||
import java.security.cert.CertPathValidator
|
||||
import java.security.cert.CertPathValidatorException
|
||||
import java.security.cert.PKIXParameters
|
||||
import kotlin.test.assertFailsWith
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
class X509NameConstraintsTest {
|
||||
|
||||
private fun makeKeyStores(subjectName: X500Name, nameConstraints: NameConstraints): Pair<KeyStore, KeyStore> {
|
||||
val rootKeys = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
||||
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 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 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 (rootCa, intermediateCa) = createDevIntermediateCaCertPath()
|
||||
val nodeCaKeyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
||||
val nodeCaCert = X509Utilities.createCertificate(
|
||||
CertificateType.NODE_CA,
|
||||
intermediateCa.certificate,
|
||||
intermediateCa.keyPair,
|
||||
CordaX500Name("Corda Client CA", "R3 Ltd", "London", "GB"),
|
||||
nodeCaKeyPair.public,
|
||||
nameConstraints = nameConstraints)
|
||||
|
||||
val keyPass = "password"
|
||||
val trustStore = KeyStore.getInstance(KEYSTORE_TYPE)
|
||||
trustStore.load(null, keyPass.toCharArray())
|
||||
trustStore.addOrReplaceCertificate(X509Utilities.CORDA_ROOT_CA, rootCACert.cert)
|
||||
trustStore.addOrReplaceCertificate(X509Utilities.CORDA_ROOT_CA, rootCa.certificate.cert)
|
||||
|
||||
val tlsKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
||||
val tlsCert = X509Utilities.createCertificate(CertificateType.TLS, clientCACert, clientCAKeyPair, subjectName, tlsKey.public)
|
||||
val tlsKeyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
||||
val tlsCert = X509Utilities.createCertificate(CertificateType.TLS, nodeCaCert, nodeCaKeyPair, subjectName, tlsKeyPair.public)
|
||||
|
||||
val keyStore = KeyStore.getInstance(KEYSTORE_TYPE)
|
||||
keyStore.load(null, keyPass.toCharArray())
|
||||
keyStore.addOrReplaceKey(X509Utilities.CORDA_CLIENT_TLS, tlsKey.private, keyPass.toCharArray(),
|
||||
Stream.of(tlsCert, clientCACert, intermediateCACert, rootCACert).map { it.cert }.toTypedArray<Certificate>())
|
||||
keyStore.addOrReplaceKey(
|
||||
X509Utilities.CORDA_CLIENT_TLS,
|
||||
tlsKeyPair.private,
|
||||
keyPass.toCharArray(),
|
||||
arrayOf(tlsCert, nodeCaCert, intermediateCa.certificate, rootCa.certificate))
|
||||
return Pair(keyStore, trustStore)
|
||||
}
|
||||
|
||||
|
@ -19,10 +19,9 @@ import java.security.cert.X509Certificate
|
||||
/**
|
||||
* Contains utility methods for generating identities for a node.
|
||||
*
|
||||
* WARNING: This is not application for production use and must never called by the node.
|
||||
* WARNING: This is not application for production use.
|
||||
*/
|
||||
// TODO Rename to DevIdentityGenerator
|
||||
object IdentityGenerator {
|
||||
object DevIdentityGenerator {
|
||||
private val log = LoggerFactory.getLogger(javaClass)
|
||||
|
||||
// TODO These don't need to be prefixes but can be the full aliases
|
@ -15,14 +15,7 @@ import org.bouncycastle.cert.X509CertificateHolder
|
||||
* the given legal name), and the SSL key store will store the TLS cert which is a sub-cert of the node CA.
|
||||
*/
|
||||
fun SSLConfiguration.createDevKeyStores(rootCert: X509CertificateHolder, intermediateCa: CertificateAndKeyPair, legalName: CordaX500Name) {
|
||||
val nodeCaKeyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
||||
val nameConstraints = NameConstraints(arrayOf(GeneralSubtree(GeneralName(GeneralName.directoryName, legalName.x500Name))), arrayOf())
|
||||
val nodeCaCert = X509Utilities.createCertificate(CertificateType.NODE_CA,
|
||||
intermediateCa.certificate,
|
||||
intermediateCa.keyPair,
|
||||
legalName,
|
||||
nodeCaKeyPair.public,
|
||||
nameConstraints = nameConstraints)
|
||||
val (nodeCaCert, nodeCaKeyPair) = createDevNodeCa(intermediateCa, legalName)
|
||||
|
||||
loadOrCreateKeyStore(nodeKeystore, keyStorePassword).apply {
|
||||
addOrReplaceKey(
|
||||
@ -44,4 +37,21 @@ fun SSLConfiguration.createDevKeyStores(rootCert: X509CertificateHolder, interme
|
||||
arrayOf(tlsCert, nodeCaCert, intermediateCa.certificate, rootCert))
|
||||
save(sslKeystore, keyStorePassword)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a dev node CA cert, as a sub-cert of the given [intermediateCa], and matching key pair using the given
|
||||
* [CordaX500Name] as the cert subject.
|
||||
*/
|
||||
fun createDevNodeCa(intermediateCa: CertificateAndKeyPair, legalName: CordaX500Name): CertificateAndKeyPair {
|
||||
val keyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
||||
val nameConstraints = NameConstraints(arrayOf(GeneralSubtree(GeneralName(GeneralName.directoryName, legalName.x500Name))), arrayOf())
|
||||
val cert = X509Utilities.createCertificate(
|
||||
CertificateType.NODE_CA,
|
||||
intermediateCa.certificate,
|
||||
intermediateCa.keyPair,
|
||||
legalName,
|
||||
keyPair.public,
|
||||
nameConstraints = nameConstraints)
|
||||
return CertificateAndKeyPair(cert, keyPair)
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ import net.corda.nodeapi.internal.serialization.kryo.KryoHeaderV0_1
|
||||
import net.corda.testing.ALICE_NAME
|
||||
import net.corda.testing.BOB_NAME
|
||||
import net.corda.testing.TestIdentity
|
||||
import net.corda.testing.internal.createDevIntermediateCaCertPath
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.bouncycastle.asn1.x500.X500Name
|
||||
import org.bouncycastle.asn1.x509.BasicConstraints
|
||||
@ -169,10 +170,10 @@ class X509UtilitiesTest {
|
||||
override val trustStorePassword = "trustpass"
|
||||
}
|
||||
|
||||
val (rootCert, intermediateCa) = createRootCertAndIntermediateCa()
|
||||
val (rootCert, intermediateCa) = createDevIntermediateCaCertPath()
|
||||
|
||||
// Generate server cert and private key and populate another keystore suitable for SSL
|
||||
sslConfig.createDevKeyStores(rootCert, intermediateCa, MEGA_CORP.name)
|
||||
sslConfig.createDevKeyStores(rootCert.certificate, intermediateCa, MEGA_CORP.name)
|
||||
|
||||
// Load back server certificate
|
||||
val serverKeyStore = loadKeyStore(sslConfig.nodeKeystore, sslConfig.keyStorePassword)
|
||||
@ -205,11 +206,11 @@ class X509UtilitiesTest {
|
||||
override val trustStorePassword = "trustpass"
|
||||
}
|
||||
|
||||
val (rootCert, intermediateCa) = createRootCertAndIntermediateCa()
|
||||
val (rootCert, intermediateCa) = createDevIntermediateCaCertPath()
|
||||
|
||||
// Generate server cert and private key and populate another keystore suitable for SSL
|
||||
sslConfig.createDevKeyStores(rootCert, intermediateCa, MEGA_CORP.name)
|
||||
sslConfig.createTrustStore(rootCert.cert)
|
||||
sslConfig.createDevKeyStores(rootCert.certificate, intermediateCa, MEGA_CORP.name)
|
||||
sslConfig.createTrustStore(rootCert.certificate.cert)
|
||||
|
||||
val keyStore = loadKeyStore(sslConfig.sslKeystore, sslConfig.keyStorePassword)
|
||||
val trustStore = loadKeyStore(sslConfig.trustStoreFile, sslConfig.trustStorePassword)
|
||||
@ -293,22 +294,6 @@ class X509UtilitiesTest {
|
||||
|
||||
private fun tempFile(name: String): Path = tempFolder.root.toPath() / name
|
||||
|
||||
private fun createRootCertAndIntermediateCa(): Pair<X509CertificateHolder, CertificateAndKeyPair> {
|
||||
val rootKeyPair = generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
||||
val baseName = CordaX500Name(organisation = "R3 Ltd", locality = "London", country = "GB")
|
||||
val rootCert = X509Utilities.createSelfSignedCACertificate(baseName.copy(commonName = "Corda Root CA"), rootKeyPair)
|
||||
|
||||
val intermediateCaKeyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
||||
val intermediateCaCert = X509Utilities.createCertificate(
|
||||
CertificateType.INTERMEDIATE_CA,
|
||||
rootCert,
|
||||
rootKeyPair,
|
||||
baseName.copy(commonName = "Corda Intermediate CA"),
|
||||
intermediateCaKeyPair.public)
|
||||
|
||||
return Pair(rootCert, CertificateAndKeyPair(intermediateCaCert, intermediateCaKeyPair))
|
||||
}
|
||||
|
||||
private fun SSLConfiguration.createTrustStore(rootCert: X509Certificate) {
|
||||
val trustStore = loadOrCreateKeyStore(trustStoreFile, trustStorePassword)
|
||||
trustStore.addOrReplaceCertificate(X509Utilities.CORDA_ROOT_CA, rootCert)
|
||||
|
@ -10,23 +10,23 @@ import net.corda.nodeapi.internal.config.SSLConfiguration
|
||||
import net.corda.nodeapi.internal.crypto.*
|
||||
import net.corda.testing.ALICE_NAME
|
||||
import net.corda.testing.driver.driver
|
||||
import org.assertj.core.api.Assertions.assertThatThrownBy
|
||||
import org.junit.Test
|
||||
import java.nio.file.Path
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFailsWith
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
class NodeKeystoreCheckTest {
|
||||
@Test
|
||||
fun `starting node in non-dev mode with no key store`() {
|
||||
driver(startNodesInProcess = true) {
|
||||
assertThatThrownBy {
|
||||
startNode(customOverrides = mapOf("devMode" to false)).getOrThrow()
|
||||
}.hasMessageContaining("Identity certificate not found")
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `node should throw exception if cert path doesn't chain to the trust root`() {
|
||||
driver(startNodesInProcess = true) {
|
||||
// This will fail because there are no keystore configured.
|
||||
assertFailsWith(IllegalArgumentException::class) {
|
||||
startNode(customOverrides = mapOf("devMode" to false)).getOrThrow()
|
||||
}.apply {
|
||||
assertTrue(message?.startsWith("Identity certificate not found. ") ?: false)
|
||||
}
|
||||
|
||||
// Create keystores
|
||||
val keystorePassword = "password"
|
||||
val config = object : SSLConfiguration {
|
||||
@ -37,9 +37,12 @@ class NodeKeystoreCheckTest {
|
||||
config.configureDevKeyAndTrustStores(ALICE_NAME)
|
||||
|
||||
// This should pass with correct keystore.
|
||||
val node = startNode(providedName = ALICE_NAME, customOverrides = mapOf("devMode" to false,
|
||||
"keyStorePassword" to keystorePassword,
|
||||
"trustStorePassword" to keystorePassword)).get()
|
||||
val node = startNode(
|
||||
providedName = ALICE_NAME,
|
||||
customOverrides = mapOf("devMode" to false,
|
||||
"keyStorePassword" to keystorePassword,
|
||||
"trustStorePassword" to keystorePassword)
|
||||
).getOrThrow()
|
||||
node.stop()
|
||||
|
||||
// Fiddle with node keystore.
|
||||
@ -53,11 +56,9 @@ class NodeKeystoreCheckTest {
|
||||
keystore.setKeyEntry(X509Utilities.CORDA_CLIENT_CA, nodeCA.keyPair.private, config.keyStorePassword.toCharArray(), arrayOf(badNodeCACert.cert, badRoot.cert))
|
||||
keystore.save(config.nodeKeystore, config.keyStorePassword)
|
||||
|
||||
assertFailsWith(IllegalArgumentException::class) {
|
||||
assertThatThrownBy {
|
||||
startNode(providedName = ALICE_NAME, customOverrides = mapOf("devMode" to false)).getOrThrow()
|
||||
}.apply {
|
||||
assertEquals("Client CA certificate must chain to the trusted root.", message)
|
||||
}
|
||||
}.hasMessage("Client CA certificate must chain to the trusted root.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ import net.corda.node.services.config.BFTSMaRtConfiguration
|
||||
import net.corda.node.services.config.NotaryConfig
|
||||
import net.corda.node.services.transactions.minClusterSize
|
||||
import net.corda.node.services.transactions.minCorrectReplicas
|
||||
import net.corda.nodeapi.internal.IdentityGenerator
|
||||
import net.corda.nodeapi.internal.DevIdentityGenerator
|
||||
import net.corda.nodeapi.internal.network.NetworkParametersCopier
|
||||
import net.corda.nodeapi.internal.network.NotaryInfo
|
||||
import net.corda.testing.chooseIdentity
|
||||
@ -60,7 +60,7 @@ class BFTNotaryServiceTests {
|
||||
(Paths.get("config") / "currentView").deleteIfExists() // XXX: Make config object warn if this exists?
|
||||
val replicaIds = (0 until clusterSize)
|
||||
|
||||
notary = IdentityGenerator.generateDistributedNotaryIdentity(
|
||||
notary = DevIdentityGenerator.generateDistributedNotaryIdentity(
|
||||
replicaIds.map { mockNet.baseDirectory(mockNet.nextNodeId + it) },
|
||||
CordaX500Name("BFT", "Zurich", "CH"))
|
||||
|
||||
|
@ -6,7 +6,10 @@ import net.corda.core.internal.cert
|
||||
import net.corda.core.internal.concurrent.transpose
|
||||
import net.corda.core.internal.toX509CertHolder
|
||||
import net.corda.core.messaging.startFlow
|
||||
import net.corda.core.utilities.*
|
||||
import net.corda.core.utilities.NetworkHostAndPort
|
||||
import net.corda.core.utilities.OpaqueBytes
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.core.utilities.minutes
|
||||
import net.corda.finance.DOLLARS
|
||||
import net.corda.finance.flows.CashIssueAndPaymentFlow
|
||||
import net.corda.nodeapi.internal.crypto.CertificateAndKeyPair
|
||||
@ -16,7 +19,6 @@ import net.corda.nodeapi.internal.crypto.X509Utilities
|
||||
import net.corda.nodeapi.internal.crypto.X509Utilities.CORDA_CLIENT_CA
|
||||
import net.corda.nodeapi.internal.crypto.X509Utilities.CORDA_INTERMEDIATE_CA
|
||||
import net.corda.nodeapi.internal.crypto.X509Utilities.CORDA_ROOT_CA
|
||||
import net.corda.nodeapi.internal.network.NotaryInfo
|
||||
import net.corda.testing.ROOT_CA
|
||||
import net.corda.testing.SerializationEnvironmentRule
|
||||
import net.corda.testing.driver.PortAllocation
|
||||
@ -25,7 +27,6 @@ import net.corda.testing.node.internal.CompatibilityZoneParams
|
||||
import net.corda.testing.node.internal.internalDriver
|
||||
import net.corda.testing.node.internal.network.NetworkMapServer
|
||||
import net.corda.testing.singleIdentity
|
||||
import net.corda.testing.singleIdentityAndCert
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.assertj.core.api.Assertions.assertThatThrownBy
|
||||
import org.bouncycastle.pkcs.PKCS10CertificationRequest
|
||||
@ -39,6 +40,7 @@ import java.io.InputStream
|
||||
import java.net.URL
|
||||
import java.security.KeyPair
|
||||
import java.security.cert.CertPath
|
||||
import java.security.cert.CertPathValidatorException
|
||||
import java.security.cert.Certificate
|
||||
import java.util.zip.ZipEntry
|
||||
import java.util.zip.ZipOutputStream
|
||||
@ -50,8 +52,10 @@ class NodeRegistrationTest {
|
||||
@Rule
|
||||
@JvmField
|
||||
val testSerialization = SerializationEnvironmentRule(true)
|
||||
|
||||
private val portAllocation = PortAllocation.Incremental(13000)
|
||||
private val registrationHandler = RegistrationHandler(ROOT_CA)
|
||||
|
||||
private lateinit var server: NetworkMapServer
|
||||
private lateinit var serverHostAndPort: NetworkHostAndPort
|
||||
|
||||
@ -73,72 +77,63 @@ class NodeRegistrationTest {
|
||||
portAllocation = portAllocation,
|
||||
compatibilityZone = compatibilityZone,
|
||||
initialiseSerialization = false,
|
||||
notarySpecs = listOf(NotarySpec(CordaX500Name(organisation = "NotaryService", locality = "Zurich", country = "CH"), validating = false)),
|
||||
notarySpecs = listOf(NotarySpec(CordaX500Name("NotaryService", "Zurich", "CH"), validating = false)),
|
||||
extraCordappPackagesToScan = listOf("net.corda.finance"),
|
||||
onNetworkParametersGeneration = { server.networkParameters = it }
|
||||
) {
|
||||
val notary = defaultNotaryNode.get()
|
||||
val aliceName = "Alice"
|
||||
val genevieveName = "Genevieve"
|
||||
|
||||
val ALICE_NAME = "Alice"
|
||||
val GENEVIEVE_NAME = "Genevieve"
|
||||
val nodesFutures = listOf(startNode(providedName = CordaX500Name(ALICE_NAME, "London", "GB")),
|
||||
startNode(providedName = CordaX500Name(GENEVIEVE_NAME, "London", "GB")))
|
||||
val nodes = listOf(
|
||||
startNode(providedName = CordaX500Name(aliceName, "London", "GB")),
|
||||
startNode(providedName = CordaX500Name(genevieveName, "London", "GB")),
|
||||
defaultNotaryNode
|
||||
).transpose().getOrThrow()
|
||||
val (alice, genevieve) = nodes
|
||||
|
||||
val (alice, genevieve) = nodesFutures.transpose().get()
|
||||
val nodes = listOf(alice, genevieve, notary)
|
||||
|
||||
assertThat(registrationHandler.idsPolled).contains(ALICE_NAME, GENEVIEVE_NAME)
|
||||
assertThat(registrationHandler.idsPolled).contains(aliceName, genevieveName)
|
||||
// Notary identities are generated beforehand hence notary nodes don't go through registration.
|
||||
// This test isn't specifically testing this, or relying on this behavior, though if this check fail,
|
||||
// this will probably lead to the rest of the test to fail.
|
||||
assertThat(registrationHandler.idsPolled).doesNotContain("NotaryService")
|
||||
|
||||
// Check each node has each other identity in their network map cache.
|
||||
val nodeIdentities = nodes.map { it.nodeInfo.singleIdentity() }
|
||||
for (node in nodes) {
|
||||
assertThat(node.rpc.networkMapSnapshot().map { it.singleIdentity() }).containsAll(nodeIdentities)
|
||||
assertThat(node.rpc.networkMapSnapshot()).containsOnlyElementsOf(nodes.map { it.nodeInfo })
|
||||
}
|
||||
|
||||
// Check we nodes communicate among themselves (and the notary).
|
||||
val anonymous = false
|
||||
genevieve.rpc.startFlow(::CashIssueAndPaymentFlow, 1000.DOLLARS, OpaqueBytes.of(12),
|
||||
genevieve.rpc.startFlow(
|
||||
::CashIssueAndPaymentFlow,
|
||||
1000.DOLLARS,
|
||||
OpaqueBytes.of(12),
|
||||
alice.nodeInfo.singleIdentity(),
|
||||
anonymous,
|
||||
notary.nodeInfo.singleIdentity())
|
||||
.returnValue
|
||||
.getOrThrow()
|
||||
defaultNotaryIdentity
|
||||
).returnValue.getOrThrow()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `node registration wrong root cert`() {
|
||||
val someCert = createSelfKeyAndSelfSignedCertificate().certificate.cert
|
||||
val compatibilityZone = CompatibilityZoneParams(URL("http://$serverHostAndPort"), rootCert = someCert)
|
||||
val someRootCert = X509Utilities.createSelfSignedCACertificate(
|
||||
CordaX500Name("Integration Test Corda Node Root CA", "R3 Ltd", "London", "GB"),
|
||||
Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME))
|
||||
val compatibilityZone = CompatibilityZoneParams(URL("http://$serverHostAndPort"), rootCert = someRootCert.cert)
|
||||
internalDriver(
|
||||
portAllocation = portAllocation,
|
||||
notarySpecs = emptyList(),
|
||||
compatibilityZone = compatibilityZone,
|
||||
initialiseSerialization = false,
|
||||
// Changing the content of the truststore makes the node fail in a number of ways if started out process.
|
||||
startNodesInProcess = true
|
||||
startNodesInProcess = true // We need to run the nodes in the same process so that we can capture the correct exception
|
||||
) {
|
||||
assertThatThrownBy {
|
||||
startNode(providedName = CordaX500Name("Alice", "London", "GB")).getOrThrow()
|
||||
}.isInstanceOf(WrongRootCertException::class.java)
|
||||
}.isInstanceOf(CertPathValidatorException::class.java)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createSelfKeyAndSelfSignedCertificate(): CertificateAndKeyPair {
|
||||
val rootCAKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
||||
val rootCACert = X509Utilities.createSelfSignedCACertificate(
|
||||
CordaX500Name(
|
||||
commonName = "Integration Test Corda Node Root CA",
|
||||
organisation = "R3 Ltd",
|
||||
locality = "London",
|
||||
country = "GB"),
|
||||
rootCAKey)
|
||||
return CertificateAndKeyPair(rootCACert, rootCAKey)
|
||||
}
|
||||
}
|
||||
|
||||
@Path("certificate")
|
||||
@ -185,13 +180,14 @@ class RegistrationHandler(private val rootCertAndKeyPair: CertificateAndKeyPair)
|
||||
caCertPath: Array<Certificate>): Pair<CertPath, CordaX500Name> {
|
||||
val request = JcaPKCS10CertificationRequest(certificationRequest)
|
||||
val name = CordaX500Name.parse(request.subject.toString())
|
||||
val x509CertificateHolder = X509Utilities.createCertificate(CertificateType.NODE_CA,
|
||||
val nodeCaCert = X509Utilities.createCertificate(
|
||||
CertificateType.NODE_CA,
|
||||
caCertPath.first().toX509CertHolder(),
|
||||
caKeyPair,
|
||||
name,
|
||||
request.publicKey,
|
||||
nameConstraints = null)
|
||||
val certPath = X509CertificateFactory().generateCertPath(x509CertificateHolder.cert, *caCertPath)
|
||||
val certPath = X509CertificateFactory().generateCertPath(nodeCaCert.cert, *caCertPath)
|
||||
return Pair(certPath, name)
|
||||
}
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ import net.corda.node.services.vault.NodeVaultService
|
||||
import net.corda.node.services.vault.VaultSoftLockManager
|
||||
import net.corda.node.shell.InteractiveShell
|
||||
import net.corda.node.utilities.AffinityExecutor
|
||||
import net.corda.nodeapi.internal.IdentityGenerator
|
||||
import net.corda.nodeapi.internal.DevIdentityGenerator
|
||||
import net.corda.nodeapi.internal.SignedNodeInfo
|
||||
import net.corda.nodeapi.internal.crypto.KeyStoreWrapper
|
||||
import net.corda.nodeapi.internal.crypto.X509CertificateFactory
|
||||
@ -726,10 +726,10 @@ abstract class AbstractNode(val configuration: NodeConfiguration,
|
||||
|
||||
val (id, singleName) = if (notaryConfig == null || !notaryConfig.isClusterConfig) {
|
||||
// Node's main identity or if it's a single node notary
|
||||
Pair(IdentityGenerator.NODE_IDENTITY_ALIAS_PREFIX, configuration.myLegalName)
|
||||
Pair(DevIdentityGenerator.NODE_IDENTITY_ALIAS_PREFIX, configuration.myLegalName)
|
||||
} else {
|
||||
// The node is part of a distributed notary whose identity must already be generated beforehand.
|
||||
Pair(IdentityGenerator.DISTRIBUTED_NOTARY_ALIAS_PREFIX, null)
|
||||
Pair(DevIdentityGenerator.DISTRIBUTED_NOTARY_ALIAS_PREFIX, null)
|
||||
}
|
||||
// TODO: Integrate with Key management service?
|
||||
val privateKeyAlias = "$id-private-key"
|
||||
|
@ -12,10 +12,10 @@ import net.corda.nodeapi.internal.crypto.X509Utilities.CORDA_ROOT_CA
|
||||
import org.bouncycastle.openssl.jcajce.JcaPEMWriter
|
||||
import org.bouncycastle.util.io.pem.PemObject
|
||||
import java.io.StringWriter
|
||||
import java.nio.file.Path
|
||||
import java.security.KeyPair
|
||||
import java.security.KeyStore
|
||||
import java.security.cert.Certificate
|
||||
import java.security.cert.X509Certificate
|
||||
|
||||
/**
|
||||
* Helper for managing the node registration process, which checks for any existing certificates and requests them if
|
||||
@ -32,7 +32,7 @@ class NetworkRegistrationHelper(private val config: NodeConfiguration, private v
|
||||
// TODO: Use different password for private key.
|
||||
private val privateKeyPassword = config.keyStorePassword
|
||||
private val trustStore: KeyStore
|
||||
private val rootCert: Certificate
|
||||
private val rootCert: X509Certificate
|
||||
|
||||
init {
|
||||
require(config.trustStoreFile.exists()) {
|
||||
@ -46,7 +46,7 @@ class NetworkRegistrationHelper(private val config: NodeConfiguration, private v
|
||||
"This file must contain the root CA cert of your compatibility zone. " +
|
||||
"Please contact your CZ operator."
|
||||
}
|
||||
this.rootCert = rootCert
|
||||
this.rootCert = rootCert as X509Certificate
|
||||
}
|
||||
|
||||
/**
|
||||
@ -94,12 +94,8 @@ class NetworkRegistrationHelper(private val config: NodeConfiguration, private v
|
||||
caKeyStore.save(config.nodeKeystore, keystorePassword)
|
||||
println("Node private key and certificate stored in ${config.nodeKeystore}.")
|
||||
|
||||
// TODO This should actually be using X509Utilities.validateCertificateChain
|
||||
// Check that the root of the signed certificate matches the expected certificate in the truststore.
|
||||
if (rootCert != certificates.last()) {
|
||||
// Assumes certificate chain always starts with client certificate and end with root certificate.
|
||||
throw WrongRootCertException(rootCert, certificates.last(), config.trustStoreFile)
|
||||
}
|
||||
println("Checking root of the certificate path is what we expect.")
|
||||
X509Utilities.validateCertificateChain(rootCert, *certificates)
|
||||
|
||||
println("Generating SSL certificate for node messaging service.")
|
||||
val sslKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
||||
@ -169,17 +165,3 @@ class NetworkRegistrationHelper(private val config: NodeConfiguration, private v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Exception thrown when the doorman root certificate doesn't match the expected (out-of-band) root certificate.
|
||||
* This usually means that there has been a Man-in-the-middle attack when contacting the doorman.
|
||||
*/
|
||||
class WrongRootCertException(expected: Certificate,
|
||||
actual: Certificate,
|
||||
expectedFilePath: Path):
|
||||
Exception("""
|
||||
The Root CA returned back from the registration process does not match the expected Root CA
|
||||
expected: $expected
|
||||
actual: $actual
|
||||
the expected certificate is stored in: $expectedFilePath with alias $CORDA_ROOT_CA
|
||||
""".trimMargin())
|
||||
|
@ -14,12 +14,14 @@ import net.corda.core.internal.createDirectories
|
||||
import net.corda.node.services.config.NodeConfiguration
|
||||
import net.corda.nodeapi.internal.crypto.*
|
||||
import net.corda.testing.ALICE_NAME
|
||||
import net.corda.testing.internal.createDevNodeCaCertPath
|
||||
import net.corda.testing.internal.rigorousMock
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.assertj.core.api.Assertions.assertThatThrownBy
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import java.security.cert.CertPathValidatorException
|
||||
import java.security.cert.Certificate
|
||||
import java.security.cert.X509Certificate
|
||||
import kotlin.test.assertFalse
|
||||
@ -29,16 +31,19 @@ class NetworkRegistrationHelperTest {
|
||||
private val fs = Jimfs.newFileSystem(unix())
|
||||
private val requestId = SecureHash.randomSHA256().toString()
|
||||
private val nodeLegalName = ALICE_NAME
|
||||
private val intermediateCaName = CordaX500Name("CORDA_INTERMEDIATE_CA", "R3 Ltd", "London", "GB")
|
||||
private val rootCaName = CordaX500Name("CORDA_ROOT_CA", "R3 Ltd", "London", "GB")
|
||||
private val nodeCaCert = createCaCert(nodeLegalName)
|
||||
private val intermediateCaCert = createCaCert(intermediateCaName)
|
||||
private val rootCaCert = createCaCert(rootCaName)
|
||||
|
||||
private lateinit var rootCaCert: X509Certificate
|
||||
private lateinit var intermediateCaCert: X509Certificate
|
||||
private lateinit var nodeCaCert: X509Certificate
|
||||
private lateinit var config: NodeConfiguration
|
||||
|
||||
@Before
|
||||
fun init() {
|
||||
val (rootCa, intermediateCa, nodeCa) = createDevNodeCaCertPath(nodeLegalName)
|
||||
this.rootCaCert = rootCa.certificate.cert
|
||||
this.intermediateCaCert = intermediateCa.certificate.cert
|
||||
this.nodeCaCert = nodeCa.certificate.cert
|
||||
|
||||
val baseDirectory = fs.getPath("/baseDir").createDirectories()
|
||||
abstract class AbstractNodeConfiguration : NodeConfiguration
|
||||
config = rigorousMock<AbstractNodeConfiguration>().also {
|
||||
@ -108,11 +113,13 @@ class NetworkRegistrationHelperTest {
|
||||
|
||||
@Test
|
||||
fun `wrong root cert in truststore`() {
|
||||
saveTrustStoreWithRootCa(createCaCert(CordaX500Name("Foo", "MU", "GB")))
|
||||
val rootKeyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
||||
val rootCert = X509Utilities.createSelfSignedCACertificate(CordaX500Name("Foo", "MU", "GB"), rootKeyPair)
|
||||
saveTrustStoreWithRootCa(rootCert.cert)
|
||||
val registrationHelper = createRegistrationHelper()
|
||||
assertThatThrownBy {
|
||||
registrationHelper.buildKeystore()
|
||||
}.isInstanceOf(WrongRootCertException::class.java)
|
||||
}.isInstanceOf(CertPathValidatorException::class.java)
|
||||
}
|
||||
|
||||
private fun createRegistrationHelper(): NetworkRegistrationHelper {
|
||||
@ -123,15 +130,11 @@ class NetworkRegistrationHelperTest {
|
||||
return NetworkRegistrationHelper(config, certService)
|
||||
}
|
||||
|
||||
private fun saveTrustStoreWithRootCa(rootCa: X509Certificate) {
|
||||
config.trustStoreFile.parent.createDirectories()
|
||||
private fun saveTrustStoreWithRootCa(rootCert: X509Certificate) {
|
||||
config.certificatesDirectory.createDirectories()
|
||||
loadOrCreateKeyStore(config.trustStoreFile, config.trustStorePassword).also {
|
||||
it.addOrReplaceCertificate(X509Utilities.CORDA_ROOT_CA, rootCa)
|
||||
it.addOrReplaceCertificate(X509Utilities.CORDA_ROOT_CA, rootCert)
|
||||
it.save(config.trustStoreFile, config.trustStorePassword)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createCaCert(name: CordaX500Name): X509Certificate {
|
||||
return X509Utilities.createSelfSignedCACertificate(name, Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)).cert
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ import net.corda.core.utilities.NetworkHostAndPort
|
||||
import net.corda.node.services.config.BFTSMaRtConfiguration
|
||||
import net.corda.node.services.config.NotaryConfig
|
||||
import net.corda.node.services.transactions.minCorrectReplicas
|
||||
import net.corda.nodeapi.internal.IdentityGenerator
|
||||
import net.corda.nodeapi.internal.DevIdentityGenerator
|
||||
import net.corda.testing.node.internal.demorun.*
|
||||
import net.corda.testing.ALICE_NAME
|
||||
import net.corda.testing.BOB_NAME
|
||||
@ -62,7 +62,7 @@ class BFTNotaryCordform : CordformDefinition() {
|
||||
}
|
||||
|
||||
override fun setup(context: CordformContext) {
|
||||
IdentityGenerator.generateDistributedNotaryIdentity(
|
||||
DevIdentityGenerator.generateDistributedNotaryIdentity(
|
||||
notaryNames.map { context.baseDirectory(it.toString()) },
|
||||
clusterName,
|
||||
minCorrectReplicas(clusterSize)
|
||||
|
@ -7,7 +7,7 @@ import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.utilities.NetworkHostAndPort
|
||||
import net.corda.node.services.config.NotaryConfig
|
||||
import net.corda.node.services.config.RaftConfig
|
||||
import net.corda.nodeapi.internal.IdentityGenerator
|
||||
import net.corda.nodeapi.internal.DevIdentityGenerator
|
||||
import net.corda.testing.node.internal.demorun.*
|
||||
import net.corda.testing.ALICE_NAME
|
||||
import net.corda.testing.BOB_NAME
|
||||
@ -58,7 +58,7 @@ class RaftNotaryCordform : CordformDefinition() {
|
||||
}
|
||||
|
||||
override fun setup(context: CordformContext) {
|
||||
IdentityGenerator.generateDistributedNotaryIdentity(
|
||||
DevIdentityGenerator.generateDistributedNotaryIdentity(
|
||||
notaryNames.map { context.baseDirectory(it.toString()) },
|
||||
clusterName
|
||||
)
|
||||
|
@ -38,7 +38,7 @@ import net.corda.node.services.transactions.BFTSMaRt
|
||||
import net.corda.node.services.transactions.InMemoryTransactionVerifierService
|
||||
import net.corda.node.utilities.AffinityExecutor
|
||||
import net.corda.node.utilities.AffinityExecutor.ServiceAffinityExecutor
|
||||
import net.corda.nodeapi.internal.IdentityGenerator
|
||||
import net.corda.nodeapi.internal.DevIdentityGenerator
|
||||
import net.corda.nodeapi.internal.config.User
|
||||
import net.corda.nodeapi.internal.network.NetworkParametersCopier
|
||||
import net.corda.nodeapi.internal.network.NotaryInfo
|
||||
@ -235,7 +235,7 @@ open class MockNetwork(private val cordappPackages: List<String>,
|
||||
|
||||
private fun generateNotaryIdentities(): List<NotaryInfo> {
|
||||
return notarySpecs.mapIndexed { index, (name, validating) ->
|
||||
val identity = IdentityGenerator.installKeyStoreWithNodeIdentity(baseDirectory(nextNodeId + index), name)
|
||||
val identity = DevIdentityGenerator.installKeyStoreWithNodeIdentity(baseDirectory(nextNodeId + index), name)
|
||||
NotaryInfo(identity, validating)
|
||||
}
|
||||
}
|
||||
|
@ -10,10 +10,12 @@ import net.corda.cordform.CordformContext
|
||||
import net.corda.cordform.CordformNode
|
||||
import net.corda.core.concurrent.CordaFuture
|
||||
import net.corda.core.concurrent.firstOf
|
||||
import net.corda.core.crypto.random63BitValue
|
||||
import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.internal.*
|
||||
import net.corda.core.internal.ThreadBox
|
||||
import net.corda.core.internal.concurrent.*
|
||||
import net.corda.core.internal.copyTo
|
||||
import net.corda.core.internal.createDirectories
|
||||
import net.corda.core.internal.div
|
||||
import net.corda.core.messaging.CordaRPCOps
|
||||
import net.corda.core.node.services.NetworkMapCache
|
||||
import net.corda.core.toFuture
|
||||
@ -28,7 +30,7 @@ import net.corda.node.services.Permissions
|
||||
import net.corda.node.services.config.*
|
||||
import net.corda.node.utilities.registration.HTTPNetworkRegistrationService
|
||||
import net.corda.node.utilities.registration.NetworkRegistrationHelper
|
||||
import net.corda.nodeapi.internal.IdentityGenerator
|
||||
import net.corda.nodeapi.internal.DevIdentityGenerator
|
||||
import net.corda.nodeapi.internal.addShutdownHook
|
||||
import net.corda.nodeapi.internal.config.User
|
||||
import net.corda.nodeapi.internal.config.parseAs
|
||||
@ -37,13 +39,13 @@ import net.corda.nodeapi.internal.crypto.X509Utilities
|
||||
import net.corda.nodeapi.internal.crypto.addOrReplaceCertificate
|
||||
import net.corda.nodeapi.internal.crypto.loadOrCreateKeyStore
|
||||
import net.corda.nodeapi.internal.crypto.save
|
||||
import net.corda.nodeapi.internal.network.NetworkParameters
|
||||
import net.corda.nodeapi.internal.network.NetworkParametersCopier
|
||||
import net.corda.nodeapi.internal.network.NodeInfoFilesCopier
|
||||
import net.corda.nodeapi.internal.network.NotaryInfo
|
||||
import net.corda.testing.ALICE_NAME
|
||||
import net.corda.testing.BOB_NAME
|
||||
import net.corda.testing.DUMMY_BANK_A_NAME
|
||||
import net.corda.nodeapi.internal.network.NetworkParameters
|
||||
import net.corda.testing.common.internal.testNetworkParameters
|
||||
import net.corda.testing.driver.*
|
||||
import net.corda.testing.node.ClusterSpec
|
||||
@ -66,7 +68,7 @@ import java.nio.file.StandardCopyOption
|
||||
import java.security.cert.X509Certificate
|
||||
import java.time.Duration
|
||||
import java.time.Instant
|
||||
import java.time.ZoneOffset
|
||||
import java.time.ZoneOffset.UTC
|
||||
import java.time.format.DateTimeFormatter
|
||||
import java.util.*
|
||||
import java.util.concurrent.Executors
|
||||
@ -266,13 +268,13 @@ class DriverDSLImpl(
|
||||
clusterNodes.put(ClusterType.NON_VALIDATING_BFT, name)
|
||||
} else {
|
||||
// We have all we need here to generate the identity for single node notaries
|
||||
val identity = IdentityGenerator.installKeyStoreWithNodeIdentity(baseDirectory(name), legalName = name)
|
||||
val identity = DevIdentityGenerator.installKeyStoreWithNodeIdentity(baseDirectory(name), legalName = name)
|
||||
notaryInfos += NotaryInfo(identity, notaryConfig.validating)
|
||||
}
|
||||
}
|
||||
|
||||
clusterNodes.asMap().forEach { type, nodeNames ->
|
||||
val identity = IdentityGenerator.generateDistributedNotaryIdentity(
|
||||
val identity = DevIdentityGenerator.generateDistributedNotaryIdentity(
|
||||
dirs = nodeNames.map { baseDirectory(it) },
|
||||
notaryName = type.clusterName
|
||||
)
|
||||
@ -360,9 +362,9 @@ class DriverDSLImpl(
|
||||
private fun generateNotaryIdentities(): List<NotaryInfo> {
|
||||
return notarySpecs.map { spec ->
|
||||
val identity = if (spec.cluster == null) {
|
||||
IdentityGenerator.installKeyStoreWithNodeIdentity(baseDirectory(spec.name), spec.name, compatibilityZone?.rootCert)
|
||||
DevIdentityGenerator.installKeyStoreWithNodeIdentity(baseDirectory(spec.name), spec.name, compatibilityZone?.rootCert)
|
||||
} else {
|
||||
IdentityGenerator.generateDistributedNotaryIdentity(
|
||||
DevIdentityGenerator.generateDistributedNotaryIdentity(
|
||||
dirs = generateNodeNames(spec).map { baseDirectory(it) },
|
||||
notaryName = spec.name,
|
||||
customRootCert = compatibilityZone?.rootCert
|
||||
@ -890,8 +892,7 @@ fun <A> internalDriver(
|
||||
}
|
||||
|
||||
fun getTimestampAsDirectoryName(): String {
|
||||
// Add a random number in case 2 tests are started in the same instant.
|
||||
return DateTimeFormatter.ofPattern("yyyyMMddHHmmss").withZone(ZoneOffset.UTC).format(Instant.now()) + random63BitValue()
|
||||
return DateTimeFormatter.ofPattern("yyyyMMdd-HHmmss.SSS").withZone(UTC).format(Instant.now())
|
||||
}
|
||||
|
||||
fun writeConfig(path: Path, filename: String, config: Config) {
|
||||
|
@ -1,26 +1,21 @@
|
||||
package net.corda.testing.node.internal.network
|
||||
|
||||
import net.corda.core.crypto.Crypto
|
||||
import net.corda.core.crypto.SecureHash
|
||||
import net.corda.core.crypto.SignedData
|
||||
import net.corda.core.crypto.sha256
|
||||
import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.crypto.*
|
||||
import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.internal.cert
|
||||
import net.corda.core.internal.toX509CertHolder
|
||||
import net.corda.core.node.NodeInfo
|
||||
import net.corda.core.serialization.SerializedBytes
|
||||
import net.corda.core.serialization.deserialize
|
||||
import net.corda.core.serialization.serialize
|
||||
import net.corda.core.utilities.NetworkHostAndPort
|
||||
import net.corda.nodeapi.internal.SignedNodeInfo
|
||||
import net.corda.nodeapi.internal.crypto.CertificateAndKeyPair
|
||||
import net.corda.nodeapi.internal.crypto.CertificateType
|
||||
import net.corda.nodeapi.internal.crypto.X509Utilities
|
||||
import net.corda.nodeapi.internal.network.DigitalSignatureWithCert
|
||||
import net.corda.nodeapi.internal.network.NetworkMap
|
||||
import net.corda.nodeapi.internal.network.NetworkParameters
|
||||
import net.corda.nodeapi.internal.network.SignedNetworkMap
|
||||
import net.corda.nodeapi.internal.*
|
||||
import net.corda.nodeapi.internal.crypto.CertificateAndKeyPair
|
||||
import net.corda.nodeapi.internal.crypto.CertificateType
|
||||
import net.corda.nodeapi.internal.crypto.X509Utilities
|
||||
import net.corda.testing.ROOT_CA
|
||||
import org.eclipse.jetty.server.Server
|
||||
import org.eclipse.jetty.server.ServerConnector
|
||||
@ -50,7 +45,7 @@ class NetworkMapServer(cacheTimeout: Duration,
|
||||
private fun networkMapKeyAndCert(rootCAKeyAndCert: CertificateAndKeyPair): CertificateAndKeyPair {
|
||||
val networkMapKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
||||
val networkMapCert = X509Utilities.createCertificate(
|
||||
CertificateType.INTERMEDIATE_CA,
|
||||
CertificateType.NETWORK_MAP,
|
||||
rootCAKeyAndCert.certificate,
|
||||
rootCAKeyAndCert.keyPair,
|
||||
CordaX500Name("Corda Network Map", "R3 Ltd", "London","GB"),
|
||||
|
@ -5,24 +5,24 @@ package net.corda.testing
|
||||
|
||||
import net.corda.core.contracts.PartyAndReference
|
||||
import net.corda.core.contracts.StateRef
|
||||
import net.corda.core.crypto.*
|
||||
import net.corda.core.crypto.SecureHash
|
||||
import net.corda.core.crypto.entropyToKeyPair
|
||||
import net.corda.core.crypto.generateKeyPair
|
||||
import net.corda.core.crypto.toStringShort
|
||||
import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.identity.PartyAndCertificate
|
||||
import net.corda.core.internal.cert
|
||||
import net.corda.core.internal.unspecifiedCountry
|
||||
import net.corda.core.internal.x500Name
|
||||
import net.corda.core.node.NodeInfo
|
||||
import net.corda.core.utilities.NetworkHostAndPort
|
||||
import net.corda.node.services.config.configureDevKeyAndTrustStores
|
||||
import net.corda.nodeapi.internal.config.SSLConfiguration
|
||||
import net.corda.nodeapi.internal.createDevNodeCa
|
||||
import net.corda.nodeapi.internal.crypto.CertificateAndKeyPair
|
||||
import net.corda.nodeapi.internal.crypto.CertificateType
|
||||
import net.corda.nodeapi.internal.crypto.X509CertificateFactory
|
||||
import net.corda.nodeapi.internal.crypto.X509Utilities
|
||||
import org.bouncycastle.asn1.x509.GeneralName
|
||||
import org.bouncycastle.asn1.x509.GeneralSubtree
|
||||
import org.bouncycastle.asn1.x509.NameConstraints
|
||||
import org.bouncycastle.cert.X509CertificateHolder
|
||||
import java.math.BigInteger
|
||||
import java.nio.file.Files
|
||||
@ -92,15 +92,7 @@ fun getTestPartyAndCertificate(party: Party): PartyAndCertificate {
|
||||
val trustRoot: X509CertificateHolder = DEV_TRUST_ROOT
|
||||
val intermediate: CertificateAndKeyPair = DEV_CA
|
||||
|
||||
|
||||
val nodeCaKeyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
||||
val nodeCaCert = X509Utilities.createCertificate(
|
||||
CertificateType.NODE_CA,
|
||||
intermediate.certificate,
|
||||
intermediate.keyPair,
|
||||
party.name,
|
||||
nodeCaKeyPair.public,
|
||||
nameConstraints = NameConstraints(arrayOf(GeneralSubtree(GeneralName(GeneralName.directoryName, party.name.x500Name))), arrayOf()))
|
||||
val (nodeCaCert, nodeCaKeyPair) = createDevNodeCa(intermediate, party.name)
|
||||
|
||||
val identityCert = X509Utilities.createCertificate(
|
||||
CertificateType.LEGAL_IDENTITY,
|
||||
|
@ -1,6 +1,12 @@
|
||||
package net.corda.testing.internal
|
||||
|
||||
import net.corda.core.crypto.Crypto
|
||||
import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.utilities.loggerFor
|
||||
import net.corda.nodeapi.internal.createDevNodeCa
|
||||
import net.corda.nodeapi.internal.crypto.CertificateAndKeyPair
|
||||
import net.corda.nodeapi.internal.crypto.CertificateType
|
||||
import net.corda.nodeapi.internal.crypto.X509Utilities
|
||||
import net.corda.nodeapi.internal.serialization.amqp.AMQP_ENABLED
|
||||
import org.mockito.Mockito
|
||||
import org.mockito.internal.stubbing.answers.ThrowsException
|
||||
@ -42,3 +48,44 @@ fun <T> rigorousMock(clazz: Class<T>): T = Mockito.mock(clazz) {
|
||||
it.callRealMethod()
|
||||
}
|
||||
}
|
||||
|
||||
private val defaultRootCaName = CordaX500Name("Corda Root CA", "R3 Ltd", "London", "GB")
|
||||
private val defaultIntermediateCaName = CordaX500Name("Corda Intermediate CA", "R3 Ltd", "London", "GB")
|
||||
|
||||
/**
|
||||
* Returns a pair of [CertificateAndKeyPair]s, the first being the root CA and the second the intermediate CA.
|
||||
* @param rootCaName The subject name for the root CA cert.
|
||||
* @param intermediateCaName The subject name for the intermediate CA cert.
|
||||
*/
|
||||
fun createDevIntermediateCaCertPath(
|
||||
rootCaName: CordaX500Name = defaultRootCaName,
|
||||
intermediateCaName: CordaX500Name = defaultIntermediateCaName
|
||||
): Pair<CertificateAndKeyPair, CertificateAndKeyPair> {
|
||||
val rootKeyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
||||
val rootCert = X509Utilities.createSelfSignedCACertificate(rootCaName, rootKeyPair)
|
||||
|
||||
val intermediateCaKeyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
||||
val intermediateCaCert = X509Utilities.createCertificate(
|
||||
CertificateType.INTERMEDIATE_CA,
|
||||
rootCert,
|
||||
rootKeyPair,
|
||||
intermediateCaName,
|
||||
intermediateCaKeyPair.public)
|
||||
|
||||
return Pair(CertificateAndKeyPair(rootCert, rootKeyPair), CertificateAndKeyPair(intermediateCaCert, intermediateCaKeyPair))
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a triple of [CertificateAndKeyPair]s, the first being the root CA, the second the intermediate CA and the third
|
||||
* the node CA.
|
||||
* @param legalName The subject name for the node CA cert.
|
||||
*/
|
||||
fun createDevNodeCaCertPath(
|
||||
legalName: CordaX500Name,
|
||||
rootCaName: CordaX500Name = defaultRootCaName,
|
||||
intermediateCaName: CordaX500Name = defaultIntermediateCaName
|
||||
): Triple<CertificateAndKeyPair, CertificateAndKeyPair, CertificateAndKeyPair> {
|
||||
val (rootCa, intermediateCa) = createDevIntermediateCaCertPath(rootCaName, intermediateCaName)
|
||||
val nodeCa = createDevNodeCa(intermediateCa, legalName)
|
||||
return Triple(rootCa, intermediateCa, nodeCa)
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ import net.corda.demobench.pty.R3Pty
|
||||
import net.corda.nodeapi.internal.network.NetworkParameters
|
||||
import net.corda.nodeapi.internal.network.NetworkParametersCopier
|
||||
import net.corda.nodeapi.internal.network.NotaryInfo
|
||||
import net.corda.nodeapi.internal.IdentityGenerator
|
||||
import net.corda.nodeapi.internal.DevIdentityGenerator
|
||||
import tornadofx.*
|
||||
import java.io.IOException
|
||||
import java.lang.management.ManagementFactory
|
||||
@ -153,7 +153,7 @@ class NodeController(check: atRuntime = ::checkExists) : Controller() {
|
||||
|
||||
// Generate notary identity and save it into node's directory. This identity will be used in network parameters.
|
||||
private fun getNotaryIdentity(config: NodeConfigWrapper): Party {
|
||||
return IdentityGenerator.installKeyStoreWithNodeIdentity(config.nodeDir, config.nodeConfig.myLegalName)
|
||||
return DevIdentityGenerator.installKeyStoreWithNodeIdentity(config.nodeDir, config.nodeConfig.myLegalName)
|
||||
}
|
||||
|
||||
fun reset() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user