CORDA-2031 put "AlgorithmParameters.SHA256WITHECDSA" to BC (#3997)

This commit is contained in:
Konstantinos Chalkias 2018-09-27 15:21:12 +01:00 committed by GitHub
parent adcd0d45df
commit e92ad538cf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 73 additions and 29 deletions

View File

@ -11,6 +11,7 @@ import net.i2p.crypto.eddsa.EdDSASecurityProvider
import org.bouncycastle.asn1.ASN1ObjectIdentifier
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo
import org.bouncycastle.jcajce.provider.asymmetric.ec.AlgorithmParametersSpi
import org.bouncycastle.jcajce.provider.util.AsymmetricKeyInfoConverter
import org.bouncycastle.jce.provider.BouncyCastleProvider
import org.bouncycastle.pqc.jcajce.provider.BouncyCastlePQCProvider
@ -30,6 +31,8 @@ internal val cordaBouncyCastleProvider = BouncyCastleProvider().apply {
override fun generatePublic(keyInfo: SubjectPublicKeyInfo) = decodePublicKey(EDDSA_ED25519_SHA512, keyInfo.encoded)
override fun generatePrivate(keyInfo: PrivateKeyInfo) = decodePrivateKey(EDDSA_ED25519_SHA512, keyInfo.encoded)
})
// Required due to [X509CRL].verify() reported issues in network-services after BC 1.60 update.
put("AlgorithmParameters.SHA256WITHECDSA", AlgorithmParametersSpi::class.java.name)
}.also {
// This registration is needed for reading back EdDSA key from java keystore.
// TODO: Find a way to make JKS work with bouncy castle provider or implement our own provide so we don't have to register bouncy castle provider.

View File

@ -25,10 +25,10 @@ import net.corda.testing.core.BOB_NAME
import net.corda.testing.core.CHARLIE_NAME
import net.corda.testing.core.MAX_MESSAGE_SIZE
import net.corda.testing.driver.PortAllocation
import net.corda.testing.internal.stubs.CertificateStoreStubs
import net.corda.testing.internal.DEV_INTERMEDIATE_CA
import net.corda.testing.internal.DEV_ROOT_CA
import net.corda.testing.internal.rigorousMock
import net.corda.testing.internal.stubs.CertificateStoreStubs
import org.bouncycastle.asn1.x500.X500Name
import org.bouncycastle.asn1.x509.*
import org.bouncycastle.cert.jcajce.JcaX509CRLConverter
@ -62,6 +62,7 @@ import javax.ws.rs.Path
import javax.ws.rs.Produces
import javax.ws.rs.core.Response
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
class CertificateRevocationListNodeTests {
@Rule
@ -81,6 +82,32 @@ class CertificateRevocationListNodeTests {
private abstract class AbstractNodeConfiguration : NodeConfiguration
companion object {
fun createRevocationList(clrServer: CrlServer, signatureAlgorithm: String, caCertificate: X509Certificate,
caPrivateKey: PrivateKey,
endpoint: String,
indirect: Boolean,
vararg serialNumbers: BigInteger): X509CRL {
println("Generating CRL for $endpoint")
val builder = JcaX509v2CRLBuilder(caCertificate.subjectX500Principal, Date(System.currentTimeMillis() - 1.minutes.toMillis()))
val extensionUtils = JcaX509ExtensionUtils()
builder.addExtension(Extension.authorityKeyIdentifier,
false, extensionUtils.createAuthorityKeyIdentifier(caCertificate))
val issuingDistPointName = GeneralName(
GeneralName.uniformResourceIdentifier,
"http://${clrServer.hostAndPort.host}:${clrServer.hostAndPort.port}/crl/$endpoint")
// This is required and needs to match the certificate settings with respect to being indirect
val issuingDistPoint = IssuingDistributionPoint(DistributionPointName(GeneralNames(issuingDistPointName)), indirect, false)
builder.addExtension(Extension.issuingDistributionPoint, true, issuingDistPoint)
builder.setNextUpdate(Date(System.currentTimeMillis() + 1.seconds.toMillis()))
serialNumbers.forEach {
builder.addCRLEntry(it, Date(System.currentTimeMillis() - 10.minutes.toMillis()), ReasonFlags.certificateHold)
}
val signer = JcaContentSignerBuilder(signatureAlgorithm).setProvider(Crypto.findProvider("BC")).build(caPrivateKey)
return JcaX509CRLConverter().setProvider(Crypto.findProvider("BC")).getCRL(builder.build(signer))
}
}
@Before
fun setUp() {
Security.addProvider(BouncyCastleProvider())
@ -455,12 +482,15 @@ class CertificateRevocationListNodeTests {
@Path("node.crl")
@Produces("application/pkcs7-crl")
fun getNodeCRL(): Response {
return Response.ok(createRevocationList(
return Response.ok(CertificateRevocationListNodeTests.createRevocationList(
server,
SIGNATURE_ALGORITHM,
INTERMEDIATE_CA.certificate,
INTERMEDIATE_CA.keyPair.private,
NODE_CRL,
false,
*revokedNodeCerts.toTypedArray()).encoded).build()
*revokedNodeCerts.toTypedArray()).encoded)
.build()
}
@GET
@ -468,11 +498,14 @@ class CertificateRevocationListNodeTests {
@Produces("application/pkcs7-crl")
fun getIntermediateCRL(): Response {
return Response.ok(createRevocationList(
server,
SIGNATURE_ALGORITHM,
ROOT_CA.certificate,
ROOT_CA.keyPair.private,
INTEMEDIATE_CRL,
false,
*revokedIntermediateCerts.toTypedArray()).encoded).build()
*revokedIntermediateCerts.toTypedArray()).encoded)
.build()
}
@GET
@ -480,33 +513,13 @@ class CertificateRevocationListNodeTests {
@Produces("application/pkcs7-crl")
fun getEmptyCRL(): Response {
return Response.ok(createRevocationList(
server,
SIGNATURE_ALGORITHM,
ROOT_CA.certificate,
ROOT_CA.keyPair.private,
EMPTY_CRL, true).encoded).build()
}
private fun createRevocationList(caCertificate: X509Certificate,
caPrivateKey: PrivateKey,
endpoint: String,
indirect: Boolean,
vararg serialNumbers: BigInteger): X509CRL {
println("Generating CRL for $endpoint")
val builder = JcaX509v2CRLBuilder(caCertificate.subjectX500Principal, Date(System.currentTimeMillis() - 1.minutes.toMillis()))
val extensionUtils = JcaX509ExtensionUtils()
builder.addExtension(Extension.authorityKeyIdentifier,
false, extensionUtils.createAuthorityKeyIdentifier(caCertificate))
val issuingDistPointName = GeneralName(
GeneralName.uniformResourceIdentifier,
"http://${server.hostAndPort.host}:${server.hostAndPort.port}/crl/$endpoint")
// This is required and needs to match the certificate settings with respect to being indirect
val issuingDistPoint = IssuingDistributionPoint(DistributionPointName(GeneralNames(issuingDistPointName)), indirect, false)
builder.addExtension(Extension.issuingDistributionPoint, true, issuingDistPoint)
builder.setNextUpdate(Date(System.currentTimeMillis() + 1.seconds.toMillis()))
serialNumbers.forEach {
builder.addCRLEntry(it, Date(System.currentTimeMillis() - 10.minutes.toMillis()), ReasonFlags.certificateHold)
}
val signer = JcaContentSignerBuilder(SIGNATURE_ALGORITHM).setProvider(BouncyCastleProvider.PROVIDER_NAME).build(caPrivateKey)
return JcaX509CRLConverter().setProvider(BouncyCastleProvider.PROVIDER_NAME).getCRL(builder.build(signer))
EMPTY_CRL,
true).encoded)
.build()
}
}
@ -546,4 +559,32 @@ class CertificateRevocationListNodeTests {
}
}
}
@Test
fun `verify CRL algorithms`() {
val ECDSA_ALGORITHM = "SHA256withECDSA"
val EC_ALGORITHM = "EC"
val EMPTY_CRL = "empty.crl"
val crl = createRevocationList(
server,
ECDSA_ALGORITHM,
ROOT_CA.certificate,
ROOT_CA.keyPair.private,
EMPTY_CRL,
true)
// This should pass.
crl.verify(ROOT_CA.keyPair.public)
// Try changing the algorithm to EC will fail.
assertFailsWith<IllegalArgumentException>("Unknown signature type requested: EC") {
createRevocationList(
server,
EC_ALGORITHM,
ROOT_CA.certificate,
ROOT_CA.keyPair.private,
EMPTY_CRL,
true)
}
}
}