1+ package eu.europa.ec.eudi.wallet.trust
2+
3+ import org.bouncycastle.asn1.x500.X500Name
4+ import org.bouncycastle.asn1.x509.BasicConstraints
5+ import org.bouncycastle.asn1.x509.Extension
6+ import org.bouncycastle.asn1.x509.KeyUsage
7+ import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter
8+ import org.bouncycastle.cert.jcajce.JcaX509ExtensionUtils
9+ import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder
10+ import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder
11+ import java.math.BigInteger
12+ import java.security.KeyPair
13+ import java.security.KeyPairGenerator
14+ import java.security.SecureRandom
15+ import java.security.cert.X509Certificate
16+ import java.security.spec.ECGenParameterSpec
17+ import java.time.Instant
18+ import java.util.Date
19+
20+ private val extUtils = JcaX509ExtensionUtils ()
21+
22+ // A dedicated RSA KeyPair for the Trust Anchor
23+ private val rsaTrustedKeyPair: KeyPair by lazy {
24+ KeyPairGenerator .getInstance(" RSA" ).apply {
25+ initialize(2048 )
26+ }.generateKeyPair()
27+ }
28+
29+ // The RSA Root CA (Trust Anchor)
30+ val rsaTrustedRootCertificate: X509Certificate by lazy {
31+ val serialNumber = BigInteger (64 , SecureRandom ())
32+ val issuer = X500Name (" CN=RSA Root CA" )
33+ val subject = X500Name (" CN=RSA Root CA" )
34+ val notBefore = Date .from(Instant .now().minusSeconds(86400 ))
35+ val notAfter = Date (notBefore.time + 30 * 86400000L )
36+
37+ val builder = JcaX509v3CertificateBuilder (
38+ issuer,
39+ serialNumber,
40+ notBefore,
41+ notAfter,
42+ subject,
43+ rsaTrustedKeyPair.public
44+ ).apply {
45+ addExtension(Extension .basicConstraints, true , BasicConstraints (true ))
46+ addExtension(Extension .keyUsage, true , KeyUsage (KeyUsage .keyCertSign or KeyUsage .cRLSign))
47+ // Subject Key ID
48+ addExtension(Extension .subjectKeyIdentifier, false , extUtils.createSubjectKeyIdentifier(rsaTrustedKeyPair.public))
49+ // Authority Key ID (Self-signed)
50+ addExtension(Extension .authorityKeyIdentifier, false , extUtils.createAuthorityKeyIdentifier(rsaTrustedKeyPair.public))
51+ }
52+
53+ // SIGNATURE Signed with RSA
54+ val signer = JcaContentSignerBuilder (" SHA256WithRSAEncryption" ).build(rsaTrustedKeyPair.private)
55+ JcaX509CertificateConverter ().getCertificate(builder.build(signer))
56+ }
57+
58+ // 2. NEW: EC Intermediate KeyPair
59+ private val ecIntermediateKeyPair: KeyPair by lazy {
60+ KeyPairGenerator .getInstance(" EC" ).apply {
61+ initialize(ECGenParameterSpec (" secp256r1" ))
62+ }.generateKeyPair()
63+ }
64+
65+ // EC Intermediate Certificate
66+ val ecIntermediateCertificate: X509Certificate by lazy {
67+ val serialNumber = BigInteger (64 , SecureRandom ())
68+ val issuer = X500Name (rsaTrustedRootCertificate.subjectX500Principal.name) // Issuer = RSA Root
69+ val subject = X500Name (" CN=EC Intermediate CA" )
70+ val notBefore = Date .from(Instant .now().minusSeconds(86400 ))
71+ val notAfter = Date (notBefore.time + 30 * 86400000L )
72+
73+ val builder = JcaX509v3CertificateBuilder (
74+ issuer,
75+ serialNumber,
76+ notBefore,
77+ notAfter,
78+ subject,
79+ ecIntermediateKeyPair.public // Intermediate has an EC Key
80+ ).apply {
81+ // Critical: Basic Constraints CA = TRUE
82+ addExtension(Extension .basicConstraints, true , BasicConstraints (true ))
83+ addExtension(Extension .keyUsage, true , KeyUsage (KeyUsage .keyCertSign or KeyUsage .cRLSign))
84+
85+ addExtension(Extension .subjectKeyIdentifier, false , extUtils.createSubjectKeyIdentifier(ecIntermediateKeyPair.public))
86+ addExtension(Extension .authorityKeyIdentifier, false , extUtils.createAuthorityKeyIdentifier(rsaTrustedRootCertificate))
87+ }
88+
89+ // SIGNATURE: Signed by RSA Root
90+ val signer = JcaContentSignerBuilder (" SHA256WithRSAEncryption" ).build(rsaTrustedKeyPair.private)
91+ JcaX509CertificateConverter ().getCertificate(builder.build(signer))
92+ }
93+
94+ // The EC Leaf Certificate (Verifier), signed by the RSA Root
95+ val ecLeafSignedByIntermediateCertificate: X509Certificate by lazy {
96+ // The Verifier has an EC KeyPair
97+ val leafEcKeyPair = KeyPairGenerator .getInstance(" EC" ).apply {
98+ initialize(ECGenParameterSpec (" secp256r1" ))
99+ }.generateKeyPair()
100+
101+ val serialNumber = BigInteger (64 , SecureRandom ())
102+ val issuer = X500Name (ecIntermediateCertificate.subjectX500Principal.name) // Intermediate Certificate signs it
103+ val subject = X500Name (" CN=EC Leaf Signed By RSA" )
104+ val notBefore = Date .from(Instant .now().minusSeconds(86400 ))
105+ val notAfter = Date (notBefore.time + 30 * 86400000L )
106+
107+ val builder = JcaX509v3CertificateBuilder (
108+ issuer,
109+ serialNumber,
110+ notBefore,
111+ notAfter,
112+ subject,
113+ leafEcKeyPair.public // The Leaf has an EC Public Key
114+ ).apply {
115+ addExtension(Extension .basicConstraints, true , BasicConstraints (false ))
116+ addExtension(Extension .keyUsage, true , KeyUsage (KeyUsage .digitalSignature))
117+
118+ // Subject Key ID (calculated from Leaf's EC key)
119+ addExtension(Extension .subjectKeyIdentifier, false , extUtils.createSubjectKeyIdentifier(leafEcKeyPair.public))
120+
121+ // AUTHORITY KEY: Refers to the EC Intermediate
122+ addExtension(Extension .authorityKeyIdentifier, false , extUtils.createAuthorityKeyIdentifier(ecIntermediateCertificate))
123+ }
124+
125+ // SIGNATURE: Signed by the Intermediate's EC Key using ECDSA Algorithm
126+ val signer = JcaContentSignerBuilder (" SHA256WithECDSA" ).build(ecIntermediateKeyPair.private)
127+ JcaX509CertificateConverter ().getCertificate(builder.build(signer))
128+ }
0 commit comments