mirror of
https://github.com/corda/corda.git
synced 2025-03-16 00:55:24 +00:00
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:
commit
52d281b66f
@ -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
|
||||
}
|
||||
}
|
@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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.
|
||||
|
Loading…
x
Reference in New Issue
Block a user