diff --git a/README.md b/README.md index 3f6955fb..388904d7 100644 --- a/README.md +++ b/README.md @@ -72,6 +72,7 @@ See https://ebourg.github.io/jsign for more information. * The log4j configuration warning displayed when signing a MSI file has been fixed (contributed by Pascal Davoust) * The value of the `storetype` parameter is now case insensitive * The Azure Key Vault account no longer needs the permission to list the keys when signing with jarsigner +* The DigiCert ONE host can now be specified with the --keystore parameter * On Windows the YubiKey library path is automatically added to the PATH of the command line tool * Signing more than one file with the `YUBIKEY` storetype no longer triggers a `CKR_USER_NOT_LOGGED_IN` error * API changes: diff --git a/docs/index.html b/docs/index.html index 13c2534b..79c81e0c 100644 --- a/docs/index.html +++ b/docs/index.html @@ -713,7 +713,8 @@

Signing with DigiCert ONE

Certificates and keys stored in the DigiCert ONE Secure Software Manager can be used directly without installing the DigiCert client tools. It requires an API key and a PKCS#12 keystore holding -a client certificate for the authentication.

+a client certificate for the authentication. The US DigiCert ONE host is used by default (https://clientauth.one.digicert.com) +but a different host can be specified with the --keystore parameter.

  jsign --storetype DIGICERTONE \
diff --git a/jsign-crypto/src/main/java/net/jsign/KeyStoreType.java b/jsign-crypto/src/main/java/net/jsign/KeyStoreType.java
index 1288cc05..e01ea9da 100644
--- a/jsign-crypto/src/main/java/net/jsign/KeyStoreType.java
+++ b/jsign-crypto/src/main/java/net/jsign/KeyStoreType.java
@@ -348,7 +348,7 @@ void validate(KeyStoreBuilder params) {
         @Override
         Provider getProvider(KeyStoreBuilder params) {
             String[] elements = params.storepass().split("\\|");
-            return new SigningServiceJcaProvider(new DigiCertOneSigningService(elements[0], params.createFile(elements[1]), elements[2]));
+            return new SigningServiceJcaProvider(new DigiCertOneSigningService(params.keystore(), elements[0], params.createFile(elements[1]), elements[2]));
         }
     },
 
diff --git a/jsign-crypto/src/main/java/net/jsign/jca/DigiCertOneSigningService.java b/jsign-crypto/src/main/java/net/jsign/jca/DigiCertOneSigningService.java
index 66c19011..b9cf2a1d 100644
--- a/jsign-crypto/src/main/java/net/jsign/jca/DigiCertOneSigningService.java
+++ b/jsign-crypto/src/main/java/net/jsign/jca/DigiCertOneSigningService.java
@@ -69,6 +69,18 @@ public DigiCertOneSigningService(String apiKey, File keystore, String storepass)
         this(apiKey, (X509KeyManager) getKeyManager(keystore, storepass));
     }
 
+    /**
+     * Creates a new DigiCert ONE signing service.
+     *
+     * @param endpoint  the URL of the DigiCert ONE host
+     * @param apiKey    the DigiCert ONE API access token
+     * @param keystore  the keystore holding the client certificate to authenticate with the server
+     * @param storepass the password of the keystore
+     */
+    public DigiCertOneSigningService(String endpoint, String apiKey, File keystore, String storepass) {
+        this(endpoint, apiKey, (X509KeyManager) getKeyManager(keystore, storepass));
+    }
+
     /**
      * Creates a new DigiCert ONE signing service.
      *
@@ -76,10 +88,13 @@ public DigiCertOneSigningService(String apiKey, File keystore, String storepass)
      * @param keyManager the key manager to authenticate the client with the server
      */
     public DigiCertOneSigningService(String apiKey, X509KeyManager keyManager) {
-        this("https://clientauth.one.digicert.com", apiKey, keyManager);
+        this(null, apiKey, keyManager);
     }
 
     DigiCertOneSigningService(String endpoint, String apiKey, X509KeyManager keyManager) {
+        if (endpoint == null) {
+            endpoint = "https://clientauth.one.digicert.com";
+        }
         this.client = new RESTClient(endpoint + "/signingmanager/api/v1/")
                 .authentication(conn -> {
                     conn.setRequestProperty("x-api-key", apiKey);
@@ -95,7 +110,7 @@ public DigiCertOneSigningService(String apiKey, X509KeyManager keyManager) {
                 })
                 .errorHandler(response -> {
                     Map error = (Map) response.get("error");
-                    return error.get("status") + ": " + error.get("message");
+                    return error != null ? error.get("status") + ": " + error.get("message") : JsonWriter.format(response);
                 });
     }
 
diff --git a/jsign-crypto/src/test/java/net/jsign/KeyStoreBuilderTest.java b/jsign-crypto/src/test/java/net/jsign/KeyStoreBuilderTest.java
index ba13bf57..a9e28c5f 100644
--- a/jsign-crypto/src/test/java/net/jsign/KeyStoreBuilderTest.java
+++ b/jsign-crypto/src/test/java/net/jsign/KeyStoreBuilderTest.java
@@ -193,6 +193,7 @@ public void testBuildDigiCertONE() throws Exception {
             assertEquals("message", "Failed to load the client certificate for DigiCert ONE", e.getMessage());
         }
 
+        builder.keystore("https://clientauth.demo.one.digicert.com");
         builder.storepass("APIKEY|target/test-classes/keystores/keystore.p12|password");
 
         KeyStore keystore = builder.build();
diff --git a/jsign-crypto/src/test/java/net/jsign/jca/DigiCertOneSigningServiceTest.java b/jsign-crypto/src/test/java/net/jsign/jca/DigiCertOneSigningServiceTest.java
index c1b5ad8c..6bf9e9a0 100644
--- a/jsign-crypto/src/test/java/net/jsign/jca/DigiCertOneSigningServiceTest.java
+++ b/jsign-crypto/src/test/java/net/jsign/jca/DigiCertOneSigningServiceTest.java
@@ -142,6 +142,25 @@ public void testGetCertificateChainWithError() {
         }
     }
 
+    @Test
+    public void testGetCertificateChainWithInvalidEndpoint() {
+        onRequest()
+                .havingMethodEqualTo("GET")
+                .respond()
+                .withStatus(404)
+                .withContentType("application/json")
+                .withBody("{\"errors\":[{\"code\":\"INTERNAL_SERVER_ERROR\",\"message\":\"Path not found\"}]}");
+
+        SigningService service = getTestService();
+        try {
+            service.getCertificateChain("jsign-1995-cert");
+            fail("Exception not thrown");
+        } catch (KeyStoreException e) {
+            assertEquals("message", "Unable to retrieve DigiCert ONE certificate 'jsign-1995-cert'", e.getMessage());
+            assertEquals("message", "{\"errors\":[{\"code\":\"INTERNAL_SERVER_ERROR\",\"message\":\"Path not found\"}]}", e.getCause().getMessage());
+        }
+    }
+
     @Test
     public void testGetPrivateKey() throws Exception {
         onRequest()
diff --git a/jsign-crypto/src/test/java/net/jsign/jca/SigningServiceTest.java b/jsign-crypto/src/test/java/net/jsign/jca/SigningServiceTest.java
index eeb81740..986d6110 100644
--- a/jsign-crypto/src/test/java/net/jsign/jca/SigningServiceTest.java
+++ b/jsign-crypto/src/test/java/net/jsign/jca/SigningServiceTest.java
@@ -171,7 +171,7 @@ public void testDigiCertProvider() throws Exception {
         KeyStore keystore = KeyStore.getInstance("DIGICERTONE", provider);
         keystore.load(null, "".toCharArray());
 
-        testCustomProvider(provider, keystore, "0a50eb72-68d0-4730-96cb-fe648d2c2fd2", "");
+        testCustomProvider(provider, keystore, "353d4f18-5325-4b78-b17c-f92375cf40ec", "");
     }
 
     @Test
diff --git a/jsign/src/deb/data/usr/share/man/man1/jsign.1 b/jsign/src/deb/data/usr/share/man/man1/jsign.1
index b29bf5ff..901138fa 100644
--- a/jsign/src/deb/data/usr/share/man/man1/jsign.1
+++ b/jsign/src/deb/data/usr/share/man/man1/jsign.1
@@ -387,7 +387,8 @@ Signing with DigiCert ONE:
 
 Certificates and keys stored in the DigiCert ONE Secure Software Manager can be used directly without installing
 the DigiCert client tools. It requires an API key and a PKCS#12 keystore holding a client certificate for the
-authentication.
+authentication. The US DigiCert ONE host is used by default (https://clientauth.one.digicert.com) but a different
+host can be specified with the --keystore parameter.
 
 jsign --storetype DIGICERTONE \\
       --storepass "|/path/to/Certificate_pkcs12.p12|" \\