Use Jsign and PKCS#11 to sign Windows artifacts

This guide provides instructions for creating a Cloud HSM key for Microsoft Authenticode signing through PKCS#11 and Jsign.

Use cases

The workflow outlined in this document helps address the following enterprise security needs:

  • Sign firmware with a private key protected by a FIPS140-2 Level 3 HSM.
  • Sign Windows artifacts without having to use signtool.

Before you begin

To complete this tutorial, you need the following:

  • A Windows machine with the artifacts you want to sign. Make sure that Java is installed on this machine.
  • Cloud Shell or your own Linux machine, to generate a certificate signing request or a certificate. On this machine, complete the configuration documented in OpenSSL Setup.

Remember to run gcloud auth application-default login if you haven't yet.

On your Windows machine, download the latest Jsign release JAR file using the following powershell command:

wget -O jsign.jar


Create a Cloud KMS-hosted signing key

Using Cloud Shell or your own machine, create a Cloud KMS key ring in your Google Cloud project using the following command:

gcloud kms keyrings create "KEY_RING" --location "LOCATION"

Then, create a Cloud KMS EC-P256-SHA256 hardware signing key in your Google Cloud project, in the key ring that you have just created:

gcloud kms keys create "KEY_NAME" --keyring "KEY_RING" \
  --project "PROJECT_ID" --location "LOCATION" \
  --purpose "asymmetric-signing" --default-algorithm "ec-sign-p256-sha256" \
  --protection-level "hsm"

Download the HSM attestation

An HSM attestation is proof that your key resides in an HSM. This proof may be required by your Certificate Authority (CA) to issue an Extended Validation (EV) certificate.

To download the HSM attestation associated with your Cloud KMS key, complete the following steps:

  1. In the Google Cloud console, go to the Key Management page.

    Go to Key Management

  2. Select the key ring that contains the key you want to attest, and then select the key.

  3. Click More for the key version you want to attest, and then click Verify attestation.

  4. In the Verify attestation dialog, click Download attestation bundle. This downloads a zip file containing the attestation and certificate chains.

See Parsing the attestation for full instructions on how to verify the downloaded attestation.

Create a self-signed certificate with OpenSSL

This step is optional, but helps you familiarize yourself with subsequent steps before you go through the process and expense of purchasing a certificate signed by a Certificate Authority.

Using Cloud Shell or your own machine, generate a self-signed certificate with the Cloud KMS-hosted signing key. You can use OpenSSL to use a PKCS #11 URI instead of a file path and identify the key by its label. In the Cloud KMS PKCS #11 library, the key label is equivalent to the CryptoKey name.

openssl req -new -x509 -days 3650 -subj '/CN=test/' -sha256 -engine pkcs11 \
  -keyform engine -key pkcs11:object=KEY_NAME > ca.cert

If this command fails, PKCS11_MODULE_PATH may have been set incorrectly, or you might not have the right permissions to use the Cloud KMS signing key.

You should now have a certificate that looks like this:


Copy the certificate to your Windows machine so that you can use it with Jsign to sign your artifacts.

Create a new certificate signing request

You can generate a certificate signing request (CSR) for a Cloud HSM signing key. Complete these steps if your certificate authority requires a CSR in order to generate a new certificate for code signing.

Using Cloud Shell or your own machine, run the following command:

openssl req -new -subj '/CN=CERTIFICATE_NAME/' DIGEST_FLAG \
  -engine pkcs11 -keyform engine \
  -key pkcs11:id=KEY_ID > REQUEST_NAME.csr

Replace the following:

  • CERTIFICATE_NAME: a name for the certificate that you want to generate.
  • DIGEST_FLAG: a flag indicating the type of digest. Use -sha256, -sha384, or -sha512 depending on the algorithm of the key.
  • KEY_ID: the fully qualified resource ID of an asymmetric signing key version—for example, projects/PROJECT_ID/locations/LOCATION/keyRings/KEY_RING/cryptoKeys/KEY_NAME/cryptoKeyVersions/1.
  • REQUEST_NAME: a name for the certificate signing request.

Make sure you use the correct -sigopt options for the type of key that you're using.

Sign an artifact with Jsign

Now that you have successfully created a certificate (either self-signed or obtained from the Certificate Authority) and copied it to your Windows machine, you can use it to sign a Windows artifact.

For a list of supported file formats, run the jsign --help command.

Use Jsign to sign the artifacts, using your Cloud KMS key and your certificate.

java -jar PATH_TO_JSIGN.JAR --storetype GOOGLECLOUD \
  --storepass $(gcloud auth application-default print-access-token) \
  --keystore projects/PROJECT_ID/locations/LOCATION/keyRings/KEY_RING \
  --alias KEY_NAME \
  --certfile PATH_TO_CA.CERT

Replace the following:

  • PATH_TO_JSIGN.JAR: the path to jsign.jar.
  • PATH_TO_CA.CERT: the path to your certificate ca.cert.
  • PATH_TO_ARTIFACT_TO_SIGN: the path to the artifact that you want to sign.

For a detailed explanation of each command option, see the official Jsign documentation.