How to sign a macOS app without Xcode

Thanks to the apple-platform-rs project you can sign your app without Xcode.

Thanks to the amazing apple-platform-rs [GitHub] project with the rcodesign CLI you can sign your app without Xcode. But you still need a 100$ developer account. Here are the steps:

1) Create a private key, this one must be protected.

openssl genrsa -out privatekey.pem 2048

2) Creating CSR (Code Signing Request)

rcodesign generate-certificate-signing-request --pem-file privatekey.pem --csr-pem-file request_to_apple.csr

3) Visit Apple Developer Portal to create a new certificate https://developer.apple.com/account/resources/certificates/add

Select "Developer ID Application", upload the request_to_apple.csr and then Download the generated developerID_application.cer to the same location as the private key. The certificate does not need to be protected.

4) Sign the app, in the following example we have an Application.app in the same folder

rcodesign sign --certificate-der-file "developerID_application.cer" --pem-file "privatekey.key" --code-signature-flags runtime Application.app

5) Next we want to "notarize" the application which means we upload it to Apple it will be scanned for virus or malicious code and then marked as safe.

In the App Store Connect Portal [link] create a new API key with access "Developer". Download the Key file, replace the ISSUER_ID and KEY_ID in the following command and run it. This will create a appstoreconnect.json that combines the credentials used for the API.

rcodesign encode-app-store-connect-api-key -o appstoreconnect.json "ISSUER_ID" "KEY_ID" "AuthKey_XXXXXXX.p8"

6) Submit the app for notarization

rcodesign notary-submit --api-key-file appstoreconnect.json --staple Application.app

7) Zip the result

zip -9 -y -r -q Application.zip "Application.app"

8) Test. If a mac downloads the zip file and opens it, there will be a confirmation dialog that mentions that the app is safe. 🎉

GitHub Action

To sign the app inside the Github Action

      - name: Mac Sign
        env: 
          # secrets are stored in Settings > Secrets and Variables, base64 encoded
          DEVELOPER_CERTIFICATE: ${{ secrets.DEVELOPER_CERTIFICATE }}
          DEVELOPER_PRIVATE_KEY: ${{ secrets.DEVELOPER_PRIVATE_KEY }}
          APPSTORE_CONNECT_JSON: ${{ secrets.APPSTORE_CONNECT_JSON }}
        shell: bash
        run: |
          set -ex
          echo $DEVELOPER_CERTIFICATE | base64 --decode > developerID_application.cer
          echo $DEVELOPER_PRIVATE_KEY | base64 --decode > privatekey.pem
          echo $APPSTORE_CONNECT_JSON | base64 --decode > appstoreconnect.json
          wget -q https://github.com/indygreg/apple-platform-rs/releases/download/apple-codesign%2F0.26.0/apple-codesign-0.26.0-x86_64-unknown-linux-musl.tar.gz \
          && tar -xzvf apple-codesign-0.26.0-x86_64-unknown-linux-musl.tar.gz -C bin --strip-components=1          
          ./bin/rcodesign sign --verbose --certificate-der-file "developerID_application.cer" --pem-file "privatekey.pem" --code-signature-flags runtime ./build/mac/$EXPORT_NAME.app
          ./bin/rcodesign notary-submit --api-key-file appstoreconnect.json --staple ./build/mac/$EXPORT_NAME.app
          cd ./build/mac/
          zip -9 -y -r -q $EXPORT_NAME.zip $EXPORT_NAME.app