mirror of
https://github.com/corda/corda.git
synced 2025-06-15 21:58:17 +00:00
Merge remote-tracking branch 'open/master' into mike-merge-4d2d9b83
This commit is contained in:
@ -18,6 +18,8 @@ import org.slf4j.LoggerFactory
|
||||
import java.nio.file.Path
|
||||
import java.security.KeyPair
|
||||
import java.security.PublicKey
|
||||
import java.security.cert.X509Certificate
|
||||
import javax.security.auth.x500.X500Principal
|
||||
|
||||
/**
|
||||
* Contains utility methods for generating identities for a node.
|
||||
@ -43,50 +45,67 @@ object DevIdentityGenerator {
|
||||
return identity.party
|
||||
}
|
||||
|
||||
fun generateDistributedNotaryCompositeIdentity(dirs: List<Path>, notaryName: CordaX500Name, threshold: Int = 1): Party {
|
||||
require(dirs.isNotEmpty())
|
||||
|
||||
log.trace { "Generating composite identity \"$notaryName\" for nodes: ${dirs.joinToString()}" }
|
||||
val keyPairs = (1..dirs.size).map { generateKeyPair() }
|
||||
val notaryKey = CompositeKey.Builder().addKeys(keyPairs.map { it.public }).build(threshold)
|
||||
keyPairs.zip(dirs) { keyPair, nodeDir ->
|
||||
generateCertificates(keyPair, notaryKey, notaryName, nodeDir)
|
||||
}
|
||||
return Party(notaryName, notaryKey)
|
||||
}
|
||||
|
||||
/** Generates a CFT notary identity, where the entire cluster shares a key pair. */
|
||||
fun generateDistributedNotarySingularIdentity(dirs: List<Path>, notaryName: CordaX500Name): Party {
|
||||
require(dirs.isNotEmpty())
|
||||
|
||||
log.trace { "Generating singular identity \"$notaryName\" for nodes: ${dirs.joinToString()}" }
|
||||
|
||||
val keyPair = generateKeyPair()
|
||||
val notaryKey = keyPair.public
|
||||
dirs.forEach { dir ->
|
||||
generateCertificates(keyPair, notaryKey, notaryName, dir)
|
||||
|
||||
dirs.forEach { nodeDir ->
|
||||
val keyStore = getKeyStore(nodeDir)
|
||||
setPrivateKey(keyStore, keyPair, notaryName.x500Principal)
|
||||
}
|
||||
return Party(notaryName, notaryKey)
|
||||
}
|
||||
|
||||
private fun generateCertificates(keyPair: KeyPair, notaryKey: PublicKey, notaryName: CordaX500Name, nodeDir: Path) {
|
||||
val (serviceKeyCert, compositeKeyCert) = listOf(keyPair.public, notaryKey).map { publicKey ->
|
||||
X509Utilities.createCertificate(
|
||||
CertificateType.SERVICE_IDENTITY,
|
||||
DEV_INTERMEDIATE_CA.certificate,
|
||||
DEV_INTERMEDIATE_CA.keyPair,
|
||||
notaryName.x500Principal,
|
||||
publicKey)
|
||||
}
|
||||
val distServKeyStoreFile = (nodeDir / "certificates").createDirectories() / "distributedService.jks"
|
||||
X509KeyStore.fromFile(distServKeyStoreFile, DEV_CA_KEY_STORE_PASS, createNew = true).update {
|
||||
setCertificate("$DISTRIBUTED_NOTARY_ALIAS_PREFIX-composite-key", compositeKeyCert)
|
||||
setPrivateKey(
|
||||
"$DISTRIBUTED_NOTARY_ALIAS_PREFIX-private-key",
|
||||
keyPair.private,
|
||||
listOf(serviceKeyCert, DEV_INTERMEDIATE_CA.certificate, DEV_ROOT_CA.certificate),
|
||||
DEV_CA_KEY_STORE_PASS // Unfortunately we have to use the same password for private key due to Artemis limitation, for more details please see:
|
||||
// org.apache.activemq.artemis.core.remoting.impl.ssl.SSLSupport.loadKeyManagerFactory
|
||||
// where it is calling `KeyManagerFactory.init()` with store password
|
||||
/*DEV_CA_PRIVATE_KEY_PASS*/)
|
||||
/** Generates a BFT notary identity: individual key pairs for each cluster member, and a shared composite key. */
|
||||
fun generateDistributedNotaryCompositeIdentity(dirs: List<Path>, notaryName: CordaX500Name, threshold: Int = 1): Party {
|
||||
require(dirs.isNotEmpty())
|
||||
|
||||
log.trace { "Generating composite identity \"$notaryName\" for nodes: ${dirs.joinToString()}" }
|
||||
|
||||
val keyPairs = (1..dirs.size).map { generateKeyPair() }
|
||||
val notaryKey = CompositeKey.Builder().addKeys(keyPairs.map { it.public }).build(threshold)
|
||||
|
||||
keyPairs.zip(dirs) { keyPair, nodeDir ->
|
||||
val keyStore = getKeyStore(nodeDir)
|
||||
setPrivateKey(keyStore, keyPair, notaryName.x500Principal)
|
||||
setCompositeKey(keyStore, notaryKey, notaryName.x500Principal)
|
||||
}
|
||||
return Party(notaryName, notaryKey)
|
||||
}
|
||||
|
||||
private fun getKeyStore(nodeDir: Path): X509KeyStore {
|
||||
val distServKeyStoreFile = nodeDir / "certificates/distributedService.jks"
|
||||
return X509KeyStore.fromFile(distServKeyStoreFile, DEV_CA_KEY_STORE_PASS, createNew = true)
|
||||
}
|
||||
|
||||
private fun setPrivateKey(keyStore: X509KeyStore, keyPair: KeyPair, notaryPrincipal: X500Principal) {
|
||||
val serviceKeyCert = createCertificate(keyPair.public, notaryPrincipal)
|
||||
keyStore.setPrivateKey(
|
||||
"$DISTRIBUTED_NOTARY_ALIAS_PREFIX-private-key",
|
||||
keyPair.private,
|
||||
listOf(serviceKeyCert, DEV_INTERMEDIATE_CA.certificate, DEV_ROOT_CA.certificate),
|
||||
DEV_CA_KEY_STORE_PASS // Unfortunately we have to use the same password for private key due to Artemis limitation, for more details please see:
|
||||
// org.apache.activemq.artemis.core.remoting.impl.ssl.SSLSupport.loadKeyManagerFactory
|
||||
// where it is calling `KeyManagerFactory.init()` with store password
|
||||
/*DEV_CA_PRIVATE_KEY_PASS*/)
|
||||
}
|
||||
|
||||
private fun setCompositeKey(keyStore: X509KeyStore, compositeKey: PublicKey, notaryPrincipal: X500Principal) {
|
||||
val compositeKeyCert = createCertificate(compositeKey, notaryPrincipal)
|
||||
keyStore.setCertificate("$DISTRIBUTED_NOTARY_ALIAS_PREFIX-composite-key", compositeKeyCert)
|
||||
}
|
||||
|
||||
private fun createCertificate(publicKey: PublicKey, principal: X500Principal): X509Certificate {
|
||||
return X509Utilities.createCertificate(
|
||||
CertificateType.SERVICE_IDENTITY,
|
||||
DEV_INTERMEDIATE_CA.certificate,
|
||||
DEV_INTERMEDIATE_CA.keyPair,
|
||||
principal,
|
||||
publicKey)
|
||||
}
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ import net.corda.serialization.internal.amqp.AbstractAMQPSerializationScheme
|
||||
import net.corda.serialization.internal.amqp.amqpMagic
|
||||
import java.io.File
|
||||
import java.io.InputStream
|
||||
import java.nio.file.FileAlreadyExistsException
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.StandardCopyOption.REPLACE_EXISTING
|
||||
import java.security.PublicKey
|
||||
@ -226,7 +227,13 @@ internal constructor(private val initSerEnv: Boolean,
|
||||
println("Copying CorDapp JARs into node directories")
|
||||
for (nodeDir in nodeDirs) {
|
||||
val cordappsDir = (nodeDir / "cordapps").createDirectories()
|
||||
cordappJars.forEach { it.copyToDirectory(cordappsDir) }
|
||||
cordappJars.forEach {
|
||||
try {
|
||||
it.copyToDirectory(cordappsDir)
|
||||
} catch (e: FileAlreadyExistsException) {
|
||||
println("WARNING: ${it.fileName} already exists in $cordappsDir, ignoring and leaving existing CorDapp untouched")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
generateServiceIdentitiesForNotaryClusters(configs)
|
||||
|
Reference in New Issue
Block a user