mirror of
https://github.com/corda/corda.git
synced 2025-05-02 16:53:22 +00:00
Moved X509Utilities, and some other crypto utilities in node, into node-api so that they can be used by services outside of the node.
There's also some cleanup as well.
This commit is contained in:
parent
0e3713237b
commit
2ceb6283af
@ -8,7 +8,7 @@ import net.corda.core.internal.div
|
|||||||
import net.corda.core.serialization.serialize
|
import net.corda.core.serialization.serialize
|
||||||
import net.corda.core.utilities.OpaqueBytes
|
import net.corda.core.utilities.OpaqueBytes
|
||||||
import net.corda.core.utilities.toBase58String
|
import net.corda.core.utilities.toBase58String
|
||||||
import net.corda.node.utilities.*
|
import net.corda.nodeapi.internal.crypto.*
|
||||||
import net.corda.testing.kryoSpecific
|
import net.corda.testing.kryoSpecific
|
||||||
import net.corda.testing.SerializationEnvironmentRule
|
import net.corda.testing.SerializationEnvironmentRule
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
|
@ -3,7 +3,7 @@ package net.corda.core.crypto
|
|||||||
import net.corda.core.identity.CordaX500Name
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.internal.toTypedArray
|
import net.corda.core.internal.toTypedArray
|
||||||
import net.corda.core.internal.cert
|
import net.corda.core.internal.cert
|
||||||
import net.corda.node.utilities.*
|
import net.corda.nodeapi.internal.crypto.*
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
import org.bouncycastle.asn1.x500.X500Name
|
||||||
import org.bouncycastle.asn1.x509.GeneralName
|
import org.bouncycastle.asn1.x509.GeneralName
|
||||||
import org.bouncycastle.asn1.x509.GeneralSubtree
|
import org.bouncycastle.asn1.x509.GeneralSubtree
|
||||||
@ -50,7 +50,7 @@ class X509NameConstraintsTest {
|
|||||||
|
|
||||||
val nameConstraints = NameConstraints(acceptableNames, arrayOf())
|
val nameConstraints = NameConstraints(acceptableNames, arrayOf())
|
||||||
val pathValidator = CertPathValidator.getInstance("PKIX")
|
val pathValidator = CertPathValidator.getInstance("PKIX")
|
||||||
val certFactory = CertificateFactory.getInstance("X509")
|
val certFactory = X509CertificateFactory().delegate
|
||||||
|
|
||||||
assertFailsWith(CertPathValidatorException::class) {
|
assertFailsWith(CertPathValidatorException::class) {
|
||||||
val (keystore, trustStore) = makeKeyStores(X500Name("CN=Bank B"), nameConstraints)
|
val (keystore, trustStore) = makeKeyStores(X500Name("CN=Bank B"), nameConstraints)
|
||||||
@ -85,7 +85,7 @@ class X509NameConstraintsTest {
|
|||||||
.map { GeneralSubtree(GeneralName(X500Name(it))) }.toTypedArray()
|
.map { GeneralSubtree(GeneralName(X500Name(it))) }.toTypedArray()
|
||||||
|
|
||||||
val nameConstraints = NameConstraints(acceptableNames, arrayOf())
|
val nameConstraints = NameConstraints(acceptableNames, arrayOf())
|
||||||
val certFactory = CertificateFactory.getInstance("X509")
|
val certFactory = X509CertificateFactory().delegate
|
||||||
Crypto.ECDSA_SECP256R1_SHA256
|
Crypto.ECDSA_SECP256R1_SHA256
|
||||||
val pathValidator = CertPathValidator.getInstance("PKIX", BouncyCastleProvider.PROVIDER_NAME)
|
val pathValidator = CertPathValidator.getInstance("PKIX", BouncyCastleProvider.PROVIDER_NAME)
|
||||||
|
|
||||||
|
@ -4,8 +4,8 @@ import net.corda.core.crypto.entropyToKeyPair
|
|||||||
import net.corda.core.internal.read
|
import net.corda.core.internal.read
|
||||||
import net.corda.core.serialization.deserialize
|
import net.corda.core.serialization.deserialize
|
||||||
import net.corda.core.serialization.serialize
|
import net.corda.core.serialization.serialize
|
||||||
import net.corda.node.utilities.KEYSTORE_TYPE
|
import net.corda.nodeapi.internal.crypto.KEYSTORE_TYPE
|
||||||
import net.corda.node.utilities.save
|
import net.corda.nodeapi.internal.crypto.save
|
||||||
import net.corda.testing.SerializationEnvironmentRule
|
import net.corda.testing.SerializationEnvironmentRule
|
||||||
import net.corda.testing.getTestPartyAndCertificate
|
import net.corda.testing.getTestPartyAndCertificate
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package net.corda.node.utilities
|
package net.corda.nodeapi.internal.crypto
|
||||||
|
|
||||||
import net.corda.core.crypto.SignatureScheme
|
import net.corda.core.crypto.SignatureScheme
|
||||||
import org.bouncycastle.asn1.x509.AlgorithmIdentifier
|
import org.bouncycastle.asn1.x509.AlgorithmIdentifier
|
@ -1,9 +1,8 @@
|
|||||||
@file:JvmName("KeyStoreUtilities")
|
@file:JvmName("KeyStoreUtilities")
|
||||||
|
|
||||||
package net.corda.node.utilities
|
package net.corda.nodeapi.internal.crypto
|
||||||
|
|
||||||
import net.corda.core.crypto.Crypto
|
import net.corda.core.crypto.Crypto
|
||||||
import net.corda.core.identity.CordaX500Name
|
|
||||||
import net.corda.core.internal.*
|
import net.corda.core.internal.*
|
||||||
import org.bouncycastle.cert.X509CertificateHolder
|
import org.bouncycastle.cert.X509CertificateHolder
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
@ -11,9 +10,7 @@ import java.io.InputStream
|
|||||||
import java.io.OutputStream
|
import java.io.OutputStream
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import java.security.*
|
import java.security.*
|
||||||
import java.security.cert.CertPath
|
|
||||||
import java.security.cert.Certificate
|
import java.security.cert.Certificate
|
||||||
import java.security.cert.CertificateFactory
|
|
||||||
import java.security.cert.X509Certificate
|
import java.security.cert.X509Certificate
|
||||||
|
|
||||||
const val KEYSTORE_TYPE = "JKS"
|
const val KEYSTORE_TYPE = "JKS"
|
||||||
@ -169,44 +166,3 @@ fun KeyStore.getSupportedKey(alias: String, keyPassword: String): PrivateKey {
|
|||||||
val key = getKey(alias, keyPass) as PrivateKey
|
val key = getKey(alias, keyPass) as PrivateKey
|
||||||
return Crypto.toSupportedPrivateKey(key)
|
return Crypto.toSupportedPrivateKey(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
class KeyStoreWrapper(private val storePath: Path, private val storePassword: String) {
|
|
||||||
private val keyStore = storePath.read { loadKeyStore(it, storePassword) }
|
|
||||||
|
|
||||||
private fun createCertificate(serviceName: CordaX500Name, pubKey: PublicKey): CertPath {
|
|
||||||
val clientCertPath = keyStore.getCertificateChain(X509Utilities.CORDA_CLIENT_CA)
|
|
||||||
// Assume key password = store password.
|
|
||||||
val clientCA = certificateAndKeyPair(X509Utilities.CORDA_CLIENT_CA)
|
|
||||||
// Create new keys and store in keystore.
|
|
||||||
val cert = X509Utilities.createCertificate(CertificateType.IDENTITY, clientCA.certificate, clientCA.keyPair, serviceName, pubKey)
|
|
||||||
val certPath = CertificateFactory.getInstance("X509").generateCertPath(listOf(cert.cert) + clientCertPath)
|
|
||||||
require(certPath.certificates.isNotEmpty()) { "Certificate path cannot be empty" }
|
|
||||||
// TODO: X509Utilities.validateCertificateChain()
|
|
||||||
return certPath
|
|
||||||
}
|
|
||||||
|
|
||||||
fun signAndSaveNewKeyPair(serviceName: CordaX500Name, privateKeyAlias: String, keyPair: KeyPair) {
|
|
||||||
val certPath = createCertificate(serviceName, keyPair.public)
|
|
||||||
// Assume key password = store password.
|
|
||||||
keyStore.addOrReplaceKey(privateKeyAlias, keyPair.private, storePassword.toCharArray(), certPath.certificates.toTypedArray())
|
|
||||||
keyStore.save(storePath, storePassword)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun savePublicKey(serviceName: CordaX500Name, pubKeyAlias: String, pubKey: PublicKey) {
|
|
||||||
val certPath = createCertificate(serviceName, pubKey)
|
|
||||||
// Assume key password = store password.
|
|
||||||
keyStore.addOrReplaceCertificate(pubKeyAlias, certPath.certificates.first())
|
|
||||||
keyStore.save(storePath, storePassword)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delegate methods to keystore. Sadly keystore doesn't have an interface.
|
|
||||||
fun containsAlias(alias: String) = keyStore.containsAlias(alias)
|
|
||||||
|
|
||||||
fun getX509Certificate(alias: String) = keyStore.getX509Certificate(alias)
|
|
||||||
|
|
||||||
fun getCertificateChain(alias: String): Array<out Certificate> = keyStore.getCertificateChain(alias)
|
|
||||||
|
|
||||||
fun getCertificate(alias: String): Certificate = keyStore.getCertificate(alias)
|
|
||||||
|
|
||||||
fun certificateAndKeyPair(alias: String): CertificateAndKeyPair = keyStore.getCertificateAndKeyPair(alias, storePassword)
|
|
||||||
}
|
|
@ -0,0 +1,52 @@
|
|||||||
|
package net.corda.nodeapi.internal.crypto
|
||||||
|
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
|
import net.corda.core.internal.cert
|
||||||
|
import net.corda.core.internal.read
|
||||||
|
import java.nio.file.Path
|
||||||
|
import java.security.KeyPair
|
||||||
|
import java.security.PublicKey
|
||||||
|
import java.security.cert.CertPath
|
||||||
|
import java.security.cert.Certificate
|
||||||
|
import java.security.cert.CertificateFactory
|
||||||
|
|
||||||
|
class KeyStoreWrapper(private val storePath: Path, private val storePassword: String) {
|
||||||
|
private val keyStore = storePath.read { loadKeyStore(it, storePassword) }
|
||||||
|
|
||||||
|
private fun createCertificate(serviceName: CordaX500Name, pubKey: PublicKey): CertPath {
|
||||||
|
val clientCertPath = keyStore.getCertificateChain(X509Utilities.CORDA_CLIENT_CA)
|
||||||
|
// Assume key password = store password.
|
||||||
|
val clientCA = certificateAndKeyPair(X509Utilities.CORDA_CLIENT_CA)
|
||||||
|
// Create new keys and store in keystore.
|
||||||
|
val cert = X509Utilities.createCertificate(CertificateType.IDENTITY, clientCA.certificate, clientCA.keyPair, serviceName, pubKey)
|
||||||
|
val certPath = X509CertificateFactory().delegate.generateCertPath(listOf(cert.cert) + clientCertPath)
|
||||||
|
require(certPath.certificates.isNotEmpty()) { "Certificate path cannot be empty" }
|
||||||
|
// TODO: X509Utilities.validateCertificateChain()
|
||||||
|
return certPath
|
||||||
|
}
|
||||||
|
|
||||||
|
fun signAndSaveNewKeyPair(serviceName: CordaX500Name, privateKeyAlias: String, keyPair: KeyPair) {
|
||||||
|
val certPath = createCertificate(serviceName, keyPair.public)
|
||||||
|
// Assume key password = store password.
|
||||||
|
keyStore.addOrReplaceKey(privateKeyAlias, keyPair.private, storePassword.toCharArray(), certPath.certificates.toTypedArray())
|
||||||
|
keyStore.save(storePath, storePassword)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun savePublicKey(serviceName: CordaX500Name, pubKeyAlias: String, pubKey: PublicKey) {
|
||||||
|
val certPath = createCertificate(serviceName, pubKey)
|
||||||
|
// Assume key password = store password.
|
||||||
|
keyStore.addOrReplaceCertificate(pubKeyAlias, certPath.certificates.first())
|
||||||
|
keyStore.save(storePath, storePassword)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delegate methods to keystore. Sadly keystore doesn't have an interface.
|
||||||
|
fun containsAlias(alias: String) = keyStore.containsAlias(alias)
|
||||||
|
|
||||||
|
fun getX509Certificate(alias: String) = keyStore.getX509Certificate(alias)
|
||||||
|
|
||||||
|
fun getCertificateChain(alias: String): Array<out Certificate> = keyStore.getCertificateChain(alias)
|
||||||
|
|
||||||
|
fun getCertificate(alias: String): Certificate = keyStore.getCertificate(alias)
|
||||||
|
|
||||||
|
fun certificateAndKeyPair(alias: String): CertificateAndKeyPair = keyStore.getCertificateAndKeyPair(alias, storePassword)
|
||||||
|
}
|
@ -1,9 +1,11 @@
|
|||||||
package net.corda.node.utilities
|
package net.corda.nodeapi.internal.crypto
|
||||||
|
|
||||||
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.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.read
|
||||||
|
import net.corda.core.internal.write
|
||||||
import net.corda.core.internal.x500Name
|
import net.corda.core.internal.x500Name
|
||||||
import net.corda.core.utilities.days
|
import net.corda.core.utilities.days
|
||||||
import net.corda.core.utilities.millis
|
import net.corda.core.utilities.millis
|
||||||
@ -25,10 +27,10 @@ import org.bouncycastle.operator.jcajce.JcaContentVerifierProviderBuilder
|
|||||||
import org.bouncycastle.pkcs.PKCS10CertificationRequest
|
import org.bouncycastle.pkcs.PKCS10CertificationRequest
|
||||||
import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequestBuilder
|
import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequestBuilder
|
||||||
import org.bouncycastle.util.io.pem.PemReader
|
import org.bouncycastle.util.io.pem.PemReader
|
||||||
import java.io.FileReader
|
|
||||||
import java.io.FileWriter
|
import java.io.FileWriter
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import java.math.BigInteger
|
import java.math.BigInteger
|
||||||
|
import java.nio.file.Files
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import java.security.KeyPair
|
import java.security.KeyPair
|
||||||
import java.security.PublicKey
|
import java.security.PublicKey
|
||||||
@ -52,6 +54,7 @@ object X509Utilities {
|
|||||||
const val CORDA_CLIENT_CA_CN = "Corda Client CA Certificate"
|
const val CORDA_CLIENT_CA_CN = "Corda Client CA Certificate"
|
||||||
|
|
||||||
private val DEFAULT_VALIDITY_WINDOW = Pair(0.millis, 3650.days)
|
private val DEFAULT_VALIDITY_WINDOW = Pair(0.millis, 3650.days)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper function to return the latest out of an instant and an optional date.
|
* Helper function to return the latest out of an instant and an optional date.
|
||||||
*/
|
*/
|
||||||
@ -89,7 +92,9 @@ 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: CordaX500Name, 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.x500Name, keyPair, subject.x500Name, keyPair.public, window)
|
return createCertificate(CertificateType.ROOT_CA, subject.x500Name, keyPair, subject.x500Name, keyPair.public, window)
|
||||||
}
|
}
|
||||||
@ -114,8 +119,9 @@ object X509Utilities {
|
|||||||
subject: CordaX500Name,
|
subject: CordaX500Name,
|
||||||
subjectPublicKey: PublicKey,
|
subjectPublicKey: PublicKey,
|
||||||
validityWindow: Pair<Duration, Duration> = DEFAULT_VALIDITY_WINDOW,
|
validityWindow: Pair<Duration, Duration> = DEFAULT_VALIDITY_WINDOW,
|
||||||
nameConstraints: NameConstraints? = null): X509CertificateHolder
|
nameConstraints: NameConstraints? = null): X509CertificateHolder {
|
||||||
= createCertificate(certificateType, issuerCertificate, issuerKeyPair, subject.x500Name, subjectPublicKey, validityWindow, nameConstraints)
|
return createCertificate(certificateType, issuerCertificate, issuerKeyPair, subject.x500Name, subjectPublicKey, validityWindow, nameConstraints)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a X509 v3 certificate for use as a CA or for TLS. This does not require a [CordaX500Name] because the
|
* Create a X509 v3 certificate for use as a CA or for TLS. This does not require a [CordaX500Name] because the
|
||||||
@ -145,10 +151,9 @@ object X509Utilities {
|
|||||||
@Throws(CertPathValidatorException::class)
|
@Throws(CertPathValidatorException::class)
|
||||||
fun validateCertificateChain(trustedRoot: X509Certificate, 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 params = PKIXParameters(setOf(TrustAnchor(trustedRoot, null)))
|
val params = PKIXParameters(setOf(TrustAnchor(trustedRoot, null)))
|
||||||
params.isRevocationEnabled = false
|
params.isRevocationEnabled = false
|
||||||
val certPath = certFactory.generateCertPath(certificates.toList())
|
val certPath = X509CertificateFactory().delegate.generateCertPath(certificates.toList())
|
||||||
val pathValidator = CertPathValidator.getInstance("PKIX")
|
val pathValidator = CertPathValidator.getInstance("PKIX")
|
||||||
pathValidator.validate(certPath, params)
|
pathValidator.validate(certPath, params)
|
||||||
}
|
}
|
||||||
@ -156,30 +161,29 @@ object X509Utilities {
|
|||||||
/**
|
/**
|
||||||
* Helper method to store a .pem/.cer format file copy of a certificate if required for import into a PC/Mac, or for inspection.
|
* Helper method to store a .pem/.cer format file copy of a certificate if required for import into a PC/Mac, or for inspection.
|
||||||
* @param x509Certificate certificate to save.
|
* @param x509Certificate certificate to save.
|
||||||
* @param filename Target filename.
|
* @param file Target file.
|
||||||
*/
|
*/
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun saveCertificateAsPEMFile(x509Certificate: X509CertificateHolder, filename: Path) {
|
fun saveCertificateAsPEMFile(x509Certificate: X509CertificateHolder, file: Path) {
|
||||||
FileWriter(filename.toFile()).use {
|
JcaPEMWriter(file.toFile().writer()).use {
|
||||||
JcaPEMWriter(it).use {
|
it.writeObject(x509Certificate)
|
||||||
it.writeObject(x509Certificate)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper method to load back a .pem/.cer format file copy of a certificate.
|
* Helper method to load back a .pem/.cer format file copy of a certificate.
|
||||||
* @param filename Source filename.
|
* @param file Source file.
|
||||||
* @return The X509Certificate that was encoded in the file.
|
* @return The X509Certificate that was encoded in the file.
|
||||||
*/
|
*/
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun loadCertificateFromPEMFile(filename: Path): X509CertificateHolder {
|
fun loadCertificateFromPEMFile(file: Path): X509CertificateHolder {
|
||||||
val reader = PemReader(FileReader(filename.toFile()))
|
val cert = file.read {
|
||||||
val pemObject = reader.readPemObject()
|
val reader = PemReader(it.reader())
|
||||||
val cert = X509CertificateHolder(pemObject.content)
|
val pemObject = reader.readPemObject()
|
||||||
return cert.apply {
|
X509CertificateHolder(pemObject.content)
|
||||||
isValidOn(Date())
|
|
||||||
}
|
}
|
||||||
|
cert.isValidOn(Date())
|
||||||
|
return cert
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -243,13 +247,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.
|
||||||
*/
|
*/
|
||||||
internal fun createCertificate(certificateType: CertificateType,
|
fun createCertificate(certificateType: CertificateType,
|
||||||
issuer: X500Name,
|
issuer: X500Name,
|
||||||
issuerSigner: ContentSigner,
|
issuerSigner: ContentSigner,
|
||||||
subject: CordaX500Name,
|
subject: CordaX500Name,
|
||||||
subjectPublicKey: PublicKey,
|
subjectPublicKey: PublicKey,
|
||||||
validityWindow: Pair<Date, Date>,
|
validityWindow: Pair<Date, Date>,
|
||||||
nameConstraints: NameConstraints? = null): X509CertificateHolder {
|
nameConstraints: NameConstraints? = null): X509CertificateHolder {
|
||||||
val builder = createCertificate(certificateType, issuer, subject.x500Name, 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()))
|
||||||
@ -266,11 +270,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.
|
||||||
*/
|
*/
|
||||||
internal fun createCertificate(certificateType: CertificateType, issuer: X500Name, issuerKeyPair: KeyPair,
|
fun createCertificate(certificateType: CertificateType,
|
||||||
subject: X500Name, subjectPublicKey: PublicKey,
|
issuer: X500Name,
|
||||||
validityWindow: Pair<Date, Date>,
|
issuerKeyPair: KeyPair,
|
||||||
nameConstraints: NameConstraints? = null): X509CertificateHolder {
|
subject: X500Name,
|
||||||
|
subjectPublicKey: PublicKey,
|
||||||
|
validityWindow: Pair<Date, Date>,
|
||||||
|
nameConstraints: NameConstraints? = null): X509CertificateHolder {
|
||||||
val signatureScheme = Crypto.findSignatureScheme(issuerKeyPair.private)
|
val signatureScheme = Crypto.findSignatureScheme(issuerKeyPair.private)
|
||||||
val provider = Crypto.findProvider(signatureScheme.providerName)
|
val provider = Crypto.findProvider(signatureScheme.providerName)
|
||||||
val builder = createCertificate(certificateType, issuer, subject, subjectPublicKey, validityWindow, nameConstraints)
|
val builder = createCertificate(certificateType, issuer, subject, subjectPublicKey, validityWindow, nameConstraints)
|
||||||
@ -285,28 +291,71 @@ object X509Utilities {
|
|||||||
/**
|
/**
|
||||||
* Create certificate signing request using provided information.
|
* Create certificate signing request using provided information.
|
||||||
*/
|
*/
|
||||||
internal fun createCertificateSigningRequest(subject: CordaX500Name, email: String, keyPair: KeyPair, signatureScheme: SignatureScheme): PKCS10CertificationRequest {
|
private 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.x500Name, 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: CordaX500Name, email: String, keyPair: KeyPair) = createCertificateSigningRequest(subject, email, keyPair, DEFAULT_TLS_SIGNATURE_SCHEME)
|
fun createCertificateSigningRequest(subject: CordaX500Name, email: String, keyPair: KeyPair): PKCS10CertificationRequest {
|
||||||
|
return createCertificateSigningRequest(subject, email, keyPair, DEFAULT_TLS_SIGNATURE_SCHEME)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
class CertificateStream(val input: InputStream) {
|
* Wraps a [CertificateFactory] to remove boilerplate. It's unclear whether [CertificateFactory] is threadsafe so best
|
||||||
private val certificateFactory = CertificateFactory.getInstance("X.509")
|
* so assume this class is not.
|
||||||
|
*/
|
||||||
fun nextCertificate(): X509Certificate = certificateFactory.generateCertificate(input) as X509Certificate
|
class X509CertificateFactory {
|
||||||
|
val delegate: CertificateFactory = CertificateFactory.getInstance("X.509")
|
||||||
|
fun generateCertificate(input: InputStream): X509Certificate {
|
||||||
|
return delegate.generateCertificate(input) as X509Certificate
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class CertificateType(val keyUsage: KeyUsage, vararg val purposes: KeyPurposeId, val isCA: Boolean) {
|
enum class CertificateType(val keyUsage: KeyUsage, vararg val purposes: KeyPurposeId, val isCA: Boolean) {
|
||||||
ROOT_CA(KeyUsage(KeyUsage.digitalSignature or KeyUsage.keyCertSign or KeyUsage.cRLSign), KeyPurposeId.id_kp_serverAuth, KeyPurposeId.id_kp_clientAuth, KeyPurposeId.anyExtendedKeyUsage, isCA = true),
|
ROOT_CA(
|
||||||
INTERMEDIATE_CA(KeyUsage(KeyUsage.digitalSignature or KeyUsage.keyCertSign or KeyUsage.cRLSign), KeyPurposeId.id_kp_serverAuth, KeyPurposeId.id_kp_clientAuth, KeyPurposeId.anyExtendedKeyUsage, isCA = true),
|
KeyUsage(KeyUsage.digitalSignature or KeyUsage.keyCertSign or KeyUsage.cRLSign),
|
||||||
CLIENT_CA(KeyUsage(KeyUsage.digitalSignature or KeyUsage.keyCertSign or KeyUsage.cRLSign), KeyPurposeId.id_kp_serverAuth, KeyPurposeId.id_kp_clientAuth, KeyPurposeId.anyExtendedKeyUsage, isCA = true),
|
KeyPurposeId.id_kp_serverAuth,
|
||||||
TLS(KeyUsage(KeyUsage.digitalSignature or KeyUsage.keyEncipherment or KeyUsage.keyAgreement), KeyPurposeId.id_kp_serverAuth, KeyPurposeId.id_kp_clientAuth, KeyPurposeId.anyExtendedKeyUsage, isCA = false),
|
KeyPurposeId.id_kp_clientAuth,
|
||||||
|
KeyPurposeId.anyExtendedKeyUsage,
|
||||||
|
isCA = true
|
||||||
|
),
|
||||||
|
|
||||||
|
INTERMEDIATE_CA(
|
||||||
|
KeyUsage(KeyUsage.digitalSignature or KeyUsage.keyCertSign or KeyUsage.cRLSign),
|
||||||
|
KeyPurposeId.id_kp_serverAuth,
|
||||||
|
KeyPurposeId.id_kp_clientAuth,
|
||||||
|
KeyPurposeId.anyExtendedKeyUsage,
|
||||||
|
isCA = true
|
||||||
|
),
|
||||||
|
|
||||||
|
CLIENT_CA(
|
||||||
|
KeyUsage(KeyUsage.digitalSignature or KeyUsage.keyCertSign or KeyUsage.cRLSign),
|
||||||
|
KeyPurposeId.id_kp_serverAuth,
|
||||||
|
KeyPurposeId.id_kp_clientAuth,
|
||||||
|
KeyPurposeId.anyExtendedKeyUsage,
|
||||||
|
isCA = true
|
||||||
|
),
|
||||||
|
|
||||||
|
TLS(
|
||||||
|
KeyUsage(KeyUsage.digitalSignature or KeyUsage.keyEncipherment or KeyUsage.keyAgreement),
|
||||||
|
KeyPurposeId.id_kp_serverAuth,
|
||||||
|
KeyPurposeId.id_kp_clientAuth,
|
||||||
|
KeyPurposeId.anyExtendedKeyUsage,
|
||||||
|
isCA = false
|
||||||
|
),
|
||||||
|
|
||||||
// TODO: Identity certs should have only limited depth (i.e. 1) CA signing capability, with tight name constraints
|
// TODO: Identity certs should have only limited depth (i.e. 1) CA signing capability, with tight name constraints
|
||||||
IDENTITY(KeyUsage(KeyUsage.digitalSignature or KeyUsage.keyCertSign), KeyPurposeId.id_kp_serverAuth, KeyPurposeId.id_kp_clientAuth, KeyPurposeId.anyExtendedKeyUsage, isCA = true)
|
IDENTITY(
|
||||||
|
KeyUsage(KeyUsage.digitalSignature or KeyUsage.keyCertSign),
|
||||||
|
KeyPurposeId.id_kp_serverAuth,
|
||||||
|
KeyPurposeId.id_kp_clientAuth,
|
||||||
|
KeyPurposeId.anyExtendedKeyUsage,
|
||||||
|
isCA = true
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
data class CertificateAndKeyPair(val certificate: X509CertificateHolder, val keyPair: KeyPair)
|
data class CertificateAndKeyPair(val certificate: X509CertificateHolder, val keyPair: KeyPair)
|
@ -1,9 +1,9 @@
|
|||||||
package net.corda.nodeapi.internal.serialization.amqp.custom
|
package net.corda.nodeapi.internal.serialization.amqp.custom
|
||||||
|
|
||||||
|
import net.corda.nodeapi.internal.crypto.X509CertificateFactory
|
||||||
import net.corda.nodeapi.internal.serialization.amqp.*
|
import net.corda.nodeapi.internal.serialization.amqp.*
|
||||||
import org.apache.qpid.proton.codec.Data
|
import org.apache.qpid.proton.codec.Data
|
||||||
import java.lang.reflect.Type
|
import java.lang.reflect.Type
|
||||||
import java.security.cert.CertificateFactory
|
|
||||||
import java.security.cert.X509Certificate
|
import java.security.cert.X509Certificate
|
||||||
|
|
||||||
object X509CertificateSerializer : CustomSerializer.Implements<X509Certificate>(X509Certificate::class.java) {
|
object X509CertificateSerializer : CustomSerializer.Implements<X509Certificate>(X509Certificate::class.java) {
|
||||||
@ -22,6 +22,6 @@ object X509CertificateSerializer : CustomSerializer.Implements<X509Certificate>(
|
|||||||
|
|
||||||
override fun readObject(obj: Any, schema: Schema, input: DeserializationInput): X509Certificate {
|
override fun readObject(obj: Any, schema: Schema, input: DeserializationInput): X509Certificate {
|
||||||
val bits = input.readObject(obj, schema, ByteArray::class.java) as ByteArray
|
val bits = input.readObject(obj, schema, ByteArray::class.java) as ByteArray
|
||||||
return CertificateFactory.getInstance("X.509").generateCertificate(bits.inputStream()) as X509Certificate
|
return X509CertificateFactory().generateCertificate(bits.inputStream())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@ import net.corda.core.serialization.SerializedBytes
|
|||||||
import net.corda.core.toFuture
|
import net.corda.core.toFuture
|
||||||
import net.corda.core.toObservable
|
import net.corda.core.toObservable
|
||||||
import net.corda.core.transactions.*
|
import net.corda.core.transactions.*
|
||||||
|
import net.corda.nodeapi.internal.crypto.X509CertificateFactory
|
||||||
import net.corda.nodeapi.internal.serialization.CordaClassResolver
|
import net.corda.nodeapi.internal.serialization.CordaClassResolver
|
||||||
import net.corda.nodeapi.internal.serialization.serializationContextKey
|
import net.corda.nodeapi.internal.serialization.serializationContextKey
|
||||||
import org.slf4j.Logger
|
import org.slf4j.Logger
|
||||||
@ -486,8 +487,7 @@ object CertPathSerializer : Serializer<CertPath>() {
|
|||||||
@ThreadSafe
|
@ThreadSafe
|
||||||
object X509CertificateSerializer : Serializer<X509Certificate>() {
|
object X509CertificateSerializer : Serializer<X509Certificate>() {
|
||||||
override fun read(kryo: Kryo, input: Input, type: Class<X509Certificate>): X509Certificate {
|
override fun read(kryo: Kryo, input: Input, type: Class<X509Certificate>): X509Certificate {
|
||||||
val factory = CertificateFactory.getInstance("X.509")
|
return X509CertificateFactory().generateCertificate(input.readBytesWithLength().inputStream())
|
||||||
return factory.generateCertificate(input.readBytesWithLength().inputStream()) as X509Certificate
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun write(kryo: Kryo, output: Output, obj: X509Certificate) {
|
override fun write(kryo: Kryo, output: Output, obj: X509Certificate) {
|
||||||
|
@ -2,11 +2,11 @@ package net.corda.services.messaging
|
|||||||
|
|
||||||
import net.corda.core.crypto.Crypto
|
import net.corda.core.crypto.Crypto
|
||||||
import net.corda.core.internal.*
|
import net.corda.core.internal.*
|
||||||
import net.corda.node.utilities.*
|
|
||||||
import net.corda.nodeapi.internal.ArtemisMessagingComponent.Companion.NODE_USER
|
import net.corda.nodeapi.internal.ArtemisMessagingComponent.Companion.NODE_USER
|
||||||
import net.corda.nodeapi.internal.ArtemisMessagingComponent.Companion.PEER_USER
|
import net.corda.nodeapi.internal.ArtemisMessagingComponent.Companion.PEER_USER
|
||||||
import net.corda.nodeapi.RPCApi
|
import net.corda.nodeapi.RPCApi
|
||||||
import net.corda.nodeapi.config.SSLConfiguration
|
import net.corda.nodeapi.config.SSLConfiguration
|
||||||
|
import net.corda.nodeapi.internal.crypto.*
|
||||||
import net.corda.testing.MEGA_CORP
|
import net.corda.testing.MEGA_CORP
|
||||||
import net.corda.testing.MINI_CORP
|
import net.corda.testing.MINI_CORP
|
||||||
import net.corda.testing.messaging.SimpleMQClient
|
import net.corda.testing.messaging.SimpleMQClient
|
||||||
|
@ -57,7 +57,10 @@ import net.corda.node.services.upgrade.ContractUpgradeServiceImpl
|
|||||||
import net.corda.node.services.vault.NodeVaultService
|
import net.corda.node.services.vault.NodeVaultService
|
||||||
import net.corda.node.services.vault.VaultSoftLockManager
|
import net.corda.node.services.vault.VaultSoftLockManager
|
||||||
import net.corda.node.shell.InteractiveShell
|
import net.corda.node.shell.InteractiveShell
|
||||||
import net.corda.node.utilities.*
|
import net.corda.node.utilities.AffinityExecutor
|
||||||
|
import net.corda.node.utilities.CordaPersistence
|
||||||
|
import net.corda.node.utilities.configureDatabase
|
||||||
|
import net.corda.nodeapi.internal.crypto.*
|
||||||
import org.apache.activemq.artemis.utils.ReusableLatch
|
import org.apache.activemq.artemis.utils.ReusableLatch
|
||||||
import org.slf4j.Logger
|
import org.slf4j.Logger
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
@ -66,7 +69,6 @@ import java.lang.reflect.InvocationTargetException
|
|||||||
import java.security.KeyPair
|
import java.security.KeyPair
|
||||||
import java.security.KeyStoreException
|
import java.security.KeyStoreException
|
||||||
import java.security.PublicKey
|
import java.security.PublicKey
|
||||||
import java.security.cert.CertificateFactory
|
|
||||||
import java.security.cert.X509Certificate
|
import java.security.cert.X509Certificate
|
||||||
import java.sql.Connection
|
import java.sql.Connection
|
||||||
import java.time.Clock
|
import java.time.Clock
|
||||||
@ -697,7 +699,7 @@ abstract class AbstractNode(val configuration: NodeConfiguration,
|
|||||||
throw ConfigurationException("The name '$singleName' for $id doesn't match what's in the key store: $subject")
|
throw ConfigurationException("The name '$singleName' for $id doesn't match what's in the key store: $subject")
|
||||||
}
|
}
|
||||||
|
|
||||||
val certPath = CertificateFactory.getInstance("X509").generateCertPath(certificates)
|
val certPath = X509CertificateFactory().delegate.generateCertPath(certificates)
|
||||||
return Pair(PartyAndCertificate(certPath), keyPair)
|
return Pair(PartyAndCertificate(certPath), keyPair)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,8 +8,8 @@ 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.*
|
import net.corda.core.internal.*
|
||||||
import net.corda.node.utilities.*
|
|
||||||
import net.corda.nodeapi.config.SSLConfiguration
|
import net.corda.nodeapi.config.SSLConfiguration
|
||||||
|
import net.corda.nodeapi.internal.crypto.*
|
||||||
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
|
||||||
|
@ -10,6 +10,7 @@ import net.corda.core.node.services.UnknownAnonymousPartyException
|
|||||||
import net.corda.core.serialization.SingletonSerializeAsToken
|
import net.corda.core.serialization.SingletonSerializeAsToken
|
||||||
import net.corda.core.utilities.contextLogger
|
import net.corda.core.utilities.contextLogger
|
||||||
import net.corda.core.utilities.trace
|
import net.corda.core.utilities.trace
|
||||||
|
import net.corda.nodeapi.internal.crypto.X509CertificateFactory
|
||||||
import org.bouncycastle.cert.X509CertificateHolder
|
import org.bouncycastle.cert.X509CertificateHolder
|
||||||
import java.security.InvalidAlgorithmParameterException
|
import java.security.InvalidAlgorithmParameterException
|
||||||
import java.security.PublicKey
|
import java.security.PublicKey
|
||||||
@ -63,7 +64,7 @@ class InMemoryIdentityService(identities: Iterable<PartyAndCertificate> = emptyS
|
|||||||
log.error("Certificate validation failed for ${identity.name} against trusted root ${trustAnchor.trustedCert.subjectX500Principal}.")
|
log.error("Certificate validation failed for ${identity.name} against trusted root ${trustAnchor.trustedCert.subjectX500Principal}.")
|
||||||
log.error("Certificate path :")
|
log.error("Certificate path :")
|
||||||
identity.certPath.certificates.reversed().forEachIndexed { index, certificate ->
|
identity.certPath.certificates.reversed().forEachIndexed { index, certificate ->
|
||||||
val space = (0 until index).map { " " }.joinToString("")
|
val space = (0 until index).joinToString("") { " " }
|
||||||
log.error("$space${certificate.toX509CertHolder().subject}")
|
log.error("$space${certificate.toX509CertHolder().subject}")
|
||||||
}
|
}
|
||||||
throw e
|
throw e
|
||||||
@ -78,8 +79,7 @@ class InMemoryIdentityService(identities: Iterable<PartyAndCertificate> = emptyS
|
|||||||
if (firstCertWithThisName != identity.certificate) {
|
if (firstCertWithThisName != identity.certificate) {
|
||||||
val certificates = identity.certPath.certificates
|
val certificates = identity.certPath.certificates
|
||||||
val idx = certificates.lastIndexOf(firstCertWithThisName)
|
val idx = certificates.lastIndexOf(firstCertWithThisName)
|
||||||
val certFactory = CertificateFactory.getInstance("X509")
|
val firstPath = X509CertificateFactory().delegate.generateCertPath(certificates.slice(idx until certificates.size))
|
||||||
val firstPath = certFactory.generateCertPath(certificates.slice(idx..certificates.size - 1))
|
|
||||||
verifyAndRegisterIdentity(PartyAndCertificate(firstPath))
|
verifyAndRegisterIdentity(PartyAndCertificate(firstPath))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,7 +104,7 @@ class InMemoryIdentityService(identities: Iterable<PartyAndCertificate> = emptyS
|
|||||||
val candidate = partyFromKey(party.owningKey)
|
val candidate = partyFromKey(party.owningKey)
|
||||||
// TODO: This should be done via the network map cache, which is the authoritative source of well known identities
|
// TODO: This should be done via the network map cache, which is the authoritative source of well known identities
|
||||||
return if (candidate != null) {
|
return if (candidate != null) {
|
||||||
require(party.nameOrNull() == null || party.nameOrNull() == candidate.name) { "Candidate party ${candidate} does not match expected ${party}" }
|
require(party.nameOrNull() == null || party.nameOrNull() == candidate.name) { "Candidate party $candidate does not match expected $party" }
|
||||||
wellKnownPartyFromX500Name(candidate.name)
|
wellKnownPartyFromX500Name(candidate.name)
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
|
@ -9,13 +9,13 @@ import net.corda.core.internal.toX509CertHolder
|
|||||||
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.core.serialization.SingletonSerializeAsToken
|
import net.corda.core.serialization.SingletonSerializeAsToken
|
||||||
import net.corda.core.utilities.debug
|
|
||||||
import net.corda.core.utilities.MAX_HASH_HEX_SIZE
|
import net.corda.core.utilities.MAX_HASH_HEX_SIZE
|
||||||
import net.corda.core.utilities.contextLogger
|
import net.corda.core.utilities.contextLogger
|
||||||
|
import net.corda.core.utilities.debug
|
||||||
import net.corda.node.utilities.AppendOnlyPersistentMap
|
import net.corda.node.utilities.AppendOnlyPersistentMap
|
||||||
import net.corda.node.utilities.NODE_DATABASE_PREFIX
|
import net.corda.node.utilities.NODE_DATABASE_PREFIX
|
||||||
|
import net.corda.nodeapi.internal.crypto.X509CertificateFactory
|
||||||
import org.bouncycastle.cert.X509CertificateHolder
|
import org.bouncycastle.cert.X509CertificateHolder
|
||||||
import java.io.ByteArrayInputStream
|
|
||||||
import java.security.InvalidAlgorithmParameterException
|
import java.security.InvalidAlgorithmParameterException
|
||||||
import java.security.PublicKey
|
import java.security.PublicKey
|
||||||
import java.security.cert.*
|
import java.security.cert.*
|
||||||
@ -32,16 +32,15 @@ class PersistentIdentityService(override val trustRoot: X509Certificate,
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val log = contextLogger()
|
private val log = contextLogger()
|
||||||
private val certFactory: CertificateFactory = CertificateFactory.getInstance("X.509")
|
|
||||||
|
|
||||||
fun createPKMap(): AppendOnlyPersistentMap<SecureHash, PartyAndCertificate, PersistentIdentity, String> {
|
fun createPKMap(): AppendOnlyPersistentMap<SecureHash, PartyAndCertificate, PersistentIdentity, String> {
|
||||||
return AppendOnlyPersistentMap(
|
return AppendOnlyPersistentMap(
|
||||||
toPersistentEntityKey = { it.toString() },
|
toPersistentEntityKey = { it.toString() },
|
||||||
fromPersistentEntity = {
|
fromPersistentEntity = {
|
||||||
Pair(SecureHash.parse(it.publicKeyHash),
|
Pair(
|
||||||
PartyAndCertificate(ByteArrayInputStream(it.identity).use {
|
SecureHash.parse(it.publicKeyHash),
|
||||||
certFactory.generateCertPath(it)
|
PartyAndCertificate(X509CertificateFactory().delegate.generateCertPath(it.identity.inputStream()))
|
||||||
}))
|
)
|
||||||
},
|
},
|
||||||
toPersistentEntity = { key: SecureHash, value: PartyAndCertificate ->
|
toPersistentEntity = { key: SecureHash, value: PartyAndCertificate ->
|
||||||
PersistentIdentity(key.toString(), value.certPath.encoded)
|
PersistentIdentity(key.toString(), value.certPath.encoded)
|
||||||
@ -135,8 +134,7 @@ class PersistentIdentityService(override val trustRoot: X509Certificate,
|
|||||||
if (firstCertWithThisName != identity.certificate) {
|
if (firstCertWithThisName != identity.certificate) {
|
||||||
val certificates = identity.certPath.certificates
|
val certificates = identity.certPath.certificates
|
||||||
val idx = certificates.lastIndexOf(firstCertWithThisName)
|
val idx = certificates.lastIndexOf(firstCertWithThisName)
|
||||||
val certFactory = CertificateFactory.getInstance("X509")
|
val firstPath = X509CertificateFactory().delegate.generateCertPath(certificates.slice(idx until certificates.size))
|
||||||
val firstPath = certFactory.generateCertPath(certificates.slice(idx until certificates.size))
|
|
||||||
verifyAndRegisterIdentity(PartyAndCertificate(firstPath))
|
verifyAndRegisterIdentity(PartyAndCertificate(firstPath))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,14 +6,14 @@ import net.corda.core.internal.cert
|
|||||||
import net.corda.core.internal.toX509CertHolder
|
import net.corda.core.internal.toX509CertHolder
|
||||||
import net.corda.core.node.services.IdentityService
|
import net.corda.core.node.services.IdentityService
|
||||||
import net.corda.core.utilities.days
|
import net.corda.core.utilities.days
|
||||||
import net.corda.node.utilities.CertificateType
|
import net.corda.nodeapi.internal.crypto.CertificateType
|
||||||
import net.corda.node.utilities.ContentSignerBuilder
|
import net.corda.nodeapi.internal.crypto.ContentSignerBuilder
|
||||||
import net.corda.node.utilities.X509Utilities
|
import net.corda.nodeapi.internal.crypto.X509CertificateFactory
|
||||||
|
import net.corda.nodeapi.internal.crypto.X509Utilities
|
||||||
import org.bouncycastle.operator.ContentSigner
|
import org.bouncycastle.operator.ContentSigner
|
||||||
import java.security.KeyPair
|
import java.security.KeyPair
|
||||||
import java.security.PublicKey
|
import java.security.PublicKey
|
||||||
import java.security.Security
|
import java.security.Security
|
||||||
import java.security.cert.CertificateFactory
|
|
||||||
import java.security.cert.X509Certificate
|
import java.security.cert.X509Certificate
|
||||||
import java.time.Duration
|
import java.time.Duration
|
||||||
|
|
||||||
@ -37,8 +37,7 @@ fun freshCertificate(identityService: IdentityService,
|
|||||||
val window = X509Utilities.getCertificateValidityWindow(Duration.ZERO, 3650.days, issuerCert)
|
val window = X509Utilities.getCertificateValidityWindow(Duration.ZERO, 3650.days, issuerCert)
|
||||||
val ourCertificate = X509Utilities.createCertificate(CertificateType.IDENTITY, issuerCert.subject,
|
val ourCertificate = X509Utilities.createCertificate(CertificateType.IDENTITY, issuerCert.subject,
|
||||||
issuerSigner, issuer.name, subjectPublicKey, window)
|
issuerSigner, issuer.name, subjectPublicKey, window)
|
||||||
val certFactory = CertificateFactory.getInstance("X509")
|
val ourCertPath = X509CertificateFactory().delegate.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)
|
||||||
identityService.verifyAndRegisterIdentity(anonymisedIdentity)
|
identityService.verifyAndRegisterIdentity(anonymisedIdentity)
|
||||||
return anonymisedIdentity
|
return anonymisedIdentity
|
||||||
|
@ -20,10 +20,10 @@ import net.corda.node.services.messaging.NodeLoginModule.Companion.NODE_ROLE
|
|||||||
import net.corda.node.services.messaging.NodeLoginModule.Companion.PEER_ROLE
|
import net.corda.node.services.messaging.NodeLoginModule.Companion.PEER_ROLE
|
||||||
import net.corda.node.services.messaging.NodeLoginModule.Companion.RPC_ROLE
|
import net.corda.node.services.messaging.NodeLoginModule.Companion.RPC_ROLE
|
||||||
import net.corda.node.services.messaging.NodeLoginModule.Companion.VERIFIER_ROLE
|
import net.corda.node.services.messaging.NodeLoginModule.Companion.VERIFIER_ROLE
|
||||||
import net.corda.node.utilities.X509Utilities
|
import net.corda.nodeapi.internal.crypto.X509Utilities
|
||||||
import net.corda.node.utilities.X509Utilities.CORDA_CLIENT_TLS
|
import net.corda.nodeapi.internal.crypto.X509Utilities.CORDA_CLIENT_TLS
|
||||||
import net.corda.node.utilities.X509Utilities.CORDA_ROOT_CA
|
import net.corda.nodeapi.internal.crypto.X509Utilities.CORDA_ROOT_CA
|
||||||
import net.corda.node.utilities.loadKeyStore
|
import net.corda.nodeapi.internal.crypto.loadKeyStore
|
||||||
import net.corda.nodeapi.*
|
import net.corda.nodeapi.*
|
||||||
import net.corda.nodeapi.internal.ArtemisMessagingComponent.Companion.INTERNAL_PREFIX
|
import net.corda.nodeapi.internal.ArtemisMessagingComponent.Companion.INTERNAL_PREFIX
|
||||||
import net.corda.nodeapi.internal.ArtemisMessagingComponent.Companion.NODE_USER
|
import net.corda.nodeapi.internal.ArtemisMessagingComponent.Companion.NODE_USER
|
||||||
|
@ -10,23 +10,23 @@ import net.corda.core.serialization.SerializationDefaults
|
|||||||
import net.corda.core.serialization.SingletonSerializeAsToken
|
import net.corda.core.serialization.SingletonSerializeAsToken
|
||||||
import net.corda.core.serialization.deserialize
|
import net.corda.core.serialization.deserialize
|
||||||
import net.corda.core.serialization.serialize
|
import net.corda.core.serialization.serialize
|
||||||
import net.corda.core.utilities.*
|
|
||||||
import net.corda.core.utilities.NetworkHostAndPort
|
import net.corda.core.utilities.NetworkHostAndPort
|
||||||
|
import net.corda.core.utilities.contextLogger
|
||||||
import net.corda.core.utilities.sequence
|
import net.corda.core.utilities.sequence
|
||||||
import net.corda.core.utilities.trace
|
import net.corda.core.utilities.trace
|
||||||
import net.corda.node.VersionInfo
|
import net.corda.node.VersionInfo
|
||||||
import net.corda.node.services.config.NodeConfiguration
|
import net.corda.node.services.config.NodeConfiguration
|
||||||
import net.corda.node.services.statemachine.StateMachineManagerImpl
|
import net.corda.node.services.statemachine.StateMachineManagerImpl
|
||||||
import net.corda.node.utilities.*
|
import net.corda.node.utilities.*
|
||||||
|
import net.corda.nodeapi.internal.ArtemisMessagingComponent
|
||||||
|
import net.corda.nodeapi.internal.ArtemisMessagingComponent.*
|
||||||
import net.corda.nodeapi.internal.ArtemisMessagingComponent.Companion.P2P_QUEUE
|
import net.corda.nodeapi.internal.ArtemisMessagingComponent.Companion.P2P_QUEUE
|
||||||
import net.corda.nodeapi.internal.ArtemisMessagingComponent.ArtemisAddress
|
|
||||||
import net.corda.nodeapi.internal.ArtemisMessagingComponent.NodeAddress
|
|
||||||
import net.corda.nodeapi.internal.ArtemisMessagingComponent.ServiceAddress
|
|
||||||
import org.apache.activemq.artemis.api.core.ActiveMQObjectClosedException
|
import org.apache.activemq.artemis.api.core.ActiveMQObjectClosedException
|
||||||
import org.apache.activemq.artemis.api.core.Message.*
|
import org.apache.activemq.artemis.api.core.Message.*
|
||||||
import org.apache.activemq.artemis.api.core.RoutingType
|
import org.apache.activemq.artemis.api.core.RoutingType
|
||||||
import org.apache.activemq.artemis.api.core.SimpleString
|
import org.apache.activemq.artemis.api.core.SimpleString
|
||||||
import org.apache.activemq.artemis.api.core.client.*
|
import org.apache.activemq.artemis.api.core.client.ClientConsumer
|
||||||
|
import org.apache.activemq.artemis.api.core.client.ClientMessage
|
||||||
import java.security.PublicKey
|
import java.security.PublicKey
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
@ -5,14 +5,17 @@ import net.corda.core.messaging.RPCOps
|
|||||||
import net.corda.core.serialization.SingletonSerializeAsToken
|
import net.corda.core.serialization.SingletonSerializeAsToken
|
||||||
import net.corda.core.utilities.NetworkHostAndPort
|
import net.corda.core.utilities.NetworkHostAndPort
|
||||||
import net.corda.node.services.RPCUserService
|
import net.corda.node.services.RPCUserService
|
||||||
import net.corda.node.utilities.*
|
|
||||||
import net.corda.nodeapi.internal.ArtemisMessagingComponent.Companion.NODE_USER
|
|
||||||
import net.corda.nodeapi.config.SSLConfiguration
|
import net.corda.nodeapi.config.SSLConfiguration
|
||||||
|
import net.corda.nodeapi.internal.ArtemisMessagingComponent.Companion.NODE_USER
|
||||||
|
import net.corda.nodeapi.internal.crypto.X509Utilities
|
||||||
|
import net.corda.nodeapi.internal.crypto.getX509Certificate
|
||||||
|
import net.corda.nodeapi.internal.crypto.loadKeyStore
|
||||||
import org.apache.activemq.artemis.api.core.management.ActiveMQServerControl
|
import org.apache.activemq.artemis.api.core.management.ActiveMQServerControl
|
||||||
|
|
||||||
class RPCMessagingClient(private val config: SSLConfiguration, serverAddress: NetworkHostAndPort) : SingletonSerializeAsToken() {
|
class RPCMessagingClient(private val config: SSLConfiguration, serverAddress: NetworkHostAndPort) : SingletonSerializeAsToken() {
|
||||||
private val artemis = ArtemisMessagingClient(config, serverAddress)
|
private val artemis = ArtemisMessagingClient(config, serverAddress)
|
||||||
private var rpcServer: RPCServer? = null
|
private var rpcServer: RPCServer? = null
|
||||||
|
|
||||||
fun start(rpcOps: RPCOps, userService: RPCUserService) = synchronized(this) {
|
fun start(rpcOps: RPCOps, userService: RPCUserService) = synchronized(this) {
|
||||||
val locator = artemis.start().sessionFactory.serverLocator
|
val locator = artemis.start().sessionFactory.serverLocator
|
||||||
val myCert = loadKeyStore(config.sslKeystore, config.keyStorePassword).getX509Certificate(X509Utilities.CORDA_CLIENT_TLS)
|
val myCert = loadKeyStore(config.sslKeystore, config.keyStorePassword).getX509Certificate(X509Utilities.CORDA_CLIENT_TLS)
|
||||||
|
@ -8,6 +8,7 @@ import net.corda.core.internal.cert
|
|||||||
import net.corda.core.internal.createDirectories
|
import net.corda.core.internal.createDirectories
|
||||||
import net.corda.core.internal.div
|
import net.corda.core.internal.div
|
||||||
import net.corda.core.utilities.trace
|
import net.corda.core.utilities.trace
|
||||||
|
import net.corda.nodeapi.internal.crypto.*
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ package net.corda.node.utilities.registration
|
|||||||
|
|
||||||
import com.google.common.net.MediaType
|
import com.google.common.net.MediaType
|
||||||
import net.corda.core.internal.openHttpConnection
|
import net.corda.core.internal.openHttpConnection
|
||||||
import net.corda.node.utilities.CertificateStream
|
import net.corda.nodeapi.internal.crypto.X509CertificateFactory
|
||||||
import org.apache.commons.io.IOUtils
|
import org.apache.commons.io.IOUtils
|
||||||
import org.bouncycastle.pkcs.PKCS10CertificationRequest
|
import org.bouncycastle.pkcs.PKCS10CertificationRequest
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
@ -32,9 +32,9 @@ class HTTPNetworkRegistrationService(compatibilityZoneURL: URL) : NetworkRegistr
|
|||||||
return when (conn.responseCode) {
|
return when (conn.responseCode) {
|
||||||
HTTP_OK -> ZipInputStream(conn.inputStream).use {
|
HTTP_OK -> ZipInputStream(conn.inputStream).use {
|
||||||
val certificates = ArrayList<Certificate>()
|
val certificates = ArrayList<Certificate>()
|
||||||
val stream = CertificateStream(it)
|
val factory = X509CertificateFactory()
|
||||||
while (it.nextEntry != null) {
|
while (it.nextEntry != null) {
|
||||||
certificates.add(stream.nextCertificate())
|
certificates += factory.generateCertificate(it)
|
||||||
}
|
}
|
||||||
certificates.toTypedArray()
|
certificates.toTypedArray()
|
||||||
}
|
}
|
||||||
|
@ -5,10 +5,10 @@ import net.corda.core.identity.CordaX500Name
|
|||||||
import net.corda.core.internal.*
|
import net.corda.core.internal.*
|
||||||
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.nodeapi.internal.crypto.*
|
||||||
import net.corda.node.utilities.X509Utilities.CORDA_CLIENT_CA
|
import net.corda.nodeapi.internal.crypto.X509Utilities.CORDA_CLIENT_CA
|
||||||
import net.corda.node.utilities.X509Utilities.CORDA_CLIENT_TLS
|
import net.corda.nodeapi.internal.crypto.X509Utilities.CORDA_CLIENT_TLS
|
||||||
import net.corda.node.utilities.X509Utilities.CORDA_ROOT_CA
|
import net.corda.nodeapi.internal.crypto.X509Utilities.CORDA_ROOT_CA
|
||||||
import org.bouncycastle.openssl.jcajce.JcaPEMWriter
|
import org.bouncycastle.openssl.jcajce.JcaPEMWriter
|
||||||
import org.bouncycastle.util.io.pem.PemObject
|
import org.bouncycastle.util.io.pem.PemObject
|
||||||
import java.io.StringWriter
|
import java.io.StringWriter
|
||||||
|
@ -6,16 +6,15 @@ import net.corda.core.identity.AnonymousParty
|
|||||||
import net.corda.core.identity.CordaX500Name
|
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.internal.cert
|
||||||
import net.corda.core.internal.toX509CertHolder
|
import net.corda.core.internal.toX509CertHolder
|
||||||
import net.corda.core.node.services.UnknownAnonymousPartyException
|
import net.corda.core.node.services.UnknownAnonymousPartyException
|
||||||
import net.corda.core.internal.cert
|
import net.corda.nodeapi.internal.crypto.CertificateAndKeyPair
|
||||||
import net.corda.node.services.identity.InMemoryIdentityService
|
import net.corda.nodeapi.internal.crypto.CertificateType
|
||||||
import net.corda.node.utilities.CertificateAndKeyPair
|
import net.corda.nodeapi.internal.crypto.X509CertificateFactory
|
||||||
import net.corda.node.utilities.CertificateType
|
import net.corda.nodeapi.internal.crypto.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 kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
import kotlin.test.assertFailsWith
|
import kotlin.test.assertFailsWith
|
||||||
import kotlin.test.assertNull
|
import kotlin.test.assertNull
|
||||||
@ -156,12 +155,11 @@ class InMemoryIdentityServiceTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun createParty(x500Name: CordaX500Name, ca: CertificateAndKeyPair): Pair<PartyAndCertificate, PartyAndCertificate> {
|
private fun createParty(x500Name: CordaX500Name, ca: CertificateAndKeyPair): Pair<PartyAndCertificate, PartyAndCertificate> {
|
||||||
val certFactory = CertificateFactory.getInstance("X509")
|
|
||||||
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.toX509CertHolder(), issuerKeyPair, x500Name, txKey.public)
|
val txCert = X509Utilities.createCertificate(CertificateType.IDENTITY, issuer.certificate.toX509CertHolder(), issuerKeyPair, x500Name, txKey.public)
|
||||||
val txCertPath = certFactory.generateCertPath(listOf(txCert.cert) + issuer.certPath.certificates)
|
val txCertPath = X509CertificateFactory().delegate.generateCertPath(listOf(txCert.cert) + issuer.certPath.certificates)
|
||||||
return Pair(issuer, PartyAndCertificate(txCertPath))
|
return Pair(issuer, PartyAndCertificate(txCertPath))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,20 +6,20 @@ import net.corda.core.identity.AnonymousParty
|
|||||||
import net.corda.core.identity.CordaX500Name
|
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.internal.cert
|
||||||
import net.corda.core.internal.toX509CertHolder
|
import net.corda.core.internal.toX509CertHolder
|
||||||
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.core.internal.cert
|
|
||||||
import net.corda.node.utilities.CertificateAndKeyPair
|
|
||||||
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.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 net.corda.testing.*
|
import net.corda.testing.*
|
||||||
import net.corda.testing.node.MockServices
|
import net.corda.testing.node.MockServices
|
||||||
import org.junit.After
|
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 kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
import kotlin.test.assertFailsWith
|
import kotlin.test.assertFailsWith
|
||||||
import kotlin.test.assertNull
|
import kotlin.test.assertNull
|
||||||
@ -28,10 +28,9 @@ import kotlin.test.assertNull
|
|||||||
* Tests for the in memory identity service.
|
* Tests for the in memory identity service.
|
||||||
*/
|
*/
|
||||||
class PersistentIdentityServiceTests {
|
class PersistentIdentityServiceTests {
|
||||||
|
private lateinit var database: CordaPersistence
|
||||||
lateinit var database: CordaPersistence
|
private lateinit var services: MockServices
|
||||||
lateinit var services: MockServices
|
private lateinit var identityService: IdentityService
|
||||||
lateinit var identityService: IdentityService
|
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setup() {
|
fun setup() {
|
||||||
@ -254,12 +253,11 @@ class PersistentIdentityServiceTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun createParty(x500Name: CordaX500Name, ca: CertificateAndKeyPair): Pair<PartyAndCertificate, PartyAndCertificate> {
|
private fun createParty(x500Name: CordaX500Name, ca: CertificateAndKeyPair): Pair<PartyAndCertificate, PartyAndCertificate> {
|
||||||
val certFactory = CertificateFactory.getInstance("X509")
|
|
||||||
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.toX509CertHolder(), issuerKeyPair, x500Name, txKey.public)
|
val txCert = X509Utilities.createCertificate(CertificateType.IDENTITY, issuer.certificate.toX509CertHolder(), issuerKeyPair, x500Name, txKey.public)
|
||||||
val txCertPath = certFactory.generateCertPath(listOf(txCert.cert) + issuer.certPath.certificates)
|
val txCertPath = X509CertificateFactory().delegate.generateCertPath(listOf(txCert.cert) + issuer.certPath.certificates)
|
||||||
return Pair(issuer, PartyAndCertificate(txCertPath))
|
return Pair(issuer, PartyAndCertificate(txCertPath))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,8 +10,8 @@ import net.corda.core.serialization.serialize
|
|||||||
import net.corda.core.utilities.NetworkHostAndPort
|
import net.corda.core.utilities.NetworkHostAndPort
|
||||||
import net.corda.core.utilities.seconds
|
import net.corda.core.utilities.seconds
|
||||||
import net.corda.node.services.network.TestNodeInfoFactory.createNodeInfo
|
import net.corda.node.services.network.TestNodeInfoFactory.createNodeInfo
|
||||||
import net.corda.node.utilities.CertificateType
|
import net.corda.nodeapi.internal.crypto.CertificateType
|
||||||
import net.corda.node.utilities.X509Utilities
|
import net.corda.nodeapi.internal.crypto.X509Utilities
|
||||||
import net.corda.testing.SerializationEnvironmentRule
|
import net.corda.testing.SerializationEnvironmentRule
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
import org.bouncycastle.asn1.x500.X500Name
|
||||||
|
@ -8,15 +8,14 @@ import net.corda.core.identity.PartyAndCertificate
|
|||||||
import net.corda.core.node.NodeInfo
|
import net.corda.core.node.NodeInfo
|
||||||
import net.corda.core.serialization.serialize
|
import net.corda.core.serialization.serialize
|
||||||
import net.corda.core.utilities.NetworkHostAndPort
|
import net.corda.core.utilities.NetworkHostAndPort
|
||||||
import net.corda.node.utilities.CertificateType
|
import net.corda.nodeapi.internal.crypto.CertificateType
|
||||||
import net.corda.node.utilities.X509Utilities
|
import net.corda.nodeapi.internal.crypto.X509CertificateFactory
|
||||||
|
import net.corda.nodeapi.internal.crypto.X509Utilities
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
import org.bouncycastle.asn1.x500.X500Name
|
||||||
import org.bouncycastle.cert.X509CertificateHolder
|
import org.bouncycastle.cert.X509CertificateHolder
|
||||||
import java.io.ByteArrayInputStream
|
|
||||||
import java.security.KeyPair
|
import java.security.KeyPair
|
||||||
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.X509Certificate
|
import java.security.cert.X509Certificate
|
||||||
|
|
||||||
object TestNodeInfoFactory {
|
object TestNodeInfoFactory {
|
||||||
@ -40,11 +39,11 @@ object TestNodeInfoFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun buildCertPath(vararg certificates: Certificate): CertPath {
|
private fun buildCertPath(vararg certificates: Certificate): CertPath {
|
||||||
return CertificateFactory.getInstance("X509").generateCertPath(certificates.asList())
|
return X509CertificateFactory().delegate.generateCertPath(certificates.asList())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun X509CertificateHolder.toX509Certificate(): X509Certificate {
|
private fun X509CertificateHolder.toX509Certificate(): X509Certificate {
|
||||||
return CertificateFactory.getInstance("X509").generateCertificate(ByteArrayInputStream(encoded)) as X509Certificate
|
return X509CertificateFactory().generateCertificate(encoded.inputStream())
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -5,6 +5,7 @@ import net.corda.core.crypto.SignatureScheme
|
|||||||
import net.corda.core.crypto.newSecureRandom
|
import net.corda.core.crypto.newSecureRandom
|
||||||
import net.corda.core.identity.CordaX500Name
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.internal.*
|
import net.corda.core.internal.*
|
||||||
|
import net.corda.nodeapi.internal.crypto.*
|
||||||
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
|
||||||
|
@ -13,10 +13,11 @@ import net.corda.core.serialization.deserialize
|
|||||||
import net.corda.core.serialization.serialize
|
import net.corda.core.serialization.serialize
|
||||||
import net.corda.node.serialization.KryoServerSerializationScheme
|
import net.corda.node.serialization.KryoServerSerializationScheme
|
||||||
import net.corda.node.services.config.createKeystoreForCordaNode
|
import net.corda.node.services.config.createKeystoreForCordaNode
|
||||||
|
import net.corda.nodeapi.internal.crypto.*
|
||||||
import net.corda.nodeapi.internal.serialization.AllWhitelist
|
import net.corda.nodeapi.internal.serialization.AllWhitelist
|
||||||
import net.corda.nodeapi.internal.serialization.kryo.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.nodeapi.internal.serialization.kryo.KryoHeaderV0_1
|
||||||
import net.corda.testing.ALICE
|
import net.corda.testing.ALICE
|
||||||
import net.corda.testing.BOB
|
import net.corda.testing.BOB
|
||||||
import net.corda.testing.BOB_PUBKEY
|
import net.corda.testing.BOB_PUBKEY
|
||||||
@ -41,7 +42,6 @@ import java.security.PrivateKey
|
|||||||
import java.security.SecureRandom
|
import java.security.SecureRandom
|
||||||
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.X509Certificate
|
import java.security.cert.X509Certificate
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.stream.Stream
|
import java.util.stream.Stream
|
||||||
@ -49,7 +49,6 @@ 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
|
||||||
@ -360,10 +359,16 @@ 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(CordaX500Name(commonName = "Corda Node Root CA", organisation = "R3CEV", locality = "London", country = "GB"), rootCAKey)
|
val baseName = CordaX500Name(organisation = "R3CEV", locality = "London", country = "GB")
|
||||||
|
val rootCACert = X509Utilities.createSelfSignedCACertificate(baseName.copy(commonName = "Corda Node Root CA"), 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, CordaX500Name(commonName = "Corda Node Intermediate CA", organisation = "R3CEV", locality = "London", country = "GB"), intermediateCAKeyPair.public)
|
val intermediateCACert = X509Utilities.createCertificate(
|
||||||
|
CertificateType.INTERMEDIATE_CA,
|
||||||
|
rootCACert,
|
||||||
|
rootCAKey,
|
||||||
|
baseName.copy(commonName = "Corda Node Intermediate CA"),
|
||||||
|
intermediateCAKeyPair.public)
|
||||||
|
|
||||||
val keyPass = keyPassword.toCharArray()
|
val keyPass = keyPassword.toCharArray()
|
||||||
val keyStore = loadOrCreateKeyStore(keyStoreFilePath, storePassword)
|
val keyStore = loadOrCreateKeyStore(keyStoreFilePath, storePassword)
|
||||||
@ -426,11 +431,10 @@ class X509UtilitiesTest {
|
|||||||
emptyMap(),
|
emptyMap(),
|
||||||
true,
|
true,
|
||||||
SerializationContext.UseCase.P2P)
|
SerializationContext.UseCase.P2P)
|
||||||
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, 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 = X509CertificateFactory().delegate.generateCertPath(listOf(certificate.cert, rootCACert.cert))
|
||||||
val serialized = expected.serialize(factory, context).bytes
|
val serialized = expected.serialize(factory, context).bytes
|
||||||
val actual: CertPath = serialized.deserialize(factory, context)
|
val actual: CertPath = serialized.deserialize(factory, context)
|
||||||
assertEquals(expected, actual)
|
assertEquals(expected, actual)
|
||||||
|
@ -5,9 +5,9 @@ import net.corda.core.crypto.Crypto
|
|||||||
import net.corda.core.crypto.SecureHash
|
import net.corda.core.crypto.SecureHash
|
||||||
import net.corda.core.identity.CordaX500Name
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.internal.*
|
import net.corda.core.internal.*
|
||||||
import net.corda.node.utilities.X509Utilities
|
import net.corda.nodeapi.internal.crypto.X509Utilities
|
||||||
import net.corda.node.utilities.getX509Certificate
|
import net.corda.nodeapi.internal.crypto.getX509Certificate
|
||||||
import net.corda.node.utilities.loadKeyStore
|
import net.corda.nodeapi.internal.crypto.loadKeyStore
|
||||||
import net.corda.testing.ALICE
|
import net.corda.testing.ALICE
|
||||||
import net.corda.testing.rigorousMock
|
import net.corda.testing.rigorousMock
|
||||||
import net.corda.testing.testNodeConfiguration
|
import net.corda.testing.testNodeConfiguration
|
||||||
|
@ -12,24 +12,22 @@ import net.corda.core.identity.Party
|
|||||||
import net.corda.core.identity.PartyAndCertificate
|
import net.corda.core.identity.PartyAndCertificate
|
||||||
import net.corda.core.internal.cert
|
import net.corda.core.internal.cert
|
||||||
import net.corda.core.node.NodeInfo
|
import net.corda.core.node.NodeInfo
|
||||||
import net.corda.core.node.services.IdentityService
|
|
||||||
import net.corda.core.utilities.NetworkHostAndPort
|
import net.corda.core.utilities.NetworkHostAndPort
|
||||||
import net.corda.core.utilities.OpaqueBytes
|
import net.corda.core.utilities.OpaqueBytes
|
||||||
import net.corda.core.utilities.loggerFor
|
import net.corda.core.utilities.loggerFor
|
||||||
import net.corda.finance.contracts.asset.DUMMY_CASH_ISSUER
|
import net.corda.finance.contracts.asset.DUMMY_CASH_ISSUER
|
||||||
import net.corda.node.services.config.configureDevKeyAndTrustStores
|
import net.corda.node.services.config.configureDevKeyAndTrustStores
|
||||||
import net.corda.node.services.identity.InMemoryIdentityService
|
|
||||||
import net.corda.node.utilities.CertificateAndKeyPair
|
|
||||||
import net.corda.node.utilities.CertificateType
|
|
||||||
import net.corda.node.utilities.X509Utilities
|
|
||||||
import net.corda.nodeapi.config.SSLConfiguration
|
import net.corda.nodeapi.config.SSLConfiguration
|
||||||
|
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 net.corda.nodeapi.internal.serialization.amqp.AMQP_ENABLED
|
import net.corda.nodeapi.internal.serialization.amqp.AMQP_ENABLED
|
||||||
import org.mockito.internal.stubbing.answers.ThrowsException
|
import org.mockito.internal.stubbing.answers.ThrowsException
|
||||||
import org.mockito.stubbing.Answer
|
import org.mockito.stubbing.Answer
|
||||||
import java.nio.file.Files
|
import java.nio.file.Files
|
||||||
import java.security.KeyPair
|
import java.security.KeyPair
|
||||||
import java.security.PublicKey
|
import java.security.PublicKey
|
||||||
import java.security.cert.CertificateFactory
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger
|
import java.util.concurrent.atomic.AtomicInteger
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -131,9 +129,8 @@ fun configureTestSSL(legalName: CordaX500Name = MEGA_CORP.name): SSLConfiguratio
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun getTestPartyAndCertificate(party: Party, trustRoot: CertificateAndKeyPair = DEV_CA): PartyAndCertificate {
|
fun getTestPartyAndCertificate(party: Party, trustRoot: CertificateAndKeyPair = DEV_CA): PartyAndCertificate {
|
||||||
val certFactory = CertificateFactory.getInstance("X509")
|
|
||||||
val certHolder = X509Utilities.createCertificate(CertificateType.IDENTITY, trustRoot.certificate, trustRoot.keyPair, party.name, 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 = X509CertificateFactory().delegate.generateCertPath(listOf(certHolder.cert, trustRoot.certificate.cert))
|
||||||
return PartyAndCertificate(certPath)
|
return PartyAndCertificate(certPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,10 +10,10 @@ 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.internal.toX509CertHolder
|
import net.corda.core.internal.toX509CertHolder
|
||||||
import net.corda.node.utilities.CertificateAndKeyPair
|
import net.corda.nodeapi.internal.crypto.CertificateAndKeyPair
|
||||||
import net.corda.node.utilities.X509Utilities
|
import net.corda.nodeapi.internal.crypto.X509Utilities
|
||||||
import net.corda.node.utilities.getCertificateAndKeyPair
|
import net.corda.nodeapi.internal.crypto.getCertificateAndKeyPair
|
||||||
import net.corda.node.utilities.loadKeyStore
|
import net.corda.nodeapi.internal.crypto.loadKeyStore
|
||||||
import org.bouncycastle.cert.X509CertificateHolder
|
import org.bouncycastle.cert.X509CertificateHolder
|
||||||
import java.math.BigInteger
|
import java.math.BigInteger
|
||||||
import java.security.KeyPair
|
import java.security.KeyPair
|
||||||
|
Loading…
x
Reference in New Issue
Block a user