diff --git a/docs/index.html b/docs/index.html index 544961e9..9020f7ef 100644 --- a/docs/index.html +++ b/docs/index.html @@ -890,9 +890,12 @@

Signing with Keyfactor SignServer

SignServer is a cloud/on-premises open source signing service developed by Keyfactor. SignServer supports various signing operations handled by signer workers. Jsign requires a Plain Signer -worker configured with the CLIENTSIDEHASHING or ALLOW_CLIENTSIDEHASHING_OVERRIDE properties -set to true, and the SIGNATUREALGORITHM property set to NONEwithRSA or -NONEwithECDSA.

+worker, preferably configured with the CLIENTSIDEHASHING or ALLOW_CLIENTSIDEHASHING_OVERRIDE +properties set to true, and the SIGNATUREALGORITHM property set to NONEwithRSA or +NONEwithECDSA. The worker may be configured with server-side hashing (i.e. with CLIENTSIDEHASHING +and ALLOW_CLIENTSIDEHASHING_OVERRIDE set to false, and a proper +SIGNATUREALGORITHM set), in this case the worker name or id in the alias has to be suffixed with +|serverside.

If necessary 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 @@ -920,6 +923,16 @@

Signing with Keyfactor SignServer

application.exe +

Using server-side hashing, the digest algorithm must match the one configured for the worker:

+ +
+ jsign --storetype SIGNSERVER \
+       --keystore https://example.com/signserver \
+       --alias "test|serverside" \
+       --alg SHA-512 \
+       application.exe
+
+

Signing with Oracle Cloud Key Management Service

diff --git a/jsign-crypto/src/main/java/net/jsign/KeyStoreType.java b/jsign-crypto/src/main/java/net/jsign/KeyStoreType.java index f2b12a00..40b4d693 100644 --- a/jsign-crypto/src/main/java/net/jsign/KeyStoreType.java +++ b/jsign-crypto/src/main/java/net/jsign/KeyStoreType.java @@ -561,9 +561,12 @@ Provider getProvider(KeyStoreBuilder params) { }, /** - * Keyfactor SignServer. This keystore requires a Plain Signer worker configured to allow client-side hashing (with - * the properties CLIENTSIDEHASHING or ALLOW_CLIENTSIDEHASHING_OVERRIDE set to true), and - * the SIGNATUREALGORITHM property set to NONEwithRSA or NONEwithECDSA. + * Keyfactor SignServer. This keystore requires a Plain Signer worker, preferably configured to allow client-side + * hashing (with the properties CLIENTSIDEHASHING or ALLOW_CLIENTSIDEHASHING_OVERRIDE set + * to true), and the SIGNATUREALGORITHM property set to NONEwithRSA or NONEwithECDSA. + * The worker may be configured with server-side hashing (i.e. with CLIENTSIDEHASHING and + * ALLOW_CLIENTSIDEHASHING_OVERRIDE set to false, and a proper SIGNATUREALGORITHM + * set), in this case the worker name or id in the alias has to be suffixed with |serverside. * *

If necessary 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 diff --git a/jsign-crypto/src/main/java/net/jsign/jca/SignServerSigningService.java b/jsign-crypto/src/main/java/net/jsign/jca/SignServerSigningService.java index fc39f87a..188dd232 100644 --- a/jsign-crypto/src/main/java/net/jsign/jca/SignServerSigningService.java +++ b/jsign-crypto/src/main/java/net/jsign/jca/SignServerSigningService.java @@ -94,7 +94,29 @@ public List aliases() throws KeyStoreException { public Certificate[] getCertificateChain(String alias) throws KeyStoreException { if (!certificates.containsKey(alias)) { try { - Map response = client.post("/rest/v1/workers/" + alias + "/process", "{\"data\":\"\"}"); + String worker = alias; + boolean serverside = false; + if (worker.endsWith("|serverside")) { + worker = worker.substring(0, worker.length() - 11); + serverside = true; + } + + Map request = new HashMap<>(); + if (serverside) { + request.put("data", ""); + Map metadata = new HashMap<>(); + metadata.put("USING_CLIENTSUPPLIED_HASH", "false"); + request.put("metaData", metadata); + } else { + request.put("data", "47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU="); + request.put("encoding", "BASE64"); + Map metadata = new HashMap<>(); + metadata.put("USING_CLIENTSUPPLIED_HASH", "true"); + metadata.put("CLIENTSIDE_HASHDIGESTALGORITHM", "SHA-256"); + request.put("metaData", metadata); + } + + Map response = client.post("/rest/v1/workers/" + worker + "/process", JsonWriter.format(request)); String encodedCertificate = response.get("signerCertificate").toString(); byte[] certificateBytes = Base64.getDecoder().decode(encodedCertificate); Certificate certificate = CertificateFactory.getInstance("X.509") @@ -120,19 +142,32 @@ public SigningServicePrivateKey getPrivateKey(String alias, char[] password) thr @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); + String worker = privateKey.getId(); + boolean serverside = false; + if (worker.endsWith("|serverside")) { + worker = worker.substring(0, worker.length() - 11); + serverside = true; + } Map request = new HashMap<>(); - request.put("data", Base64.getEncoder().encodeToString(data)); + if (serverside) { + request.put("data", Base64.getEncoder().encodeToString(data)); + Map metadata = new HashMap<>(); + metadata.put("USING_CLIENTSUPPLIED_HASH", "false"); + request.put("metaData", metadata); + } else { + DigestAlgorithm digestAlgorithm = DigestAlgorithm.of(algorithm.substring(0, algorithm.toLowerCase().indexOf("with"))); + data = digestAlgorithm.getMessageDigest().digest(data); + request.put("data", Base64.getEncoder().encodeToString(data)); + Map metadata = new HashMap<>(); + metadata.put("USING_CLIENTSUPPLIED_HASH", "true"); + metadata.put("CLIENTSIDE_HASHDIGESTALGORITHM", digestAlgorithm.id); + request.put("metaData", metadata); + } request.put("encoding", "BASE64"); - Map metadata = new HashMap<>(); - metadata.put("USING_CLIENTSUPPLIED_HASH", "true"); - metadata.put("CLIENTSIDE_HASHDIGESTALGORITHM", digestAlgorithm.id); - request.put("metaData", metadata); try { - Map response = client.post("/rest/v1/workers/" + privateKey.getId() + "/process", JsonWriter.format(request)); + Map response = client.post("/rest/v1/workers/" + worker + "/process", JsonWriter.format(request)); return Base64.getDecoder().decode((String) response.get("data")); } catch (IOException e) { throw new GeneralSecurityException(e); 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 5c6e981d..eb59e6f8 100644 --- a/jsign/src/deb/data/usr/share/man/man1/jsign.1 +++ b/jsign/src/deb/data/usr/share/man/man1/jsign.1 @@ -512,13 +512,14 @@ jsign --storetype HASHICORPVAULT \\ .TP - Signing with Keyfactor SignServer: SignServer is a cloud/on-premises open source signing service developed by Keyfactor. SignServer supports various -signing operations handled by signer workers. Jsign requires a Plain Signer worker configured with the CLIENTSIDEHASHING -or ALLOW_CLIENTSIDEHASHING_OVERRIDE properties set to true, and the SIGNATUREALGORITHM property set to NONEwithRSA or -NONEwithECDSA. +signing operations handled by signer workers. Jsign requires a Plain Signer worker, preferably configured with the +CLIENTSIDEHASHING or ALLOW_CLIENTSIDEHASHING_OVERRIDE properties set to true, and the SIGNATUREALGORITHM property +set to NONEwithRSA or NONEwithECDSA. The worker may be configured with server-side hashing (i.e. with CLIENTSIDEHASHING +and ALLOW_CLIENTSIDEHASHING_OVERRIDE set to false, and a proper SIGNATUREALGORITHM set), in this case the worker name +or id in the alias has to be suffixed with '|serverside'. If necessary 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 @@ -542,6 +543,16 @@ jsign --storetype SIGNSERVER \ --alias test \ application.exe +Using server-side hashing, the digest algorithm must match the one configured for the worker: + +jsign --storetype SIGNSERVER \ + --keystore https://example.com/signserver \ + --alias 'test|serverside' \ + --alg SHA-512 \ + application.exe + + +.TP Signing with Oracle Cloud Key Management Service