From ea3ead8488511c6bedaeac0a9689bf78beb52785 Mon Sep 17 00:00:00 2001 From: Emmanuel Bourg Date: Wed, 29 May 2024 15:24:34 +0200 Subject: [PATCH] GaraSign support --- README.md | 2 + docs/index.html | 31 ++ .../src/main/java/net/jsign/JsignCLI.java | 1 + .../main/java/net/jsign/KeyStoreBuilder.java | 18 + .../src/main/java/net/jsign/KeyStoreType.java | 32 ++ .../net/jsign/jca/GaraSignCredentials.java | 88 ++++ .../net/jsign/jca/GaraSignSigningService.java | 228 ++++++++++ .../main/java/net/jsign/jca/RESTClient.java | 16 + .../java/net/jsign/KeyStoreBuilderTest.java | 40 ++ .../jsign/jca/GaraSignCredentialsTest.java | 76 ++++ .../jsign/jca/GaraSignSigningServiceTest.java | 402 ++++++++++++++++++ .../net/jsign/jca/SigningServiceTest.java | 16 + .../services/garasign-authenticate.json | 5 + .../resources/services/garasign-keystore.json | 24 ++ .../resources/services/garasign-sign.json | 5 + .../src/main/java/net/jsign/JsignMojo.java | 2 +- .../share/bash-completion/completions/jsign | 2 +- jsign/src/deb/data/usr/share/man/man1/jsign.1 | 28 ++ 18 files changed, 1014 insertions(+), 2 deletions(-) create mode 100644 jsign-core/src/main/java/net/jsign/jca/GaraSignCredentials.java create mode 100644 jsign-core/src/main/java/net/jsign/jca/GaraSignSigningService.java create mode 100644 jsign-core/src/test/java/net/jsign/jca/GaraSignCredentialsTest.java create mode 100644 jsign-core/src/test/java/net/jsign/jca/GaraSignSigningServiceTest.java create mode 100644 jsign-core/src/test/resources/services/garasign-authenticate.json create mode 100644 jsign-core/src/test/resources/services/garasign-keystore.json create mode 100644 jsign-core/src/test/resources/services/garasign-sign.json diff --git a/README.md b/README.md index 07f4adbd..50dd5cb4 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,7 @@ Jsign is free to use and licensed under the [Apache License version 2.0](https:/ * [Azure Key Vault](https://azure.microsoft.com/services/key-vault/) * [Azure Trusted Signing](https://learn.microsoft.com/en-us/azure/trusted-signing/) * [DigiCert ONE](https://one.digicert.com) + * [GaraSign](https://garantir.io/garasign/) * [Google Cloud KMS](https://cloud.google.com/security-key-management) * [HashiCorp Vault](https://www.vaultproject.io/) * [Oracle Cloud KMS](https://www.oracle.com/security/cloud-security/key-management/) @@ -55,6 +56,7 @@ See https://ebourg.github.io/jsign for more information. * The Azure Trusted Signing service has been integrated * The Oracle Cloud signing service has been integrated +* The GaraSign signing service has been integrated * Signing of NuGet packages has been implemented (contributed by Sebastian Stamm) * The intermediate certificates are downloaded if missing from the keystore or the certificate chain file * File list files prefixed with `@` are now supported with the command line tool to sign multiple files diff --git a/docs/index.html b/docs/index.html index d76e95cf..645ad53c 100644 --- a/docs/index.html +++ b/docs/index.html @@ -73,6 +73,7 @@

Features

  • Azure Key Vault
  • Azure Trusted Signing
  • DigiCert ONE
  • +
  • GaraSign
  • Google Cloud KMS
  • HashiCorp Vault
  • Oracle Cloud KMS
  • @@ -198,6 +199,7 @@

    Attributes

  • AZUREKEYVAULT: Azure Key Vault key management system
  • DIGICERTONE: DigiCert ONE Secure Software Manager
  • ESIGNER: SSL.com eSigner
  • +
  • GARASIGN: Garantir Remote Signing
  • GOOGLECLOUD: Google Cloud KMS
  • HASHICORPVAULT: Google Cloud KMS via HashiCorp Vault
  • ORACLECLOUD: Oracle Cloud Key Management Service
  • @@ -505,6 +507,7 @@

    Command Line Tool

    - AZUREKEYVAULT: Azure Key Vault key management system - DIGICERTONE: DigiCert ONE Secure Software Manager - ESIGNER: SSL.com eSigner + - GARASIGN: Garantir Remote Signing - GOOGLECLOUD: Google Cloud KMS - HASHICORPVAULT: Google Cloud KMS via HashiCorp Vault - ORACLECLOUD: Oracle Cloud Key Management Service @@ -737,6 +740,34 @@

    Signing with SSL.com eSigner

    SSL.com provides a sandbox environment, to use a test certificate simply add the parameter --keystore https://cs-try.ssl.com.

    +

    Signing with GaraSign

    + +

    GaraSign is a remote signing service provided by Garantir. +The authentication is performed by specifying the username/password or the TLS client certificate in the +storepass parameter. If the TLS client certificate is stored in a password protected keystore, +the password is specified in the keypass parameter. The keystore parameter references +the URL of the GaraSign REST API (https://garasign.com:8443/CodeSigningRestService/ by default).

    + +

    Authenticating with a username and a password:

    + +
    + jsign --storetype GARASIGN \
    +       --storepass "<username>|<password>" \
    +       --alias test \
    +       application.exe
    +
    + +

    Authenticating with a TLS client certificate and a non-default endpoint:

    + +
    + jsign --storetype GARASIGN \
    +       --keystore https://demo.garantir.io/CodeSigningRestService \
    +       --storepass "/path/to/client-certificate.p12" \
    +       --keypass <client-certificate-password> \
    +       --alias test \
    +       application.exe
    +
    +

    Signing with Google Cloud KMS

    Google Cloud KMS stores only the private key, the certificate must be provided separately. The keystore parameter diff --git a/jsign-cli/src/main/java/net/jsign/JsignCLI.java b/jsign-cli/src/main/java/net/jsign/JsignCLI.java index 37bf408f..3c0f5cdd 100644 --- a/jsign-cli/src/main/java/net/jsign/JsignCLI.java +++ b/jsign-cli/src/main/java/net/jsign/JsignCLI.java @@ -88,6 +88,7 @@ public static void main(String... args) { + "- AZUREKEYVAULT: Azure Key Vault key management system\n" + "- DIGICERTONE: DigiCert ONE Secure Software Manager\n" + "- ESIGNER: SSL.com eSigner\n" + + "- GARASIGN: Garantir Remote Signing\n" + "- GOOGLECLOUD: Google Cloud KMS\n" + "- HASHICORPVAULT: Google Cloud KMS via HashiCorp Vault\n" + "- ORACLECLOUD: Oracle Cloud Key Management Service\n" diff --git a/jsign-core/src/main/java/net/jsign/KeyStoreBuilder.java b/jsign-core/src/main/java/net/jsign/KeyStoreBuilder.java index cede7b38..51d75f0b 100644 --- a/jsign-core/src/main/java/net/jsign/KeyStoreBuilder.java +++ b/jsign-core/src/main/java/net/jsign/KeyStoreBuilder.java @@ -284,4 +284,22 @@ public KeyStore build() throws KeyStoreException { validate(); return storetype().getKeystore(this, provider()); } + + /** + * Returns a java.security.KeyStore.Builder using the parameters of this builder. + */ + public KeyStore.Builder builder() { + return new KeyStore.Builder() { + @Override + public KeyStore getKeyStore() throws KeyStoreException { + return build(); + } + + @Override + public KeyStore.ProtectionParameter getProtectionParameter(String alias) { + String storepass = storepass(); + return new KeyStore.PasswordProtection(storepass != null ? storepass.toCharArray() : null); + } + }; + } } diff --git a/jsign-core/src/main/java/net/jsign/KeyStoreType.java b/jsign-core/src/main/java/net/jsign/KeyStoreType.java index 30851799..1288cc05 100644 --- a/jsign-core/src/main/java/net/jsign/KeyStoreType.java +++ b/jsign-core/src/main/java/net/jsign/KeyStoreType.java @@ -40,6 +40,8 @@ import net.jsign.jca.AzureTrustedSigningService; import net.jsign.jca.DigiCertOneSigningService; import net.jsign.jca.ESignerSigningService; +import net.jsign.jca.GaraSignCredentials; +import net.jsign.jca.GaraSignSigningService; import net.jsign.jca.GoogleCloudSigningService; import net.jsign.jca.HashiCorpVaultSigningService; import net.jsign.jca.OpenPGPCardSigningService; @@ -511,6 +513,36 @@ void validate(KeyStoreBuilder params) { Provider getProvider(KeyStoreBuilder params) { return new SigningServiceJcaProvider(new AzureTrustedSigningService(params.keystore(), params.storepass())); } + }, + + GARASIGN(false, false, false) { + @Override + void validate(KeyStoreBuilder params) { + if (params.storepass() == null || params.storepass().split("\\|").length > 3) { + throw new IllegalArgumentException("storepass " + params.parameterName() + " must specify the GaraSign username/password and/or the path to the keystore containing the TLS client certificate: |, , or ||"); + } + } + + @Override + Provider getProvider(KeyStoreBuilder params) { + String[] elements = params.storepass().split("\\|"); + String username = null; + String password = null; + String certificate = null; + if (elements.length == 1) { + certificate = elements[0]; + } else if (elements.length == 2) { + username = elements[0]; + password = elements[1]; + } else if (elements.length == 3) { + username = elements[0]; + password = elements[1]; + certificate = elements[2]; + } + + GaraSignCredentials credentials = new GaraSignCredentials(username, password, certificate, params.keypass()); + return new SigningServiceJcaProvider(new GaraSignSigningService(params.keystore(), credentials)); + } }; diff --git a/jsign-core/src/main/java/net/jsign/jca/GaraSignCredentials.java b/jsign-core/src/main/java/net/jsign/jca/GaraSignCredentials.java new file mode 100644 index 00000000..0395aaa9 --- /dev/null +++ b/jsign-core/src/main/java/net/jsign/jca/GaraSignCredentials.java @@ -0,0 +1,88 @@ +/** + * Copyright 2024 Emmanuel Bourg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.jsign.jca; + +import java.io.IOException; +import java.security.GeneralSecurityException; +import java.security.KeyStore; +import java.security.SecureRandom; +import java.util.LinkedHashMap; +import java.util.Map; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; + +import net.jsign.KeyStoreBuilder; + +/** + * Credentials for the Garantir Remote Signing service. + * + * @since 6.1 + */ +public class GaraSignCredentials { + + public String username; + public String password; + public KeyStore.Builder keystore; + public String sessionToken; + + public GaraSignCredentials(String username, String password, String keystore, String storepass) { + this(username, password, new KeyStoreBuilder().keystore(keystore).storepass(storepass).builder()); + } + + public GaraSignCredentials(String username, String password, KeyStore.Builder keystore) { + this.username = username; + this.password = password; + this.keystore = keystore; + } + + public String getSessionToken(String endpoint) throws IOException { + if (sessionToken == null) { + RESTClient client = new RESTClient(endpoint) + .authentication((conn, data) -> { + if (conn instanceof HttpsURLConnection && keystore != null) { + try { + KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + kmf.init(keystore.getKeyStore(), ((KeyStore.PasswordProtection) keystore.getProtectionParameter("")).getPassword()); + + SSLContext context = SSLContext.getInstance("TLS"); + context.init(kmf.getKeyManagers(), null, new SecureRandom()); + ((HttpsURLConnection) conn).setSSLSocketFactory(context.getSocketFactory()); + } catch (GeneralSecurityException e) { + throw new RuntimeException("Unable to load the GaraSign client certificate", e); + } + } + }); + + Map params = new LinkedHashMap<>(); + params.put("api_version", "1.0"); + if (username != null && password != null) { + params.put("username", username); + params.put("password", password); + } + + Map response = client.post("/authenticate", params); + String status = (String) response.get("status"); + if (!"SUCCESS".equals(status)) { + throw new IOException("Failed to authenticate with GaraSign: " + response.get("message")); + } + sessionToken = (String) response.get("sessionToken"); + } + + return sessionToken; + } +} diff --git a/jsign-core/src/main/java/net/jsign/jca/GaraSignSigningService.java b/jsign-core/src/main/java/net/jsign/jca/GaraSignSigningService.java new file mode 100644 index 00000000..70f39e73 --- /dev/null +++ b/jsign-core/src/main/java/net/jsign/jca/GaraSignSigningService.java @@ -0,0 +1,228 @@ +/** + * Copyright 2024 Emmanuel Bourg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.jsign.jca; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.security.GeneralSecurityException; +import java.security.KeyStoreException; +import java.security.UnrecoverableKeyException; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.util.ArrayList; +import java.util.Base64; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import net.jsign.DigestAlgorithm; + +/** + * Signing service using the Garantir Remote Signing REST Service API. + * + * @since 6.1 + */ +public class GaraSignSigningService implements SigningService { + + /** Cache of certificates indexed by alias */ + private final Map> certificates = new LinkedHashMap<>(); + + /** The API endpoint of the Garantir Remote Signing service */ + private final String endpoint; + + private final RESTClient client; + + /** The credentials to authenticate with the service */ + private final GaraSignCredentials credentials; + + /** Timeout in seconds for the signing operation */ + private long timeout = 60 * 60; // one hour + + /** + * Creates a new GaraSign signing service. + * + * @param endpoint the GaraSign API endpoint (for example https://demo.garantir.io/CodeSigningRestService/) + * @param credentials the GaraSign credentials + */ + public GaraSignSigningService(String endpoint, GaraSignCredentials credentials) { + this.endpoint = endpoint != null ? endpoint : "https://garasign.com:8443/CodeSigningRestService/"; + this.credentials = credentials; + this.client = new RESTClient(endpoint); + } + + void setTimeout(int timeout) { + this.timeout = timeout; + } + + @Override + public String getName() { + return "GaraSign"; + } + + private void loadKeyStore() throws KeyStoreException { + if (certificates.isEmpty()) { + try { + Map params = new LinkedHashMap<>(); + params.put("api_version", "1.0"); + params.put("session_token", credentials.getSessionToken(endpoint)); + + Map response = client.post("/keystore", params); + String status = (String) response.get("status"); + if (!"SUCCESS".equals(status)) { + throw new KeyStoreException("Unable to retrieve the GaraSign keystore: " + response.get("message")); + } + + Object[] keys = (Object[]) response.get("keys"); + for (Object key : keys) { + String name = (String) ((Map) key).get("name"); + certificates.put(name, (Map) key); + } + } catch (IOException e) { + throw new KeyStoreException("Unable to retrieve the GaraSign keystore", e); + } + } + } + + @Override + public List aliases() throws KeyStoreException { + loadKeyStore(); + return new ArrayList<>(certificates.keySet()); + } + + @Override + public Certificate[] getCertificateChain(String alias) throws KeyStoreException { + loadKeyStore(); + + Map key = certificates.get(alias); + if (key == null) { + throw new KeyStoreException("Unable to retrieve GaraSign certificate '" + alias + "'"); + } + + Object[] certChain = (Object[]) key.get("certChain"); + Certificate[] chain = new Certificate[certChain.length]; + + for (int i = 0; i < certChain.length; i++) { + byte[] data = decode((Object[]) certChain[i]); + + try { + chain[i] = CertificateFactory.getInstance("X.509").generateCertificate(new ByteArrayInputStream(data)); + } catch (CertificateException e) { + throw new KeyStoreException(e); + } + } + + return chain; + } + + private String getAlgorithm(String alias) throws KeyStoreException { + loadKeyStore(); + Map key = certificates.get(alias); + if (key == null) { + return null; + } + + return (String) key.get("algorithm"); + } + + @Override + public SigningServicePrivateKey getPrivateKey(String alias, char[] password) throws UnrecoverableKeyException { + try { + String algorithm = getAlgorithm(alias); + if (algorithm == null) { + throw new UnrecoverableKeyException("Unable to fetch GaraSign private key for the certificate '" + alias + "'"); + } + return new SigningServicePrivateKey(alias, algorithm, this); + } catch (KeyStoreException e) { + throw (UnrecoverableKeyException) new UnrecoverableKeyException().initCause(e); + } + } + + @Override + public byte[] sign(SigningServicePrivateKey privateKey, String algorithm, byte[] data) throws GeneralSecurityException { + DigestAlgorithm digestAlgorithm = DigestAlgorithm.of(algorithm.substring(0, algorithm.toLowerCase().indexOf("with"))); + data = digestAlgorithm.getMessageDigest().digest(data); + + try { + Map params = new LinkedHashMap<>(); + params.put("api_version", "1.0"); + params.put("session_token", credentials.getSessionToken(endpoint)); + params.put("key_name", privateKey.getId()); + params.put("signature_scheme", algorithm); + params.put("data_to_sign", Base64.getEncoder().encodeToString(data)); + + Map response = client.post("/sign", params); + + String status = (String) response.get("status"); + if ("FAILURE".equals(status)) { + throw new IOException("Signing operation failed: " + response.get("message")); + } + + String requestId = (String) response.get("requestId"); + + params.put("request_id", requestId); + params.remove("key_name"); + params.remove("signature_scheme"); + params.remove("data_to_sign"); + + String message = null; + if ("IN_PROGRESS".equals(status)) { + // poll until the operation is completed + long startTime = System.currentTimeMillis(); + int i = 0; + while (System.currentTimeMillis() - startTime < timeout * 1000) { + try { + Thread.sleep(Math.min(1000, 100 + 100 * i++)); + } catch (InterruptedException e) { + break; + } + response = client.post("/sign", params); + status = (String) response.get("status"); + if ("IN_PROGRESS".equals(status)) { + // display the message once if the operation is pending for more than 3 seconds + if (System.currentTimeMillis() - startTime > 3000 && response.get("message") != null && !response.get("message").equals(message)) { + message = (String) response.get("message"); + } + continue; + } + if ("SUCCESS".equals(status)) { + break; + } + + throw new IOException("Signing operation " + requestId + " failed: " + response.get("message")); + } + } + + if (!"SUCCESS".equals(response.get("status"))) { + throw new IOException("Signing operation " + requestId + " timed out"); + } + + return decode((Object[]) response.get("signature")); + + } catch (IOException e) { + throw new GeneralSecurityException(e); + } + } + + private byte[] decode(Object[] array) { + byte[] data = new byte[array.length]; + for (int i = 0; i < array.length; i++) { + data[i] = ((Number) array[i]).byteValue(); + } + return data; + } +} diff --git a/jsign-core/src/main/java/net/jsign/jca/RESTClient.java b/jsign-core/src/main/java/net/jsign/jca/RESTClient.java index 1290b3b5..e3d302fd 100644 --- a/jsign-core/src/main/java/net/jsign/jca/RESTClient.java +++ b/jsign-core/src/main/java/net/jsign/jca/RESTClient.java @@ -19,6 +19,7 @@ import java.io.IOException; import java.net.HttpURLConnection; import java.net.URL; +import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.List; @@ -76,6 +77,21 @@ public RESTClient errorHandler(Function, String> errorHandler) { return query("POST", resource, body, headers); } + public Map post(String resource, Map params) throws IOException { + StringBuilder body = new StringBuilder(); + for (Map.Entry param : params.entrySet()) { + if (body.length() > 0) { + body.append('&'); + } + body.append(param.getKey()).append('=').append(URLEncoder.encode(param.getValue(), "UTF-8")); + } + + Map headers = new HashMap<>(); + headers.put("Content-Type", "application/x-www-form-urlencoded"); + + return post(resource, body.toString(), headers); + } + private Map query(String method, String resource, String body, Map headers) throws IOException { URL url = new URL(resource.startsWith("http") ? resource : endpoint + resource); log.finest(method + " " + url); diff --git a/jsign-core/src/test/java/net/jsign/KeyStoreBuilderTest.java b/jsign-core/src/test/java/net/jsign/KeyStoreBuilderTest.java index 715ab881..ba13bf57 100644 --- a/jsign-core/src/test/java/net/jsign/KeyStoreBuilderTest.java +++ b/jsign-core/src/test/java/net/jsign/KeyStoreBuilderTest.java @@ -364,6 +364,46 @@ public void testBuildTrustedSigning() throws Exception { assertNotNull("keystore", keystore); } + @Test + public void testBuildGaraSign() throws Exception { + KeyStoreBuilder builder = new KeyStoreBuilder().storetype(GARASIGN); + + try { + builder.build(); + fail("Exception not thrown"); + } catch (IllegalArgumentException e) { + assertEquals("message", "storepass parameter must specify the GaraSign username/password and/or the path to the keystore containing the TLS client certificate: |, , or ||", e.getMessage()); + } + + builder.storepass("username|password|keystore.p12|storepass"); + + try { + builder.build(); + fail("Exception not thrown"); + } catch (IllegalArgumentException e) { + assertEquals("message", "storepass parameter must specify the GaraSign username/password and/or the path to the keystore containing the TLS client certificate: |, , or ||", e.getMessage()); + } + + builder.storepass("username|password"); + + KeyStore keystore = builder.build(); + assertNotNull("keystore", keystore); + + builder = new KeyStoreBuilder().storetype(GARASIGN).keystore("https://api.garantir.io"); + builder.storepass("keystore.p12"); + + keystore = builder.build(); + assertNotNull("keystore", keystore); + + builder = new KeyStoreBuilder().storetype(GARASIGN).keystore("https://api.garantir.io"); + builder.storepass("keystore.p12"); + builder.storepass("username|password|keystore.p12"); + builder.keypass("keypass"); + + keystore = builder.build(); + assertNotNull("keystore", keystore); + } + @Test public void testBuildJKS() throws Exception { KeyStoreBuilder builder = new KeyStoreBuilder().storetype(JKS); diff --git a/jsign-core/src/test/java/net/jsign/jca/GaraSignCredentialsTest.java b/jsign-core/src/test/java/net/jsign/jca/GaraSignCredentialsTest.java new file mode 100644 index 00000000..e50340e7 --- /dev/null +++ b/jsign-core/src/test/java/net/jsign/jca/GaraSignCredentialsTest.java @@ -0,0 +1,76 @@ +/** + * Copyright 2024 Emmanuel Bourg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.jsign.jca; + +import java.io.FileReader; +import java.io.IOException; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import static net.jadler.Jadler.*; +import static org.junit.Assert.*; + +public class GaraSignCredentialsTest { + + @Before + public void setUp() { + initJadler().withDefaultResponseStatus(404); + } + + @After + public void tearDown() { + closeJadler(); + } + + @Test + public void testGetSessionToken() throws Exception { + onRequest() + .havingMethodEqualTo("POST") + .havingPathEqualTo("/authenticate") + .havingParameterEqualTo("api_version", "1.0") + .havingParameterEqualTo("username", "ebourg") + .havingParameterEqualTo("password", "123456") + .respond() + .withStatus(200) + .withBody(new FileReader("target/test-classes/services/garasign-authenticate.json")); + + GaraSignCredentials credentials = new GaraSignCredentials("ebourg", "123456", null, null); + String sessionToken = credentials.getSessionToken("http://localhost:" + port()); + + assertEquals("session token", "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJrdG11c2VyIiwibmJmIjoxNTIyMjgzNzU1LCJleHAiOjE1MjIzNzAxNTUsImVuY3J5cHRlZF9jbGFpbXMiOiJyV1Q1TlljWi83TFV1eTB3YlFnbDR5K08zbXJtS3RrOGFtdjFVSnpOYy8vM0JvaVkrai9RS0lYYTdJSGRicWIxUTVCaWNIQ2VMYWJRQjhzMWQ3ZjJBZDNKeVR6dlliS1gzVGloUThmY3RyZWRyQ21sTFZ2dDZMRFlrZ2IxbURibWVuQ1Z2VFNKbnlXWEplRzRPMGJUUXQwN1RqTHVRdGhPendQR0xXSGFhT0U1cWNSZUUzVjMzb0U0RzJ1R2duR25tSFJNZVFzUTgxQXU3bGp1c2FDR1J6enpwaTFhZmxBdHRCcjNsbThWYmdrV0VWQ3ZDNndjTlNHZXA3YzJnNG0yQzI2MzhzMml2K2hLOTFzPSJ9.kZ7ab16YLhDioc9BE0Xha9QgELXbU2GBze2x7XXALXw", sessionToken); + } + + @Test + public void testGetSessionTokenFailed() { + onRequest() + .havingMethodEqualTo("POST") + .havingPathEqualTo("/authenticate") + .respond() + .withStatus(200) + .withBody("{\"requestId\": \"auth\", \"status\": \"FAILED\", \"message\": \"Error authenticating user\"}"); + + GaraSignCredentials credentials = new GaraSignCredentials("ebourg", "123456", null, null); + try { + credentials.getSessionToken("http://localhost:" + port()); + fail("Exception not thrown"); + } catch (IOException e) { + assertEquals("message", "Failed to authenticate with GaraSign: Error authenticating user", e.getMessage()); + } + } +} diff --git a/jsign-core/src/test/java/net/jsign/jca/GaraSignSigningServiceTest.java b/jsign-core/src/test/java/net/jsign/jca/GaraSignSigningServiceTest.java new file mode 100644 index 00000000..d7baa4ca --- /dev/null +++ b/jsign-core/src/test/java/net/jsign/jca/GaraSignSigningServiceTest.java @@ -0,0 +1,402 @@ +/** + * Copyright 2024 Emmanuel Bourg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.jsign.jca; + +import java.io.FileReader; +import java.security.GeneralSecurityException; +import java.security.KeyStoreException; +import java.security.UnrecoverableKeyException; +import java.security.cert.Certificate; +import java.security.cert.X509Certificate; +import java.util.Arrays; +import java.util.List; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import static net.jadler.Jadler.*; +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.*; + +public class GaraSignSigningServiceTest { + + @Before + public void setUp() { + initJadler().withDefaultResponseStatus(404); + } + + @After + public void tearDown() { + closeJadler(); + } + + @Test + public void testGetAliases() throws Exception { + onRequest() + .havingMethodEqualTo("POST") + .havingPathEqualTo("/authenticate") + .respond() + .withStatus(200) + .withBody(new FileReader("target/test-classes/services/garasign-authenticate.json")); + onRequest() + .havingMethodEqualTo("POST") + .havingPathEqualTo("/keystore") + .havingParameterEqualTo("api_version", "1.0") + .havingParameter("session_token") + .respond() + .withStatus(200) + .withBody(new FileReader("target/test-classes/services/garasign-keystore.json")); + + SigningService service = new GaraSignSigningService("http://localhost:" + port(), new GaraSignCredentials("username", "password", null)); + List aliases = service.aliases(); + + assertEquals("aliases", Arrays.asList("java_keystore_rsa_key", "java_keystore_ecdsa_key"), aliases); + } + + @Test + public void testGetCertificateChain() throws Exception { + onRequest() + .havingMethodEqualTo("POST") + .havingPathEqualTo("/authenticate") + .respond() + .withStatus(200) + .withBody(new FileReader("target/test-classes/services/garasign-authenticate.json")); + onRequest() + .havingMethodEqualTo("POST") + .havingPathEqualTo("/keystore") + .havingParameterEqualTo("api_version", "1.0") + .havingParameter("session_token") + .respond() + .withStatus(200) + .withBody(new FileReader("target/test-classes/services/garasign-keystore.json")); + + SigningService service = new GaraSignSigningService("http://localhost:" + port(), new GaraSignCredentials("username", "password", null)); + Certificate[] chain = service.getCertificateChain("java_keystore_rsa_key"); + assertNotNull("null chain", chain); + assertEquals("length", 3, chain.length); + assertEquals("subject 1", "CN=rsa_code_signer, OU=test, O=Garantir, L=San Diego, ST=CA, C=US", ((X509Certificate) chain[0]).getSubjectDN().getName()); + assertEquals("subject 2", "CN=intermediary_rsa_ca, OU=test, O=Garantir, L=San Diego, ST=CA, C=US", ((X509Certificate) chain[1]).getSubjectDN().getName()); + assertEquals("subject 3", "CN=root_rsa_ca, OU=test, O=Garantir, L=San Diego, ST=CA, C=US", ((X509Certificate) chain[2]).getSubjectDN().getName()); + } + + @Test + public void testGetCertificateChainWithInvalidAlias() throws Exception { + onRequest() + .havingMethodEqualTo("POST") + .havingPathEqualTo("/authenticate") + .respond() + .withStatus(200) + .withBody(new FileReader("target/test-classes/services/garasign-authenticate.json")); + onRequest() + .havingMethodEqualTo("POST") + .havingPathEqualTo("/keystore") + .havingParameter("session_token") + .respond() + .withStatus(200) + .withBody(new FileReader("target/test-classes/services/garasign-keystore.json")); + + SigningService service = new GaraSignSigningService("http://localhost:" + port(), new GaraSignCredentials("username", "password", null)); + + try { + service.getCertificateChain("jsign"); + fail("Exception not thrown"); + } catch (KeyStoreException e) { + assertEquals("message", "Unable to retrieve GaraSign certificate 'jsign'", e.getMessage()); + } + } + + @Test + public void testGetCertificateChainWithError() throws Exception { + onRequest() + .havingMethodEqualTo("POST") + .havingPathEqualTo("/authenticate") + .respond() + .withStatus(200) + .withBody(new FileReader("target/test-classes/services/garasign-authenticate.json")); + onRequest() + .havingMethodEqualTo("POST") + .havingPathEqualTo("/keystore") + .respond() + .withStatus(200) + .withBody("{\"requestId\": \"keystore_request\", \"status\": \"FAILURE\", \"message\": \"Keystore not found\", \"sessionToken\": null}"); + + SigningService service = new GaraSignSigningService("http://localhost:" + port(), new GaraSignCredentials("username", "password", null)); + try { + service.getCertificateChain("java_keystore_rsa_key"); + fail("Exception not thrown"); + } catch (KeyStoreException e) { + assertEquals("message", "Unable to retrieve the GaraSign keystore: Keystore not found", e.getMessage()); + } + } + + @Test + public void testGetCertificateChainWithHTTPError() throws Exception { + onRequest() + .havingMethodEqualTo("POST") + .havingPathEqualTo("/authenticate") + .respond() + .withStatus(200) + .withBody(new FileReader("target/test-classes/services/garasign-authenticate.json")); + onRequest() + .havingMethodEqualTo("POST") + .havingPathEqualTo("/keystore") + .respond() + .withStatus(502) + .withBody("Bad Gateway"); + + SigningService service = new GaraSignSigningService("http://localhost:" + port(), new GaraSignCredentials("username", "password", null)); + try { + service.getCertificateChain("java_keystore_rsa_key"); + fail("Exception not thrown"); + } catch (KeyStoreException e) { + assertEquals("message", "Unable to retrieve the GaraSign keystore", e.getMessage()); + } + } + + @Test + public void testGetPrivateKey() throws Exception { + onRequest() + .havingMethodEqualTo("POST") + .havingPathEqualTo("/authenticate") + .respond() + .withStatus(200) + .withBody(new FileReader("target/test-classes/services/garasign-authenticate.json")); + onRequest() + .havingMethodEqualTo("POST") + .havingPathEqualTo("/keystore") + .respond() + .withStatus(200) + .withBody(new FileReader("target/test-classes/services/garasign-keystore.json")); + + SigningService service = new GaraSignSigningService("http://localhost:" + port(), new GaraSignCredentials("username", "password", null)); + + SigningServicePrivateKey key = service.getPrivateKey("java_keystore_rsa_key", null); + assertNotNull("null key", key); + assertEquals("id", "java_keystore_rsa_key", key.getId()); + assertEquals("algorithm", "RSA", key.getAlgorithm()); + } + + @Test + public void testGetPrivateKeyWithInvalidAlias() throws Exception { + onRequest() + .havingMethodEqualTo("POST") + .havingPathEqualTo("/authenticate") + .respond() + .withStatus(200) + .withBody(new FileReader("target/test-classes/services/garasign-authenticate.json")); + onRequest() + .havingMethodEqualTo("POST") + .havingPathEqualTo("/keystore") + .respond() + .withStatus(200) + .withBody(new FileReader("target/test-classes/services/garasign-keystore.json")); + + SigningService service = new GaraSignSigningService("http://localhost:" + port(), new GaraSignCredentials("username", "password", null)); + + try { + service.getPrivateKey("jsign", null); + fail("Exception not thrown"); + } catch (UnrecoverableKeyException e) { + assertEquals("message", "Unable to fetch GaraSign private key for the certificate 'jsign'", e.getMessage()); + } + } + + @Test + public void testSignWithPolling() throws Exception { + onRequest() + .havingMethodEqualTo("POST") + .havingPathEqualTo("/authenticate") + .respond() + .withStatus(200) + .withBody(new FileReader("target/test-classes/services/garasign-authenticate.json")); + onRequest() + .havingMethodEqualTo("POST") + .havingPathEqualTo("/keystore") + .respond() + .withStatus(200) + .withBody(new FileReader("target/test-classes/services/garasign-keystore.json")); + onRequest() + .havingMethodEqualTo("POST") + .havingPathEqualTo("/sign") + .havingParameterEqualTo("api_version", "1.0") + .havingParameter("session_token") + .havingParameter("data_to_sign") + .havingParameterEqualTo("key_name", "java_keystore_rsa_key") + .havingParameterEqualTo("signature_scheme", "SHA256withRSA") + .havingParameter("request_id", nullValue()) + .respond() + .withStatus(200) + .withBody("{\"requestId\": \"60\", \"status\": \"IN_PROGRESS\", \"message\": \"Pending approvals\"}"); + onRequest() + .havingMethodEqualTo("POST") + .havingPathEqualTo("/sign") + .havingParameterEqualTo("api_version", "1.0") + .havingParameter("session_token") + .havingParameter("data_to_sign", nullValue()) + .havingParameter("key_name", nullValue()) + .havingParameter("signature_scheme", nullValue()) + .havingParameterEqualTo("request_id", "60") + .respond() + .withStatus(200) + .withBody("{\"requestId\": \"60\", \"status\": \"IN_PROGRESS\", \"message\": \"Pending approvals\"}") + .thenRespond() + .withStatus(200) + .withBody("{\"requestId\": \"60\", \"status\": \"IN_PROGRESS\", \"message\": \"Pending approvals\"}") + .thenRespond() + .withStatus(200) + .withBody(new FileReader("target/test-classes/services/garasign-sign.json")); + + SigningService service = new GaraSignSigningService("http://localhost:" + port(), new GaraSignCredentials("username", "password", null)); + SigningServicePrivateKey privateKey = service.getPrivateKey("java_keystore_rsa_key", null); + + byte[] signature = service.sign(privateKey, "SHA256withRSA", "Hello".getBytes()); + + assertNotNull("null signature", signature); + assertEquals("length", 256, signature.length); + } + + @Test + public void testSignWithoutPolling() throws Exception { + onRequest() + .havingMethodEqualTo("POST") + .havingPathEqualTo("/authenticate") + .respond() + .withStatus(200) + .withBody(new FileReader("target/test-classes/services/garasign-authenticate.json")); + onRequest() + .havingMethodEqualTo("POST") + .havingPathEqualTo("/keystore") + .respond() + .withStatus(200) + .withBody(new FileReader("target/test-classes/services/garasign-keystore.json")); + onRequest() + .havingMethodEqualTo("POST") + .havingPathEqualTo("/sign") + .respond() + .withStatus(200) + .withBody(new FileReader("target/test-classes/services/garasign-sign.json")) + .thenRespond() + .withStatus(200) + .withBody("{\"requestId\": \"60\", \"status\": \"FAILED\", \"message\": \"Data to sign is missing\"}"); + + SigningService service = new GaraSignSigningService("http://localhost:" + port(), new GaraSignCredentials("username", "password", null)); + SigningServicePrivateKey privateKey = service.getPrivateKey("java_keystore_rsa_key", null); + + byte[] signature = service.sign(privateKey, "SHA256withRSA", "Hello".getBytes()); + + assertNotNull("null signature", signature); + assertEquals("length", 256, signature.length); + } + + @Test + public void testSignWithTimeout() throws Exception { + onRequest() + .havingMethodEqualTo("POST") + .havingPathEqualTo("/authenticate") + .respond() + .withStatus(200) + .withBody(new FileReader("target/test-classes/services/garasign-authenticate.json")); + onRequest() + .havingMethodEqualTo("POST") + .havingPathEqualTo("/keystore") + .respond() + .withStatus(200) + .withBody(new FileReader("target/test-classes/services/garasign-keystore.json")); + onRequest() + .havingMethodEqualTo("POST") + .havingPathEqualTo("/sign") + .respond() + .withStatus(200) + .withBody("{\"requestId\": \"60\", \"status\": \"IN_PROGRESS\", \"message\": \"Pending approvals\"}"); + + GaraSignSigningService service = new GaraSignSigningService("http://localhost:" + port(), new GaraSignCredentials("username", "password", null)); + service.setTimeout(5); + SigningServicePrivateKey privateKey = service.getPrivateKey("java_keystore_rsa_key", null); + try { + service.sign(privateKey, "SHA256withRSA", "Hello".getBytes()); + fail("Exception not thrown"); + } catch (GeneralSecurityException e) { + assertEquals("message", "java.io.IOException: Signing operation 60 timed out", e.getMessage()); + } + } + + @Test + public void testSignWithFailure() throws Exception { + onRequest() + .havingMethodEqualTo("POST") + .havingPathEqualTo("/authenticate") + .respond() + .withStatus(200) + .withBody(new FileReader("target/test-classes/services/garasign-authenticate.json")); + onRequest() + .havingMethodEqualTo("POST") + .havingPathEqualTo("/keystore") + .respond() + .withStatus(200) + .withBody(new FileReader("target/test-classes/services/garasign-keystore.json")); + onRequest() + .havingMethodEqualTo("POST") + .havingPathEqualTo("/sign") + .respond() + .withStatus(200) + .withBody("{\"requestId\": \"60\", \"status\": \"FAILURE\", \"message\": \"Internal server error\"}"); + + SigningService service = new GaraSignSigningService("http://localhost:" + port(), new GaraSignCredentials("username", "password", null)); + SigningServicePrivateKey privateKey = service.getPrivateKey("java_keystore_rsa_key", null); + try { + service.sign(privateKey, "SHA256withRSA", "Hello".getBytes()); + fail("Exception not thrown"); + } catch (GeneralSecurityException e) { + assertEquals("message", "java.io.IOException: Signing operation failed: Internal server error", e.getMessage()); + } + } + + @Test + public void testSignWithPollingFailure() throws Exception { + onRequest() + .havingMethodEqualTo("POST") + .havingPathEqualTo("/authenticate") + .respond() + .withStatus(200) + .withBody(new FileReader("target/test-classes/services/garasign-authenticate.json")); + onRequest() + .havingMethodEqualTo("POST") + .havingPathEqualTo("/keystore") + .respond() + .withStatus(200) + .withBody(new FileReader("target/test-classes/services/garasign-keystore.json")); + onRequest() + .havingMethodEqualTo("POST") + .havingPathEqualTo("/sign") + .respond() + .withStatus(200) + .withBody("{\"requestId\": \"60\", \"status\": \"IN_PROGRESS\", \"message\": \"Pending approvals\"}") + .thenRespond() + .withStatus(200) + .withBody("{\"requestId\": \"60\", \"status\": \"FAILURE\", \"message\": \"Internal server error\"}"); + + SigningService service = new GaraSignSigningService("http://localhost:" + port(), new GaraSignCredentials("username", "password", null)); + SigningServicePrivateKey privateKey = service.getPrivateKey("java_keystore_rsa_key", null); + try { + service.sign(privateKey, "SHA256withRSA", "Hello".getBytes()); + fail("Exception not thrown"); + } catch (GeneralSecurityException e) { + assertEquals("message", "java.io.IOException: Signing operation 60 failed: Internal server error", e.getMessage()); + } + } +} diff --git a/jsign-core/src/test/java/net/jsign/jca/SigningServiceTest.java b/jsign-core/src/test/java/net/jsign/jca/SigningServiceTest.java index cdc407ab..8e61c6cc 100644 --- a/jsign-core/src/test/java/net/jsign/jca/SigningServiceTest.java +++ b/jsign-core/src/test/java/net/jsign/jca/SigningServiceTest.java @@ -35,6 +35,7 @@ import net.jsign.pe.PEFile; import static net.jsign.DigestAlgorithm.*; +import static org.junit.Assert.*; public class SigningServiceTest { @@ -210,4 +211,19 @@ public void testTrustedSigningProvider() throws Exception { testCustomProvider(provider, keystore, "MyAccount/MyProfile", ""); } + + @Test + public void testGaraSignProvider() throws Exception { + GaraSignCredentials credentials = new GaraSignCredentials("demo_user", "password", "src/test/resources/keystores/keystore.p12", "password"); + Provider provider = new SigningServiceJcaProvider(new GaraSignSigningService(null, credentials)); + KeyStore keystore = KeyStore.getInstance("GARASIGN", provider); + keystore.load(null, "".toCharArray()); + + try { + testCustomProvider(provider, keystore, "windows_codesign", ""); + fail("Exception not thrown"); + } catch (Exception e) { + assertEquals("message", "Failed to authenticate with GaraSign: Error authenticating user", e.getCause().getMessage()); + } + } } diff --git a/jsign-core/src/test/resources/services/garasign-authenticate.json b/jsign-core/src/test/resources/services/garasign-authenticate.json new file mode 100644 index 00000000..0adbfc4a --- /dev/null +++ b/jsign-core/src/test/resources/services/garasign-authenticate.json @@ -0,0 +1,5 @@ +{ + "sessionToken": "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJrdG11c2VyIiwibmJmIjoxNTIyMjgzNzU1LCJleHAiOjE1MjIzNzAxNTUsImVuY3J5cHRlZF9jbGFpbXMiOiJyV1Q1TlljWi83TFV1eTB3YlFnbDR5K08zbXJtS3RrOGFtdjFVSnpOYy8vM0JvaVkrai9RS0lYYTdJSGRicWIxUTVCaWNIQ2VMYWJRQjhzMWQ3ZjJBZDNKeVR6dlliS1gzVGloUThmY3RyZWRyQ21sTFZ2dDZMRFlrZ2IxbURibWVuQ1Z2VFNKbnlXWEplRzRPMGJUUXQwN1RqTHVRdGhPendQR0xXSGFhT0U1cWNSZUUzVjMzb0U0RzJ1R2duR25tSFJNZVFzUTgxQXU3bGp1c2FDR1J6enpwaTFhZmxBdHRCcjNsbThWYmdrV0VWQ3ZDNndjTlNHZXA3YzJnNG0yQzI2MzhzMml2K2hLOTFzPSJ9.kZ7ab16YLhDioc9BE0Xha9QgELXbU2GBze2x7XXALXw", + "requestId": "auth", + "status": "SUCCESS" +} diff --git a/jsign-core/src/test/resources/services/garasign-keystore.json b/jsign-core/src/test/resources/services/garasign-keystore.json new file mode 100644 index 00000000..285c2076 --- /dev/null +++ b/jsign-core/src/test/resources/services/garasign-keystore.json @@ -0,0 +1,24 @@ +{ + "keys": [ + { + "name": "java_keystore_rsa_key", + "algorithm": "RSA", + "certChain": [ + [48,-126,3,122,48,-126,2,98,-96,3,2,1,2,2,4,90,116,-44,123,48,13,6,9,42,-122,72,-122,-9,13,1,1,11,5,0,48,110,49,11,48,9,6,3,85,4,6,19,2,85,83,49,11,48,9,6,3,85,4,8,12,2,67,65,49,18,48,16,6,3,85,4,7,12,9,83,97,110,32,68,105,101,103,111,49,17,48,15,6,3,85,4,10,12,8,71,97,114,97,110,116,105,114,49,13,48,11,6,3,85,4,11,12,4,116,101,115,116,49,28,48,26,6,3,85,4,3,12,19,105,110,116,101,114,109,101,100,105,97,114,121,95,114,115,97,95,99,97,48,30,23,13,49,56,48,50,48,50,50,49,49,52,52,48,90,23,13,50,56,48,50,48,50,50,49,49,52,52,48,90,48,106,49,11,48,9,6,3,85,4,6,19,2,85,83,49,11,48,9,6,3,85,4,8,12,2,67,65,49,18,48,16,6,3,85,4,7,12,9,83,97,110,32,68,105,101,103,111,49,17,48,15,6,3,85,4,10,12,8,71,97,114,97,110,116,105,114,49,13,48,11,6,3,85,4,11,12,4,116,101,115,116,49,24,48,22,6,3,85,4,3,12,15,114,115,97,95,99,111,100,101,95,115,105,103,110,101,114,48,-126,1,34,48,13,6,9,42,-122,72,-122,-9,13,1,1,1,5,0,3,-126,1,15,0,48,-126,1,10,2,-126,1,1,0,-19,-120,54,109,121,90,-92,6,46,-83,10,-67,-15,57,-17,18,-17,-29,-48,53,39,31,-47,-29,-26,30,-64,33,21,127,-25,77,-25,-18,72,-79,-103,-105,-73,67,57,-98,-94,-108,94,108,66,87,-17,-60,-24,42,114,-91,55,-8,-28,14,57,53,100,97,120,7,104,86,-50,-107,-51,-75,77,-16,-36,-123,-88,122,-71,70,4,110,63,-121,105,-70,29,-8,13,-123,-77,54,36,-9,-2,-44,10,-83,-48,92,-118,39,24,32,-8,10,80,90,73,107,-11,23,-63,81,-23,84,-102,23,-126,28,75,117,-39,64,83,37,97,-73,94,-40,-123,-94,122,-81,-81,-100,104,-69,22,6,13,-30,34,22,61,96,-3,16,-82,-17,79,-92,-39,-104,-107,56,-93,-19,-94,-87,49,32,113,100,30,119,91,-116,107,-67,-104,79,-84,-121,-119,33,-17,-104,10,-61,-101,-54,79,-81,-20,28,-12,-116,83,41,-98,-66,-100,57,-32,118,-122,-25,47,108,-58,-82,82,99,-62,24,-33,58,95,-56,-5,-74,-72,-58,-72,-80,2,-110,-5,-38,-30,-95,72,35,-54,-98,-95,-43,125,61,-40,33,126,85,-29,-51,88,-60,-21,110,-40,3,-96,-125,-111,1,26,84,-76,-56,125,21,46,-72,-19,97,24,105,2,3,1,0,1,-93,36,48,34,48,11,6,3,85,29,15,4,4,3,2,6,64,48,19,6,3,85,29,37,4,12,48,10,6,8,43,6,1,5,5,7,3,3,48,13,6,9,42,-122,72,-122,-9,13,1,1,11,5,0,3,-126,1,1,0,76,-105,-58,-39,-8,16,-116,61,-106,11,-102,-73,-64,-22,118,-80,-92,-82,-77,-96,93,30,-59,-50,-96,-69,-7,55,-46,45,-42,-86,9,120,-6,-76,43,84,-123,-17,-81,-123,-30,108,-107,0,41,37,-25,68,-33,50,86,-120,12,87,106,-8,-60,-51,-41,11,10,-25,-60,61,100,-6,-6,25,55,-37,112,57,34,-71,46,-63,-29,-76,58,-80,-43,68,59,35,116,100,-76,-71,-28,-31,-64,-78,-16,100,-99,-13,6,113,-60,-110,-93,-64,83,42,-12,-72,-127,74,-13,53,-9,117,-42,10,69,69,95,20,-48,12,61,126,114,-20,-117,108,43,-2,28,-124,52,33,-49,-79,-31,-118,-24,-70,-87,-82,65,-56,-84,44,-108,-54,41,90,-94,88,-78,-24,127,-11,113,-125,52,80,19,-104,103,-16,45,29,13,-29,-25,-121,-32,75,89,37,-105,20,-79,36,-55,60,83,-11,-83,-4,54,-13,118,-119,37,60,-83,-33,-4,18,-99,-90,-114,27,81,89,35,77,-54,17,122,-105,112,-27,-62,113,39,97,-26,-127,94,-125,-97,-12,6,-128,109,-80,-98,-80,21,36,-58,23,-5,-79,93,109,103,-117,126,71,-42,61,-84,-126,-111,-127,65,12,-41,-124,-44,-12,10,67,29,83,94,64,24,-43], + [48,-126,4,114,48,-126,2,90,-96,3,2,1,2,2,4,90,116,-44,14,48,13,6,9,42,-122,72,-122,-9,13,1,1,11,5,0,48,102,49,11,48,9,6,3,85,4,6,19,2,85,83,49,11,48,9,6,3,85,4,8,12,2,67,65,49,18,48,16,6,3,85,4,7,12,9,83,97,110,32,68,105,101,103,111,49,17,48,15,6,3,85,4,10,12,8,71,97,114,97,110,116,105,114,49,13,48,11,6,3,85,4,11,12,4,116,101,115,116,49,20,48,18,6,3,85,4,3,12,11,114,111,111,116,95,114,115,97,95,99,97,48,30,23,13,49,56,48,50,48,50,50,49,49,50,51,57,90,23,13,51,48,48,50,48,50,50,49,49,50,51,57,90,48,110,49,11,48,9,6,3,85,4,6,19,2,85,83,49,11,48,9,6,3,85,4,8,12,2,67,65,49,18,48,16,6,3,85,4,7,12,9,83,97,110,32,68,105,101,103,111,49,17,48,15,6,3,85,4,10,12,8,71,97,114,97,110,116,105,114,49,13,48,11,6,3,85,4,11,12,4,116,101,115,116,49,28,48,26,6,3,85,4,3,12,19,105,110,116,101,114,109,101,100,105,97,114,121,95,114,115,97,95,99,97,48,-126,1,34,48,13,6,9,42,-122,72,-122,-9,13,1,1,1,5,0,3,-126,1,15,0,48,-126,1,10,2,-126,1,1,0,-75,-97,-11,-55,15,67,-66,80,4,-77,27,90,66,-6,-42,52,4,-128,-62,88,75,-90,90,-92,11,-82,104,-74,-10,88,115,110,-127,59,-8,-116,12,62,-52,119,56,-10,-77,-112,-40,96,-92,19,122,62,60,-87,-19,82,40,13,108,-59,127,-12,55,-57,11,88,-88,82,66,58,-22,63,25,105,55,11,-90,-76,107,21,87,-81,-87,-20,-119,45,-8,-27,72,-23,-74,101,-58,126,20,-124,53,-108,-58,-112,53,34,-28,52,-71,-5,18,40,-101,113,-89,-63,-50,44,-61,70,-44,-5,-73,-70,-34,-122,25,32,93,-52,-120,63,108,102,61,-16,-19,-82,111,110,94,-57,53,-103,100,108,116,35,-125,-116,-124,-105,-78,-91,-49,41,29,39,-102,-76,-107,-110,14,-3,97,-74,-98,39,105,97,5,-120,-108,57,78,60,-102,10,-79,110,11,-124,-126,-12,-13,80,-125,27,36,-36,-121,99,31,-64,122,71,-87,-124,-41,119,-27,-40,89,-50,68,-41,67,-63,-5,73,-113,122,-9,-75,-78,-57,119,62,-109,87,-22,106,-81,-31,120,-120,-86,-38,-128,85,120,-28,8,-90,26,88,-19,118,92,-104,45,-27,-84,116,-26,-75,9,-23,33,24,-62,36,-11,67,-43,-86,-1,-4,58,3,-98,-101,2,3,1,0,1,-93,32,48,30,48,15,6,3,85,29,19,4,8,48,6,1,1,-1,2,1,0,48,11,6,3,85,29,15,4,4,3,2,1,70,48,13,6,9,42,-122,72,-122,-9,13,1,1,11,5,0,3,-126,2,1,0,-127,44,-123,17,-65,29,91,-6,-37,107,72,109,103,40,16,3,-42,-31,51,-6,103,-11,-102,-81,33,32,30,-117,59,18,116,57,-59,-13,-123,50,80,125,64,98,-18,114,-28,-78,-98,-41,109,-106,14,-117,-92,94,17,-97,120,-115,5,66,98,75,-126,-59,-88,61,104,103,-119,-28,125,45,85,8,-26,42,-107,-25,-23,41,110,-18,1,-85,-7,-89,-96,19,-105,98,103,-58,-21,-116,-120,-8,-43,-4,29,92,112,75,32,-97,-94,107,-20,-67,46,-127,10,17,125,36,-96,-88,-27,19,53,112,-51,-9,90,-62,31,-66,47,77,-102,54,-64,-99,85,114,-39,4,120,-54,-92,3,-17,89,-19,109,-49,-40,117,-54,43,33,11,22,124,-21,-77,-51,-19,-98,58,2,-36,68,31,-123,-83,49,122,73,-35,-97,-108,-80,28,-88,-67,-47,32,-75,9,100,-108,-100,71,36,-80,-32,16,72,-20,96,-58,23,-68,127,-55,-126,107,-55,-126,-77,62,127,45,67,54,75,-103,-46,-34,14,49,-67,-30,-1,-75,81,71,-31,57,-87,-19,-98,-81,-127,119,98,118,57,-121,45,-1,56,-12,-20,-43,-26,75,-19,119,-75,-45,4,-41,-28,115,-47,-58,2,13,41,-103,-48,-59,-65,42,-47,-26,14,-46,-111,-72,-27,-108,-26,-57,-128,-54,109,127,39,86,105,93,46,-6,-9,72,-69,-44,6,70,13,-49,-112,47,127,125,-110,-110,-41,99,-59,63,-121,-85,-25,-4,44,-124,63,-123,-64,-15,-6,116,-96,-126,-102,-8,-73,-59,-105,89,94,-54,9,-71,-114,-38,-97,38,6,-72,67,42,119,66,-103,91,76,-55,84,-98,-6,124,113,-34,-6,-119,68,9,75,80,48,117,-74,-117,77,18,92,-46,-91,-19,99,48,-43,70,34,-72,100,-73,52,80,32,84,-59,-76,-32,-11,-41,103,54,8,-119,-122,117,82,-90,107,35,70,49,37,32,68,-34,-49,51,109,31,-24,-93,31,88,36,86,38,34,34,51,-100,12,3,87,22,47,76,-67,-29,108,-116,68,64,-37,-10,-84,-90,88,22,-77,-99,-111,6,123,16,-11,78,-64,-87,-124,60,44,-26,102,97,-121,127,-72,70,-98,-99,-114,-111,25,-65,-91,87,-116,-49,-57,-120,9,-61,7,-11,32,-55,-52,84,54,42,0,-108,83,97,-50,11,28,-81,-23,16,-127,98,63,74,-37,122,-69,38,95,-66,-28,9,-13,-42,78,-109,-67,-36,-2,-89,-21,105,35,-1,91,72,1,-68,70,61,77,-24,-127,65,125,-10,-23,48,-110,46,-4,-17,-67], + [48,-126,5,106,48,-126,3,82,-96,3,2,1,2,2,4,90,116,-45,-124,48,13,6,9,42,-122,72,-122,-9,13,1,1,11,5,0,48,102,49,11,48,9,6,3,85,4,6,19,2,85,83,49,11,48,9,6,3,85,4,8,12,2,67,65,49,18,48,16,6,3,85,4,7,12,9,83,97,110,32,68,105,101,103,111,49,17,48,15,6,3,85,4,10,12,8,71,97,114,97,110,116,105,114,49,13,48,11,6,3,85,4,11,12,4,116,101,115,116,49,20,48,18,6,3,85,4,3,12,11,114,111,111,116,95,114,115,97,95,99,97,48,30,23,13,49,56,48,50,48,50,50,49,49,48,53,56,90,23,13,51,51,48,50,48,50,50,49,49,48,53,56,90,48,102,49,11,48,9,6,3,85,4,6,19,2,85,83,49,11,48,9,6,3,85,4,8,12,2,67,65,49,18,48,16,6,3,85,4,7,12,9,83,97,110,32,68,105,101,103,111,49,17,48,15,6,3,85,4,10,12,8,71,97,114,97,110,116,105,114,49,13,48,11,6,3,85,4,11,12,4,116,101,115,116,49,20,48,18,6,3,85,4,3,12,11,114,111,111,116,95,114,115,97,95,99,97,48,-126,2,34,48,13,6,9,42,-122,72,-122,-9,13,1,1,1,5,0,3,-126,2,15,0,48,-126,2,10,2,-126,2,1,0,-32,-47,55,118,87,70,113,108,-96,-81,-41,-125,-67,-123,-110,84,-11,-3,16,116,31,-16,-106,85,-124,115,-106,87,-53,-101,-11,15,82,-95,-99,100,77,-94,-83,-38,-55,-72,-50,27,50,-14,-49,-42,-128,-45,79,-25,-44,86,-43,-120,-34,-95,4,88,-31,-82,90,37,66,-73,-43,22,-61,-121,42,81,41,30,-47,37,-86,43,-93,-88,-117,46,29,-90,74,19,-28,-91,4,-31,94,-76,12,-1,-111,71,125,21,1,-106,-126,71,-84,25,-112,-70,-4,21,34,-25,24,119,-23,-98,73,-122,51,65,106,-110,48,49,-125,-101,-111,76,-119,-40,47,96,-78,27,-88,-17,-90,-95,47,-106,70,-41,-117,-55,-91,-35,124,-68,-113,-23,-83,5,95,-92,-4,29,-108,-103,-67,-104,-7,63,9,16,28,-101,120,61,60,91,113,117,83,-27,-64,-70,116,94,94,73,112,61,127,76,-56,-70,100,49,18,126,2,-4,66,-124,72,-127,64,74,-32,1,21,118,79,54,64,48,-1,-23,-76,-100,-3,74,91,97,14,-14,85,73,89,-72,101,51,-1,9,29,5,-26,120,-107,113,87,3,106,123,-121,60,-13,86,-95,84,-89,41,2,-40,90,122,-56,17,31,118,-78,-75,126,24,98,88,-122,-128,-50,50,-49,54,-64,-27,15,6,-104,-111,88,8,-66,-3,-33,-105,-69,-17,69,-33,119,26,-42,25,100,-6,32,18,-83,63,115,13,-68,124,91,-77,-13,98,32,-34,24,104,123,-64,-13,0,44,83,-127,15,53,88,-64,53,-124,20,10,84,-6,-28,-126,76,43,-112,117,-57,-77,-94,75,-68,-109,-54,-56,93,29,15,-102,-17,-50,-46,-74,113,-88,-60,-49,-67,-99,-28,-78,117,78,37,-51,26,-13,123,73,112,-82,-126,66,-19,-14,-89,-22,32,18,127,-20,5,112,43,94,112,75,-84,72,0,30,11,-6,-3,23,88,-51,-76,-24,101,101,-124,-16,-13,116,-46,93,21,-40,89,-53,-88,-45,58,85,-88,-31,-40,-49,119,52,-3,10,-126,-51,37,72,76,50,48,-55,-61,91,-111,-8,-63,62,-96,126,-77,89,-8,-72,-119,56,42,44,16,-11,99,-113,-64,-3,-2,81,-109,13,99,-31,67,-23,71,31,62,-112,81,102,72,51,-15,47,17,-80,-31,-57,-95,-20,95,29,-63,108,-127,-74,5,51,78,-5,-112,82,6,-87,-98,-127,65,-34,-14,-21,51,20,107,116,-127,-5,29,15,124,100,-61,-116,-81,-72,-28,-35,88,64,112,87,82,-113,-8,36,31,-43,91,-125,-62,-88,103,2,3,1,0,1,-93,32,48,30,48,15,6,3,85,29,19,4,8,48,6,1,1,-1,2,1,1,48,11,6,3,85,29,15,4,4,3,2,1,70,48,13,6,9,42,-122,72,-122,-9,13,1,1,11,5,0,3,-126,2,1,0,77,81,109,-109,93,65,-125,49,-78,115,123,64,-37,10,47,28,55,120,115,94,47,76,5,-54,9,-17,127,115,32,-21,78,-23,58,-83,123,124,99,-35,-110,67,107,-12,-104,-73,-102,86,10,-60,-79,74,-39,21,-127,-100,-58,-118,-62,-7,-108,6,53,-55,-34,53,-117,114,18,70,25,-80,66,-30,-5,0,96,5,-39,-6,21,-25,105,-51,-101,-30,-105,70,56,-13,-43,-69,57,93,7,-62,71,-108,-89,11,37,-84,9,92,37,-76,20,38,15,-61,83,23,65,25,81,98,110,8,78,-16,27,-75,53,47,96,70,-112,-90,90,-60,-27,17,97,73,120,50,74,63,21,-20,-83,-127,85,-11,-26,47,-59,-96,-47,8,107,-38,8,70,-122,-23,-55,-86,-61,-88,-71,-51,21,-59,103,-91,-83,103,48,100,74,69,-9,-107,15,23,34,-40,-97,-98,-116,110,81,-65,97,-59,-12,-60,-124,-100,-116,34,-18,-117,-127,-105,-27,94,122,24,4,92,-126,-49,-107,58,-99,-47,-29,108,-26,124,-110,-86,-123,-101,24,-81,47,6,-114,-56,19,49,8,-54,-118,-87,-17,-71,83,-10,-2,-71,48,-95,-25,43,28,-27,45,119,-28,-36,39,-45,68,-91,73,122,-95,-46,-6,-111,-127,41,79,-23,-38,-78,-10,86,-56,23,-4,-67,96,-74,-37,-89,120,49,-66,94,63,-58,66,-84,-45,66,39,105,92,-3,-27,107,-62,83,-94,-74,-4,-126,103,-41,55,-56,-112,122,98,-118,-40,-1,-3,40,88,-75,-123,-106,91,25,67,-10,-28,16,-82,-101,30,82,49,73,24,-78,-49,-79,-11,-125,120,-80,-43,44,-31,-51,83,-63,-33,93,-79,-117,46,26,-38,45,-75,34,-92,-90,48,88,-92,-64,-68,60,27,-9,-99,76,-7,-53,-29,-117,64,65,-46,-94,-38,-31,78,-85,121,-84,106,89,81,13,-49,-40,36,-17,27,2,78,115,-41,45,71,114,99,12,23,-55,60,52,32,-79,-65,19,80,48,-41,52,-35,64,-20,109,-72,118,123,4,-66,-80,-84,-90,22,-119,107,107,31,46,-1,108,105,-73,18,55,20,104,90,-128,66,-61,112,47,45,-34,74,40,6,-37,93,85,100,56,-125,-88,-85,-1,102,48,-75,-46,21,80,94,11,-67,-31,-15,40,-74,-30,116,-127,-100,27,-12,-64,95,-121,-68,51,98,0,73,-115,-110,56,-64,-5,117,41,50,91,59,-100,6,124,63,-33,-23,-64,7,25,-40,36,41,-32,20,-72,-48,-82,-107,118,1,-102,71,105,-98,13,107,38,-103,95,-46,82] + ] + }, + { + "name": "java_keystore_ecdsa_key", + "algorithm": "EC", + "certChain": [ + [48,-126,1,-20,48,-126,1,-110,-96,3,2,1,2,2,4,90,116,-35,-49,48,10,6,8,42,-122,72,-50,61,4,3,2,48,109,49,11,48,9,6,3,85,4,6,19,2,85,83,49,11,48,9,6,3,85,4,8,12,2,67,65,49,18,48,16,6,3,85,4,7,12,9,83,97,110,32,68,105,101,103,111,49,17,48,15,6,3,85,4,10,12,8,71,97,114,97,110,116,105,114,49,13,48,11,6,3,85,4,11,12,4,116,101,115,116,49,27,48,25,6,3,85,4,3,12,18,105,110,116,101,114,109,101,100,105,97,114,121,95,101,99,95,99,97,48,30,23,13,49,56,48,50,48,50,50,49,53,52,48,56,90,23,13,50,56,48,50,48,50,50,49,53,52,48,56,90,48,105,49,11,48,9,6,3,85,4,6,19,2,85,83,49,11,48,9,6,3,85,4,8,12,2,67,65,49,18,48,16,6,3,85,4,7,12,9,83,97,110,32,68,105,101,103,111,49,17,48,15,6,3,85,4,10,12,8,71,97,114,97,110,116,105,114,49,13,48,11,6,3,85,4,11,12,4,116,101,115,116,49,23,48,21,6,3,85,4,3,12,14,101,99,95,99,111,100,101,95,115,105,103,110,101,114,48,89,48,19,6,7,42,-122,72,-50,61,2,1,6,8,42,-122,72,-50,61,3,1,7,3,66,0,4,57,-43,11,-123,49,-102,-107,-69,29,-24,29,45,-82,29,100,72,-96,1,-11,-30,31,115,-116,32,-98,-103,65,41,55,43,105,54,-70,60,-1,75,-61,60,115,77,-92,-67,-120,34,1,-66,62,-61,-32,-33,-77,67,127,71,113,113,-54,6,71,-6,9,-111,52,-69,-93,36,48,34,48,19,6,3,85,29,37,4,12,48,10,6,8,43,6,1,5,5,7,3,3,48,11,6,3,85,29,15,4,4,3,2,6,64,48,10,6,8,42,-122,72,-50,61,4,3,2,3,72,0,48,69,2,32,32,-32,54,-120,46,-49,-60,-29,109,83,89,-43,89,58,-43,-93,-112,-123,19,51,38,31,3,-110,-91,-73,-73,4,-29,77,-26,7,2,33,0,-58,-72,11,4,57,25,9,-60,117,-42,1,-17,-17,33,-3,-126,20,41,43,47,117,55,-60,-109,22,-54,18,97,112,-72,70,-101], + [48,-126,1,-28,48,-126,1,-118,-96,3,2,1,2,2,4,90,116,-35,113,48,10,6,8,42,-122,72,-50,61,4,3,2,48,101,49,11,48,9,6,3,85,4,6,19,2,85,83,49,11,48,9,6,3,85,4,8,12,2,67,65,49,18,48,16,6,3,85,4,7,12,9,83,97,110,32,68,105,101,103,111,49,17,48,15,6,3,85,4,10,12,8,71,97,114,97,110,116,105,114,49,13,48,11,6,3,85,4,11,12,4,116,101,115,116,49,19,48,17,6,3,85,4,3,12,10,114,111,111,116,95,101,99,95,99,97,48,30,23,13,49,56,48,50,48,50,50,49,53,50,51,56,90,23,13,51,48,48,50,48,50,50,49,53,50,51,56,90,48,109,49,11,48,9,6,3,85,4,6,19,2,85,83,49,11,48,9,6,3,85,4,8,12,2,67,65,49,18,48,16,6,3,85,4,7,12,9,83,97,110,32,68,105,101,103,111,49,17,48,15,6,3,85,4,10,12,8,71,97,114,97,110,116,105,114,49,13,48,11,6,3,85,4,11,12,4,116,101,115,116,49,27,48,25,6,3,85,4,3,12,18,105,110,116,101,114,109,101,100,105,97,114,121,95,101,99,95,99,97,48,89,48,19,6,7,42,-122,72,-50,61,2,1,6,8,42,-122,72,-50,61,3,1,7,3,66,0,4,-110,-4,127,36,-39,-31,13,-126,-41,121,-72,-68,61,12,53,-55,65,-53,-9,-15,55,22,-99,43,43,55,121,-65,-121,115,-91,-111,-30,-74,-46,76,110,54,-41,110,-113,-47,78,-105,48,77,-74,96,-19,-94,2,-49,-121,117,-69,-6,-15,66,-39,10,-30,-127,78,98,-93,32,48,30,48,15,6,3,85,29,19,4,8,48,6,1,1,-1,2,1,0,48,11,6,3,85,29,15,4,4,3,2,1,70,48,10,6,8,42,-122,72,-50,61,4,3,2,3,72,0,48,69,2,32,65,-49,-110,-57,-75,-17,-85,114,-74,7,-12,-25,-7,47,-91,-55,-71,21,-89,76,14,108,59,-40,-108,21,8,127,36,35,-92,-115,2,33,0,-40,37,-38,-61,-125,27,-14,-124,67,121,-100,80,-58,-114,66,108,101,-121,-24,-61,-99,-75,14,93,6,-84,58,-86,-74,-97,-16,59], + [48,-126,1,-36,48,-126,1,-126,-96,3,2,1,2,2,4,90,116,-35,27,48,10,6,8,42,-122,72,-50,61,4,3,2,48,101,49,11,48,9,6,3,85,4,6,19,2,85,83,49,11,48,9,6,3,85,4,8,12,2,67,65,49,18,48,16,6,3,85,4,7,12,9,83,97,110,32,68,105,101,103,111,49,17,48,15,6,3,85,4,10,12,8,71,97,114,97,110,116,105,114,49,13,48,11,6,3,85,4,11,12,4,116,101,115,116,49,19,48,17,6,3,85,4,3,12,10,114,111,111,116,95,101,99,95,99,97,48,30,23,13,49,56,48,50,48,50,50,49,53,49,49,49,90,23,13,51,51,48,50,48,50,50,49,53,49,49,49,90,48,101,49,11,48,9,6,3,85,4,6,19,2,85,83,49,11,48,9,6,3,85,4,8,12,2,67,65,49,18,48,16,6,3,85,4,7,12,9,83,97,110,32,68,105,101,103,111,49,17,48,15,6,3,85,4,10,12,8,71,97,114,97,110,116,105,114,49,13,48,11,6,3,85,4,11,12,4,116,101,115,116,49,19,48,17,6,3,85,4,3,12,10,114,111,111,116,95,101,99,95,99,97,48,89,48,19,6,7,42,-122,72,-50,61,2,1,6,8,42,-122,72,-50,61,3,1,7,3,66,0,4,-41,-63,7,35,10,-56,104,-41,94,3,57,-110,-17,-26,-12,124,-93,15,40,110,-94,103,-29,-16,83,15,-68,97,-28,22,-31,97,99,4,44,87,-60,-4,107,83,65,-66,33,-35,-29,44,73,32,-107,81,63,97,118,40,-82,68,25,-22,-34,112,44,-101,11,44,-93,32,48,30,48,15,6,3,85,29,19,4,8,48,6,1,1,-1,2,1,1,48,11,6,3,85,29,15,4,4,3,2,1,70,48,10,6,8,42,-122,72,-50,61,4,3,2,3,72,0,48,69,2,32,68,31,-79,94,-54,-46,-42,-12,-90,47,-81,3,65,67,109,82,-61,-98,98,107,63,118,44,-101,35,15,-32,72,42,69,-65,88,2,33,0,-11,-85,-104,-66,55,-120,-16,-112,-14,-119,-100,4,61,95,90,3,-117,-32,87,28,13,-64,-39,10,65,-117,59,-118,-59,79,-59,5] + ] + } + ], + "requestId": "keystore_request", + "status": "SUCCESS" +} diff --git a/jsign-core/src/test/resources/services/garasign-sign.json b/jsign-core/src/test/resources/services/garasign-sign.json new file mode 100644 index 00000000..5feea206 --- /dev/null +++ b/jsign-core/src/test/resources/services/garasign-sign.json @@ -0,0 +1,5 @@ +{ + "signature": [-79,-39,14,0,18,-6,27,-19,23,-33,41,113,20,35,124,36,-42,-97,-80,30,-63,123,15,-73,-88,97,-98,35,42,-60,20,-14,-104,33,-25,107,-4,60,-84,-17,-45,-110,-4,-112,46,-21,119,69,93,-37,10,5,-91,125,3,42,-102,122,103,114,66,18,16,-104,-65,108,40,-44,52,58,69,122,4,-65,111,-31,10,51,118,-31,92,-26,13,-86,-53,-108,63,121,86,-13,-59,-32,114,60,3,-122,-25,29,-22,104,-4,74,-106,-37,92,-78,-113,-44,60,-63,1,15,-37,-84,-9,58,-100,46,-119,-61,54,28,-53,25,82,107,100,19,35,66,-118,-121,-55,22,61,102,32,-102,-93,15,-18,-27,12,-36,72,-21,66,-76,-92,-89,-18,74,-64,43,43,19,0,78,9,46,84,-25,-65,126,-100,98,73,49,-4,-29,-7,65,97,-90,-57,60,27,-71,7,-40,-34,-55,20,7,-7,-124,-119,-81,-47,-61,-9,110,-115,-72,88,-59,-106,-79,67,-36,-101,-110,53,12,-114,72,0,107,84,116,-112,-19,84,38,35,-93,-15,67,3,-64,119,-24,17,-3,-19,-26,-101,-52,5,88,-107,-30,-65,14,-97,-10,121,4,-113,11,10,34,92,-16,33,-102,-110,2,-54,-6,-73,-4,-53,-45,68,119], + "requestId": "61", + "status": "SUCCESS" +} diff --git a/jsign-maven-plugin/src/main/java/net/jsign/JsignMojo.java b/jsign-maven-plugin/src/main/java/net/jsign/JsignMojo.java index c66290ad..35792a25 100644 --- a/jsign-maven-plugin/src/main/java/net/jsign/JsignMojo.java +++ b/jsign-maven-plugin/src/main/java/net/jsign/JsignMojo.java @@ -90,7 +90,7 @@ public class JsignMojo extends AbstractMojo { /** * The type of the keystore (JKS, JCEKS, PKCS12, PKCS11, ETOKEN, NITROKEY, OPENPGP, OPENSC, PIV, YUBIKEY, AWS, - * AZUREKEYVAULT, DIGICERTONE, ESIGNER, GOOGLECLOUD, HASHICORPVAULT, ORACLECLOUD or TRUSTEDSIGNING). + * AZUREKEYVAULT, DIGICERTONE, ESIGNER, GARASIGN, GOOGLECLOUD, HASHICORPVAULT, ORACLECLOUD or TRUSTEDSIGNING). */ @Parameter( property = "jsign.storetype" ) private String storetype; diff --git a/jsign/src/deb/data/usr/share/bash-completion/completions/jsign b/jsign/src/deb/data/usr/share/bash-completion/completions/jsign index e158fa2b..8e567e08 100644 --- a/jsign/src/deb/data/usr/share/bash-completion/completions/jsign +++ b/jsign/src/deb/data/usr/share/bash-completion/completions/jsign @@ -22,7 +22,7 @@ _jsign() return 0 ;; --storetype) - COMPREPLY=( $( compgen -W 'JKS JCEKS PKCS12 PKCS11 AWS AZUREKEYVAULT DIGICERTONE ESIGNER ETOKEN GOOGLECLOUD HASHICORPVAULT ORACLECLOUD TRUSTEDSIGNING YUBIKEY NITROKEY OPENPGP OPENSC PIV' -- "$cur" ) ) + COMPREPLY=( $( compgen -W 'JKS JCEKS PKCS12 PKCS11 AWS AZUREKEYVAULT DIGICERTONE ESIGNER ETOKEN GARASIGN GOOGLECLOUD HASHICORPVAULT ORACLECLOUD TRUSTEDSIGNING YUBIKEY NITROKEY OPENPGP OPENSC PIV' -- "$cur" ) ) return 0 ;; --storepass|-a|--alias|--keypass|-t|--tsaurl|-r|--tsretries|-w|--tsretrywait|-n|--name|-u|--url|-e|--encoding) 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 004c18d9..58f19031 100644 --- a/jsign/src/deb/data/usr/share/man/man1/jsign.1 +++ b/jsign/src/deb/data/usr/share/man/man1/jsign.1 @@ -69,6 +69,8 @@ The type of the keystore: .br - ESIGNER : SSL.com eSigner .br +- GARASIGN : Garantir Remote Signing +.br - GOOGLECLOUD : Google Cloud KMS .br - HASHICORPVAULT : Google Cloud KMS via HashiCorp Vault @@ -392,6 +394,32 @@ SSL.com provides a sandbox environment, to use a test certificate simply add the "--keystore https://cs-try.ssl.com". +.TP + +Signing with GaraSign: + +GaraSign is a remote signing service provided by Garantir. The authentication is performed by specifying +the username/password or the TLS client certificate in the storepass parameter. If the TLS client certificate +is stored in a password protected keystore, the password is specified in the keypass parameter. The keystore +parameter references the URL of the GaraSign REST API (https://garasign.com:8443/CodeSigningRestService/ by default). + +Authenticating with a username and a password: + +jsign --storetype GARASIGN \\ + --storepass "|" \\ + --alias test \\ + application.exe + +Authenticating with a TLS client certificate and a non-default endpoint: + +jsign --storetype GARASIGN \\ + --keystore https://demo.garantir.io/CodeSigningRestService \\ + --storepass "/path/to/client-certificate.p12" \\ + --keypass \\ + --alias test \\ + application.exe + + .TP Signing with Google Cloud KMS: