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 @@
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| " \\