From 7bf4b21a8636880a7cc514d49c503fa809c5a94a Mon Sep 17 00:00:00 2001 From: Igor Hnizdo Date: Tue, 6 Sep 2022 18:37:37 +0200 Subject: [PATCH] Simplify signing, enable notarization I have simplified signing and enabled notarization in docker with rcodesign (a Rust-based tool, fully open-source; but it does connect to Apple servers for notarization). This tool enables notarization and signing fully in Docker on any OS, so it should work in CLI too. There is some prep-work that needs to be done on Mac OS side and on Apple website; but after that, the signing and notarization works automatically. It's not directly relevant to this commit, but I think you can also use it on Trezor Suite; a cursory glance there tells me that Trezor Suit is using electron-notarize, which needs to be run on Mac OS; rcodesign does not need that. Note that we need to use ldflags -s because of this issue of rcodesign https://github.com/indygreg/PyOxidizer/issues/636 --- .gitignore | 7 +++ release/macos/Dockerfile | 4 +- release/macos/Makefile | 6 ++- release/macos/certs/.empty | 0 release/macos/release.sh | 88 ++++++++++++++++++++++++++++---------- 5 files changed, 80 insertions(+), 25 deletions(-) create mode 100644 release/macos/certs/.empty diff --git a/.gitignore b/.gitignore index 683b8443..05dd66d0 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,13 @@ release/linux/privkey.asc release/linux/build/ release/macos/cert0* release/macos/key.pem +release/macos/certs/installer.passphrase +release/macos/certs/installer.p12 +release/macos/certs/app.passphrase +release/macos/certs/app.p12 +release/macos/certs/notarization-key-id +release/macos/certs/notarization-issuer-id +release/macos/certs/notarization-authkey.p8 release/macos/build/ release/windows/authenticode.* release/windows/build/ diff --git a/release/macos/Dockerfile b/release/macos/Dockerfile index a1028315..c6393c11 100644 --- a/release/macos/Dockerfile +++ b/release/macos/Dockerfile @@ -8,7 +8,7 @@ RUN dnf update -y # install tools -RUN dnf install -y gcc gcc-c++ git make gzip cpio findutils autoconf libxml2-devel openssl-devel +RUN dnf install -y gcc gcc-c++ git make gzip cpio findutils autoconf libxml2-devel openssl-devel cargo # build bomutils and xar from sources with fixes @@ -17,3 +17,5 @@ RUN cd xar && cd xar && ./autogen.sh --noconfigure && ./configure && make && mak RUN git clone https://github.com/BC-SECURITY/bomutils RUN cd bomutils && CFLAGS="-fsigned-char" make && make install + +RUN cargo install apple-codesign diff --git a/release/macos/Makefile b/release/macos/Makefile index d93f6f5b..c8188e89 100644 --- a/release/macos/Makefile +++ b/release/macos/Makefile @@ -16,19 +16,21 @@ clean: .binary: $(info Building with crossbuild ...) mkdir -p build + # we need to use ldflags because of this issue + # https://github.com/indygreg/PyOxidizer/issues/636 docker run -it --rm \ -v $(IMPORT_PATH):/trezord \ -w /trezord \ -e CGO_ENABLED=1 \ docker.elastic.co/beats-dev/golang-crossbuild:1.19-darwin-debian10 \ - --build-cmd "go build -o release/macos/build/trezord-amd64" \ + --build-cmd "go build -o release/macos/build/trezord-amd64 -ldflags=-s" \ -p "darwin/amd64" docker run -it --rm \ -v $(IMPORT_PATH):/trezord \ -w /trezord \ -e CGO_ENABLED=1 \ docker.elastic.co/beats-dev/golang-crossbuild:1.19-darwin-arm64-debian10 \ - --build-cmd "go build -o release/macos/build/trezord-arm64" \ + --build-cmd "go build -o release/macos/build/trezord-arm64 -ldflags=-s" \ -p "darwin/arm64" docker run -it --rm \ -v $(IMPORT_PATH):/trezord \ diff --git a/release/macos/certs/.empty b/release/macos/certs/.empty new file mode 100644 index 00000000..e69de29b diff --git a/release/macos/release.sh b/release/macos/release.sh index 61db00df..dac62d7f 100755 --- a/release/macos/release.sh +++ b/release/macos/release.sh @@ -1,5 +1,39 @@ #!/bin/sh +# In order to get the necessary files for signing and notarization, we need to do a lot of work: +# 1) register as Apple developer, get signing certificate from Apple +# (can take months for organizations; it is fast for individuals, but costs money) +# 2) On Mac, install XCode, generate certificates with type "Developer ID Installer" +# 3) On Mac, still in XCode, right-click in on the cert and select "export", That creates installer.p12 file (with passphrase) +# 4) Put the file to installer.p12 in certs/ dir, so as `certs/installer.p12`` +# 5) Put the passphrase to certs/installer.passphrase (without newline at the end) +# 6) Then do the same, but with type "Developer ID Application" +# 7) Put those to certs/app.passphrase and certs/app.p12 +# +# You will need App Store Connect API. To do that: +# 8) Go to https://appstoreconnect.apple.com/access/api +# 9) Select a user +# 10) Click on "keys", "Request access", "agree", "submit", "gereate API key" +# 11) Select "Developer" role, "Generate" +# 12) you will need to save "Issuer ID", "Key ID" and the API key (which will be PEM) +# 13) now, save +# a) issuer ID to "certs/notarization-issuer-id" +# b) key ID to "certs/notarization-key-id" +# c) key to "certs/notarization-authkey.p8" + +# In all, there should be those 8 files in certs +# 1. installer.passphrase +# 2. installer.p12 +# 3. app.passphrase +# 4. app.p12 +# 5. notarization-authkey.p8 +# 6. notarization-issuer-id +# 7. notarization-key-id +# 8. .empty (invisible file to keep folder in git) + + + + # Recommended reading for flat packages: # https://matthew-brett.github.io/docosx/flat_packages.html # http://bomutils.dyndns.org/tutorial.html @@ -9,6 +43,12 @@ set -ex +PATH=$PATH:~/.cargo/bin +SIGN_APP_PASSPHRASE_F=/release/certs/app.passphrase +SIGN_APP_CERT=/release/certs/app.p12 +SIGN_INSTALLER_PASSPHRASE_F=/release/certs/installer.passphrase +SIGN_INSTALLER_CERT=/release/certs/installer.p12 + cd $(dirname $0) TARGET=$1 @@ -47,6 +87,11 @@ cd .. rm -rf /release/build/flat-uninstall +if [ -r $SIGN_INSTALLER_PASSPHRASE_F ]; then + rcodesign sign --p12-file $SIGN_INSTALLER_CERT --p12-password-file $SIGN_INSTALLER_PASSPHRASE_F uninstall.pkg +fi + + # second, make installer and add trezord and uninstaller rm -rf /release/build/flat-install @@ -60,6 +105,10 @@ rm -r scripts mv Scripts-zip Scripts cd payload +if [ -r $SIGN_INSTALLER_APP_F ]; then + rcodesign sign --p12-file $SIGN_APP_CERT --p12-password-file $SIGN_APP_PASSPHRASE_F --code-signature-flags runtime /release/build/trezord +fi + cp /release/build/trezord Applications/Utilities/TREZOR\ Bridge/ cp ../../../uninstall.pkg Applications/Utilities/TREZOR\ Bridge/ @@ -87,29 +136,24 @@ rm uninstall.pkg mv install.pkg $INSTALLER -# In order to get the necessary files for signing, do the following: -# 1) register as Apple developer, get signing certificate from Apple (can take months) -# 2) On Mac, install XCode, generate certificates with type "Developer ID Installer" -# 3) On Mac, still in XCode, right-click in on the cert and select "export", That creates cert.p12 file (with passphrase) -# 4) On Mac, do `productsign --sign 'Developer ID Installer: YourDeveloperId' 'unsigned-package.pkg' 'signed-package.pkg'` -# where YourDeveloperId is your developer ID and unsigned-package is an unsigned package (this needs to be done only once) -# 5) Copy the cert.p12 and signed-package.pkg to Linux -# 6) On linux, do `mkdir certs ; xar -f signed-package.pkg --extract-certs certs`, that puts cert00, cert01 and cert02 in the certs dir -# 7) On linux, do `openssl pkcs12 -in cert.p12 -nodes | openssl rsa -out key.pem`, that creates key.pem -# The cert00, cert01 and cert02 files can now be used for pkg signing. +# sign the installer +if [ -r $SIGN_INSTALLER_PASSPHRASE_F ]; then + rcodesign sign --p12-file $SIGN_INSTALLER_CERT --p12-password-file $SIGN_INSTALLER_PASSPHRASE_F $INSTALLER +fi -# sign the installer -PRIVKEY=/release/key.pem -if [ -r $PRIVKEY ]; then - SIGNLEN=$(: | openssl dgst -sign $PRIVKEY -binary | wc -c) - xar --sign -f $INSTALLER --digestinfo-to-sign digestinfo.dat \ - --sig-size $SIGNLEN \ - --cert-loc /release/cert00 \ - --cert-loc /release/cert01 \ - --cert-loc /release/cert02 - openssl rsautl -sign -inkey $PRIVKEY -in digestinfo.dat -out signature.dat - xar --inject-sig signature.dat -f $INSTALLER - rm -f signature.dat digestinfo.dat +NOT_KEY_ID_F=/release/certs/notarization-key-id +NOT_ISSUER_ID_F=/release/certs/notarization-issuer-id +NOT_AUTHKEY=/release/certs/notarization-authkey.p8 +if [ -r $NOT_KEY_ID_F ]; then + NOT_KEY_ID=$(cat $NOT_KEY_ID_F) + NOT_ISSUER_ID=$(cat $NOT_ISSUER_ID_F) + NOT_JSON=not-data.json + rcodesign encode-app-store-connect-api-key -o $NOT_JSON $NOT_ISSUER_ID $NOT_KEY_ID $NOT_AUTHKEY + rcodesign notary-submit \ + --api-key-path $NOT_JSON \ + --staple \ + $INSTALLER + rm $NOT_JSON fi