CertificateUtils { public static X509Certificate createTlsAlpn01Certificate(KeyPair keypair, Identifier id, byte[] acmeValidation) throws IOException { Objects.requireNonNull(keypair, "keypair"); Objects.requireNonNull(id, "id"); if (acmeValidation == null || acmeValidation.length != 32) { throw new IllegalArgumentException("Bad acmeValidation parameter"); } final long now = System.currentTimeMillis(); X500Name issuer = new X500Name("CN=acme.invalid"); BigInteger serial = BigInteger.valueOf(now); Instant notBefore = Instant.ofEpochMilli(now); Instant notAfter = notBefore.plus(Duration.ofDays(7)); JcaX509v3CertificateBuilder certBuilder = new JcaX509v3CertificateBuilder( issuer, serial, Date.from(notBefore), Date.from(notAfter), issuer, keypair.getPublic()); GeneralName[] gns = new GeneralName[1]; switch (id.getType()) { case Identifier.TYPE_DNS: gns[0] = new GeneralName(GeneralName.dNSName, id.getDomain()); break; case Identifier.TYPE_IP: gns[0] = new GeneralName(GeneralName.iPAddress, id.getIP().getHostAddress()); break; default: throw new IllegalArgumentException("Unsupported Identifier type " + id.getType()); } certBuilder.addExtension(Extension.subjectAlternativeName, false, new GeneralNames(gns)); certBuilder.addExtension(ACME_VALIDATION, true, new DEROctetString(acmeValidation)); return buildCertificate(certBuilder::build, keypair.getPrivate()); } private  CertificateUtils(); static PKCS10CertificationRequest readCSR(InputStream in); static X509Certificate createTlsAlpn01Certificate(KeyPair keypair, Identifier id, byte[] acmeValidation); static X509Certificate createTestRootCertificate(String subject,
            Instant notBefore, Instant notAfter, KeyPair keypair); static X509Certificate createTestIntermediateCertificate(String subject,
            Instant notBefore, Instant notAfter, PublicKey intermediatePublicKey,
            X509Certificate issuer, PrivateKey issuerPrivateKey); static X509Certificate createTestCertificate(PKCS10CertificationRequest csr,
            Instant notBefore, Instant notAfter, X509Certificate issuer, PrivateKey issuerPrivateKey); static final ASN1ObjectIdentifier ACME_VALIDATION; }
@Test public void testCreateTlsAlpn01Certificate() throws IOException, CertificateParsingException { KeyPair keypair = KeyPairUtils.createKeyPair(2048); String subject = "example.com"; byte[] acmeValidationV1 = AcmeUtils.sha256hash("rSoI9JpyvFi-ltdnBW0W1DjKstzG7cHixjzcOjwzAEQ"); X509Certificate cert = CertificateUtils.createTlsAlpn01Certificate(keypair, Identifier.dns(subject), acmeValidationV1); Instant now = Instant.now(); Instant end = now.plus(Duration.ofDays(8)); assertThat(cert, not(nullValue())); assertThat(cert.getNotAfter(), is(greaterThan(Date.from(now)))); assertThat(cert.getNotAfter(), is(lessThan(Date.from(end)))); assertThat(cert.getNotBefore(), is(lessThanOrEqualTo(Date.from(now)))); assertThat(cert.getSubjectX500Principal().getName(), is("CN=acme.invalid")); assertThat(getSANs(cert), contains(subject)); assertThat(cert.getCriticalExtensionOIDs(), hasItem(TlsAlpn01Challenge.ACME_VALIDATION_OID)); byte[] encodedExtensionValue = cert.getExtensionValue(TlsAlpn01Challenge.ACME_VALIDATION_OID); assertThat(encodedExtensionValue, is(notNullValue())); try (ASN1InputStream asn = new ASN1InputStream(new ByteArrayInputStream(encodedExtensionValue))) { DEROctetString derOctetString = (DEROctetString) asn.readObject(); byte[] test = new byte[acmeValidationV1.length + 2]; test[0] = BERTags.OCTET_STRING; test[1] = (byte) acmeValidationV1.length; System.arraycopy(acmeValidationV1, 0, test, 2, acmeValidationV1.length); assertThat(derOctetString.getOctets(), is(test)); } }
@Test public void testCreateTlsAlpn01CertificateWithIp() throws IOException, CertificateParsingException { KeyPair keypair = KeyPairUtils.createKeyPair(2048); InetAddress subject = InetAddress.getLocalHost(); byte[] acmeValidationV1 = AcmeUtils.sha256hash("rSoI9JpyvFi-ltdnBW0W1DjKstzG7cHixjzcOjwzAEQ"); X509Certificate cert = CertificateUtils.createTlsAlpn01Certificate(keypair, Identifier.ip(subject), acmeValidationV1); assertThat(cert.getSubjectX500Principal().getName(), is("CN=acme.invalid")); assertThat(getIpSANs(cert), contains(subject)); }