Skip to content

Commit

Permalink
Switch to server-side hashing for SignServer support
Browse files Browse the repository at this point in the history
  • Loading branch information
Vampire committed Nov 19, 2024
1 parent 6acd186 commit ef1aae3
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 19 deletions.
16 changes: 9 additions & 7 deletions docs/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -887,17 +887,19 @@ <h4 id="example-hashicorpvault">Signing with HashiCorp Vault</h4>

<h4 id="example-signserver">Signing with Keyfactor SignServer</h4>

<p><a href="https://www.signserver.org">SignServer</a> is an on-premises open source signing service developed by Keyfactor.
<p><a href="https://www.signserver.org">SignServer</a> is an on-premises (or cloud) open source signing service developed by Keyfactor.
SignServer supports various signing operations handled by signer workers. Jsign requires a
<a href="https://doc.primekey.com/signserver/signserver-reference/signserver-workers/signserver-signers/plain-signer">Plain Signer</a>
worker configured with the <code>CLIENTSIDEHASHING</code> or <code>ALLOW_CLIENTSIDEHASHING_OVERRIDE</code> properties
set to <code>true</code>, and the <code>SIGNATUREALGORITHM</code> property set to <code>NONEwithRSA</code> or
<code>NONEwithECDSA</code>.</p>
worker configured with the <code>CLIENTSIDEHASHING</code> property not set or set to <code>false</code> or
<code>ALLOW_CLIENTSIDEHASHING_OVERRIDE</code> property set to <code>true</code>, and the <code>SIGNATUREALGORITHM</code> property
set to a supported algorithm that ends in <code>withRSA</code> or <code>withECDSA</code>.
Configuring the hashing algorithm when invoking Jsign will be ignored.</p>

<p>The authentication is performed by specifying the username/password or the TLS client certificate in the
<code>storepass</code> parameter. If the TLS client certificate is stored in a password protected keystore, the password
is specified in the <code>keypass</code> parameter. The <code>keystore</code> parameter references the URL of the
SignServer REST API. The <code>alias</code> parameter specifies the id or the name of the worker. </p>
<code>storepass</code> parameter if authentication is necessary. If the TLS client certificate is stored in
a password protected keystore, the password is specified in the <code>keypass</code> parameter.
The <code>keystore</code> parameter references the URL of the SignServer REST API. The <code>alias</code> parameter
specifies the id or the name of the worker. </p>

<p>Authenticating with a username and a password:</p>

Expand Down
14 changes: 8 additions & 6 deletions jsign-crypto/src/main/java/net/jsign/KeyStoreType.java
Original file line number Diff line number Diff line change
Expand Up @@ -561,14 +561,16 @@ Provider getProvider(KeyStoreBuilder params) {
},

/**
* Keyfactor SignServer. This keystore requires a Plain Signer worker configured to allow client-side hashing (with
* the properties <code>CLIENTSIDEHASHING</code> or <code>ALLOW_CLIENTSIDEHASHING_OVERRIDE</code> set to true), and
* the <code>SIGNATUREALGORITHM</code> property set to <code>NONEwithRSA</code> or <code>NONEwithECDSA</code>.
* Keyfactor SignServer. This keystore requires a Plain Signer worker configured to allow server-side hashing (with
* the property <code>CLIENTSIDEHASHING</code> not set or set to <code>false</code> or
* <code>ALLOW_CLIENTSIDEHASHING_OVERRIDE</code> set to <code>true</code>), and the <code>SIGNATUREALGORITHM</code>
* property set to a supported algorithm that ends in <code>withRSA</code> or <code>withECDSA</code>. Configuring
* the hashing algorithm when invoking Jsign will be ignored.
*
* <p>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 SignServer REST API. The
* alias parameter specifies the id or the name of the worker.</p>
* storepass parameter if authentication is necessary. 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 SignServer REST API. The alias parameter specifies the id or the name of the worker.</p>
*/
SIGNSERVER(false, false) {
@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,13 @@ public List<String> aliases() throws KeyStoreException {
public Certificate[] getCertificateChain(String alias) throws KeyStoreException {
if (!certificates.containsKey(alias)) {
try {
Map<String, ?> response = client.post("/rest/v1/workers/" + alias + "/process", "{\"data\":\"\"}");
Map<String, Object> request = new HashMap<>();
request.put("data", "");
Map<String, String> metadata = new HashMap<>();
metadata.put("USING_CLIENTSUPPLIED_HASH", "false");
request.put("metaData", metadata);

Map<String, ?> response = client.post("/rest/v1/workers/" + alias + "/process", JsonWriter.format(request));
String encodedCertificate = response.get("signerCertificate").toString();
byte[] certificateBytes = Base64.getDecoder().decode(encodedCertificate);
Certificate certificate = CertificateFactory.getInstance("X.509")
Expand All @@ -120,15 +126,11 @@ 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);

Map<String, Object> request = new HashMap<>();
request.put("data", Base64.getEncoder().encodeToString(data));
request.put("encoding", "BASE64");
Map<String, String> metadata = new HashMap<>();
metadata.put("USING_CLIENTSUPPLIED_HASH", "true");
metadata.put("CLIENTSIDE_HASHDIGESTALGORITHM", digestAlgorithm.id);
metadata.put("USING_CLIENTSUPPLIED_HASH", "false");
request.put("metaData", metadata);

try {
Expand Down

0 comments on commit ef1aae3

Please sign in to comment.