Last active 1 month ago

create_cert.sh Raw
1#!/usr/bin/env bash
2# create_cert.sh — creates a local self-signed Mac code-signing certificate
3# Run once. Requires no Apple Developer account.
4
5set -euo pipefail
6
7CERT_NAME="${1:-"Local Mac Developer"}"
8KEYCHAIN_NAME="build.keychain"
9KEYCHAIN_PASS="keychain_pass" # change this
10P12_PASS="p12_pass" # change this
11
12echo "==> Creating build keychain: $KEYCHAIN_NAME"
13
14security delete-keychain "$KEYCHAIN_NAME" 2>/dev/null || true
15security create-keychain -p "$KEYCHAIN_PASS" "$KEYCHAIN_NAME" 2>/dev/null || true
16security set-keychain-settings -lut 21600 "$KEYCHAIN_NAME" # lock after 6 h
17security unlock-keychain -p "$KEYCHAIN_PASS" "$KEYCHAIN_NAME"
18
19# Add to keychain search list so tools can find it
20security list-keychains -d user -s "$KEYCHAIN_NAME" $(security list-keychains -d user | tr -d '"')
21
22echo "==> Generating self-signed certificate: '$CERT_NAME'"
23# Use Keychain Access UI approach (most reliable for self-signed)
24cat >/tmp/cert_req.cfg <<EOF
25[ req ]
26default_bits = 2048
27prompt = no
28default_md = sha256
29distinguished_name = dn
30x509_extensions = v3_req
31
32[ dn ]
33CN = $CERT_NAME
34
35[ v3_req ]
36keyUsage = digitalSignature
37extendedKeyUsage = codeSigning
38EOF
39
40# Generate key + cert via openssl, then import
41openssl req -x509 -newkey rsa:2048 -days 3650 -nodes \
42 -keyout /tmp/codesign.key \
43 -out /tmp/codesign.crt \
44 -config /tmp/cert_req.cfg
45
46# Bundle into PKCS#12
47openssl pkcs12 -export \
48 -inkey /tmp/codesign.key \
49 -in /tmp/codesign.crt \
50 -out /tmp/codesign.p12 \
51 -passout pass:"$P12_PASS" \
52 -legacy \
53 -keypbe PBE-SHA1-3DES \
54 -certpbe PBE-SHA1-3DES \
55 -macalg sha1
56
57# Import into build keychain (trust for code signing)
58security import /tmp/codesign.p12 \
59 -k "$KEYCHAIN_NAME" \
60 -P "$P12_PASS" \
61 -T /usr/bin/codesign \
62 -T /usr/bin/security
63
64# Grant codesign permission without UI prompt
65security set-key-partition-list \
66 -S apple-tool:,apple:,codesign: \
67 -s -k "$KEYCHAIN_PASS" "$KEYCHAIN_NAME"
68
69# Clean up temp files
70rm -f /tmp/codesign.key /tmp/codesign.crt /tmp/codesign.p12 /tmp/cert_req.cfg
71
72echo ""
73echo "✅ Certificate '$CERT_NAME' created in '$KEYCHAIN_NAME'."
74echo " Use this identity string in sign.sh:"
75security find-identity -v -p codesigning "$KEYCHAIN_NAME" | grep "$CERT_NAME" | head -1
76
sign.sh Raw
1#!/usr/bin/env bash
2# sign.sh — sign a single binary executable for local use or distribution
3# Usage: ./sign.sh path/to/mybinary
4
5set -euo pipefail
6
7# ── CONFIG ────────────────────────────────────────────────────────────────────
8BINARY_PATH="${1:?Usage: $0 path/to/mybinary}"
9CERT_IDENTITY="Local Mac Developer" # must match CN in create_cert.sh
10 # for real Apple certs use:
11 # "Developer ID Application: Your Name (TEAMID)"
12KEYCHAIN_PATH="build.keychain-db"
13KEYCHAIN_PASS="build_keychain_password" # must match create_cert.sh
14
15# For notarization (optional, set NOTARIZE=true to enable):
16NOTARIZE=false
17APPLE_ID="longnghia2.00@gmail.com"
18APPLE_TEAM_ID="PaulCoding"
19APPLE_APP_PASSWORD="some_password" # app-specific password from appleid.apple.com
20# ── END CONFIG ────────────────────────────────────────────────────────────────
21
22if [ ! -f "$BINARY_PATH" ]; then
23 echo "❌ File not found: $BINARY_PATH"
24 exit 1
25fi
26
27BINARY_NAME="$(basename "$BINARY_PATH")"
28ZIP_PATH="$(dirname "$BINARY_PATH")/${BINARY_NAME}.zip"
29
30echo "==> Unlocking build keychain"
31security unlock-keychain -p "$KEYCHAIN_PASS" "$KEYCHAIN_PATH"
32security list-keychains -d user -s "$KEYCHAIN_PATH" \
33 $(security list-keychains -d user | tr -d '"')
34
35# ── Sign ──────────────────────────────────────────────────────────────────────
36echo "==> Signing binary: $BINARY_NAME"
37codesign --sign "$CERT_IDENTITY" \
38 --keychain "$KEYCHAIN_PATH" \
39 --timestamp \
40 --options runtime \
41 --force \
42 "$BINARY_PATH"
43
44# ── Verify ────────────────────────────────────────────────────────────────────
45echo "==> Verifying signature"
46codesign --verify --strict --verbose=4 "$BINARY_PATH"
47
48echo "==> Signature details"
49codesign --display --verbose=4 "$BINARY_PATH" 2>&1
50
51echo "==> Gatekeeper assessment (self-signed certs will show 'rejected' — expected)"
52spctl --assess --type execute --verbose "$BINARY_PATH" 2>&1 || true
53
54# ── Optional: notarize ────────────────────────────────────────────────────────
55if [ "$NOTARIZE" = "true" ]; then
56 echo "==> Zipping binary for notarization submission"
57 ditto -c -k --keepParent "$BINARY_PATH" "$ZIP_PATH"
58
59 echo "==> Submitting to Apple notary service"
60 xcrun notarytool submit "$ZIP_PATH" \
61 --apple-id "$APPLE_ID" \
62 --team-id "$APPLE_TEAM_ID" \
63 --password "$APPLE_APP_PASSWORD" \
64 --wait
65
66 echo "==> Stapling notarization ticket"
67 xcrun stapler staple "$BINARY_PATH"
68 xcrun stapler validate "$BINARY_PATH"
69
70 rm -f "$ZIP_PATH"
71fi
72
73echo ""
74echo "✅ Done: $BINARY_PATH"
75codesign -dv "$BINARY_PATH" 2>&1 | grep -E "^(Authority|TeamIdentifier|Signature size|Hash|CDHash)"
76