Search code examples
code-signingsigntoolyubikey

Automate Extended Validation (EV) code signing with Yubico Yubikey


I want to EV Code sign using a private key on a Yubico Yubikey 5 using signtool.exe, However everytime I sign a file, it prompts for the password. I would like the entry of this key to be automated as part of a build pipeline triggered on a secure machine.

I previously used a Safenet token and was able to do this using solutions from this question, however my understanding is that this functionality was a specific implementation for the eToken Cryptographic Security Provider used by Safenet.

I have exported the public certificate from the Yubikey and used certutil to dump info about the key container (which is a GUID like 0bababab-0000-aaaa-baba-cdcdcdcdcdcd) and the CSP which is Microsoft Smart Card Key Storage Provider but when I use this info I get the following issue:

signtool sign /f <cert file>.crt /csp "Microsoft Smart Card Key Storage Provider" /v /kc <container_id>
Error information: "CryptExportPublicKeyInfoEx failed" (-2146893819/0x80090005)
SignTool Error: An unexpected internal error has occurred.

Solution

  • In addition to Microsoft Smart Card support the Yubikey also supports PKCS11. This interface isn't natively supported by signtool.exe but it is supported by third party tools like osslsigncode which allows the key password to be supplied over the CLI.

    Here's how you can get it working:

    1. Download osslsigncode from Github i.e. here and extract
    2. Additionally download pkcs11.dll from the Github release as well (seperate download)
    3. Place pkcs11.dll into the bin folder
    4. Download and install the yubico-piv-tool i.e. from here
    5. Move all of the .dll files from C:\Program Files\Yubico\Yubico PIV Tool\bin into your osslsigncode bin folder
    6. Add your osslsigncode bin folder to PATH
    7. Use Yubikey Manager to export the public certificate to a .crt file and note its location
    8. Finally you can use the following command:
      osslsigncode sign -pkcs11module libykcs11 -pkcs11engine pkcs11 -pass <yubikey_passcode> -ts <timestamp_server_url> -key "pkcs11:id=%01" -certs <path_to_public_cert.crt> -in "input_file.exe" -out "output_file.exe"

    Additional resources: