Raft notaries can share a single key pair for the service identity (i… (#2269)

* Raft notaries can share a single key pair for the service identity (in contrast to a shared composite public key, and individual signing key pairs). This allows adjusting the cluster size on the fly.
This commit is contained in:
Andrius Dagys
2018-01-09 08:17:59 +00:00
committed by GitHub
parent 4a995870c8
commit 3e00676851
10 changed files with 184 additions and 93 deletions

View File

@ -12,6 +12,9 @@ import net.corda.nodeapi.internal.config.NodeSSLConfiguration
import net.corda.nodeapi.internal.crypto.*
import org.slf4j.LoggerFactory
import java.nio.file.Path
import java.security.KeyPair
import java.security.PublicKey
import java.security.cert.X509Certificate
/**
* Contains utility methods for generating identities for a node.
@ -47,37 +50,56 @@ object DevIdentityGenerator {
return identity.party
}
fun generateDistributedNotaryIdentity(dirs: List<Path>, notaryName: CordaX500Name, threshold: Int = 1): Party {
fun generateDistributedNotaryCompositeIdentity(dirs: List<Path>, notaryName: CordaX500Name, threshold: Int = 1): Party {
require(dirs.isNotEmpty())
log.trace { "Generating identity \"$notaryName\" for nodes: ${dirs.joinToString()}" }
val keyPairs = (1..dirs.size).map { generateKeyPair() }
val compositeKey = CompositeKey.Builder().addKeys(keyPairs.map { it.public }).build(threshold)
log.trace { "Generating composite identity \"$notaryName\" for nodes: ${dirs.joinToString()}" }
val caKeyStore = loadKeyStore(javaClass.classLoader.getResourceAsStream("certificates/cordadevcakeys.jks"), "cordacadevpass")
val intermediateCa = caKeyStore.getCertificateAndKeyPair(X509Utilities.CORDA_INTERMEDIATE_CA, "cordacadevkeypass")
val rootCert = caKeyStore.getCertificate(X509Utilities.CORDA_ROOT_CA)
val rootCert = caKeyStore.getX509Certificate(X509Utilities.CORDA_ROOT_CA)
val keyPairs = (1..dirs.size).map { generateKeyPair() }
val notaryKey = CompositeKey.Builder().addKeys(keyPairs.map { it.public }).build(threshold)
keyPairs.zip(dirs) { keyPair, nodeDir ->
val (serviceKeyCert, compositeKeyCert) = listOf(keyPair.public, compositeKey).map { publicKey ->
X509Utilities.createCertificate(
CertificateType.SERVICE_IDENTITY,
intermediateCa.certificate,
intermediateCa.keyPair,
notaryName.x500Principal,
publicKey)
}
val distServKeyStoreFile = (nodeDir / "certificates").createDirectories() / "distributedService.jks"
val keystore = loadOrCreateKeyStore(distServKeyStoreFile, "cordacadevpass")
keystore.setCertificateEntry("$DISTRIBUTED_NOTARY_ALIAS_PREFIX-composite-key", compositeKeyCert)
keystore.setKeyEntry(
"$DISTRIBUTED_NOTARY_ALIAS_PREFIX-private-key",
keyPair.private,
"cordacadevkeypass".toCharArray(),
arrayOf(serviceKeyCert, intermediateCa.certificate, rootCert))
keystore.save(distServKeyStoreFile, "cordacadevpass")
generateCertificates(keyPair, notaryKey, intermediateCa, notaryName, nodeDir, rootCert)
}
return Party(notaryName, compositeKey)
return Party(notaryName, notaryKey)
}
fun generateDistributedNotarySingularIdentity(dirs: List<Path>, notaryName: CordaX500Name): Party {
require(dirs.isNotEmpty())
log.trace { "Generating singular identity \"$notaryName\" for nodes: ${dirs.joinToString()}" }
val caKeyStore = loadKeyStore(javaClass.classLoader.getResourceAsStream("certificates/cordadevcakeys.jks"), "cordacadevpass")
val intermediateCa = caKeyStore.getCertificateAndKeyPair(X509Utilities.CORDA_INTERMEDIATE_CA, "cordacadevkeypass")
val rootCert = caKeyStore.getX509Certificate(X509Utilities.CORDA_ROOT_CA)
val keyPair = generateKeyPair()
val notaryKey = keyPair.public
dirs.forEach { dir ->
generateCertificates(keyPair, notaryKey, intermediateCa, notaryName, dir, rootCert)
}
return Party(notaryName, notaryKey)
}
private fun generateCertificates(keyPair: KeyPair, notaryKey: PublicKey, intermediateCa: CertificateAndKeyPair, notaryName: CordaX500Name, nodeDir: Path, rootCert: X509Certificate) {
val (serviceKeyCert, compositeKeyCert) = listOf(keyPair.public, notaryKey).map { publicKey ->
X509Utilities.createCertificate(
CertificateType.SERVICE_IDENTITY,
intermediateCa.certificate,
intermediateCa.keyPair,
notaryName.x500Principal,
publicKey)
}
val distServKeyStoreFile = (nodeDir / "certificates").createDirectories() / "distributedService.jks"
val keystore = loadOrCreateKeyStore(distServKeyStoreFile, "cordacadevpass")
keystore.setCertificateEntry("$DISTRIBUTED_NOTARY_ALIAS_PREFIX-composite-key", compositeKeyCert)
keystore.setKeyEntry(
"$DISTRIBUTED_NOTARY_ALIAS_PREFIX-private-key",
keyPair.private,
"cordacadevkeypass".toCharArray(),
arrayOf(serviceKeyCert, intermediateCa.certificate, rootCert))
keystore.save(distServKeyStoreFile, "cordacadevpass")
}
}