Code Signing with the YubiKey on Windows


 

 

Description

This article explains how the YubiKey can be used to sign code in a Windows environment using common tools, such as SignTool or JarSigner. It is assumed that the YubiKey has already been provisioned with a code signing Private Key and the corresponding Code Signing Certificate in one of its PIV slots (most commonly 9a or 9c).

 

Please note:

Due to the increased RSA key size (>= RSA3072) requirements from CA/B forum, June 2023, code signing keys provisioned to the YubiKey need to be using Elliptic Curve (ECCP256 or ECCP384), rather than RSA. The YubiKey's PIV application can only store RSA keys of sizes 1024 and 2048.
If there is a need to use RSA keys larger than 2048 we would recommend taking a look at our YubiHSM2 module instead.

 

 

SignTool

Prerequisites

  • Download and install the YubiKey Smart Card MiniDriver
    • IMPORTANT :
      The MiniDriver will block the PUK if the PUK is set to the default value ('123456'). It is therefore important that the PUK is changed before using the YubiKey on a machine where the MiniDriver is installed.

    • If the code signing is executed on a remote server, make sure to install the YubiKey Smart Card MiniDriver with INSTALL_LEGACY_NODE=1, according to our article Deploying the YubiKey Minidriver to Workstations and Servers
  • Generate a Private Key on the YubiKey and obtain a signed Code Signing Certificate from a CA
  • Download and Install SignTool. SignTool can be acquired as a part of the Windows SDK.
  • Make sure that the Windows Smart Card Service (SCardSvr) is started and is running as a Local Service
  • Optional: Import the complete Certificate Chain to the YubiKey

Procedure

  1. Plug in the YubiKey and find the Code Signing Certificate in the Users Personal Certificates store.
      ⊞ Win   +   r   certmgr.msc  → Certificates - Current User → Personal → Certificates 
  2. Obtain the signing certificate’s sha1 thumbprint
    1. Double Click on the Code Signing Certificate in the Users Personal Certificates store →Details →Thumbprint 
    2. Mark the whole string and use  ctrl  +  c  to copy
  3. Open a command prompt, navigate to the folder containing signtool.exe and perform the signature:
    1. cd C:\Program Files (x86)\Microsoft SDKs\ClickOnce\SignTool
    2. Signtool sign /sha1 <sha1_thumbprint> /fd SHA256 /t <url_to_TimeStamp_Server> <file_to_sign>

      Example:
      signtool sign /sha1 83fe6c0f1f0d1db0a09ba2cd97015df7a852b4d3 /fd SHA256 /t http://timestamp.sectigo.com "C:\Users\YubicoTest\projects\file.exe"

 

 

JarSigner

Prerequisites

  • Java JDK or OpenJDK
  • Download and install the Yubico-PIV-Tool
  • Generate a pkcs11.config file in the same directory that the libykcs11.dll library is located.
    • Please see section ykcs11.conf below for detailed instructions
  • Optional: Import the complete Certificate Chain to the YubiKey
    • In order to see the full Certificate Chain with CA Root and Intermediate Certificates imported to slot 82 - 95, make sure that libykcs11.dll is used instead of other PKCS#11 modules.

 

ykcs11.conf

The pkcs11.config is a configuration file used by JarSigner to locate the PKCS#11 module that is used to interact with the token storing the private key. This config file needs to be located in the same directory as the pkcs#11 library that is being used.

 

In the case of the libykcs11.dll is being used, the default location would be

C:\Program Files\Yubico\Yubico PIV Tool\bin

 

The contents of the file would look something like this:

name = ykcs11
library = "C:\\Program Files\\Yubico\\Yubico PIV Tool\\bin\\libykcs11.dll"

 

Procedure

  1. Open cmd.exe
  2. Navigate to the location of the libykcs11.dll file
    cd "C:\Program Files\Yubico\Yubico PIV Tool\bin"
  3. Check if the configuration is working and retrieve the signing certificate object label.
    keytool -list -keystore NONE -storepass <PIV_PIN> -storetype PKCS11 -providerclass sun.security.pkcs11.SunPKCS11 -providerarg ykcs11.conf

    Example:
    C:\Program Files\Yubico\Yubico PIV Tool\bin>keytool -list -keystore NONE -storepass 123456 -storetype PKCS11 -providerclass sun.security.pkcs11.SunPKCS11 -providerarg ykcs11.conf
    Keystore type: PKCS11
    Keystore provider: SunPKCS11-ykcs11
    Your keystore contains 2 entries

    X.509 Certificate for PIV Attestation, PrivateKeyEntry,
    Certificate fingerprint (SHA-256): FB:FC:AB:E1:63:28:8A:B0:7E:8E:03:97:6C:1A:93:D6:E7:D6:D4:6C:D0:B8:34:A0:8F:AE:94:49:CC:10:AE:1E
    X.509 Certificate for PIV Authentication, PrivateKeyEntry,
    Certificate fingerprint (SHA-256): 0D:BF:B1:A3:CA:E3:1C:45:1B:D6:E4:84:D3:0A:BD:C6:5E:DF:DD:01:40:81:3B:0A:ED:68:98:70:D3:0D:C4:B1
  4. Sign with the following command.
    jarsigner -keystore NONE -storepass <PIV_PIN> -storetype PKCS11 -providerClass sun.security.pkcs11.SunPKCS11 -providerArg <path_to_ykcs11.conf> -signedjar <path_to_signed_file_output> <unsigned_file_path> <signing_ykcs11_object_label> -tsa <TimeStamp_server_URL>
    Example:
    C:\Program Files\Yubico\Yubico PIV Tool\bin>jarsigner -keystore NONE -storepass 123456 -storetype PKCS11 -providerClass sun.security.pkcs11.SunPKCS11 -providerArg ykcs11.conf -signedjar C:\Users\Administrator\Documents\jarFiles\SignedFile.jar C:\Users\Administrator\Documents\jarFiles\unsigned.jar "X.509 Certificate for PIV Authentication" -tsa http://timestamp.digicert.com

    jar signed.

    The signer certificate will expire on 2024-07-08.
    The timestamp will expire on 2031-11-09.

 

 

 

Import the complete Certificate Chain to the YubiKey

In the case that your Code Signing Certificate is issued by a public CA you might want to make sure that the complete Certificate Chain is loaded unto the YubiKey.

This can be done using the YubiKey Manager CLI (ykman) software, which would allow you to import the CA Root and Intermediate certificates to the PIV slots for retired Keys and Certificates (82 and 83, for instance). In the case that your CA has multiple intermediate CA certificates, please repeat the steps for slot 84 - 95.

 

Importing the Certificate Chain to the YubiKey:

  1. ykman piv certificates import 82 "<PATH\TO\ROOT\CERTIFICATE.pem>"
  2. ykman piv certificates import 83 "<PATH\TO\INTERMEDIATE\CERTIFICATE.pem>"

 

Verify that the CA and Intermediate Certificates were correctly imported:

ykman piv info

 

 

Troubleshooting

Please see the KB Article: Troubleshooting Code Signing on Windows for troubleshooting steps.