Merge pull request #1261 from corda/pat/crl-check-cherry-pick

CRL url checks and warning for mis-configurated CRL endpoint (#1258)
This commit is contained in:
Patrick Kuo 2018-07-16 11:43:21 +01:00 committed by GitHub
commit 52d281b66f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 49 additions and 4 deletions

View File

@ -22,9 +22,13 @@ import net.corda.core.serialization.serialize
import net.corda.core.utilities.OpaqueBytes
import net.corda.core.utilities.toBase58
import net.corda.core.utilities.toSHA256Bytes
import org.bouncycastle.asn1.x509.CRLDistPoint
import org.bouncycastle.asn1.x509.Extension
import org.bouncycastle.x509.extension.X509ExtensionUtil
import java.math.BigInteger
import java.nio.ByteBuffer
import java.security.*
import java.security.cert.X509Certificate
/**
* Utility to simplify the act of signing a byte array.
@ -117,6 +121,7 @@ val PublicKey.keys: Set<PublicKey> get() = (this as? CompositeKey)?.leafKeys ?:
/** Return true if [otherKey] fulfils the requirements of this [PublicKey]. */
fun PublicKey.isFulfilledBy(otherKey: PublicKey): Boolean = isFulfilledBy(setOf(otherKey))
/** Return true if [otherKeys] fulfil the requirements of this [PublicKey]. */
fun PublicKey.isFulfilledBy(otherKeys: Iterable<PublicKey>): Boolean = (this as? CompositeKey)?.isFulfilledBy(otherKeys) ?: (this in otherKeys)
@ -133,6 +138,7 @@ fun Iterable<TransactionSignature>.byKeys() = map { it.by }.toSet()
// val (private, public) = keyPair
/* The [PrivateKey] of this [KeyPair]. */
operator fun KeyPair.component1(): PrivateKey = this.private
/* The [PublicKey] of this [KeyPair]. */
operator fun KeyPair.component2(): PublicKey = this.public
@ -207,6 +213,7 @@ private class DummySecureRandomSpi : SecureRandomSpi() {
return ByteArray(numberOfBytes)
}
}
object DummySecureRandom : SecureRandom(DummySecureRandomSpi(), null)
/**
@ -273,3 +280,19 @@ fun <T : Any> serializedHash(x: T): SecureHash = x.serialize(context = Serializa
* @return SHA256(SHA256(privacySalt || groupIndex || internalIndex))
*/
fun computeNonce(privacySalt: PrivacySalt, groupIndex: Int, internalIndex: Int) = SecureHash.sha256Twice(privacySalt.bytes + ByteBuffer.allocate(8).putInt(groupIndex).putInt(internalIndex).array())
/**
* Method to check if the certificate path contains blacklisted CRL distribution point URL.
*/
val blacklistedCrlEndpoints = setOf("r3-test.com")
fun isCRLDistributionPointBlacklisted(certChain: List<X509Certificate>): Boolean {
// Doorman certificate checks for mis-configured CRL endpoint.
return certChain.any {
it.getExtensionValue(Extension.cRLDistributionPoints.id)?.let {
CRLDistPoint.getInstance(X509ExtensionUtil.fromExtensionValue(it)).distributionPoints.any { distPoint ->
blacklistedCrlEndpoints.any { distPoint.distributionPoint.toString().contains(it) }
}
} ?: false
}
}

View File

@ -11,6 +11,11 @@
package net.corda.core.crypto
import com.google.common.collect.Sets
import net.corda.core.identity.CordaX500Name
import net.corda.nodeapi.internal.DEV_INTERMEDIATE_CA
import net.corda.nodeapi.internal.DEV_ROOT_CA
import net.corda.nodeapi.internal.crypto.CertificateType
import net.corda.nodeapi.internal.crypto.X509Utilities
import net.i2p.crypto.eddsa.EdDSAKey
import net.i2p.crypto.eddsa.EdDSAPrivateKey
import net.i2p.crypto.eddsa.EdDSAPublicKey
@ -902,4 +907,13 @@ class CryptoUtilsTest {
val keyPairBiggerThan258bits = Crypto.deriveKeyPairFromEntropy(Crypto.ECDSA_SECP256K1_SHA256, BigInteger("2").pow(259).plus(BigInteger.ONE))
assertEquals("DL7NbssqvuuJ4cqFkkaVYu9j1MsVswESGgCfbqBS9ULwuM", keyPairBiggerThan258bits.public.toStringShort())
}
@Test
fun `crl distribution point is blacklisted`() {
val intermediateCert = X509Utilities.createCertificate(CertificateType.INTERMEDIATE_CA, DEV_ROOT_CA.certificate, DEV_ROOT_CA.keyPair, DEV_INTERMEDIATE_CA.certificate.subjectX500Principal, DEV_INTERMEDIATE_CA.keyPair.public, crlDistPoint = "http://r3-test.com/certificate-revocation-list/root")
val nodeCA = X509Utilities.createCertificate(CertificateType.NODE_CA, intermediateCert, DEV_INTERMEDIATE_CA.keyPair, CordaX500Name("Test", "London", "GB").x500Principal, generateKeyPair().public)
assertTrue {
isCRLDistributionPointBlacklisted(listOf(nodeCA, intermediateCert, DEV_ROOT_CA.certificate))
}
}
}

View File

@ -19,6 +19,7 @@ import net.corda.confidential.SwapIdentitiesHandler
import net.corda.core.CordaException
import net.corda.core.concurrent.CordaFuture
import net.corda.core.context.InvocationContext
import net.corda.core.crypto.isCRLDistributionPointBlacklisted
import net.corda.core.crypto.newSecureRandom
import net.corda.core.crypto.sign
import net.corda.core.flows.ContractUpgradeFlow
@ -35,13 +36,10 @@ import net.corda.core.identity.AbstractParty
import net.corda.core.identity.CordaX500Name
import net.corda.core.identity.Party
import net.corda.core.identity.PartyAndCertificate
import net.corda.core.internal.Emoji
import net.corda.core.internal.FlowStateMachine
import net.corda.core.internal.VisibleForTesting
import net.corda.core.internal.*
import net.corda.core.internal.concurrent.map
import net.corda.core.internal.concurrent.openFuture
import net.corda.core.internal.notary.NotaryService
import net.corda.core.internal.uncheckedCast
import net.corda.core.messaging.CordaRPCOps
import net.corda.core.messaging.FlowHandle
import net.corda.core.messaging.FlowHandleImpl
@ -159,6 +157,9 @@ import net.corda.nodeapi.internal.persistence.isH2Database
import net.corda.nodeapi.internal.storeLegalIdentity
import net.corda.tools.shell.InteractiveShell
import org.apache.activemq.artemis.utils.ReusableLatch
import org.bouncycastle.asn1.x509.CRLDistPoint
import org.bouncycastle.asn1.x509.Extension
import org.bouncycastle.x509.extension.X509ExtensionUtil
import org.hibernate.type.descriptor.java.JavaTypeDescriptorRegistry
import org.slf4j.Logger
import rx.Observable
@ -870,6 +871,13 @@ abstract class AbstractNode(val configuration: NodeConfiguration,
require(sslCertChainRoot == trustRoot) { "TLS certificate must chain to the trusted root." }
require(nodeCaCertChainRoot == trustRoot) { "Client CA certificate must chain to the trusted root." }
if (configuration.devMode) {
val blacklisted = isCRLDistributionPointBlacklisted(configuration.loadNodeKeyStore().getCertificateChain(X509Utilities.CORDA_CLIENT_CA))
if(blacklisted){
log.warn("The format of the autogenerated dev. mode certificate this system uses has been deprecated. Please contact support@r3.com for information on how to upgrade.")
}
}
}
// Specific class so that MockNode can catch it.