Skip to content

Signing Application Packages

Jean-Christophe Fillion-Robin edited this page Dec 12, 2023 · 11 revisions

This document outlines the code signing and notarization process for Slicer on macOS and Windows platforms.

macOS

The Gatekeeper feature in macOS helps protect against malicious software. If a user runs an application downloaded from the internet, Gatekeeper verifies the application's digital signature as well as its notarization status and displays a warning if the verification fails. Reasons verification might fail include the app having been tampered with, or the app not having been signed & notarized at all.

The following steps guide the code signing and notarization process for macOS:

Code Signing

The steps described below are expected to be performed by a @kitware employee and requires to be connected to the internal network.

  • SSH to your.name@sign-srv-mac.kitware.com.

    To request an account, email Kitware Sysadmin cc'ing Jean-Christophe Fillion-Robin and Sam Horvath using the subject Grant access to sign-srv-mac.kitware.com to Your Name

    Once the account is created, log in through the console using RealVNC for full initialization and ensure the home directory created.

  • Download signing scripts:

    mkdir -p ~/tmp
    cd ~/tmp
    
    if [[ ! -e slicer-macos-codesign-scripts ]]; then
      git clone https://github.com/KitwareMedical/slicer-macos-codesign-scripts
    fi
  • Download the unsigned package:

    Set the download_url variable specifying the URL reported on CDash after clicking on the 📦 icon.

    download_url=https://slicer-packages.kitware.com/api/v1/file/hashsum/SHA512/17bb74c8fbad8ca11ad47b7209de5349c6561b8712e8161a8800bed045d0c6e821bb18f3ae4a019cf0ce02b5595b12b9d23dc8909ee5043e875731b3d5b985b8/download
    
    cd ~/tmp
    curl -L# $download_url -O -J
  • Verify the downloaded package:

    Replace X.Y.Z with the expected version.

    PACKAGE_NAME=Slicer
    PACKAGE_VERSION=X.Y.Z
    
    cd ~/tmp
    shasum -a 512 ./${PACKAGE_NAME}-${PACKAGE_VERSION}-macosx-amd64.dmg

    ⚠️ The computed checksum should match the one specified in the download URL.

  • Run signing script:

    Replace X.Y.Z with the expected version.

    PACKAGE_NAME=Slicer
    PACKAGE_VERSION=X.Y.Z
    PACKAGE_IDENTIFIER=org.slicer.slicer
    
    cd ~/tmp
    ./slicer-macos-codesign-scripts/sign.bash \
      ${PACKAGE_IDENTIFIER} ${PACKAGE_VERSION} \
      "Developer ID Application: Kitware Inc. (W38PE5Y733)" \
      "Developer ID Installer: Kitware Inc. (W38PE5Y733)" \
      ./${PACKAGE_NAME}-${PACKAGE_VERSION}-macosx-amd64.dmg

Notarization Initial Setup

Notarization

The following steps are expected to be performed by a @kitware employee and require to be connected to the internal network.

  • SSH to your.name@sign-srv-mac.kitware.com.

    Instructions for creating an account are documented in the Code Signing section.

  • Unlock the keychain:

    security unlock-keychain "$HOME/Library/Keychains/login.keychain"

    Source: https://docs.j7k6.org/osx-keychain-unlock-commandline/

  • Store the notarization credentials in the keychain:

    apple_id_email=<your-apple-id>
    team_id=<your-team-id> # "W38PE5Y733" is kitware team ID
    
    keychain_profile=notarytool-credentials
    
    xcrun notarytool store-credentials "$keychain_profile" --apple-id "$apple_id_email" --team-id "$team_id"
    

    The requested password corresponds to the application specific one created above in the Notarization Initial Setup.

  • Notarize

    apple_id_email=<your-apple-id>
    team_id=<your-team-id> # "W38PE5Y733" is kitware team ID
    
    PACKAGE_NAME=Slicer
    PACKAGE_VERSION=X.Y.Z
    
    keychain_profile=notarytool-credentials
    
    xcrun notarytool submit ./$PACKAGE_NAME-$PACKAGE_VERSION-macosx-amd64.dmg --keychain-profile "$keychain_profile" --wait

    The --keychain-profile "$keychain_profile" argument references the app-specific password stored in your keychain using notarytool store-credentials.

Notarization Troubleshoot

If notarization returns Gateway Timeout and an email titled Your Mac software was successfully notarized. was received, manually perform the stapling using:

xcrun stapler staple -v ./$PACKAGE_NAME-$PACKAGE_VERSION-macosx-amd64.dmg

Source: https://developer.apple.com/documentation/security/notarizing_macos_software_before_distribution/customizing_the_notarization_workflow#3087720

Notarization History and Info

You can look at your own notarization history like this:

$ xcrun altool --notarization-history -u $appleid -p @keychain:altool-notarize --asc-provider KitwareInc

To see detailed results from one of the runs, take its uuid:

$ xcrun altool --notarization-info $uuid -u $appleid -p @keychain:altool-notarize

It will print out a LogFileURL you can visit in a browser to get the results.

Code Signing Details

This section provides additional details that may be helpful to better understand the signing process.

Developer ID certificate

A Developer ID certificate is required to sign an application for distribution outside of the Mac App Store. Once a Slicer package is signed with this type of certificate, Gatekeeper's verification will succeed and users will be able to run the application without warnings.

Only the team agent for an organization in the Apple Developer program has authority to create Developer ID certificates. Certificates can be created using Xcode or on the Apple Developer site: https://developer.apple.com/account/mac/certificate/.

There are two types of Developer ID certificates:

  • The Developer ID Application certificate is used to sign installers in the .dmg format.
  • The Developer ID Installer certificate is used to sign installers in .pkg format.

Using a self-signed certificate as opposed to a Developer ID certificate is appropriate while testing the packaging process. To create a self-signed certificate, follow the steps in Obtaining a Signing Identity described in the section titled "To obtain a self-signed certificate using Certificate Assistant."

App identifier

Code signing an application requires a unique app identifier. If each new build of an application is signed using the same identifier, Gatekeeper will recognize new builds as being an updated version and will transparently run the updated version as usually without requested verification from the user.

The unique app identifiers are typically hierarchical names in reverse DNS notation. The default value for Slicer is org.slicer.slicer and the value for Slicer-based applications is set in the top-level CMakeLists.txt.

Authentication

Depending on the environment in which code signing is being performed, it may be necessary to take one or more of the following steps to use the codesign tool without user interaction (i.e. authentication):

  • Run security unlock-keychain
  • In Keychain Access, edit the certificate's private key to "allow all applications to access this item" (right click on the private key, then choose Get Info)
  • Add the signing certificate to the system keychain instead of the login keychain

Acknowledgments and History

  • 2023

    • Updated the Notarization section to use Kitware macOS signing server instead of developer workstation.

    • Added Code Signing Details section adapted from Prerequisites section originally written by Max Smolens and referenced below.

  • 2022

    • Renamed macos-codesign-scripts to slicer-macos-codesign-scripts

    • Transferred macos-codesign-scripts repository from jcfr GitHub user to KitwareMedical GitHub organization.

    • Jean-Christophe Fillion-Robin updated entitlements to support installing Slicer extensions or python packages providing unsigned libraries. See Slicer#6065

  • 2020: Jean-Christophe Fillion-Robin updated the signing script and included the required entitlements to support notarization.

  • 2018: Jean-Christophe Fillion-Robin created https://github.com/jcfr/macos-codesign-scripts adapted from an original script contributed by Chuck Atkins.

  • 2016: Max Smolens created the original page https://www.slicer.org/wiki/Documentation/Nightly/Developers/Mac_OS_X_Code_Signing.

Windows

The steps described below are expected to be performed by a @kitware employee and requires to be connected to the internal network.

Code Signing using SHA-256

For reference, the command below was used to sign the Slicer installers starting with version 4.6.

signtool.exe sign /f "C:\Users\dashboard\Downloads\codecert.pfx" /p <password> /fd sha256 /tr http://timestamp.digicert.com /td sha256 /v "C:\Users\dashboard\Downloads\installer.exe"

Then, with recent version of Slicer, the use of /f "C:\path\to\cert.pfx" /p <password> was switched with /a to support use of a hardware token.

/f specifies the path to the code signing certificate
/p specifies the password for the code signing certificate
/a select the best signing cert automatically
/fd specifies the file digest algorithm
/tr specifies the URL of the RFC-3161 timestamp server
/td specifies the digest algorithm to be used by the timestamp server
/v displays verbose output

Acknowledgments and History