mirror of
https://github.com/corda/corda.git
synced 2025-02-21 17:56:54 +00:00
CORDA-2031 put "AlgorithmParameters.SHA256WITHECDSA" to BC (#3997)
This commit is contained in:
parent
adcd0d45df
commit
e92ad538cf
@ -11,6 +11,7 @@ import net.i2p.crypto.eddsa.EdDSASecurityProvider
|
|||||||
import org.bouncycastle.asn1.ASN1ObjectIdentifier
|
import org.bouncycastle.asn1.ASN1ObjectIdentifier
|
||||||
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo
|
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo
|
||||||
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo
|
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo
|
||||||
|
import org.bouncycastle.jcajce.provider.asymmetric.ec.AlgorithmParametersSpi
|
||||||
import org.bouncycastle.jcajce.provider.util.AsymmetricKeyInfoConverter
|
import org.bouncycastle.jcajce.provider.util.AsymmetricKeyInfoConverter
|
||||||
import org.bouncycastle.jce.provider.BouncyCastleProvider
|
import org.bouncycastle.jce.provider.BouncyCastleProvider
|
||||||
import org.bouncycastle.pqc.jcajce.provider.BouncyCastlePQCProvider
|
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 generatePublic(keyInfo: SubjectPublicKeyInfo) = decodePublicKey(EDDSA_ED25519_SHA512, keyInfo.encoded)
|
||||||
override fun generatePrivate(keyInfo: PrivateKeyInfo) = decodePrivateKey(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 {
|
}.also {
|
||||||
// This registration is needed for reading back EdDSA key from java keystore.
|
// 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.
|
// 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.
|
||||||
|
@ -25,10 +25,10 @@ import net.corda.testing.core.BOB_NAME
|
|||||||
import net.corda.testing.core.CHARLIE_NAME
|
import net.corda.testing.core.CHARLIE_NAME
|
||||||
import net.corda.testing.core.MAX_MESSAGE_SIZE
|
import net.corda.testing.core.MAX_MESSAGE_SIZE
|
||||||
import net.corda.testing.driver.PortAllocation
|
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_INTERMEDIATE_CA
|
||||||
import net.corda.testing.internal.DEV_ROOT_CA
|
import net.corda.testing.internal.DEV_ROOT_CA
|
||||||
import net.corda.testing.internal.rigorousMock
|
import net.corda.testing.internal.rigorousMock
|
||||||
|
import net.corda.testing.internal.stubs.CertificateStoreStubs
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
import org.bouncycastle.asn1.x500.X500Name
|
||||||
import org.bouncycastle.asn1.x509.*
|
import org.bouncycastle.asn1.x509.*
|
||||||
import org.bouncycastle.cert.jcajce.JcaX509CRLConverter
|
import org.bouncycastle.cert.jcajce.JcaX509CRLConverter
|
||||||
@ -62,6 +62,7 @@ import javax.ws.rs.Path
|
|||||||
import javax.ws.rs.Produces
|
import javax.ws.rs.Produces
|
||||||
import javax.ws.rs.core.Response
|
import javax.ws.rs.core.Response
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
import kotlin.test.assertFailsWith
|
||||||
|
|
||||||
class CertificateRevocationListNodeTests {
|
class CertificateRevocationListNodeTests {
|
||||||
@Rule
|
@Rule
|
||||||
@ -81,6 +82,32 @@ class CertificateRevocationListNodeTests {
|
|||||||
|
|
||||||
private abstract class AbstractNodeConfiguration : NodeConfiguration
|
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
|
@Before
|
||||||
fun setUp() {
|
fun setUp() {
|
||||||
Security.addProvider(BouncyCastleProvider())
|
Security.addProvider(BouncyCastleProvider())
|
||||||
@ -455,12 +482,15 @@ class CertificateRevocationListNodeTests {
|
|||||||
@Path("node.crl")
|
@Path("node.crl")
|
||||||
@Produces("application/pkcs7-crl")
|
@Produces("application/pkcs7-crl")
|
||||||
fun getNodeCRL(): Response {
|
fun getNodeCRL(): Response {
|
||||||
return Response.ok(createRevocationList(
|
return Response.ok(CertificateRevocationListNodeTests.createRevocationList(
|
||||||
|
server,
|
||||||
|
SIGNATURE_ALGORITHM,
|
||||||
INTERMEDIATE_CA.certificate,
|
INTERMEDIATE_CA.certificate,
|
||||||
INTERMEDIATE_CA.keyPair.private,
|
INTERMEDIATE_CA.keyPair.private,
|
||||||
NODE_CRL,
|
NODE_CRL,
|
||||||
false,
|
false,
|
||||||
*revokedNodeCerts.toTypedArray()).encoded).build()
|
*revokedNodeCerts.toTypedArray()).encoded)
|
||||||
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@ -468,11 +498,14 @@ class CertificateRevocationListNodeTests {
|
|||||||
@Produces("application/pkcs7-crl")
|
@Produces("application/pkcs7-crl")
|
||||||
fun getIntermediateCRL(): Response {
|
fun getIntermediateCRL(): Response {
|
||||||
return Response.ok(createRevocationList(
|
return Response.ok(createRevocationList(
|
||||||
|
server,
|
||||||
|
SIGNATURE_ALGORITHM,
|
||||||
ROOT_CA.certificate,
|
ROOT_CA.certificate,
|
||||||
ROOT_CA.keyPair.private,
|
ROOT_CA.keyPair.private,
|
||||||
INTEMEDIATE_CRL,
|
INTEMEDIATE_CRL,
|
||||||
false,
|
false,
|
||||||
*revokedIntermediateCerts.toTypedArray()).encoded).build()
|
*revokedIntermediateCerts.toTypedArray()).encoded)
|
||||||
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@ -480,33 +513,13 @@ class CertificateRevocationListNodeTests {
|
|||||||
@Produces("application/pkcs7-crl")
|
@Produces("application/pkcs7-crl")
|
||||||
fun getEmptyCRL(): Response {
|
fun getEmptyCRL(): Response {
|
||||||
return Response.ok(createRevocationList(
|
return Response.ok(createRevocationList(
|
||||||
|
server,
|
||||||
|
SIGNATURE_ALGORITHM,
|
||||||
ROOT_CA.certificate,
|
ROOT_CA.certificate,
|
||||||
ROOT_CA.keyPair.private,
|
ROOT_CA.keyPair.private,
|
||||||
EMPTY_CRL, true).encoded).build()
|
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))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user