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).
Note:
YubiKeys with firmware 5.7.1 are able to handle RSA1024-RSA4096 which can be used for code signing. YubiKeys with a pre-dating firmware version (5.4.3 and lower) would have to use Elliptic Curve keys (ECCP256 or ECCP384) instead, due to the updated minimum requirements for RSA keys used for Code Signing by the CA/B Forum in June 2023.
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
-
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 -
Obtain the signing certificate’s sha1 thumbprint
- Double Click on the Code Signing Certificate in the Users Personal Certificates store →Details →Thumbprint
- Mark the whole string and use ctrl + c to copy
-
Open a command prompt, navigate to the folder containing signtool.exe and perform the signature:
- cd C:\Program Files (x86)\Microsoft SDKs\ClickOnce\SignTool
-
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"
Tips: SignTool.exe requires that the PIN is entered once per signature when the private key is stored on a Smart Card. For large amounts of signatures we would recommend our YubiHSM2, which is a fully fledged HSM and does not require a PIN to code sign with SignTool
JarSigner
Prerequisites
- Java JDK or OpenJDK
- Download and install the Yubico-PIV-Tool
- Add the "C:\Program Files\Yubico\Yubico PIV Tool\bin" directory to the System Path
- 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
- Open cmd.exe
- Navigate to the location of the libykcs11.dll file
cd "C:\Program Files\Yubico\Yubico PIV Tool\bin"
- 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 - 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:
-
ykman piv certificates import 82 "<PATH\TO\ROOT\CERTIFICATE.pem>"
-
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.