Skip to content

Instantly share code, notes, and snippets.

@Jolg42
Created January 25, 2020 14:13
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Jolg42/201f75a3699f5742a9605170dc50bfbc to your computer and use it in GitHub Desktop.
Save Jolg42/201f75a3699f5742a9605170dc50bfbc to your computer and use it in GitHub Desktop.
Code Signing on macOS and Windows + Apple Notarization

macOS

Steps

  • What we want is to get a Developer Id https://developer.apple.com/developer-id/ to be able to sign the binaries for distribution.
  • The company needs to get an Apple Developer Account Membership for macOS for $99/y https://developer.apple.com/programs/enroll/
  • Apple needs a A D-U-N-S® Number to register the account, the person doing the registration will need to get in touch with somebody that knows the legal part.
  • The registration could take a couple days
  • When done, a certificate can be created for signing, you'll need to sync it with Xcode.
  • Now the binary can be signed, and the signature can be verified.
  • Wait... There is a new extra step now, called notarization! The idea is that the signed binary is sent to Apple for verification and Apple returns some metadata if success or fail
  • This metadata needs to be added to the binary using the stapler tool.
  • Then the binary is ready for distribution 🚀

Notarization process

See https://developer.apple.com/documentation/security/notarizing_your_app_before_distribution/customizing_the_notarization_workflow

Add password to keychain

See documentation for creating an app specific password

security add-generic-password -a "username@domain.com" -w REPLACE_WITH_THE_APP_SPECIFIC_PASSWORD -s "NOTARIZATION_PASSWORD"

Upload for notarization

xcrun altool --notarize-app --primary-bundle-id "com.bundlename.hello" --username "username@domain.com" --password "@keychain:NOTARIZATION_PASSWORD" --file ./the_file_to_notarize.zip

Verify status

xcrun altool --notarization-history 0 --username "username@domain.com" --password "@keychain:NOTARIZATION_PASSWORD"

Date                      RequestUUID                          Status  Status Code Status Message   
------------------------- ------------------------------------ ------- ----------- ---------------- 
2019-07-25 16:09:01 +0000 7147b28a-b277-4a7d-ab11-a2fb58239892 success 0           Package Approved

Get info about

xcrun altool --notarization-info 7147b28a-b277-4a7d-ab11-a2fb58239892 --username "username@domain.com" --password "@keychain:NOTARIZATION_PASSWORD"

2019-07-25 15:34:54.617 altool[60393:556446] No errors getting notarization info.

   RequestUUID: 7147b28a-b277-4a7d-ab11-a2fb58239892
          Date: 2019-07-25 16:09:01 +0000
        Status: success
    LogFileURL: <https://osxapps-ssl.itunes.apple.com/itunes-assets/Enigma123/v4/cf/59/3f/cf593.../developer_log.json?accessKey=156425....>
   Status Code: 0
Status Message: Package Approved

Note: Check the log file, even if notarization succeeds, because it might contain warnings that you can fix prior to your next submission.

Log File Example

    {
      "logFormatVersion": 1,
      "jobId": "7147b2...",
      "status": "Accepted",
      "statusSummary": "Ready for distribution",
      "statusCode": 0,
      "archiveFilename": "MyArchiveNameFile.zip",
      "uploadDate": "2019-07-25T16:09:01Z",
      "sha256": "77302a5f1e0c1c62a7191d72...",
      "ticketContents": [
        {
          "path": "MyArchiveNameFile.zip/App.dmg",
          "digestAlgorithm": "SHA-256",
          "cdhash": "e04310bf..."
        },
        {
          "path": "MyArchiveNameFile.zip/Installer.pkg",
          "digestAlgorithm": "SHA-1",
          "cdhash": "1ad88d..."
        }
      ],
      "issues": null
    }

Staple the Ticket to Your Distribution

xcrun stapler staple "File_to_staple"

See common errors: https://developer.apple.com/documentation/security/notarizing_your_app_before_distribution/resolving_common_notarization_issues

Handle Stapler Issues

You can resolve a few common stapler issues by upgrading your tools. In particular, if you see error -68 on macOS 10.13.x, you can resolve the issue by upgrading to macOS 10.14 or later. Alternatively, run the following command once to clear the Valid cache:

sudo killall -9 trustd; sudo rm /Library/Keychains/crls/valid.sqlite3

Full example (this can take a few minutes depending to the size of the file)

	echo "-> Upload file to Apple for Notarize process";
    xcrun altool --notarize-app --primary-bundle-id "com.bundlename.hello" --username "username@domain.com" --password "@keychain:NOTARIZATION_PASSWORD" --file "pathtofile"
	
	echo "-> Check status";
    xcrun altool --notarization-history 0 --username "username@domain.com" --password "@keychain:NOTARIZATION_PASSWORD"
	# Or for a specific id
    # xcrun altool --notarization-info REPLACE_WITH_ID --username "username@domain.com" --password "@keychain:NOTARIZATION_PASSWORD"
    
	echo "-> Staple file";
    xcrun stapler staple "the_file_to_notarize"

Alternative

An alternative is to use Mortennn/Notarize

For first time setup

What does Mortennn/Notarize actually do? Uses xcrun altool to upload the app package to Apple's servers. Waits for the app to be notarized. Checks every 30 seconds. Staples the app package with the generated certificate using xcrun stapler staple <path>

Windows

Steps

  • Get a Code Signign Certificate multiple options
    • Choose between OV and EV certificate
      • EV would be the best (if possible), it's more expensive but gets an INSTANT SmartScreen Reputation, the downside is that it's only available with Two Factor Authentication USB key: Private keys are stored on an external hardware token which is required in order to sign code, protecting your certificate from being exported and used by unauthorized personnel.
    • See Microsoft doc for more info https://docs.microsoft.com/en-us/windows-hardware/drivers/dashboard/get-a-code-signing-certificate
    • Get the certificate from a provider
      • I used ksoftware with an OV certificate, which is a reseller of Sectigo
      • The process involves a lot of legal stuff
      • When the legal process is done the certificate can be issued or sent if hardware token. (For my OV certificate I had to use Internet Explorer 😭)

Signing can be done on macOS like this for example with the OV certificate:

var path = require('path');
var signcode = require('signcode');
var keytar = require('keytar');

keytar.findPassword('code_signing_password').then(function (pass) {
    var options = {
        overwrite: true,
        cert: path.join(__dirname, 'CodeSigning-Certificate.p12'),
        path: path.join(process.argv[2]),
        password: pass
    };

    signcode.sign(options, function (error) {
        if (error) {
            console.error('!!! Signing failed - ERROR !!!', error.message);
        } else {
            console.log(options.path + ' is now signed.');
        }
    });
});
@j1mmie
Copy link

j1mmie commented May 5, 2023

I just went through... literally months of figuring all this stuff out. And this was STILL helpful. Thank you for sharing this!

@Jolg42
Copy link
Author

Jolg42 commented May 5, 2023

Thanks @j1mmie 😄 I don't need to do it anymore these days but I remember it was a bit painful! Good luck 🤞

@jbfaden
Copy link

jbfaden commented Jul 25, 2023

Thanks I'm also finding this useful!

@ericoporto
Copy link

to anyone finding this, altool has been deprecated in favor for notarytool

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment