Windows Code Signing with eSigner

3 minute read.

I miss the good old days, when we still were able to use a private key for code signing.

Nowadays, in addition to a highly expensive certificate that requires validation of your company with “reliable third-party websites” that may have a bunch of misinformation on you, we’re also expected to pay a dollar per API request to sign a piece of code. Because it requires specialized hardware to host your private key or something like that. I heard it might be almost as expensive as an Nvidia H100, or maybe not even close, yet somehow is way more expensive to run a REST API request on to justify the price… hmmm.

Thanks to these new requirements, we now have to deal with a beautiful Java-based tool that ships the JDK instead of the JRE and ends up being a 200+ MB download (compressed!).

Installation

Ideally, just have it installed on your runner once. If that’s not an option, here is a script:

# Install eSigner CodeSignTool from SSL.com
Invoke-WebRequest -OutFile CodeSignTool.zip "https://www.ssl.com/download/codesigntool-for-windows/"
Expand-Archive -Force CodeSignTool.zip
Remove-Item CodeSignTool.zip
Move-Item -Destination "$Env:USERPROFILE\Desktop\CodeSignTool" -Path "CodeSignTool"

You can use it in your .gitlab-ci.yml directly or save it as a install-esigner-tool.ps1 file and run it.

Code Sign from CMake

We code sign directly from CMake, since we use CPack to package up the signed executables, and then run a POST_PACKAGE script to sign the installer.

This is our custom target to sign the executable:

set(CODESIGN_TOOL .\\CodeSignTool.bat)
set(CODESIGN_TOOL_DIR $ENV{USERPROFILE}\\Desktop\\CodeSignTool\\)
if(NOT EXISTS "${CODESIGN_TOOL_DIR}\\${CODESIGN_TOOL}")
    message(FATAL_ERROR "Missing ${CODESIGN_TOOL}")
endif()

# Windows code signing
add_custom_target(YourExecutableSigned
    COMMAND ${CODESIGN_TOOL} sign
        -credential_id="$ENV{CODESIGN_CREDENTIAL_ID}"
        -username="$ENV{CODESIGN_USER}"
        -password="$ENV{CODESIGN_PWD}"
        -input_file_path="$<SHELL_PATH:$<TARGET_FILE:YouExecutableTarget>>"
        -totp_secret="$ENV{CODESIGN_TOTP}"
        -override="true"
    WORKING_DIRECTORY ${CODESIGN_TOOL_DIR}
    COMMENT "Signing Editor executable")

Run it with cmake --build . --target YourExecutableSigned.

The WORKING_DIRECTORY is not optional. Our tool can only run from inside its own directory.

Note that all the credentials are provided via environment variables. Add them as CI secrets:

  • CODESIGN_CREDENTIAL_ID: The eSigner credential ID from SSL.com.
  • CODESIGN_USER: Your SSL.com username.
  • CODESIGN_PWD: Your SSL.com password.
  • CODESIGN_TOTP: The seed for the OTPs. This is required, since you can’t input the time-based authenticator codes via CI, so you input the private token instead, that the tool will use to generate a OTP with.

You’ll have to replace YouExecutableTarget with your target, of course.

Hope this saved you some time.