CORDA-1995 - Removing DigitalSignatureWithCertPath (Cherry Pick) (#3970)

* CORDA-1995 Adding the parent certificate chain to the DigitalSignatureWithCert class

* Addressing review comments
This commit is contained in:
Michal Kit 2018-09-20 16:07:53 +01:00 committed by Katelyn Baker
parent 52b7a798d4
commit a61de95102
3 changed files with 36 additions and 16 deletions

View File

@ -202,7 +202,7 @@ class JacksonSupportTest(@Suppress("unused") private val name: String, factory:
fun DigitalSignatureWithCert() {
val digitalSignature = DigitalSignatureWithCert(MINI_CORP.identity.certificate, secureRandomBytes(128))
val json = mapper.valueToTree<ObjectNode>(digitalSignature)
val (by, bytes) = json.assertHasOnlyFields("by", "bytes")
val (by, bytes) = json.assertHasOnlyFields("by", "bytes", "parentCertsChain")
assertThat(by.valueAs<X509Certificate>(mapper)).isEqualTo(MINI_CORP.identity.certificate)
assertThat(bytes.binaryValue()).isEqualTo(digitalSignature.bytes)
assertThat(mapper.convertValue<DigitalSignatureWithCert>(json)).isEqualTo(digitalSignature)

View File

@ -4,26 +4,46 @@ import net.corda.core.crypto.DigitalSignature
import net.corda.core.crypto.SignedData
import net.corda.core.crypto.verify
import net.corda.core.serialization.CordaSerializable
import net.corda.core.serialization.DeprecatedConstructorForDeserialization
import net.corda.core.serialization.SerializedBytes
import net.corda.core.serialization.deserialize
import net.corda.core.utilities.OpaqueBytes
import java.security.cert.CertPath
import java.security.cert.X509Certificate
import java.security.cert.*
// TODO: Rename this to DigitalSignature.WithCert once we're happy for it to be public API. The methods will need documentation
// and the correct exceptions will be need to be annotated
/** A digital signature with attached certificate of the public key. */
open class DigitalSignatureWithCert(val by: X509Certificate, bytes: ByteArray) : DigitalSignature(bytes) {
/** A digital signature with attached certificate of the public key and (optionally) the remaining chain of the certificates from the certificate path. */
class DigitalSignatureWithCert(val by: X509Certificate, val parentCertsChain: List<X509Certificate>, bytes: ByteArray) : DigitalSignature(bytes) {
@DeprecatedConstructorForDeserialization(1)
constructor(by: X509Certificate, bytes: ByteArray) : this(by, emptyList(), bytes)
/* The difference between this and the master branch with respect to the implementation of the following two properties
* is due to the missing changes in the JSON/YAML serialization framework. In the master branch the following are
* expressed as properties instead of functions.
*/
fun fullCertChain(): List<X509Certificate> = listOf(by) + parentCertsChain
fun fullCertPath(): CertPath = CertificateFactory.getInstance("X.509").generateCertPath(fullCertChain())
fun verify(content: ByteArray): Boolean = by.publicKey.verify(content, this)
fun verify(content: OpaqueBytes): Boolean = verify(content.bytes)
}
/**
* A digital signature with attached certificate path. The first certificate in the path corresponds to the data signer key.
* @param path certificate path associated with this signature
* @param bytes signature bytes
*/
class DigitalSignatureWithCertPath(val path: List<X509Certificate>, bytes: ByteArray): DigitalSignatureWithCert(path.first(), bytes)
init {
if (parentCertsChain.isNotEmpty()) {
val parameters = PKIXParameters(setOf(TrustAnchor(parentCertsChain.last(), null))).apply { isRevocationEnabled = false }
try {
CertPathValidator.getInstance("PKIX").validate(fullCertPath(), parameters)
} catch (e: CertPathValidatorException) {
throw IllegalArgumentException(
"""Cert path failed to validate.
Reason: ${e.reason}
Offending cert index: ${e.index}
Cert path: ${fullCertPath()}
""", e)
}
}
}
}
/** Similar to [SignedData] but instead of just attaching the public key, the certificate for the key is attached instead. */
@CordaSerializable

View File

@ -2,7 +2,6 @@ package net.corda.nodeapi.internal.network
import net.corda.core.crypto.SecureHash
import net.corda.core.internal.CertRole
import net.corda.core.internal.DigitalSignatureWithCertPath
import net.corda.core.internal.SignedDataWithCert
import net.corda.core.node.NetworkParameters
import net.corda.core.node.NodeInfo
@ -57,9 +56,10 @@ data class ParametersUpdate(
/** Verify that a Network Map certificate path and its [CertRole] is correct. */
fun <T : Any> SignedDataWithCert<T>.verifiedNetworkMapCert(rootCert: X509Certificate): T {
require(CertRole.extract(sig.by) == CertRole.NETWORK_MAP) { "Incorrect cert role: ${CertRole.extract(sig.by)}" }
val path = when (this.sig) {
is DigitalSignatureWithCertPath -> (sig as DigitalSignatureWithCertPath).path
else -> listOf(sig.by, rootCert)
val path = if (sig.parentCertsChain.isEmpty()) {
listOf(sig.by, rootCert)
} else {
sig.fullCertChain()
}
X509Utilities.validateCertificateChain(rootCert, path)
return verified()