diff --git a/acme4j-utils/src/main/java/org/shredzone/acme4j/util/CSRBuilder.java b/acme4j-utils/src/main/java/org/shredzone/acme4j/util/CSRBuilder.java index f15118bd..a320b96a 100644 --- a/acme4j-utils/src/main/java/org/shredzone/acme4j/util/CSRBuilder.java +++ b/acme4j-utils/src/main/java/org/shredzone/acme4j/util/CSRBuilder.java @@ -16,6 +16,8 @@ package org.shredzone.acme4j.util; import java.io.IOException; import java.io.Writer; import java.security.KeyPair; +import java.security.PrivateKey; +import java.security.interfaces.ECKey; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -46,6 +48,7 @@ import org.bouncycastle.util.io.pem.PemWriter; */ public class CSRBuilder { private static final String SIGNATURE_ALG = "SHA256withRSA"; + private static final String EC_SIGNATURE_ALG = "SHA256withECDSA"; private final X500NameBuilder namebuilder = new X500NameBuilder(X500Name.getDefaultStyle()); private final List namelist = new ArrayList<>(); @@ -156,8 +159,10 @@ public class CSRBuilder { extensionsGenerator.addExtension(Extension.subjectAlternativeName, false, subjectAltName); p10Builder.addAttribute(PKCSObjectIdentifiers.pkcs_9_at_extensionRequest, extensionsGenerator.generate()); - JcaContentSignerBuilder csBuilder = new JcaContentSignerBuilder(SIGNATURE_ALG); - ContentSigner signer = csBuilder.build(keypair.getPrivate()); + PrivateKey pk = keypair.getPrivate(); + JcaContentSignerBuilder csBuilder = new JcaContentSignerBuilder( + pk instanceof ECKey ? EC_SIGNATURE_ALG : SIGNATURE_ALG); + ContentSigner signer = csBuilder.build(pk); csr = p10Builder.build(signer); } catch (OperatorCreationException ex) { diff --git a/acme4j-utils/src/test/java/org/shredzone/acme4j/util/CSRBuilderTest.java b/acme4j-utils/src/test/java/org/shredzone/acme4j/util/CSRBuilderTest.java index 90e76819..6b432042 100644 --- a/acme4j-utils/src/test/java/org/shredzone/acme4j/util/CSRBuilderTest.java +++ b/acme4j-utils/src/test/java/org/shredzone/acme4j/util/CSRBuilderTest.java @@ -20,6 +20,7 @@ import java.io.IOException; import java.io.StringReader; import java.io.StringWriter; import java.security.KeyPair; +import java.security.Security; import java.util.Arrays; import org.bouncycastle.asn1.ASN1Encodable; @@ -33,6 +34,7 @@ import org.bouncycastle.asn1.x509.Extension; import org.bouncycastle.asn1.x509.Extensions; import org.bouncycastle.asn1.x509.GeneralName; import org.bouncycastle.asn1.x509.GeneralNames; +import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.openssl.PEMException; import org.bouncycastle.openssl.PEMParser; import org.bouncycastle.pkcs.PKCS10CertificationRequest; @@ -51,10 +53,14 @@ import com.jcabi.matchers.RegexMatchers; public class CSRBuilderTest { private static KeyPair testKey; + private static KeyPair testEcKey; @BeforeClass public static void setup() { + Security.addProvider(new BouncyCastleProvider()); + testKey = KeyPairUtils.createKeyPair(512); + testEcKey = KeyPairUtils.createECKeyPair("secp256r1"); } /** @@ -88,6 +94,37 @@ public class CSRBuilderTest { writerTest(builder); } + /** + * Test if the generated CSR is plausible using a ECDSA key. + */ + @Test + public void testECCGenerate() throws IOException { + CSRBuilder builder = new CSRBuilder(); + builder.addDomain("abc.de"); + builder.addDomain("fg.hi"); + builder.addDomains("jklm.no", "pqr.st"); + builder.addDomains(Arrays.asList("uv.wx", "y.z")); + + builder.setCountry("XX"); + builder.setLocality("Testville"); + builder.setOrganization("Testing Co"); + builder.setOrganizationalUnit("Testunit"); + builder.setState("ABC"); + + assertThat(builder.toString(), is("CN=abc.de,C=XX,L=Testville,O=Testing Co," + + "OU=Testunit,ST=ABC," + + "DNS=abc.de,DNS=fg.hi,DNS=jklm.no,DNS=pqr.st,DNS=uv.wx,DNS=y.z")); + + builder.sign(testEcKey); + + PKCS10CertificationRequest csr = builder.getCSR(); + assertThat(csr, is(notNullValue())); + assertThat(csr.getEncoded(), is(equalTo(builder.getEncoded()))); + + csrTest(csr); + writerTest(builder); + } + /** * Checks if the CSR contains the right parameters. *