mirror of
https://github.com/corda/corda.git
synced 2025-06-14 05:08:18 +00:00
Removed all remaining special treatment of the X500 common name.
With network parameters the CN is no longer needed to identify notaries. This frees it up to be used in the node's name alongside the other attributes. Also, the identity generation logic has been simplified, removing the need to have magic string values for storing distributed identities in the keystore. Now there are just two alias prefixes: "identity" as it was previously, and "distributed-notary".
This commit is contained in:
@ -13,42 +13,54 @@ import org.slf4j.LoggerFactory
|
||||
import java.nio.file.Path
|
||||
import java.security.cert.X509Certificate
|
||||
|
||||
object ServiceIdentityGenerator {
|
||||
object IdentityGenerator {
|
||||
private val log = LoggerFactory.getLogger(javaClass)
|
||||
|
||||
const val NODE_IDENTITY_ALIAS_PREFIX = "identity"
|
||||
const val DISTRIBUTED_NOTARY_ALIAS_PREFIX = "distributed-notary"
|
||||
|
||||
fun generateNodeIdentity(dir: Path, legalName: CordaX500Name, customRootCert: X509Certificate? = null): Party {
|
||||
return generateToDisk(listOf(dir), legalName, NODE_IDENTITY_ALIAS_PREFIX, threshold = 1, customRootCert = customRootCert)
|
||||
}
|
||||
|
||||
fun generateDistributedNotaryIdentity(dirs: List<Path>, notaryName: CordaX500Name, threshold: Int = 1, customRootCert: X509Certificate? = null): Party {
|
||||
return generateToDisk(dirs, notaryName, DISTRIBUTED_NOTARY_ALIAS_PREFIX, threshold, customRootCert)
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates signing key pairs and a common distributed service identity for a set of nodes.
|
||||
* The key pairs and the group identity get serialized to disk in the corresponding node directories.
|
||||
* This method should be called *before* any of the nodes are started.
|
||||
*
|
||||
* @param dirs List of node directories to place the generated identity and key pairs in.
|
||||
* @param serviceName The legal name of the distributed service.
|
||||
* @param name The name of the identity.
|
||||
* @param threshold The threshold for the generated group [CompositeKey].
|
||||
* @param customRootCert the certificate to use a Corda root CA. If not specified the one in
|
||||
* certificates/cordadevcakeys.jks is used.
|
||||
* @param customRootCert the certificate to use as the Corda root CA. If not specified the one in
|
||||
* internal/certificates/cordadevcakeys.jks is used.
|
||||
*/
|
||||
fun generateToDisk(dirs: List<Path>,
|
||||
serviceName: CordaX500Name,
|
||||
serviceId: String,
|
||||
threshold: Int = 1,
|
||||
customRootCert: X509Certificate? = null): Party {
|
||||
log.trace { "Generating a group identity \"serviceName\" for nodes: ${dirs.joinToString()}" }
|
||||
private fun generateToDisk(dirs: List<Path>,
|
||||
name: CordaX500Name,
|
||||
aliasPrefix: String,
|
||||
threshold: Int,
|
||||
customRootCert: X509Certificate?): Party {
|
||||
log.trace { "Generating identity \"$name\" for nodes: ${dirs.joinToString()}" }
|
||||
val keyPairs = (1..dirs.size).map { generateKeyPair() }
|
||||
val notaryKey = CompositeKey.Builder().addKeys(keyPairs.map { it.public }).build(threshold)
|
||||
val key = CompositeKey.Builder().addKeys(keyPairs.map { it.public }).build(threshold)
|
||||
|
||||
val caKeyStore = loadKeyStore(javaClass.classLoader.getResourceAsStream("certificates/cordadevcakeys.jks"), "cordacadevpass")
|
||||
val intermediateCa = caKeyStore.getCertificateAndKeyPair(X509Utilities.CORDA_INTERMEDIATE_CA, "cordacadevkeypass")
|
||||
val rootCert = customRootCert ?: caKeyStore.getCertificate(X509Utilities.CORDA_ROOT_CA)
|
||||
|
||||
keyPairs.zip(dirs) { keyPair, dir ->
|
||||
val serviceKeyCert = X509Utilities.createCertificate(CertificateType.SERVICE_IDENTITY, intermediateCa.certificate, intermediateCa.keyPair, serviceName, keyPair.public)
|
||||
val compositeKeyCert = X509Utilities.createCertificate(CertificateType.SERVICE_IDENTITY, intermediateCa.certificate, intermediateCa.keyPair, serviceName, notaryKey)
|
||||
val serviceKeyCert = X509Utilities.createCertificate(CertificateType.SERVICE_IDENTITY, intermediateCa.certificate, intermediateCa.keyPair, name, keyPair.public)
|
||||
val compositeKeyCert = X509Utilities.createCertificate(CertificateType.SERVICE_IDENTITY, intermediateCa.certificate, intermediateCa.keyPair, name, key)
|
||||
val certPath = (dir / "certificates").createDirectories() / "distributedService.jks"
|
||||
val keystore = loadOrCreateKeyStore(certPath, "cordacadevpass")
|
||||
keystore.setCertificateEntry("$serviceId-composite-key", compositeKeyCert.cert)
|
||||
keystore.setKeyEntry("$serviceId-private-key", keyPair.private, "cordacadevkeypass".toCharArray(), arrayOf(serviceKeyCert.cert, intermediateCa.certificate.cert, rootCert))
|
||||
keystore.setCertificateEntry("$aliasPrefix-composite-key", compositeKeyCert.cert)
|
||||
keystore.setKeyEntry("$aliasPrefix-private-key", keyPair.private, "cordacadevkeypass".toCharArray(), arrayOf(serviceKeyCert.cert, intermediateCa.certificate.cert, rootCert))
|
||||
keystore.save(certPath, "cordacadevpass")
|
||||
}
|
||||
return Party(serviceName, notaryKey)
|
||||
|
||||
return Party(name, key)
|
||||
}
|
||||
}
|
@ -7,7 +7,8 @@ import net.corda.core.crypto.random63BitValue
|
||||
import net.corda.core.internal.CertRole
|
||||
import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.internal.cert
|
||||
import net.corda.core.internal.read
|
||||
import net.corda.core.internal.reader
|
||||
import net.corda.core.internal.writer
|
||||
import net.corda.core.internal.x500Name
|
||||
import net.corda.core.utilities.days
|
||||
import net.corda.core.utilities.millis
|
||||
@ -48,8 +49,6 @@ object X509Utilities {
|
||||
const val CORDA_CLIENT_TLS = "cordaclienttls"
|
||||
const val CORDA_CLIENT_CA = "cordaclientca"
|
||||
|
||||
const val CORDA_CLIENT_CA_CN = "Corda Client CA Certificate"
|
||||
|
||||
private val DEFAULT_VALIDITY_WINDOW = Pair(0.millis, 3650.days)
|
||||
|
||||
/**
|
||||
@ -162,7 +161,7 @@ object X509Utilities {
|
||||
*/
|
||||
@JvmStatic
|
||||
fun saveCertificateAsPEMFile(x509Certificate: X509Certificate, file: Path) {
|
||||
JcaPEMWriter(file.toFile().writer()).use {
|
||||
JcaPEMWriter(file.writer()).use {
|
||||
it.writeObject(x509Certificate)
|
||||
}
|
||||
}
|
||||
@ -174,9 +173,8 @@ object X509Utilities {
|
||||
*/
|
||||
@JvmStatic
|
||||
fun loadCertificateFromPEMFile(file: Path): X509Certificate {
|
||||
return file.read {
|
||||
val reader = PemReader(it.reader())
|
||||
val pemObject = reader.readPemObject()
|
||||
return file.reader().use {
|
||||
val pemObject = PemReader(it).readPemObject()
|
||||
val certHolder = X509CertificateHolder(pemObject.content)
|
||||
certHolder.isValidOn(Date())
|
||||
certHolder.cert
|
||||
|
Reference in New Issue
Block a user