diff --git a/acme4j-example/src/main/java/org/shredzone/acme4j/ClientTest.java b/acme4j-example/src/main/java/org/shredzone/acme4j/ClientTest.java index 0995a945..ff1a78e4 100644 --- a/acme4j-example/src/main/java/org/shredzone/acme4j/ClientTest.java +++ b/acme4j-example/src/main/java/org/shredzone/acme4j/ClientTest.java @@ -21,6 +21,7 @@ import java.io.Writer; import java.net.URI; import java.security.KeyPair; import java.security.Security; +import java.security.cert.CertificateEncodingException; import java.security.cert.X509Certificate; import java.util.Arrays; import java.util.Collection; @@ -34,6 +35,7 @@ import org.shredzone.acme4j.challenge.Http01Challenge; import org.shredzone.acme4j.challenge.TlsSni02Challenge; import org.shredzone.acme4j.exception.AcmeConflictException; import org.shredzone.acme4j.exception.AcmeException; +import org.shredzone.acme4j.util.AcmeUtils; import org.shredzone.acme4j.util.CSRBuilder; import org.shredzone.acme4j.util.CertificateUtils; import org.shredzone.acme4j.util.KeyPairUtils; @@ -389,8 +391,8 @@ public class ClientTest { // Create a validation certificate try (FileWriter fw = new FileWriter("tlssni.crt")) { X509Certificate cert = CertificateUtils.createTlsSni02Certificate(domainKeyPair, subject, sanB); - CertificateUtils.writeX509Certificate(cert, fw); - } catch (IOException ex) { + AcmeUtils.writeToPem(cert.getEncoded(), "CERTIFICATE", fw); + } catch (IOException | CertificateEncodingException ex) { throw new AcmeException("Could not write certificate", ex); } diff --git a/acme4j-utils/src/main/java/org/shredzone/acme4j/util/CertificateUtils.java b/acme4j-utils/src/main/java/org/shredzone/acme4j/util/CertificateUtils.java index a5c3c9eb..b1d3e716 100644 --- a/acme4j-utils/src/main/java/org/shredzone/acme4j/util/CertificateUtils.java +++ b/acme4j-utils/src/main/java/org/shredzone/acme4j/util/CertificateUtils.java @@ -17,9 +17,6 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.Writer; import java.math.BigInteger; import java.security.KeyPair; import java.security.cert.CertificateException; @@ -35,7 +32,6 @@ import org.bouncycastle.asn1.x509.GeneralName; import org.bouncycastle.asn1.x509.GeneralNames; import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder; import org.bouncycastle.openssl.PEMParser; -import org.bouncycastle.openssl.jcajce.JcaPEMWriter; import org.bouncycastle.operator.OperatorCreationException; import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; import org.bouncycastle.pkcs.PKCS10CertificationRequest; @@ -52,103 +48,6 @@ public final class CertificateUtils { // utility class without constructor } - /** - * Reads an {@link X509Certificate} PEM file from an {@link InputStream}. - * - * @param in - * {@link InputStream} to read the certificate from. The - * {@link InputStream} is closed after use. - * @return {@link X509Certificate} that was read - */ - public static X509Certificate readX509Certificate(InputStream in) throws IOException { - try (InputStream uin = in) { - CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509"); - return (X509Certificate) certificateFactory.generateCertificate(uin); - } catch (CertificateException ex) { - throw new IOException(ex); - } - } - - /** - * Writes an X.509 certificate PEM file. - * - * @param cert - * {@link X509Certificate} to write - * @param out - * {@link OutputStream} to write the PEM file to. The {@link OutputStream} - * is closed after use. - */ - public static void writeX509Certificate(X509Certificate cert, OutputStream out) throws IOException { - writeX509Certificate(cert, new OutputStreamWriter(out, "utf-8")); - } - - /** - * Writes an X.509 certificate PEM file. - * - * @param cert - * {@link X509Certificate} to write - * @param w - * {@link Writer} to write the PEM file to. The {@link Writer} is closed - * after use. - */ - public static void writeX509Certificate(X509Certificate cert, Writer w) throws IOException { - try (JcaPEMWriter jw = new JcaPEMWriter(w)) { - writeCertIfNotNull(jw, cert); - } - } - - /** - * Writes a X.509 certificate chain to a PEM file. - * - * @param w - * {@link Writer} to write the certificate chain to. The {@link Writer} is - * closed after use. - * @param cert - * {@link X509Certificate} to write, {@code null} to skip this certificate - * @param chain - * {@link X509Certificate} chain to add to the certificate. {@code null} - * values are ignored, array may be empty. - */ - public static void writeX509CertificateChain(Writer w, X509Certificate cert, X509Certificate... chain) - throws IOException { - try (JcaPEMWriter jw = new JcaPEMWriter(w)) { - writeCertIfNotNull(jw, cert); - for (X509Certificate c : chain) { - writeCertIfNotNull(jw, c); - } - } - } - - /** - * Writes an {@link X509Certificate} unless it is {@code null}. - * - * @param jw - * {@link JcaPEMWriter} to write to - * @param cert - * {@link X509Certificate} to write, or {@code null} - */ - private static void writeCertIfNotNull(JcaPEMWriter jw, X509Certificate cert) throws IOException { - if (cert != null) { - jw.writeObject(cert); - } - } - - /** - * Writes an X.509 certificate chain PEM file. - * - * @param chain - * {@link X509Certificate[]} to write - * @param w - * {@link Writer} to write the PEM file to. The {@link Writer} is closed - * after use. - * @deprecated Use - * {@link #writeX509CertificateChain(Writer, X509Certificate, X509Certificate...)} - */ - @Deprecated - public static void writeX509CertificateChain(X509Certificate[] chain, Writer w) throws IOException { - writeX509CertificateChain(w, null, chain); - } - /** * Reads a CSR PEM file. * diff --git a/acme4j-utils/src/test/java/org/shredzone/acme4j/util/CertificateUtilsTest.java b/acme4j-utils/src/test/java/org/shredzone/acme4j/util/CertificateUtilsTest.java index fecdeb21..5aee3cf0 100644 --- a/acme4j-utils/src/test/java/org/shredzone/acme4j/util/CertificateUtilsTest.java +++ b/acme4j-utils/src/test/java/org/shredzone/acme4j/util/CertificateUtilsTest.java @@ -20,12 +20,9 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; -import java.io.StringWriter; import java.lang.reflect.Constructor; import java.lang.reflect.Modifier; import java.security.KeyPair; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; import java.security.cert.CertificateParsingException; import java.security.cert.X509Certificate; import java.time.Duration; @@ -37,90 +34,13 @@ import java.util.Set; import org.bouncycastle.asn1.x509.GeneralName; import org.bouncycastle.pkcs.PKCS10CertificationRequest; -import org.junit.Before; import org.junit.Test; -import com.jcabi.matchers.RegexMatchers; - /** * Unit tests for {@link CertificateUtils}. */ public class CertificateUtilsTest { - private CertificateFactory certificateFactory; - - @Before - public void setup() throws CertificateException { - certificateFactory = CertificateFactory.getInstance("X.509"); - } - - /** - * Test if {@link CertificateUtils#readX509Certificate(InputStream)} reads and - * {@link CertificateUtils#writeX509Certificate(X509Certificate, java.io.Writer)} - * writes a proper X.509 certificate. - */ - @Test - public void testReadWriteX509Certificate() throws IOException, CertificateException { - // Read a demonstration certificate - X509Certificate original = createCertificate(); - - // Write to Byte Array - byte[] pem; - try (ByteArrayOutputStream out = new ByteArrayOutputStream()) { - CertificateUtils.writeX509Certificate(original, out); - pem = out.toByteArray(); - } - - // Make sure it is a good PEM file - assertThat(new String(pem, "utf-8"), RegexMatchers.matchesPattern( - "-----BEGIN CERTIFICATE-----[\\r\\n]+" - + "([a-zA-Z0-9/+=]+[\\r\\n]+)+" - + "-----END CERTIFICATE-----[\\r\\n]*")); - - // Read it back in - X509Certificate written = CertificateUtils.readX509Certificate(new ByteArrayInputStream(pem)); - - // Verify that both certificates are the same - assertThat(original.getEncoded(), is(equalTo(written.getEncoded()))); - } - - /** - * Test if - * {@link CertificateUtils#writeX509CertificateChain(java.io.Writer, X509Certificate, X509Certificate...)} - * writes a correct chain. - */ - @Test - public void testWriteX509CertificateChain() throws IOException, CertificateException { - X509Certificate leaf = createCertificate(); - X509Certificate chain1 = createCertificate(); - X509Certificate chain2 = createCertificate(); - - String out; - try (StringWriter w = new StringWriter()) { - CertificateUtils.writeX509CertificateChain(w, leaf); - out = w.toString(); - } - assertThat(countCertificates(out), is(1)); - - try (StringWriter w = new StringWriter()) { - CertificateUtils.writeX509CertificateChain(w, leaf, chain1); - out = w.toString(); - } - assertThat(countCertificates(out), is(2)); - - try (StringWriter w = new StringWriter()) { - CertificateUtils.writeX509CertificateChain(w, leaf, chain1, chain2); - out = w.toString(); - } - assertThat(countCertificates(out), is(3)); - - try (StringWriter w = new StringWriter()) { - CertificateUtils.writeX509CertificateChain(w, leaf, chain1, null, chain2); - out = w.toString(); - } - assertThat(countCertificates(out), is(3)); - } - /** * Test if {@link CertificateUtils#createTlsSni02Certificate(KeyPair, String, String)} * creates a good certificate. @@ -169,18 +89,6 @@ public class CertificateUtilsTest { } } - /** - * Returns a test certificates. - */ - private X509Certificate createCertificate() throws IOException, CertificateException { - X509Certificate original; - try (InputStream cert = getClass().getResourceAsStream("/cert.pem")) { - original = (X509Certificate) certificateFactory.generateCertificate(cert); - } - assertThat(original, is(notNullValue())); - return original; - } - /** * Test that constructor is private. */ @@ -192,25 +100,6 @@ public class CertificateUtilsTest { constructor.newInstance(); } - /** - * Counts number of certificates in a PEM string. - * - * @param str - * String containing certificates in PEM format - * @return Number of certificates found - */ - private int countCertificates(String str) { - int count = 0; - int pos = 0; - while (true) { - pos = str.indexOf("-----BEGIN CERTIFICATE-----", pos); - if (pos < 0) break; - count++; - pos++; - } - return count; - } - /** * Extracts all DNSName SANs from a certificate. *