Skip to main content

GitHub custom action for keypair signing

Code Signing with DigiCert​​®​​ Software Trust Manager GitHub action streamlines the keypair-based signing process, improving software security while seamlessly integrating with DevOps processes. This action supports signing binaries on both Windows and Linux platforms. It accelerates the installation and configuration of essential clients and signing tools, enabling developers to quickly become signing-ready for GitHub action workflows.

Prerequisites

User authentication

Software Trust Manager enforces multifactor authentication for security. To access keypairs, certificates, and sign code, you need to set up two types of credentials: an API token and an authentication certificate.

Create an API token

The API token is an authentication method used to verify you as a user and your permissions assigned in DigiCert ONE. The API token provides the first factor authentication.

Follow these steps to generate an API token:

  1. Sign in to DigiCert ONE.

  2. Select the profile icon (top-right).

  3. Select Admin Profile.

  4. Scroll down to API Tokens.

  5. Select  Create API token.

    Note

    The API token is only shown once, securely store the API key to use it later.

Create an authentication certificate

The client authentication certificate is an authentication method used to verify you as a user and your permissions assigned in DigiCert ONE. The client authentication certificate provides the second factor authentication.

Follow these steps to create a client authentication certificate:

  1. Sign in to DigiCert ONE.

  2. Select the profile icon (top-right).

  3. Select Admin Profile.

  4. Scroll down to Authentication certificates.

  5. Select Create authentication certificate.

    Note

    The client authentication certificate password shown after creating an client authentication certificate cannot be accessed again, download the certificate and securely store the password to use it later.

Convert your client authentication certificate to a base64 string

To add a client authentication certificate to GitHub secrets, it needs to be encoded as a base64 string. The following commands demonstrate how to achieve this based on your operating system.

Secure GitHub use

For secure GitHub usage with Software Trust Manager, we recommend using secrets and secure files. This ensures security and accountability for your GitHub users, particularly when they are using Software Trust Manager for code signing. Follow these instructions to set up GitHub secrets.

Note

The code examples provided in this article assumes that you are using secrets and secure files.

GitHub secrets

GitHub Secrets allows you to encrypt variables so users can input sensitive information without exposing the actual values. For example, you can hide your API keys while still allowing collaborators to use them for signing tools through Software Trust Manager. GitHub secrets are commonly used in GitHub Actions workflows to make sensitive or configuration-related information available to various steps without exposing it directly in the workflow file.

Configure GitHub secrets

Configure your credentials to encrypt them in GitHub Secrets and connect to DigiCert​​®​​ Software Trust Manager.

Note

When you save credentials as a secret, it becomes fully encrypted, even the creator (you) cannot access it. If you anticipate needing it in the future, be sure to store it separately.

Follow these steps to configure your credentials in GitHub secrets:

  1. Access GitHub repository.

  2. Navigate to: Settings > Secrets > Actions.

  3. Select New repository secret.

  4. Create a repository secret for each of the following credentials:

    Name

    Value

    SM_CLIENT_CERT_PASSWORD

    Insert the password that you were shown when you created your client authentication certificate above.

    SM_CLIENT_CERT_FILE_B64

    Insert the base64 encoded string of your client authentication certificate that you created above.

    SM_HOST

    The path to the DigiCert ONE portal with client authorization.  The SM_HOST value you use depends on whether you are using demo or prod.

    Tip

    For assistance, refer to host environment.

    SM_API_KEY

    Insert the API token you created above.

    SM_CODE_SIGNING_CERT_SHA1_HASH

    The certificate fingerprint.

Set up environment variables

Once you have stored your credentials in GitHub secrets, use the code snippets below to set up your environment variables.

Decode your base64-encoded client authentication certificate

Use the snippet below to decode your base64-encoded client authentication certificate stored in a GitHub secret (SM_CLIENT_CERT_FILE_B64) and saves it as a PKCS#12 certificate file named "Certificate_pkcs12.p12" in the /d/ directory for later use in the workflow.

- name: Set up certificate 

  run: | 
    echo "${{ secrets.SM_CLIENT_CERT_FILE_B64 }}" | base64 --decode > /d/Certificate_pkcs12.p12 
  shell: bash 

Configure environment variables

Use this code snippet to configure the necessary environment variables that are used in subsequent steps of this workflow to perform code signing.

- name: Set variables 
  id: variables 
  run: | 
    echo "::set-output name=version::${GITHUB_REF#refs/tags/v}" 
    echo "SM_HOST=${{ secrets.SM_HOST }}" >> "$GITHUB_ENV" 
    echo "SM_API_KEY=${{ secrets.SM_API_KEY }}" >> "$GITHUB_ENV" 
    echo "SM_CLIENT_CERT_FILE=D:\\Certificate_pkcs12.p12" >> "$GITHUB_ENV" 
    echo "SM_CLIENT_CERT_PASSWORD=${{ secrets.SM_CLIENT_CERT_PASSWORD }}" >> "$GITHUB_ENV" 
  shell: bash

Client tools setup

Follow these steps to set up DigiCert​​®​​ Software Trust Manager client tools securely.

Note

Ensure that the third-party signing tools you want to use are already installed before proceeding with this step.

Initiate the client tools setup

Use this code snippet to install and configure DigiCert​​®​​ Software Trust Manager client tools, including the SMCTL, the PKCS#11 library, and Software Trust Manager KSP library. The task also automatically writes the PKCS11 config file into the task variable.

- run: echo “The config file path ${{ steps.SSMClientToolSetup.outputs.PKCS11_CONFIG }}” 

Tip

During this task configuration step, you will be a prompt to input an API key. We recommend that you skip this and instead reference your API key stored in GitHub secrets in the code snippet below to add the API key.

Set your API key to GitHub secrets

Use this code snippet to set your (SM_API_KEY) environment variable to GitHub secrets so that it can be used by subsequent steps in this workflow. This approach helps maintain security while allowing flexibility in configuring workflows.

 - name: Get API key from GitHub secrets and save to environment variables
   id: variables
   run: |
     echo "SM_API_KEY=${{ secrets.SM_API_KEY }}" >> "$GITHUB_ENV"

KSP signing using GitHub action

Copy and paste the following workflow snippet into your .yml file to implement code signing with Software Trust Manager.

name: Sign with Software Trust Manager KSP

on: push

jobs: 
  release: 
    runs-on: ${{ matrix.os }} 

    strategy: 
      matrix: 
        os: [windows-latest,ubuntu-latest] 
         
    steps: 
      - name: Check out Git repository 
        uses: actions/checkout@v2 

      - name: Install Node.js, NPM and Yarn 
        uses: actions/setup-node@v2 
        with:  
          node-version: 14 

      - name: Build/release Electron app 
        uses: samuelmeuli/action-electron-builder@v1 
        with:  
          github_token: ${{ secrets.github_token }} 
          release: ${{ startsWith(github.ref, 'refs/tags/v') }} 
          build_script_name: dist  

      - name: NuGet Install 
        uses: NuGet/setup-nuget@v1.0.5 
        with: 
          nuget-version: latest 

      - name: Setup Certificate 
        run: | 
          echo "${{secrets.SM_CLIENT_CERT_FILE_B64 }}" | base64 --decode > /d/Certificate_pkcs12.p12 
          cat /d/Certificate_pkcs12.p12 
     shell: bash             

      - name: Set variables 
        id: variables 
        run: | 
          echo "::set-output name=version::${GITHUB_REF#refs/tags/v}" 
          echo "SM_HOST=${{ secrets.SM_HOST }}" >> "$GITHUB_ENV" 
          echo "SM_API_KEY=${{ secrets.SM_API_KEY }}" >> "$GITHUB_ENV" 
          echo "SM_CLIENT_CERT_FILE=D:\\Certificate_pkcs12.p12" >> "$GITHUB_ENV" 
          echo "SM_CLIENT_CERT_PASSWORD=${{ secrets.SM_CLIENT_CERT_PASSWORD }}" >> "$GITHUB_ENV" 
          echo "C:\Program Files (x86)\Windows Kits\10\App Certification Kit" >> $GITHUB_PATH 
          echo "C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools" >> $GITHUB_PATH 
          echo "C:\Program Files\DigiCert\DigiCert One Signing Manager Tools" >> $GITHUB_PATH 
        shell: bash  

      - name: Setup SSM KSP on windows latest 
        run: | 
          curl -X GET  https://one.digicert.com/signingmanager/api-ui/v1/releases/smtools-windows-x64.msi/download -H "x-api-key:%SM_API_KEY%" -o smtools-windows-x64.msi 
          msiexec /i smtools-windows-x64.msi /quiet /qn 
          smksp_registrar.exe list 
          smctl.exe keypair ls 
          C:\Windows\System32\certutil.exe -csp "DigiCert Signing Manager KSP" -key -user 
          smksp_cert_sync.exe 
        shell: cmd 

      - name: Signing using Signtool 
        run: | 
          signtool.exe sign /sha1 ${{ secrets.SM_CODE_SIGNING_CERT_SHA1_HASH }} /tr http://timestamp.digicert.com /td SHA256 /fd SHA256 "D:\a\github-action-electron\github-action-electron\dist\my-electron-app Setup ${{ steps.variables.outputs.version }}.exe" 
          signtool.exe verify /v /pa "D:\a\github-action-electron\github-action-electron\dist\my-electron-app Setup ${{ steps.variables.outputs.version }}.exe" 

      - name: Signing using Nuget 
        run: | 
          copy D:\a\github-action-electron\github-action-electron\UNSIGNED.nupkg D:\a\github-action-electron\github-action-electron\dist\UNSIGNED.nupkg 
          nuget sign "D:\a\github-action-electron\github-action-electron\dist\UNSIGNED.nupkg" -Timestamper http://timestamp.digicert.com -outputdirectory "D:\a\github-action-electron\github-action-electron\dist\Signed" -CertificateFingerprint ${{ secrets.SM_CODE_SIGNING_CERT_SHA1_HASH }} -HashAlgorithm SHA256 -Verbosity detailed -Overwrite 
          nuget verify -All "D:\a\github-action-electron\github-action-electron\dist\Signed\*" 

      - name: Signing using Mage 
        run: | 
          copy D:\a\github-action-electron\github-action-electron\UNSIGNED2.manifest D:\a\github-action-electron\github-action-electron\dist\UNSIGNED2.manifest 
          mage.exe -sign "D:\a\github-action-electron\github-action-electron\dist\UNSIGNED2.manifest" -CertHash ${{ secrets.SM_CODE_SIGNING_CERT_SHA1_HASH }} -a sha256RSA 
          mage -Verify "D:\a\github-action-electron\github-action-electron\dist\UNSIGNED2.manifest" 

      - name: Upload artifacts 
        uses: actions/upload-artifact@v2 
        with: 
          name: ${{ matrix.os }} 
          path: | 
            dist