mirror of
https://github.com/corda/corda.git
synced 2024-12-21 05:53:23 +00:00
Add support for X509Certificate and CertPath serialization
This commit is contained in:
parent
b8755ccdb2
commit
36a091dd6a
@ -188,15 +188,15 @@ object X509Utilities {
|
||||
* @param revocationEnabled whether revocation of certificates in the path should be checked.
|
||||
*/
|
||||
fun createCertificatePath(rootCertAndKey: CertificateAndKeyPair,
|
||||
targetCertAndKey: CertificateAndKeyPair,
|
||||
targetCertAndKey: X509Certificate,
|
||||
revocationEnabled: Boolean): CertPathBuilderResult {
|
||||
val intermediateCertificates = setOf(targetCertAndKey.certificate)
|
||||
val intermediateCertificates = setOf(targetCertAndKey)
|
||||
val certStore = CertStore.getInstance("Collection", CollectionCertStoreParameters(intermediateCertificates))
|
||||
val certPathFactory = CertPathBuilder.getInstance("PKIX")
|
||||
val trustAnchor = TrustAnchor(rootCertAndKey.certificate, null)
|
||||
val certPathParameters = try {
|
||||
PKIXBuilderParameters(setOf(trustAnchor), X509CertSelector().apply {
|
||||
certificate = targetCertAndKey.certificate
|
||||
certificate = targetCertAndKey
|
||||
})
|
||||
} catch (ex: InvalidAlgorithmParameterException) {
|
||||
throw RuntimeException(ex)
|
||||
|
@ -26,9 +26,12 @@ import org.bouncycastle.pqc.jcajce.provider.sphincs.BCSphincs256PrivateKey
|
||||
import org.bouncycastle.pqc.jcajce.provider.sphincs.BCSphincs256PublicKey
|
||||
import org.objenesis.strategy.StdInstantiatorStrategy
|
||||
import org.slf4j.Logger
|
||||
import sun.security.provider.certpath.X509CertPath
|
||||
import java.io.BufferedInputStream
|
||||
import java.io.FileInputStream
|
||||
import java.io.InputStream
|
||||
import java.security.cert.CertPath
|
||||
import java.security.cert.X509Certificate
|
||||
import java.util.*
|
||||
|
||||
object DefaultKryoCustomizer {
|
||||
@ -97,6 +100,12 @@ object DefaultKryoCustomizer {
|
||||
// Note that return type should be specifically set to InputStream, otherwise it may not work, i.e. val aStream : InputStream = HashCheckingStream(...).
|
||||
addDefaultSerializer(InputStream::class.java, InputStreamSerializer)
|
||||
|
||||
register(CertPath::class.java, CertPathSerializer)
|
||||
register(X509CertPath::class.java, CertPathSerializer)
|
||||
// TODO: We shouldn't need to serialize raw certificates, and if we do then we need a cleaner solution
|
||||
// than this mess.
|
||||
val x509CertObjectClazz = Class.forName("org.bouncycastle.jcajce.provider.asymmetric.x509.X509CertificateObject")
|
||||
register(x509CertObjectClazz, X509CertificateSerializer)
|
||||
register(X500Name::class.java, X500NameSerializer)
|
||||
|
||||
register(BCECPrivateKey::class.java, PrivateKeySerializer)
|
||||
|
@ -30,6 +30,9 @@ import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
import java.security.PrivateKey
|
||||
import java.security.PublicKey
|
||||
import java.security.cert.CertPath
|
||||
import java.security.cert.CertificateFactory
|
||||
import java.security.cert.X509Certificate
|
||||
import java.security.spec.InvalidKeySpecException
|
||||
import java.time.Instant
|
||||
import java.util.*
|
||||
@ -613,6 +616,36 @@ object X500NameSerializer : Serializer<X500Name>() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* For serialising an [CertPath] in an X.500 standard format.
|
||||
*/
|
||||
@ThreadSafe
|
||||
object CertPathSerializer : Serializer<CertPath>() {
|
||||
val factory = CertificateFactory.getInstance("X.509")
|
||||
override fun read(kryo: Kryo, input: Input, type: Class<CertPath>): CertPath {
|
||||
return factory.generateCertPath(input)
|
||||
}
|
||||
|
||||
override fun write(kryo: Kryo, output: Output, obj: CertPath) {
|
||||
output.writeBytes(obj.encoded)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* For serialising an [CX509Certificate] in an X.500 standard format.
|
||||
*/
|
||||
@ThreadSafe
|
||||
object X509CertificateSerializer : Serializer<X509Certificate>() {
|
||||
val factory = CertificateFactory.getInstance("X.509")
|
||||
override fun read(kryo: Kryo, input: Input, type: Class<X509Certificate>): X509Certificate {
|
||||
return factory.generateCertificate(input) as X509Certificate
|
||||
}
|
||||
|
||||
override fun write(kryo: Kryo, output: Output, obj: X509Certificate) {
|
||||
output.writeBytes(obj.encoded)
|
||||
}
|
||||
}
|
||||
|
||||
class KryoPoolWithContext(val baseKryoPool: KryoPool, val contextKey: Any, val context: Any) : KryoPool {
|
||||
override fun <T : Any?> run(callback: KryoCallback<T>): T {
|
||||
val kryo = borrow()
|
||||
|
@ -3,8 +3,11 @@ package net.corda.core.serialization
|
||||
import com.esotericsoftware.kryo.Kryo
|
||||
import com.google.common.primitives.Ints
|
||||
import net.corda.core.crypto.*
|
||||
import net.corda.core.utilities.ALICE
|
||||
import net.corda.core.utilities.BOB
|
||||
import net.corda.node.services.messaging.Ack
|
||||
import net.corda.node.services.persistence.NodeAttachmentService
|
||||
import net.corda.testing.BOB_PUBKEY
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.assertj.core.api.Assertions.assertThatThrownBy
|
||||
import org.junit.Before
|
||||
@ -12,6 +15,8 @@ import org.junit.Test
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.io.ByteArrayInputStream
|
||||
import java.io.InputStream
|
||||
import java.security.cert.CertPath
|
||||
import java.security.cert.X509Certificate
|
||||
import java.time.Instant
|
||||
import java.util.*
|
||||
import kotlin.test.assertEquals
|
||||
@ -136,6 +141,24 @@ class KryoTests {
|
||||
assertEquals(-1, readRubbishStream.read())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `serialize - deserialize X509Certififcate`() {
|
||||
val expected = X509Utilities.createSelfSignedCACert(ALICE.name).certificate
|
||||
val serialized = expected.serialize(kryo).bytes
|
||||
val actual: X509Certificate = serialized.deserialize(kryo)
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `serialize - deserialize X509CertPath`() {
|
||||
val rootCA = X509Utilities.createSelfSignedCACert(ALICE.name)
|
||||
val certificate = X509Utilities.createTlsServerCert(BOB.name, BOB_PUBKEY, rootCA, emptyList(), emptyList())
|
||||
val expected = X509Utilities.createCertificatePath(rootCA, certificate, false).certPath
|
||||
val serialized = expected.serialize(kryo).bytes
|
||||
val actual: CertPath = serialized.deserialize(kryo)
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
|
||||
@CordaSerializable
|
||||
private data class Person(val name: String, val birthday: Instant?)
|
||||
|
||||
|
@ -87,10 +87,10 @@ class InMemoryIdentityServiceTests {
|
||||
fun `assert ownership`() {
|
||||
val aliceRootCertAndKey = X509Utilities.createSelfSignedCACert(ALICE.name)
|
||||
val aliceTxCertAndKey = X509Utilities.createIntermediateCert(ALICE.name, aliceRootCertAndKey)
|
||||
val aliceCertPath = X509Utilities.createCertificatePath(aliceRootCertAndKey, aliceTxCertAndKey, false).certPath
|
||||
val aliceCertPath = X509Utilities.createCertificatePath(aliceRootCertAndKey, aliceTxCertAndKey.certificate, false).certPath
|
||||
val bobRootCertAndKey = X509Utilities.createSelfSignedCACert(BOB.name)
|
||||
val bobTxCertAndKey = X509Utilities.createIntermediateCert(BOB.name, bobRootCertAndKey)
|
||||
val bobCertPath = X509Utilities.createCertificatePath(bobRootCertAndKey, bobTxCertAndKey, false).certPath
|
||||
val bobCertPath = X509Utilities.createCertificatePath(bobRootCertAndKey, bobTxCertAndKey.certificate, false).certPath
|
||||
val service = InMemoryIdentityService()
|
||||
val alice = Party(aliceRootCertAndKey)
|
||||
val anonymousAlice = AnonymousParty(aliceTxCertAndKey.keyPair.public)
|
||||
|
Loading…
Reference in New Issue
Block a user