/** * Update the contact URLs for an account with an ACME server. * * @param account the ACME account information to use (must not be {@code null}) * @param staging whether or not the staging server URL should be used * @param contactUrls the new account contact URLs * @throws AcmeException if an error occurs while attempting to update the account */ public void updateAccount(AcmeAccount account, boolean staging, String[] contactUrls) throws AcmeException { updateAccount(account, staging, account.isTermsOfServiceAgreed(), contactUrls); }
private byte[] getNonce(AcmeAccount account, boolean staging) throws AcmeException { byte[] nonce = account.getNonce(); if (nonce == null) { nonce = getNewNonce(account, staging); } return nonce; }
private HttpURLConnection sendPostAsGetRequest(AcmeAccount account, boolean staging, String resourceUrl, String expectedContentType, int... expectedResponseCodes) throws AcmeException { // payload of the JWS must be a zero-length octet string return sendPostRequestWithRetries(account, staging, resourceUrl, false, EMPTY_STRING, expectedContentType, expectedResponseCodes); }
private String getEncodedProtectedHeader(boolean useJwk, String resourceUrl, AcmeAccount account, boolean staging) throws AcmeException { JsonObjectBuilder protectedHeaderBuilder = Json.createObjectBuilder().add(ALG, account.getAlgHeader()); if (useJwk) { protectedHeaderBuilder.add(JWK, getJwk(account.getPublicKey(), account.getAlgHeader())); } else { protectedHeaderBuilder.add(KID, getAccountUrl(account, staging)); } protectedHeaderBuilder .add(NONCE, base64UrlEncode(getNonce(account, staging))) .add(URL, resourceUrl); return getEncodedJson(protectedHeaderBuilder.build()); }
/** * Change the key that is associated with the given ACME account. * * @param account the ACME account information to use (must not be {@code null}) * @param staging whether or not the staging server URL should be used * @throws AcmeException if an error occurs while attempting to change the key that is associated with the given ACME account */ public void changeAccountKey(AcmeAccount account, boolean staging) throws AcmeException { Assert.checkNotNullParam("account", account); SelfSignedX509CertificateAndSigningKey newCertificateAndSigningKey = SelfSignedX509CertificateAndSigningKey.builder() .setKeySize(account.getKeySize()) .setKeyAlgorithmName(account.getKeyAlgorithmName()) .setDn(account.getDn()) .build(); changeAccountKey(account, staging, newCertificateAndSigningKey.getSelfSignedCertificate(), newCertificateAndSigningKey.getSigningKey()); }
private String getAccountUrl(AcmeAccount account, boolean staging) throws AcmeException { String accountUrl = account.getAccountUrl(); if (accountUrl == null) { createAccount(account, staging, true); accountUrl = account.getAccountUrl(); if (accountUrl == null) { acme.acmeAccountDoesNotExist(); } } return accountUrl; }
String queryAccountStatus(AcmeAccount account, boolean staging) throws AcmeException { Assert.checkNotNullParam("account", account); HttpURLConnection connection = sendPostAsGetRequest(account, staging, getAccountUrl(account, staging), null, HttpURLConnection.HTTP_OK); JsonObject jsonResponse = getJsonResponse(connection); return jsonResponse.getString(STATUS); }
private URL getResourceUrl(AcmeAccount account, AcmeResource resource, boolean staging) throws AcmeException { URL resourceUrl = getResourceUrls(account, staging).get(resource); if (resourceUrl == null) { throw acme.resourceNotSupportedByAcmeServer(resource.getValue()); } return resourceUrl; }
private static String getEncodedProtectedHeader(String algHeader, PublicKey publicKey, String resourceUrl) { JsonObject protectedHeader = Json.createObjectBuilder() .add(ALG, algHeader) .add(JWK, getJwk(publicKey, algHeader)) .add(URL, resourceUrl) .build(); return getEncodedJson(protectedHeader); }
/** * Revoke the given certificate. * * @param account the ACME account information to use (must not be {@code null}) * @param staging whether or not the staging server URL should be used * @param certificate the certificate to be revoked (must not be {@code null}) * @throws AcmeException if an error occurs while attempting to revoke the given certificate */ public void revokeCertificate(AcmeAccount account, boolean staging, X509Certificate certificate) throws AcmeException { revokeCertificate(account, staging, certificate, null); }
/** * Update whether or not the terms of service have been agreed to for an account with an ACME server. * * @param account the ACME account information to use (must not be {@code null}) * @param staging whether or not the staging server URL should be used * @param termsOfServiceAgreed the new value for whether or not the terms of service have been agreed to * @throws AcmeException if an error occurs while attempting to update the account */ public void updateAccount(AcmeAccount account, boolean staging, boolean termsOfServiceAgreed) throws AcmeException { updateAccount(account, staging, termsOfServiceAgreed, null); }
/** * Obtain a certificate chain using the given ACME account. * * @param account the ACME account information to use (must not be {@code null}) * @param staging whether or not the staging server URL should be used * @param domainNames the domain names to request the certificate for (must not be {@code null}) * @return the X509 certificate chain and private key * @throws AcmeException if an occur occurs while attempting to obtain the certificate */ public X509CertificateChainAndSigningKey obtainCertificateChain(AcmeAccount account, boolean staging, String... domainNames) throws AcmeException { return obtainCertificateChain(account, staging, null, -1, domainNames); }
/** * Create an account with an ACME server using the given account information. * * @param account the ACME account information to use (must not be {@code null}) * @param staging whether or not the staging server URL should be used * @return {@code true} if the account was created, {@code false} if the account already existed * @throws AcmeException if an error occurs while attempting to create or lookup an account with * the ACME server */ public boolean createAccount(AcmeAccount account, boolean staging) throws AcmeException { return createAccount(account, staging, false); }
/** * Construct a new builder instance. * * @return the new builder instance */ public static Builder builder() { return new Builder(); }
/** * Construct a new builder instance. * * @return the new builder instance */ public static Builder builder() { return new Builder(); }
/** * Create the ACME metadata. * * @return the newly created ACME metadata */ public AcmeMetadata build() throws IllegalArgumentException { return new AcmeMetadata(this); } }
static Type forName(String name) { switch (name) { case "http-01": return HTTP_01; case "dns-01": return DNS_01; case "tls-sni-01": return TLS_SNI_01; case "tls-sni-02": return TLS_SNI_02; case "tls-alpn-01": return TLS_ALPN_01; default: return new UnknownType(name); } } }
private static String getProblemMessage(JsonObject jsonResponse) { String type = getOptionalJsonString(jsonResponse, TYPE); String detail = getOptionalJsonString(jsonResponse, DETAIL); String title = getOptionalJsonString(jsonResponse, TITLE); String problemMessage = null; if (detail != null) { problemMessage = detail; } else if (title != null) { problemMessage = title; } else if (type != null) { problemMessage = type; } return problemMessage; }
private static String getEncodedSignature(PrivateKey privateKey, String signatureAlgorithm, String encodedProtectedHeader, String encodedPayload) throws AcmeException { try { Signature signature = Signature.getInstance(signatureAlgorithm); signature.initSign(privateKey); return getEncodedSignature(privateKey, signature, encodedProtectedHeader, encodedPayload); } catch (NoSuchAlgorithmException | InvalidKeyException e) { throw acme.unableToCreateAcmeSignature(e); } }
private HttpURLConnection sendPostRequestWithRetries(AcmeAccount account, boolean staging, String resourceUrl, boolean useJwk, String encodedPayload, int... expectedResponseCodes) throws AcmeException { return sendPostRequestWithRetries(account, staging, resourceUrl, useJwk, encodedPayload, null, expectedResponseCodes); }