diff options
author | Bjørn Christian Seime <bjorncs@oath.com> | 2018-03-19 14:55:17 +0100 |
---|---|---|
committer | Bjørn Christian Seime <bjorncs@oath.com> | 2018-03-19 16:03:30 +0100 |
commit | e4047a959051838b358909290b1540ca5f533ea1 (patch) | |
tree | 837eb592ec8f6abaea77ad3f70dde074ea5546c9 /vespa-athenz | |
parent | 518d8a9a8bac25f96228dac74a2d74e65cc7e460 (diff) |
Add builders and helpers for x509 certificate and csr
Diffstat (limited to 'vespa-athenz')
13 files changed, 575 insertions, 0 deletions
diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/tls/BouncyCastleProviderHolder.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/tls/BouncyCastleProviderHolder.java new file mode 100644 index 00000000000..03049961dc0 --- /dev/null +++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/tls/BouncyCastleProviderHolder.java @@ -0,0 +1,14 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.athenz.tls; + +import org.bouncycastle.jce.provider.BouncyCastleProvider; + +/** + * @author bjorncs + */ +class BouncyCastleProviderHolder { + + private static final BouncyCastleProvider bcProvider = new BouncyCastleProvider(); + + static BouncyCastleProvider getInstance() { return bcProvider; } +} diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/tls/KeyAlgorithm.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/tls/KeyAlgorithm.java new file mode 100644 index 00000000000..4c4198adaac --- /dev/null +++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/tls/KeyAlgorithm.java @@ -0,0 +1,19 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.athenz.tls; + +/** + * @author bjorncs + */ +public enum KeyAlgorithm { + RSA("RSA"); + + private final String algorithmName; + + KeyAlgorithm(String algorithmName) { + this.algorithmName = algorithmName; + } + + String getAlgorithmName() { + return algorithmName; + } +} diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/tls/KeyUtils.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/tls/KeyUtils.java new file mode 100644 index 00000000000..9182544675c --- /dev/null +++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/tls/KeyUtils.java @@ -0,0 +1,23 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.athenz.tls; + +import java.security.GeneralSecurityException; +import java.security.KeyPair; +import java.security.KeyPairGenerator; + +/** + * @author bjorncs + */ +public class KeyUtils { + private KeyUtils() {} + + public static KeyPair generateKeypair(KeyAlgorithm algorithm, int keySize) { + try { + KeyPairGenerator keyGen = KeyPairGenerator.getInstance(algorithm.getAlgorithmName()); + keyGen.initialize(keySize); + return keyGen.genKeyPair(); + } catch (GeneralSecurityException e) { + throw new RuntimeException(e); + } + } +} diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/tls/Pkcs10Csr.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/tls/Pkcs10Csr.java new file mode 100644 index 00000000000..7a43b5a1fd5 --- /dev/null +++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/tls/Pkcs10Csr.java @@ -0,0 +1,30 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.athenz.tls; + +import org.bouncycastle.openssl.PEMParser; +import org.bouncycastle.pkcs.PKCS10CertificationRequest; + +import javax.security.auth.x500.X500Principal; +import java.io.IOException; +import java.io.StringReader; +import java.io.UncheckedIOException; + +/** + * @author bjorncs + */ +public class Pkcs10Csr { + + private final PKCS10CertificationRequest csr; + + Pkcs10Csr(PKCS10CertificationRequest csr) { + this.csr = csr; + } + + PKCS10CertificationRequest getBcCsr() { + return csr; + } + + public X500Principal getSubject() { + return new X500Principal(csr.getSubject().toString()); + } +} diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/tls/Pkcs10CsrBuilder.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/tls/Pkcs10CsrBuilder.java new file mode 100644 index 00000000000..877f05f998a --- /dev/null +++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/tls/Pkcs10CsrBuilder.java @@ -0,0 +1,77 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.athenz.tls; + +import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; +import org.bouncycastle.asn1.x509.Extension; +import org.bouncycastle.asn1.x509.ExtensionsGenerator; +import org.bouncycastle.asn1.x509.GeneralName; +import org.bouncycastle.asn1.x509.GeneralNames; +import org.bouncycastle.operator.ContentSigner; +import org.bouncycastle.operator.OperatorCreationException; +import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; +import org.bouncycastle.pkcs.PKCS10CertificationRequestBuilder; +import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequestBuilder; + +import javax.security.auth.x500.X500Principal; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.security.KeyPair; +import java.util.ArrayList; +import java.util.List; + +/** + * @author bjorncs + */ +public class Pkcs10CsrBuilder { + + private final X500Principal subject; + private final KeyPair keyPair; + private final List<String> subjectAlternativeNames = new ArrayList<>(); + private final SignatureAlgorithm signatureAlgorithm; + + private Pkcs10CsrBuilder(X500Principal subject, + KeyPair keyPair, + SignatureAlgorithm signatureAlgorithm) { + this.subject = subject; + this.keyPair = keyPair; + this.signatureAlgorithm = signatureAlgorithm; + } + + public static Pkcs10CsrBuilder fromKeypair(X500Principal subject, + KeyPair keyPair, + SignatureAlgorithm signatureAlgorithm) { + return new Pkcs10CsrBuilder(subject, keyPair, signatureAlgorithm); + } + + public Pkcs10CsrBuilder addSubjectAlternativeName(String san) { + this.subjectAlternativeNames.add(san); + return this; + } + + public Pkcs10Csr build() { + try { + PKCS10CertificationRequestBuilder requestBuilder = + new JcaPKCS10CertificationRequestBuilder(subject, keyPair.getPublic()); + + if (!subjectAlternativeNames.isEmpty()) { + GeneralNames generalNames = new GeneralNames( + subjectAlternativeNames.stream() + .map(san -> new GeneralName(GeneralName.dNSName, san)) + .toArray(GeneralName[]::new)); + ExtensionsGenerator extGen = new ExtensionsGenerator(); + extGen.addExtension(Extension.subjectAlternativeName, false, generalNames); + requestBuilder.addAttribute(PKCSObjectIdentifiers.pkcs_9_at_extensionRequest, extGen.generate()); + } + ContentSigner contentSigner = new JcaContentSignerBuilder(signatureAlgorithm.getAlgorithmName()) + .setProvider(BouncyCastleProviderHolder.getInstance()) + .build(keyPair.getPrivate()); + return new Pkcs10Csr(requestBuilder.build(contentSigner)); + } catch (OperatorCreationException e) { + throw new RuntimeException(e); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + + } + +} diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/tls/Pkcs10CsrUtils.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/tls/Pkcs10CsrUtils.java new file mode 100644 index 00000000000..2289c9ac0ee --- /dev/null +++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/tls/Pkcs10CsrUtils.java @@ -0,0 +1,38 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.athenz.tls; + +import org.bouncycastle.openssl.PEMParser; +import org.bouncycastle.openssl.jcajce.JcaPEMWriter; +import org.bouncycastle.pkcs.PKCS10CertificationRequest; +import org.bouncycastle.util.io.pem.PemObject; + +import java.io.IOException; +import java.io.StringReader; +import java.io.StringWriter; +import java.io.UncheckedIOException; + +/** + * @author bjorncs + */ +public class Pkcs10CsrUtils { + + private Pkcs10CsrUtils() {} + + public static Pkcs10Csr fromPem(String pem) { + try (PEMParser pemParser = new PEMParser(new StringReader(pem))) { + return new Pkcs10Csr((PKCS10CertificationRequest) pemParser.readObject()); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + public static String toPem(Pkcs10Csr csr) { + try (StringWriter stringWriter = new StringWriter(); JcaPEMWriter pemWriter = new JcaPEMWriter(stringWriter)) { + pemWriter.writeObject(new PemObject("CERTIFICATE REQUEST", csr.getBcCsr().getEncoded())); + pemWriter.flush(); + return stringWriter.toString(); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } +} diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/tls/SignatureAlgorithm.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/tls/SignatureAlgorithm.java new file mode 100644 index 00000000000..3d85a12f714 --- /dev/null +++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/tls/SignatureAlgorithm.java @@ -0,0 +1,19 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.athenz.tls; + +/** + * @author bjorncs + */ +public enum SignatureAlgorithm { + SHA256_WITH_RSA("SHA256withRSA"); + + private final String algorithmName; + + SignatureAlgorithm(String algorithmName) { + this.algorithmName = algorithmName; + } + + public String getAlgorithmName() { + return algorithmName; + } +} diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/tls/X509CertificateBuilder.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/tls/X509CertificateBuilder.java new file mode 100644 index 00000000000..e60592db2f5 --- /dev/null +++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/tls/X509CertificateBuilder.java @@ -0,0 +1,154 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.athenz.tls; + +import org.bouncycastle.asn1.x509.BasicConstraints; +import org.bouncycastle.asn1.x509.Extension; +import org.bouncycastle.asn1.x509.GeneralName; +import org.bouncycastle.asn1.x509.GeneralNames; +import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; +import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.operator.ContentSigner; +import org.bouncycastle.operator.OperatorException; +import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; +import org.bouncycastle.pkcs.PKCS10CertificationRequest; +import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequest; + +import javax.security.auth.x500.X500Principal; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.math.BigInteger; +import java.security.GeneralSecurityException; +import java.security.KeyPair; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.cert.X509Certificate; +import java.sql.Date; +import java.time.Instant; +import java.util.ArrayList; +import java.util.List; + +/** + * @author bjorncs + */ +public class X509CertificateBuilder { + + private final long serialNumber; + private final SignatureAlgorithm signingAlgorithm; + private final PrivateKey caPrivateKey; + private final Instant notBefore; + private final Instant notAfter; + private final List<String> subjectAlternativeNames = new ArrayList<>(); + private final X500Principal issuer; + private final X500Principal subject; + private final PublicKey certPublicKey; + private BasicConstraintsExtension basicConstraintsExtension; + + private X509CertificateBuilder(X500Principal issuer, + X500Principal subject, + Instant notBefore, + Instant notAfter, + PublicKey certPublicKey, + PrivateKey caPrivateKey, + SignatureAlgorithm signingAlgorithm, + long serialNumber) { + this.issuer = issuer; + this.subject = subject; + this.notBefore = notBefore; + this.notAfter = notAfter; + this.certPublicKey = certPublicKey; + this.caPrivateKey = caPrivateKey; + this.signingAlgorithm = signingAlgorithm; + this.serialNumber = serialNumber; + } + + public static X509CertificateBuilder fromCsr(Pkcs10Csr csr, + X500Principal caIssuer, + Instant notBefore, + Instant notAfter, + PrivateKey caPrivateKey, + SignatureAlgorithm signingAlgorithm, + long serialNumber) { + try { + PKCS10CertificationRequest bcCsr = csr.getBcCsr(); + PublicKey publicKey = new JcaPKCS10CertificationRequest(bcCsr).getPublicKey(); + return new X509CertificateBuilder(caIssuer, + new X500Principal(bcCsr.getSubject().getEncoded()), + notBefore, + notAfter, + publicKey, + caPrivateKey, + signingAlgorithm, + serialNumber); + } catch (GeneralSecurityException e) { + throw new RuntimeException(e); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + public static X509CertificateBuilder fromKeypair(KeyPair keyPair, + X500Principal subject, + Instant notBefore, + Instant notAfter, + SignatureAlgorithm signingAlgorithm, + long serialNumber) { + return new X509CertificateBuilder(subject, + subject, + notBefore, + notAfter, + keyPair.getPublic(), + keyPair.getPrivate(), + signingAlgorithm, + serialNumber); + } + + public X509CertificateBuilder addSubjectAlternativeName(String san) { + this.subjectAlternativeNames.add(san); + return this; + } + + public X509CertificateBuilder setBasicConstraints(boolean isCritical, boolean isCertAuthorityCertificate) { + this.basicConstraintsExtension = new BasicConstraintsExtension(isCritical, isCertAuthorityCertificate); + return this; + } + + public X509Certificate build() { + try { + JcaX509v3CertificateBuilder jcaCertBuilder = new JcaX509v3CertificateBuilder( + issuer, BigInteger.valueOf(serialNumber), Date.from(notBefore), Date.from(notAfter), subject, certPublicKey); + if (basicConstraintsExtension != null) { + jcaCertBuilder.addExtension( + Extension.basicConstraints, + basicConstraintsExtension.isCritical, + new BasicConstraints(basicConstraintsExtension.isCertAuthorityCertificate)); + } + if (!subjectAlternativeNames.isEmpty()) { + GeneralNames generalNames = new GeneralNames( + subjectAlternativeNames.stream() + .map(san -> new GeneralName(GeneralName.dNSName, san)) + .toArray(GeneralName[]::new)); + jcaCertBuilder.addExtension(Extension.subjectAlternativeName, false, generalNames); + } + ContentSigner contentSigner = new JcaContentSignerBuilder(signingAlgorithm.getAlgorithmName()) + .setProvider(BouncyCastleProviderHolder.getInstance()) + .build(caPrivateKey); + return new JcaX509CertificateConverter() + .setProvider(BouncyCastleProviderHolder.getInstance()) + .getCertificate(jcaCertBuilder.build(contentSigner)); + } catch (OperatorException | GeneralSecurityException e) { + throw new RuntimeException(e); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + private static class BasicConstraintsExtension { + final boolean isCritical, isCertAuthorityCertificate; + + BasicConstraintsExtension(boolean isCritical, boolean isCertAuthorityCertificate) { + this.isCritical = isCritical; + this.isCertAuthorityCertificate = isCertAuthorityCertificate; + } + } +} diff --git a/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/tls/X509CertificateUtils.java b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/tls/X509CertificateUtils.java new file mode 100644 index 00000000000..072c6d41fda --- /dev/null +++ b/vespa-athenz/src/main/java/com/yahoo/vespa/athenz/tls/X509CertificateUtils.java @@ -0,0 +1,55 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.athenz.tls; + +import org.bouncycastle.cert.X509CertificateHolder; +import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; +import org.bouncycastle.openssl.PEMParser; +import org.bouncycastle.openssl.jcajce.JcaPEMWriter; +import org.bouncycastle.util.io.pem.PemObject; + +import java.io.IOException; +import java.io.StringReader; +import java.io.StringWriter; +import java.io.UncheckedIOException; +import java.security.GeneralSecurityException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; + +/** + * @author bjorncs + */ +public class X509CertificateUtils { + + private X509CertificateUtils() {} + + public static X509Certificate fromPem(String pem) { + try (PEMParser parser = new PEMParser(new StringReader(pem))) { + Object pemObject = parser.readObject(); + if (pemObject instanceof X509Certificate) { + return (X509Certificate) pemObject; + } + if (pemObject instanceof X509CertificateHolder) { + return new JcaX509CertificateConverter() + .setProvider(BouncyCastleProviderHolder.getInstance()) + .getCertificate((X509CertificateHolder) pemObject); + } + throw new IllegalArgumentException("Invalid type of PEM object: " + pemObject); + } catch (IOException e) { + throw new UncheckedIOException(e); + } catch (CertificateException e) { + throw new RuntimeException(e); + } + } + + public static String toPem(X509Certificate certificate) { + try (StringWriter stringWriter = new StringWriter(); JcaPEMWriter pemWriter = new JcaPEMWriter(stringWriter)) { + pemWriter.writeObject(new PemObject("CERTIFICATE", certificate.getEncoded())); + pemWriter.flush(); + return stringWriter.toString(); + } catch (GeneralSecurityException e) { + throw new RuntimeException(e); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } +} diff --git a/vespa-athenz/src/test/java/com/yahoo/vespa/athenz/tls/Pkcs10CsrBuilderTest.java b/vespa-athenz/src/test/java/com/yahoo/vespa/athenz/tls/Pkcs10CsrBuilderTest.java new file mode 100644 index 00000000000..e3aaba66efe --- /dev/null +++ b/vespa-athenz/src/test/java/com/yahoo/vespa/athenz/tls/Pkcs10CsrBuilderTest.java @@ -0,0 +1,27 @@ +package com.yahoo.vespa.athenz.tls; + +import org.junit.Test; + +import javax.security.auth.x500.X500Principal; + +import java.security.KeyPair; + +import static org.junit.Assert.*; + +/** + * @author bjorncs + */ +public class Pkcs10CsrBuilderTest { + + @Test + public void can_build_csr_with_sans() { + X500Principal subject = new X500Principal("CN=subject"); + KeyPair keypair = KeyUtils.generateKeypair(KeyAlgorithm.RSA, 2048); + Pkcs10Csr csr = Pkcs10CsrBuilder.fromKeypair(subject, keypair, SignatureAlgorithm.SHA256_WITH_RSA) + .addSubjectAlternativeName("san1.com") + .addSubjectAlternativeName("san2.com") + .build(); + assertEquals(subject, csr.getSubject()); + } + +}
\ No newline at end of file diff --git a/vespa-athenz/src/test/java/com/yahoo/vespa/athenz/tls/Pkcs10CsrUtilsTest.java b/vespa-athenz/src/test/java/com/yahoo/vespa/athenz/tls/Pkcs10CsrUtilsTest.java new file mode 100644 index 00000000000..1927e18eba0 --- /dev/null +++ b/vespa-athenz/src/test/java/com/yahoo/vespa/athenz/tls/Pkcs10CsrUtilsTest.java @@ -0,0 +1,24 @@ +package com.yahoo.vespa.athenz.tls; + +import org.junit.Test; + +import javax.security.auth.x500.X500Principal; +import java.security.KeyPair; + +import static org.junit.Assert.*; + +/** + * @author bjorncs + */ +public class Pkcs10CsrUtilsTest { + + @Test + public void can_deserialize_serialized_pem_csr() { + X500Principal subject = new X500Principal("CN=subject"); + KeyPair keypair = KeyUtils.generateKeypair(KeyAlgorithm.RSA, 2048); + Pkcs10Csr csr = Pkcs10CsrBuilder.fromKeypair(subject, keypair, SignatureAlgorithm.SHA256_WITH_RSA).build(); + Pkcs10Csr deserializedCsr = Pkcs10CsrUtils.fromPem(Pkcs10CsrUtils.toPem(csr)); + assertEquals(subject, deserializedCsr.getSubject()); + } + +}
\ No newline at end of file diff --git a/vespa-athenz/src/test/java/com/yahoo/vespa/athenz/tls/X509CertificateBuilderTest.java b/vespa-athenz/src/test/java/com/yahoo/vespa/athenz/tls/X509CertificateBuilderTest.java new file mode 100644 index 00000000000..4a6340ab0d5 --- /dev/null +++ b/vespa-athenz/src/test/java/com/yahoo/vespa/athenz/tls/X509CertificateBuilderTest.java @@ -0,0 +1,59 @@ +package com.yahoo.vespa.athenz.tls; + +import org.junit.Test; + +import javax.security.auth.x500.X500Principal; +import java.security.KeyPair; +import java.security.NoSuchAlgorithmException; +import java.security.cert.X509Certificate; +import java.time.Instant; +import java.time.temporal.ChronoUnit; + +import static com.yahoo.vespa.athenz.tls.TestUtils.createKeyPair; +import static org.junit.Assert.assertEquals; + +/** + * @author bjorncs + */ +public class X509CertificateBuilderTest { + + @Test + public void can_build_self_signed_certificate() throws NoSuchAlgorithmException { + KeyPair keyPair = createKeyPair(); + X500Principal subject = new X500Principal("CN=myservice"); + X509Certificate cert = + X509CertificateBuilder.fromKeypair( + keyPair, + subject, + Instant.now(), + Instant.now().plus(1, ChronoUnit.DAYS), + SignatureAlgorithm.SHA256_WITH_RSA, + 1) + .setBasicConstraints(true, true) + .build(); + assertEquals(subject, cert.getSubjectX500Principal()); + } + + @Test + public void can_build_certificate_from_csr() { + X500Principal subject = new X500Principal("CN=subject"); + X500Principal issuer = new X500Principal("CN=issuer"); + KeyPair csrKeypair = KeyUtils.generateKeypair(KeyAlgorithm.RSA, 2048); + Pkcs10Csr csr = Pkcs10CsrBuilder.fromKeypair(subject, csrKeypair, SignatureAlgorithm.SHA256_WITH_RSA).build(); + KeyPair caKeypair = KeyUtils.generateKeypair(KeyAlgorithm.RSA, 2048); + X509Certificate cert = X509CertificateBuilder + .fromCsr( + csr, + issuer, + Instant.now(), + Instant.now().plus(1, ChronoUnit.DAYS), + caKeypair.getPrivate(), + SignatureAlgorithm.SHA256_WITH_RSA, + 1) + .addSubjectAlternativeName("subject1.alt") + .addSubjectAlternativeName("subject2.alt") + .build(); + assertEquals(subject, cert.getSubjectX500Principal()); + } + +}
\ No newline at end of file diff --git a/vespa-athenz/src/test/java/com/yahoo/vespa/athenz/tls/X509CertificateUtilsTest.java b/vespa-athenz/src/test/java/com/yahoo/vespa/athenz/tls/X509CertificateUtilsTest.java new file mode 100644 index 00000000000..3ba011b1efb --- /dev/null +++ b/vespa-athenz/src/test/java/com/yahoo/vespa/athenz/tls/X509CertificateUtilsTest.java @@ -0,0 +1,36 @@ +package com.yahoo.vespa.athenz.tls; + +import org.junit.Test; + +import javax.security.auth.x500.X500Principal; +import java.security.KeyPair; +import java.security.cert.X509Certificate; +import java.time.Instant; +import java.time.temporal.ChronoUnit; + +import static org.junit.Assert.assertEquals; + +/** + * @author bjorncs + */ +public class X509CertificateUtilsTest { + @Test + public void can_deserialize_serialized_pem_certificate() { + KeyPair keypair = KeyUtils.generateKeypair(KeyAlgorithm.RSA, 2048); + X500Principal subject = new X500Principal("CN=myservice"); + X509Certificate cert = X509CertificateBuilder + .fromKeypair( + keypair, + subject, + Instant.now(), + Instant.now().plus(1, ChronoUnit.DAYS), + SignatureAlgorithm.SHA256_WITH_RSA, + 1) + .build(); + assertEquals(subject, cert.getSubjectX500Principal()); + X509Certificate deserializedCert = X509CertificateUtils.fromPem(X509CertificateUtils.toPem(cert)); + assertEquals(subject, deserializedCert.getSubjectX500Principal()); + } + + +}
\ No newline at end of file |