Code Signing
The identity is the same on every CI release, so users can verify what they downloaded:
codesign -dv --verbose=4 Justty.app
# expect Authority=Justty Self-Signed
codesign --verify --verbose=4 Justty.appSelf-signing does not satisfy Gatekeeper for downloads, which is why first launch needs the steps in First Launch.
Maintainers: create the identity#
You create it once, then export it into two GitHub secrets the release workflow imports.
The quick path from the repo root:
./Script/setup-signing.shThat creates the identity if it is missing and prints the gh secret set commands, or runs them when gh is already authed for the repo.
Manual creation#
openssl req -x509 -newkey rsa:2048 -nodes -days 3650 \
-keyout /tmp/justty-key.pem -out /tmp/justty-cert.pem \
-subj "/CN=Justty Self-Signed" \
-addext "basicConstraints=critical,CA:false" \
-addext "keyUsage=critical,digitalSignature" \
-addext "extendedKeyUsage=critical,codeSigning"
# OpenSSL 3 defaults break macOS `security import` — use classic PBE.
openssl pkcs12 -export -inkey /tmp/justty-key.pem -in /tmp/justty-cert.pem \
-name "Justty Self-Signed" -out /tmp/justty.p12 -passout pass:justty \
-keypbe PBE-SHA1-3DES -certpbe PBE-SHA1-3DES -macalg sha1
security import /tmp/justty.p12 -k ~/Library/Keychains/login.keychain-db \
-P justty -A -T /usr/bin/codesign
rm -f /tmp/justty-key.pem /tmp/justty-cert.pem /tmp/justty.p12Verify it landed:
security find-identity -p codesigning | grep "Justty Self-Signed"Maintainers: CI secrets#
P12_PASSWORD="$(openssl rand -hex 24)"; echo "password: $P12_PASSWORD"
security export -t identities -f pkcs12 \
-k ~/Library/Keychains/login.keychain-db \
-P "$P12_PASSWORD" -o /tmp/signing.p12
base64 -i /tmp/signing.p12 | tr -d '\n' > /tmp/signing.p12.base64
rm -f /tmp/signing.p12
gh secret set SIGNING_P12_BASE64 < /tmp/signing.p12.base64
gh secret set SIGNING_P12_PASSWORD --body "$P12_PASSWORD"
rm -f /tmp/signing.p12.base64Lost the secrets but still have the identity in your keychain? Re-export using the block above. Lost the identity entirely? Recreate it and redo the secrets. The Authority string stays Justty Self-Signed, but it is a new key.
Related#
- Homebrew Tap — how the cask clears quarantine for users
- Troubleshooting — what users see when Gatekeeper blocks a launch