Merge commit '22af527b7943c0c4376af582de6505893817111a' into andr3ej-ross-merge

# Conflicts:
#	docs/source/changelog.rst
This commit is contained in:
Andrzej Cichocki
2017-12-19 17:07:17 +00:00
25 changed files with 405 additions and 106 deletions

View File

@ -37,16 +37,16 @@ object ServiceIdentityGenerator {
val notaryKey = CompositeKey.Builder().addKeys(keyPairs.map { it.public }).build(threshold)
val caKeyStore = loadKeyStore(javaClass.classLoader.getResourceAsStream("certificates/cordadevcakeys.jks"), "cordacadevpass")
val issuer = caKeyStore.getCertificateAndKeyPair(X509Utilities.CORDA_INTERMEDIATE_CA, "cordacadevkeypass")
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.NODE_CA, issuer.certificate, issuer.keyPair, serviceName, keyPair.public)
val compositeKeyCert = X509Utilities.createCertificate(CertificateType.NODE_CA, issuer.certificate, issuer.keyPair, serviceName, notaryKey)
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 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, issuer.certificate.cert, rootCert))
keystore.setKeyEntry("$serviceId-private-key", keyPair.private, "cordacadevkeypass".toCharArray(), arrayOf(serviceKeyCert.cert, intermediateCa.certificate.cert, rootCert))
keystore.save(certPath, "cordacadevpass")
}
return Party(serviceName, notaryKey)

View File

@ -17,7 +17,7 @@ class KeyStoreWrapper(private val storePath: Path, private val storePassword: St
// Assume key password = store password.
val clientCA = certificateAndKeyPair(X509Utilities.CORDA_CLIENT_CA)
// Create new keys and store in keystore.
val cert = X509Utilities.createCertificate(CertificateType.WELL_KNOWN_IDENTITY, clientCA.certificate, clientCA.keyPair, serviceName, pubKey)
val cert = X509Utilities.createCertificate(CertificateType.LEGAL_IDENTITY, clientCA.certificate, clientCA.keyPair, serviceName, pubKey)
val certPath = X509CertificateFactory().generateCertPath(cert.cert, *clientCertPath)
require(certPath.certificates.isNotEmpty()) { "Certificate path cannot be empty" }
// TODO: X509Utilities.validateCertificateChain()

View File

@ -1,18 +1,17 @@
package net.corda.nodeapi.internal.crypto
import net.corda.core.CordaOID
import net.corda.core.crypto.Crypto
import net.corda.core.crypto.SignatureScheme
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.x500Name
import net.corda.core.utilities.days
import net.corda.core.utilities.millis
import org.bouncycastle.asn1.ASN1EncodableVector
import org.bouncycastle.asn1.ASN1Sequence
import org.bouncycastle.asn1.DERSequence
import org.bouncycastle.asn1.DERUTF8String
import org.bouncycastle.asn1.*
import org.bouncycastle.asn1.x500.X500Name
import org.bouncycastle.asn1.x500.style.BCStyle
import org.bouncycastle.asn1.x509.*
@ -221,6 +220,7 @@ object X509Utilities {
val serial = BigInteger.valueOf(random63BitValue())
val keyPurposes = DERSequence(ASN1EncodableVector().apply { certificateType.purposes.forEach { add(it) } })
val subjectPublicKeyInfo = SubjectPublicKeyInfo.getInstance(ASN1Sequence.getInstance(subjectPublicKey.encoded))
val role = certificateType.role
val builder = JcaX509v3CertificateBuilder(issuer, serial, validityWindow.first, validityWindow.second,
subject, subjectPublicKey)
@ -229,9 +229,13 @@ object X509Utilities {
.addExtension(Extension.keyUsage, false, certificateType.keyUsage)
.addExtension(Extension.extendedKeyUsage, false, keyPurposes)
if (role != null) {
builder.addExtension(ASN1ObjectIdentifier(CordaOID.X509_EXTENSION_CORDA_ROLE), false, role)
}
if (nameConstraints != null) {
builder.addExtension(Extension.nameConstraints, true, nameConstraints)
}
return builder
}
@ -322,13 +326,14 @@ class X509CertificateFactory {
}
}
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, val role: CertRole?) {
ROOT_CA(
KeyUsage(KeyUsage.digitalSignature or KeyUsage.keyCertSign or KeyUsage.cRLSign),
KeyPurposeId.id_kp_serverAuth,
KeyPurposeId.id_kp_clientAuth,
KeyPurposeId.anyExtendedKeyUsage,
isCA = true
isCA = true,
role = null
),
INTERMEDIATE_CA(
@ -336,7 +341,26 @@ enum class CertificateType(val keyUsage: KeyUsage, vararg val purposes: KeyPurpo
KeyPurposeId.id_kp_serverAuth,
KeyPurposeId.id_kp_clientAuth,
KeyPurposeId.anyExtendedKeyUsage,
isCA = true
isCA = true,
role = CertRole.INTERMEDIATE_CA
),
NETWORK_MAP(
KeyUsage(KeyUsage.digitalSignature),
KeyPurposeId.id_kp_serverAuth,
KeyPurposeId.id_kp_clientAuth,
KeyPurposeId.anyExtendedKeyUsage,
isCA = false,
role = CertRole.NETWORK_MAP
),
SERVICE_IDENTITY(
KeyUsage(KeyUsage.digitalSignature),
KeyPurposeId.id_kp_serverAuth,
KeyPurposeId.id_kp_clientAuth,
KeyPurposeId.anyExtendedKeyUsage,
isCA = false,
role = CertRole.SERVICE_IDENTITY
),
NODE_CA(
@ -344,7 +368,8 @@ enum class CertificateType(val keyUsage: KeyUsage, vararg val purposes: KeyPurpo
KeyPurposeId.id_kp_serverAuth,
KeyPurposeId.id_kp_clientAuth,
KeyPurposeId.anyExtendedKeyUsage,
isCA = true
isCA = true,
role = CertRole.NODE_CA
),
TLS(
@ -352,24 +377,27 @@ enum class CertificateType(val keyUsage: KeyUsage, vararg val purposes: KeyPurpo
KeyPurposeId.id_kp_serverAuth,
KeyPurposeId.id_kp_clientAuth,
KeyPurposeId.anyExtendedKeyUsage,
isCA = false
isCA = false,
role = CertRole.TLS
),
// TODO: Identity certs should have only limited depth (i.e. 1) CA signing capability, with tight name constraints
WELL_KNOWN_IDENTITY(
// TODO: Identity certs should have tight name constraints on child certificates
LEGAL_IDENTITY(
KeyUsage(KeyUsage.digitalSignature or KeyUsage.keyCertSign),
KeyPurposeId.id_kp_serverAuth,
KeyPurposeId.id_kp_clientAuth,
KeyPurposeId.anyExtendedKeyUsage,
isCA = true
isCA = true,
role = CertRole.LEGAL_IDENTITY
),
CONFIDENTIAL_IDENTITY(
CONFIDENTIAL_LEGAL_IDENTITY(
KeyUsage(KeyUsage.digitalSignature),
KeyPurposeId.id_kp_serverAuth,
KeyPurposeId.id_kp_clientAuth,
KeyPurposeId.anyExtendedKeyUsage,
isCA = false
isCA = false,
role = CertRole.CONFIDENTIAL_LEGAL_IDENTITY
)
}