mirror of
https://github.com/corda/corda.git
synced 2024-12-19 21:17:58 +00:00
CORDA-4043: Generate 16-octets certificate serial numbers (#6746)
This commit is contained in:
parent
2dd2029e24
commit
396671cb87
@ -44,6 +44,7 @@ import net.corda.coretesting.internal.NettyTestServer
|
|||||||
import net.corda.testing.internal.createDevIntermediateCaCertPath
|
import net.corda.testing.internal.createDevIntermediateCaCertPath
|
||||||
import net.corda.coretesting.internal.stubs.CertificateStoreStubs
|
import net.corda.coretesting.internal.stubs.CertificateStoreStubs
|
||||||
import net.corda.nodeapi.internal.crypto.CertificateType
|
import net.corda.nodeapi.internal.crypto.CertificateType
|
||||||
|
import net.corda.nodeapi.internal.crypto.X509CertificateFactory
|
||||||
import net.corda.nodeapi.internal.crypto.X509Utilities
|
import net.corda.nodeapi.internal.crypto.X509Utilities
|
||||||
import net.corda.nodeapi.internal.crypto.checkValidity
|
import net.corda.nodeapi.internal.crypto.checkValidity
|
||||||
import net.corda.nodeapi.internal.crypto.getSupportedKey
|
import net.corda.nodeapi.internal.crypto.getSupportedKey
|
||||||
@ -51,6 +52,7 @@ import net.corda.nodeapi.internal.crypto.loadOrCreateKeyStore
|
|||||||
import net.corda.nodeapi.internal.crypto.save
|
import net.corda.nodeapi.internal.crypto.save
|
||||||
import net.corda.nodeapi.internal.crypto.toBc
|
import net.corda.nodeapi.internal.crypto.toBc
|
||||||
import net.corda.nodeapi.internal.crypto.x509
|
import net.corda.nodeapi.internal.crypto.x509
|
||||||
|
import net.corda.nodeapi.internal.crypto.x509Certificates
|
||||||
import net.i2p.crypto.eddsa.EdDSAPrivateKey
|
import net.i2p.crypto.eddsa.EdDSAPrivateKey
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.bouncycastle.asn1.x509.*
|
import org.bouncycastle.asn1.x509.*
|
||||||
@ -565,4 +567,16 @@ class X509UtilitiesTest {
|
|||||||
cert.checkValidity({ "Error text" }, { }, Date.from(today.toInstant() + 51.days))
|
cert.checkValidity({ "Error text" }, { }, Date.from(today.toInstant() + 51.days))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(timeout = 300_000)
|
||||||
|
fun `check certificate serial number`() {
|
||||||
|
val keyPair = generateKeyPair()
|
||||||
|
val subject = X500Principal("CN=Test,O=R3 Ltd,L=London,C=GB")
|
||||||
|
val cert = X509Utilities.createSelfSignedCACertificate(subject, keyPair)
|
||||||
|
assertTrue(cert.serialNumber.signum() > 0)
|
||||||
|
assertEquals(127, cert.serialNumber.bitLength())
|
||||||
|
val serialized = X509Utilities.buildCertPath(cert).encoded
|
||||||
|
val deserialized = X509CertificateFactory().delegate.generateCertPath(serialized.inputStream()).x509Certificates.first()
|
||||||
|
assertEquals(cert.serialNumber, deserialized.serialNumber)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ package net.corda.nodeapi.internal.crypto
|
|||||||
|
|
||||||
import net.corda.core.CordaOID
|
import net.corda.core.CordaOID
|
||||||
import net.corda.core.crypto.Crypto
|
import net.corda.core.crypto.Crypto
|
||||||
import net.corda.core.crypto.random63BitValue
|
import net.corda.core.crypto.newSecureRandom
|
||||||
import net.corda.core.internal.*
|
import net.corda.core.internal.*
|
||||||
import net.corda.core.utilities.days
|
import net.corda.core.utilities.days
|
||||||
import net.corda.core.utilities.millis
|
import net.corda.core.utilities.millis
|
||||||
@ -35,6 +35,8 @@ import java.time.Instant
|
|||||||
import java.time.temporal.ChronoUnit
|
import java.time.temporal.ChronoUnit
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import javax.security.auth.x500.X500Principal
|
import javax.security.auth.x500.X500Principal
|
||||||
|
import kotlin.experimental.and
|
||||||
|
import kotlin.experimental.or
|
||||||
|
|
||||||
object X509Utilities {
|
object X509Utilities {
|
||||||
// Note that this default value only applies to BCCryptoService. Other implementations of CryptoService may have to use different
|
// Note that this default value only applies to BCCryptoService. Other implementations of CryptoService may have to use different
|
||||||
@ -58,6 +60,7 @@ object X509Utilities {
|
|||||||
const val TLS_CERTIFICATE_DAYS_TO_EXPIRY_WARNING_THRESHOLD = 30
|
const val TLS_CERTIFICATE_DAYS_TO_EXPIRY_WARNING_THRESHOLD = 30
|
||||||
private const val KEY_ALIAS_REGEX = "[a-z0-9-]+"
|
private const val KEY_ALIAS_REGEX = "[a-z0-9-]+"
|
||||||
private const val KEY_ALIAS_MAX_LENGTH = 100
|
private const val KEY_ALIAS_MAX_LENGTH = 100
|
||||||
|
private const val CERTIFICATE_SERIAL_NUMBER_LENGTH = 16
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the provided key alias does not exceed maximum length and
|
* Checks if the provided key alias does not exceed maximum length and
|
||||||
@ -184,7 +187,7 @@ object X509Utilities {
|
|||||||
nameConstraints: NameConstraints? = null,
|
nameConstraints: NameConstraints? = null,
|
||||||
crlDistPoint: String? = null,
|
crlDistPoint: String? = null,
|
||||||
crlIssuer: X500Name? = null): X509v3CertificateBuilder {
|
crlIssuer: X500Name? = null): X509v3CertificateBuilder {
|
||||||
val serial = BigInteger.valueOf(random63BitValue())
|
val serial = generateCertificateSerialNumber()
|
||||||
val keyPurposes = DERSequence(ASN1EncodableVector().apply { certificateType.purposes.forEach { add(it) } })
|
val keyPurposes = DERSequence(ASN1EncodableVector().apply { certificateType.purposes.forEach { add(it) } })
|
||||||
val subjectPublicKeyInfo = SubjectPublicKeyInfo.getInstance(ASN1Sequence.getInstance(subjectPublicKey.encoded))
|
val subjectPublicKeyInfo = SubjectPublicKeyInfo.getInstance(ASN1Sequence.getInstance(subjectPublicKey.encoded))
|
||||||
val role = certificateType.role
|
val role = certificateType.role
|
||||||
@ -364,6 +367,15 @@ object X509Utilities {
|
|||||||
builder.addExtension(Extension.cRLDistributionPoints, false, CRLDistPoint(arrayOf(distPoint)))
|
builder.addExtension(Extension.cRLDistributionPoints, false, CRLDistPoint(arrayOf(distPoint)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("MagicNumber")
|
||||||
|
private fun generateCertificateSerialNumber(): BigInteger {
|
||||||
|
val bytes = ByteArray(CERTIFICATE_SERIAL_NUMBER_LENGTH)
|
||||||
|
newSecureRandom().nextBytes(bytes)
|
||||||
|
// Set highest byte to 01xxxxxx to ensure positive sign and constant bit length.
|
||||||
|
bytes[0] = bytes[0].and(0x3F).or(0x40)
|
||||||
|
return BigInteger(bytes)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assuming cert type to role is 1:1
|
// Assuming cert type to role is 1:1
|
||||||
|
Loading…
Reference in New Issue
Block a user