Skip to main content

Scripts for Apple signing using CryptoTokenKit (CTK) on GitHub

Download and set up the DigiCert​​®​​ Software Trust Manager CryptoTokenKit on the GitHub hosted Apple virtual machine (VM) for signing.

Prerequisites

  • DigiCert​​®​​ Software Trust Manager CryptoTokenKit

  • DigiCert​​®​​ Software Trust Manager credentials

  • DigiCert​​®​​ Software Trust Manager client tools

  • An Apple certificate

  • A GitHub repository

Software Trust Manager account

You must have access to DigiCert ONE to use the client tools and connect to DigiCert​​®​​ Software Trust Manager for operations. If you do not have access to DigiCert​​®​​ Software Trust Manager (STM), contact an administrator for DigiCert ONE and request access.

User authentication

DigiCert​​®​​ Software Trust Manager requires multifactor authentication. You will need to set up two credential types, namely an API token and an authentication certificate before you can access keypairs, certificates, and to sign code.

Create an API token

The API token is an authentication method used to verify the user and their permissions as set in DigiCert ONE. The client authentication provides the first factor authentication.

To generate an API token:

  1. Sign in to DigiCert ONE.

  2. Select the profile icon.

  3. Select Admin Profile.

  4. Scroll down to API Tokens.

  5. Select Create API token.

    Anmerkung

    The information shown after creating an API token cannot be accessed again, securely store all the information specified on the screen to use it later.

Create an authentication certificate

The client authentication certificate is an authentication method used to verify the user and their permissions as set in DigiCert ONE. The client authentication certificate provides the second factor authentication.

To create a client authentication certificate:

  1. Sign in to DigiCert ONE.

  2. Navigate to Profile icon > Admin Profile.

  3. Scroll down to Authentication certificates.

  4. Select Create authentication certificate.

    Anmerkung

    The information shown after creating an client authentication certificate cannot be accessed again, securely store all the information specified on the screen to use it later.

Authorization

Permissions

Select the required permissions for the user to use the client tools and perform operations with DigiCert​​®​​ Software Trust Manager. To remain compliant, the administrator must enable multifactor authentication for the user.

The following permissions are required:

  • Generate keypair

  • View keypair

  • Import keypair

  • Sign

  • View certificate

  • Generate certificate

  • Manage certificate

  • Manage certificate hierarchy

  • Import certificate

Best practices for secure GitHub use

Use secrets and secure files to ensure security and accountability among your GitHub users when they use DigiCert​​®​​ Software Trust Manager to sign code. The code examples later assume that you are using secrets and secure files.

GitHub Secrets

Secrets are variables in GitHub encrypted so users can input information without knowing what the value of that information is. For example, with API keys, you do not want all of your GitHub collaborators knowing what your unique API key is, but they may need to use it to use signing tools through DigiCert​​®​​ Software Trust Manager . You can set up a variable where "(api_key)" is the name and the value is the API key itself.

Set certificate file in environment variables

To download the certificate from DigiCert​​®​​ Software Trust Manager:

  1. Sign in to DigiCert ONE.

  2. Navigate to DigiCert​​®​​ Software Trust Manager > Certificates.

  3. Click on the certificate alias that you want to download.

  4. Select the download icon next to the Certificate field.

To add a certificate to GitHub secrets, you need to encode the certificate to a base64 string.

To encode the certificate file to base 64, run:

base64 file_name

Configure GitHub Secrets

The client tools need these environment variables to connect with DigiCert​​®​​ Software Trust Manager.

To integrate environment variables as GitHub secrets:

  1. Access GitHub repository.

  2. Navigate to: Settings > Secrets > Actions.

  3. Select New repository secret.

  4. Enter the following environment variables:

    Environment variables

    Description

    SM_CLIENT_CERT_PASSWORD

    The password from client authentication certificate setup.

    SM_CLIENT_CERT_FILE_B64

    The base64 encoded text of certificate downloaded from client authentication certificate setup.

    SM_HOST

    The path to the DigiCert ONE portal with client authorization. 

    Anmerkung

    In most cases, this path stays as it is unless you are connecting to a self-hosted instance of the DigiCert ONE product.

    SM_API_KEY

    The API token generated during API token setup.

    SM_CODE_SIGNING_CERT_SHA1_HASH

    The certificate fingerprint.

Anmerkung

The SM_HOST value you use for the commands below will depend on whether you are using demo or prod.

Tabelle 1. SM_HOST values

Country

Host type

SM_HOST value

United States of America (USA)

Demo

https://clientauth.demo.one.digicert.com

Production

https://clientauth.one.digicert.com

Switzerland (CH)

Demo

https://clientauth.demo.one.ch.digicert.com

Production

https://clientauth.one.ch.digicert.com

Japan (JP)

Demo

https://clientauth.demo.one.digicert.co.jp

Production

https://clientauth.one.digicert.co.jp

Netherlands (NL)

Demo

https://clientauth.demo.one.nl.digicert.com

Production

https://clientauth.one.nl.digicert.com


Commands to set environment variables

Once you save the variable, it is fully encrypted. Not even the creator of the value (you) can see the value. Make sure you save it elsewhere if it is something you will need in the future.

To set the API token as a new repository secret:

Name

SM_ SM_API_KEY

Value

Insert the API token you created.

To set the client authentication certificate as a new repository secret:

Name

SM_CLIENT_CERT_FILE_B64

Value

Insert the base 64 encoded string you generating when creating the client authentication certificate.

To set the client authentication certificate as a new repository secret:

Name

SM_CLIENT_CERT_PASSWORD

Value

Insert the password you were shown when creating the client certificate password.

YAML command to set up the certificate file for signing:

- name: Setup Certificate
  run: |
    echo "${{ secrets.SM_CLIENT_CERT_FILE_B64 }}" | base64 -D > Certificate_pkcs12.p12
    mv Certificate_pkcs12.p12 /Users/runner/Downloads/Certificate_pkcs12.p12
    chmod 777 /Users/runner/Downloads/Certificate_pkcs12.p12

Set up CryptoTokenKit

To properly understand how to set up the CryptoTokenKit, refer to the CryptoTokenKit CLI tool documentation.

Client tool setup

To install the DigiCert​​®​​ Software Trust Manager client tools:

  1. Sign in to DigiCert ONE.

  2. Navigate to DigiCert​​®​​ Software Trust Manager > Resources > Client tool repository.

  3. Download DigiCert​​®​​ Software Trust Manager CryptoTokenKit (portable zip).

  4. Add the zip file in the GitHub repository.

To access the client tools from GitHub actions:

  1. Unzip the DigiCert​​®​​ Software Trust Manager CryptoTokenKit.

  2. Move the DigiCert SSM Signing Clients.app to /Applications folder.

YAML command to install the Apple Client tools:

- name: Apple ClientTools Installation
  run: |
    unzip "DigiCert SSM Signing Clients.zip"
    sudo mv "DigiCert SSM Signing Clients/DigiCert SSM Signing Clients.app"  "/Applications/DigiCert SSM Signing Clients.app"
    chmod 777 "/Applications/DigiCert SSM Signing Clients.app"
    mkdir dist

Set up CryptoTokenKit in GitHub Actions

The DigiCert​​®​​ Software Trust Manager CryptoTokenKit is an implementation of the Apple CryptoTokenKit extension used to sign Apple binaries.

YAML command to register a new token driver:

- name: Register a new token driver
  run: |
    open "/Applications/DigiCert SSM Signing Clients.app"
    pluginkit -a "/Applications/DigiCert SSM Signing Clients.app/Contents/PlugIns/TokenExtension.appex"

YAML command to verify the token driver:

- name: Verify the token driver
  run: |
    pluginkit -m -v -p com.apple.ctk-tokens

YAML command to create a symlink to run the tool:

- name: Create a symlink
  run: |
    ln -s "/Applications/DigiCert SSM Signing Clients.app/Contents/MacOS/DigiCert SSM Signing Clients" DigicertSmctl
    ./DigicertSmctl smctl

Add environment variables

You can add different DigiCert​​®​​ Software Trust Manager credentials to your macOS keychain by using the environment command.

YAML command to add the environment variables:

- name: Add an environment variables
  run: |
    ./DigicertSmctl smctl environment add --host ${{ secrets.SM_HOST }} --api-key ${{ secrets.SM_API_KEY }} --client-certificate-file /Users/runner/Downloads/Certificate_pkcs12.p12 --client-certificate-password ${{ secrets.SM_CLIENT_CERT_PASSWORD }}
    ./DigicertSmctl smctl environment show 

Token management

You must add a token so that you can add keys which is used for codesign and productsign.

YAML command for adding the token:

- name: Add a token
  run: |
    ./DigicertSmctl smctl token add-token

Keypair management

To create a keypair for codesign and product sign:

  1. Sign in to DigiCert ONE®.

  2. Navigate to DigiCert​​®​​ Software Trust Manager > Keypairs > Create keypair.

YAML command to fetch the keypair from DigiCert​​®​​ Software Trust Manager and add them to the token present on the MacOS:

- name: Add keypairs
  run: |
    ./DigicertSmctl smctl keypair add-keys Apple_CodeSign Apple_ProductSign

Keypair verification

YAML command to verify the keypair added to token:

- name: Verify keys added to the token
  run: |
    security export-smartcard

Codesign signing and verification

The following command requires:

  • The Apple developer identity.

  • The path to the file to be signed.

YAML command for codesign signing and verifying:

- name : Codesign Signing
  run: |
    /usr/bin/codesign --deep --force --verify --verbose --sign "<Apple Developer ID>" --options runtime “<Path to app bundle>”
    /usr/bin/codesign -dv --verbose <path to signed file> 

Product signing and verification

The following command requires:

  • The Apple developer identity.

  • The path to the file to be signed.

  • Path where signed file should be stored

- name: Productsign Signing
  run: |
    /usr/bin/productsign --sign "<Apple Developer ID>" <Unsigned file path> <Signed output file path>    
    pkgutil --check-signature <path to signed file> 

Apple code signing sample

YAML script for signing apple files using codesign and productsign:

- name: 'build and release electron installer'
on:
  push:
    tags:
      - 'v*'
      
jobs:
  release:
    runs-on: ${{ matrix.os }}
    
    strategy:
      matrix:
        os: [macOS-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: Setup Certificate
        run: |
          echo "${{ secrets.SM_CLIENT_CERT_FILE_B64 }}" | base64 -D > Certificate_pkcs12.p12
          mv Certificate_pkcs12.p12 /Users/runner/Downloads/Certificate_pkcs12.p12
          chmod 777 /Users/runner/Downloads/Certificate_pkcs12.p12

      - name: Apple ClientTools Installation
        run: |
          unzip "DigiCert SSM Signing Clients.zip"
          sudo mv "DigiCert SSM Signing Clients/DigiCert SSM Signing Clients.app"  "/Applications/DigiCert SSM Signing Clients.app"
          chmod 777 "/Applications/DigiCert SSM Signing Clients.app"
          mkdir dist

      - name: Setup CryptoTokenKit
        run: |
          open "/Applications/DigiCert SSM Signing Clients.app"
          pluginkit -a "/Applications/DigiCert SSM Signing Clients.app/Contents/PlugIns/TokenExtension.appex"
          pluginkit -m -v -p com.apple.ctk-tokens
          ln -s "/Applications/DigiCert SSM Signing Clients.app/Contents/MacOS/DigiCert SSM Signing Clients" DigicertSmctl
          ./DigicertSmctl smctl
          ./DigicertSmctl smctl environment add --host ${{ secrets.SM_HOST }} --api-key ${{ secrets.SM_API_KEY }} --client-certificate-file /Users/runner/Downloads/Certificate_pkcs12.p12 --client-certificate-password ${{ secrets.SM_CLIENT_CERT_PASSWORD }}
          ./DigicertSmctl smctl environment show
          ./DigicertSmctl smctl token add-token
          ./DigicertSmctl smctl keypair add-keys Apple_CodeSign Apple_ProductSign
          security export-smartcard

      - name : Codesign Signing
        run: |
          mv UNSIGNED.app dist/UNSIGNED.app
          /usr/bin/codesign --deep --force --verify --verbose --sign "Apple Development: Rosemary Thomas (85W9468PYV)" --options runtime dist/UNSIGNED.app
          /usr/bin/codesign -dv --verbose dist/UNSIGNED.app

      - name: Productsign Signing
        run: |
          /usr/bin/productsign --sign "Developer ID Installer: Rosemary Thomas (DHPK4B64QS)" UNSIGNED_PKG.pkg dist/Signed.pkg
          pkgutil --check-signature dist/Signed.pkg

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