Skip to content

Cloud Code Signing (Windows)

Jaifroid edited this page Aug 17, 2024 · 3 revisions

Our regular Code Signing certificate expiring on 2024-08-27, we have switched to a new SSL.com-provided Code Signing certificate for which we dont have the private key. See https://github.com/kiwix/overview/issues/88 for additional details.

How to cloud sign in GH Actions?

Needed secrets

  • ESIGNER_USERNAME (kiwixbot)
  • ESIGNER_PASSWORD
  • ESIGNER_CREDENTIAL_ID
  • ESIGNER_TOTP_SECRET

Single GA step

steps:
  - name: Sign binary with CodeSignTool
    uses: sslcom/esigner-codesign@v1.3.1
    with:
      command: sign
      username: ${{secrets.ESIGNER_USERNAME}}
      password: ${{secrets.ESIGNER_PASSWORD}}
      credential_id: ${{secrets.ESIGNER_CREDENTIAL_ID}}
      totp_secret: ${{secrets.ESIGNER_TOTP_SECRET}}
      file_path: ${GITHUB_WORKSPACE}/dist/myfile.exe
      override: true

Integration alternative

Should you not be able to use the Action step (cause signing is integrated into code), execute the following (you need a working Java setup – openjdk is OK)

steps:
  - uses: actions/setup-java@v4
    with:
      distribution: 'temurin'
      java-version: '21'
  - name: Get CodeSignTool
    run: |
      export CODE_SIGN_TOOL_PATH=$(pwd)/CodeSignTool
      echo "CODE_SIGN_TOOL_PATH=${CODE_SIGN_TOOL_PATH}" >> $GITHUB_ENV
      mkdir -p ${CODE_SIGN_TOOL_PATH} && curl -s https://www.ssl.com/download/codesigntool-for-linux-and-macos/ -o cst.zip && unzip -d ${CODE_SIGN_TOOL_PATH} cst.zip && chmod +x ${CODE_SIGN_TOOL_PATH}/CodeSignTool.sh && ${CODE_SIGN_TOOL_PATH}/CodeSignTool.sh --version
  - name: Sign (that part in your code)
    env:
      ESIGNER_USERNAME: ${{ secrets.ESIGNER_USERNAME }}
      ESIGNER_PASSWORD: ${{ secrets.ESIGNER_PASSWORD }}
      ESIGNER_CREDENTIAL_ID: ${{ secrets.ESIGNER_CREDENTIAL_ID }}
      ESIGNER_TOTP_SECRET: ${{ secrets.ESIGNER_TOTP_SECRET }}
    run: ${CODE_SIGN_TOOL_PATH}/CodeSignTool.sh sign -credential_id="${ESIGNER_CREDENTIAL_ID}" -username="${ESIGNER_USERNAME}" -password="${ESIGNER_PASSWORD}" -input_file_path="$(pwd)/kiwix-serve.exe" -totp_secret="${ESIGNER_TOTP_SECRET}" -override

The following are additional information for documentation's sake.


Overview

  • Team (named KIWIX, ID adf-1j8smko).
  • We can invite up to 5 users to the team
  • One Code Signing Certificate with eSigner capability
  • We can invite users on this cert to allow signing access using this certificate
  • Signing users must first enroll in Cloud Signing by creating an OTP passcode in the web UI.
  • Under the Signing credentials expandable section at the bottom of the certificate page, make sur to disable malware detection. It's too suspicious and prevents legitimate binaries from being signed.
  • Our certificate is an OV Code Signing (Organization Validation). Docs very frequently mention EV Code Signing (Extended Validation). AFAIK, there is no difference in signing and tools so consider EVCS applicable in docs.
  • we have very limited quota of signings available (240 per year for all Kiwix softwares). Don't sign for fun. Only sign releases.

How to track signing quota?

  • There is no API at the moment to retrieve the information. Checked Rest API and Postman API.
  • One must open the certificate in WebUI and check the END ENTITY CERTIFICATES section and look for Signings This Month and Unused Signings lines. It seems to only refresh daily.
  • See Pricing

Using SSL.com's CodeSignTool

CodeSignTool is an SSL.com custom Java tool for remote code signing. You need SSL.com credentials (username and password) to use it.

  • CodeSignTool documentation and download
  • runs on Windows/Linux/macOS. You can sign Windows binaries without Windows
  • Computes hashes locally, uploaded them, signs them online and applies the signature locally. Actual binary not uploaded.
# this returns a credential ID. That credential ID is also visible in the webUI
# so this is not that useful but helps ensure your username/password are OK and you have access to the certificate
❯ java -jar ./jar/code_sign_tool-1.3.1.jar get_credential_ids -username="xxx" -password='yyy'
EVCS Credential ID(s):
- 01a24709-249b-41a5-bbe2-e72018da2ed2

# only useful to ensure you have access to the certificate
❯ java -jar ./jar/code_sign_tool-1.3.1.jar credential_info -credential_id='zzz' -username="xxx" -password='yyy'
EVCS Certificate Subject Information:
- Subject DN: CN=Association Kiwix, O=Association Kiwix, L=Lausanne, ST=Canton of Vaud, C=CH
- Certificate Expiry: Fri Jul 11 07:55:27 GMT 2025
- Issuer DN: CN=SSL.com Code Signing Intermediate CA RSA R1, O=SSL Corp, L=Houston, ST=Texas, C=US

# now sign the binary
❯ java -jar ./jar/code_sign_tool-1.3.1.jar sign -credential_id='zzz' -username="xxx" -password='yyy' -input_file_path=/full/path/to/kiwix-manage.exe -totp_secret='aaa' -override
Code signed successfully: /full/path/to/kiwix-manage.exe

# can be verified (on Windows, with Windows SDK installed)
PS C:\Users\reg> signtool.exe verify /pa C:\Users\reg\kiwix-manage.exe
File: C:\Users\reg\kiwix-manage.exe
Index  Algorithm  Timestamp
========================================
0      sha256     RFC3161

Successfully verified: C:\Users\reg\kiwix-manage.exe

# right click on file in Explorer should show Digital Signatures tab listing the certificate

Using Signtool (Windows only)

Signtool is the Microsoft tool we've been using to sign all our binaries with our previous, regular certificates. It is possible to continue to use it with our new certificate by installing SSL.com's Cloud Key Adapter. It's a Key Service Provider (KSP) for the CNG Interface (the standard for this). It acts as a virtual USB token provider.

  • Download and install Signtool (part of Windows SDK)
  • Download and extract eSigner CKA
  • Install and configure the CKA
# DIR is the target folder to install into
# TYPE is important to be able to sign without user interaction
# the rest is for headless install
PS> ./eSigner_CKA_Installer.exe /DIR="C:\esigner" /TYPE=automatic  /CURRENTUSER /VERYSILENT /SUPPRESSMSGBOXES

# configure the CKA with SSL.com credentials
PS> C:\esigner/eSignerCKATool.exe config -mode "product" -user "xxx" -pass "yyy" -totp "zzz" -key "C:\esigner\master.key" -r

# remove CKA downloaded certs from local certificates store (recommended before loading)
PS> C:\esigner/eSignerCKATool.exe unload
# download certs from SSL.com and load them into local certificates store
PS> C:\esigner/eSignerCKATool.exe load

# Confirm certificate has correctly been retrieved ; and copy its thumbprint
PS> Get-ChildItem Cert:\CurrentUser\My -CodeSigningCert
# can also be checked by launching certmgr.exe and looking into Personal/Certificates folder (use refresh if it was opened prior to load)

# sign as you would with signtool, bbb being the thumbprint of the certificate to use (retrieved just before)
PS> signtool.exe sign /fd sha256 /tr http://ts.ssl.com /td sha256 /sha1 bbb .\kiwix-serve.exe

With some Windows executable formats such as appx, msix, and possibly others, you will need to ensure that the subject name of the app's manifest (aka publisher) exactly matches the subject mane of the certificate. See https://learn.microsoft.com/en-gb/windows/win32/appxpkg/how-to-sign-a-package-using-signtool for more information.