Skip to content

Commit 45d7611

Browse files
committed
Upload the macOS App Store accepted
o Must sign with "Developer ID...", not "3rd Party Mac Developer" (See if pyinstaller direct signing works w/ correct sig. key) o .pkg doesn't work; only .zip of bare .app
1 parent b2360dd commit 45d7611

File tree

5 files changed

+265
-28
lines changed

5 files changed

+265
-28
lines changed

GNUmakefile

Lines changed: 181 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,12 @@
44

55
# Change to your own Apple Developer ID, if you want to code-sign the resultant .app
66
TEAMID ?= ZD8TVTCXDS
7-
DEVID ?= Developer ID Application: Perry Kundert ($(TEAMID))
7+
DEVID ?= 3rd Party Mac Developer Application: Perry Kundert ($(TEAMID))
8+
DEVIDLOC ?= Developer ID Application: Perry Kundert ($(TEAMID))
89
PKGID ?= 3rd Party Mac Developer Installer: Perry Kundert ($(TEAMID))
910
BUNDLEID ?= ca.kundert.perry.SLIP39
11+
APIISSUER ?= 5f3b4519-83ae-4e01-8d31-f7db26f68290
12+
APIKEY ?= 5H98J7LKPC
1013

1114
# PY[3] is the target Python interpreter. It must have pytest installed.
1215
PY3 ?= python3
@@ -61,6 +64,8 @@ dist/slip39-$(VERSION)-py3-none-any.whl: build-check FORCE
6164
install: dist/slip39-$(VERSION)-py3-none-any.whl FORCE
6265
$(PY3) -m pip install --force-reinstall $<[gui,serial,json]
6366

67+
# Building a macOS App
68+
6469

6570
app: dist/SLIP39.app
6671

@@ -76,8 +81,8 @@ app-pkg-signed: dist/SLIP39-$(VERSION)-signed.pkg
7681
# See: https://gist.github.com/txoof/0636835d3cc65245c6288b2374799c43
7782
# See: https://wiki.lazarus.freepascal.org/Code_Signing_for_macOS
7883
app-upload: dist/SLIP39-$(VERSION).app.zip
79-
xcrun altool --validate-app -f $< -t osx --apiKey 5H98J7LKPC --apiIssuer 5f3b4519-83ae-4e01-8d31-f7db26f68290 \
80-
&& xcrun altool --upload-app -f $< -t osx --apiKey 5H98J7LKPC --apiIssuer 5f3b4519-83ae-4e01-8d31-f7db26f68290 \
84+
xcrun altool --validate-app -f $< -t osx --apiKey $(APIKEY) --apiIssuer $(APIISSUER) \
85+
&& xcrun altool --upload-app -f $< -t osx --apiKey $(APIKEY) --apiIssuer $(APIISSUER)
8186

8287
# dist/SLIP39-$(VERSION).pkg: dist/SLIP39.app FORCE
8388
# pkgbuild --install-location /Applications --component $< $@
@@ -92,38 +97,95 @@ app-upload: dist/SLIP39-$(VERSION).app.zip
9297
# codesign -vvvv -R="anchor apple" $</Contents/MacOS/Python
9398

9499
# doesn't work... code is not signed by an apple-anchored Dev. ID
95-
dist/SLIP39-$(VERSION).pkg: dist/SLIP39.app FORCE
100+
#
101+
# Create the .pkg, ensuring that the App was created and signed appropriately
102+
# o Sign this w/ the ...Developer ID?
103+
# - Nope: "...An installer signing identity (not an application signing identity) is required for signing flat-style products."
104+
# See: https://lessons.livecode.com/m/4071/l/876834-signing-and-uploading-apps-to-the-mac-app-store
105+
# o Need ... --product <path-to-app-bundle-Info.plist>
106+
dist/SLIP39-$(VERSION).pkg: dist/SLIP39.app \
107+
dist/SLIP39.app-signed
108+
productbuild --sign "$(PKGID)" --timestamp \
109+
--identifier "$(BUNDLEID).pkg" \
110+
--version $(VERSION) \
111+
--component $< /Applications \
112+
$@
113+
xcrun altool --validate-app -f $@ -t osx --apiKey $(APIKEY) --apiIssuer $(APIISSUER)
114+
115+
dist/SLIP39.pkg: dist/SLIP39.app # dist/SLIP39.app-signed
116+
echo "Checking signature..."; ./SLIP39.metadata/check-signature $<
96117
productbuild --sign "$(PKGID)" --timestamp \
97118
--identifier "$(BUNDLEID).pkg" \
98119
--version $(VERSION) \
99120
--component $< /Applications \
100121
$@
101-
xcrun altool --validate-app -f $@ -t osx --apiKey 5H98J7LKPC --apiIssuer 5f3b4519-83ae-4e01-8d31-f7db26f68290
122+
xcrun altool --validate-app -f $@ -t osx --apiKey $(APIKEY) --apiIssuer $(APIISSUER)
123+
124+
.PHONY: dist/SLIP39.pkg-verify
125+
dist/SLIP39.pkg-verify: dist/SLIP39.pkg
126+
@echo "\n\n*** Verifying signing of $<..."
127+
#codesign --verify -v $< \
128+
# || ( echo "!!! Unable to verify codesign: "; codesign --verify -vv $<; false )
129+
spctl --assess --type install --context context:primary-signature -vvv $< || \
130+
spctl --assess --type execute --context context:primary-signature -vvv $< || \
131+
spctl --assess --type open --context context:primary-signature -vvv $< || \
132+
spctl --assess --type install -vvv $< || \
133+
spctl --assess --type execute -vvv $< || \
134+
spctl --assess --type open -vvv $<
102135

103-
dist/SLIP39-$(VERSION)-signed.pkg: dist/SLIP39-$(VERSION).pkg
136+
137+
#
138+
# Sign the pkg with the Installer ID, if not already done.
139+
#
140+
# o doesn't work -- notarization complains: "The binary is not signed with a valid Developer ID certificate."
141+
#
142+
dist/SLIP39-signed.pkg: dist/SLIP39.pkg FORCE
143+
@echo "\n\n*** Signing $<..."
104144
productsign --timestamp --sign "$(PKGID)" $< $@
105-
spctl -vv --assess --type install $@
106145

107146

108-
dist/SLIP39-$(VERSION).notarization: dist/SLIP39-$(VERSION).pkg
109-
xcrun altool --notarize-app -f $< \
147+
148+
# macOS Package Notarization
149+
# See: https://developer.apple.com/documentation/security/notarizing_macos_software_before_distribution/resolving_common_notarization_issues
150+
151+
dist/SLIP39.pkg.notarization: dist/SLIP39.pkg
152+
jq -r '.["notarization-upload"]["RequestUUID"]' $@ 2>/dev/null \
153+
|| xcrun altool --notarize-app -f $< \
110154
--team-id ZD8TVTCXDS \
111155
--primary-bundle-id ca.kundert.perry.SLIP39 \
112-
--apiKey 5H98J7LKPC --apiIssuer 5f3b4519-83ae-4e01-8d31-f7db26f68290 \
156+
--apiKey $(APIKEY) --apiIssuer $(APIISSUER) \
113157
--output-format json \
114158
> $@
115159

116-
dist/SLIP39-$(VERSION).status: FORCE # dist/SLIP39-$(VERSION).notarization
160+
dist/SLIP39.pkg.notarization-status: dist/SLIP39.pkg.notarization FORCE
117161
xcrun altool \
118-
--apiKey 5H98J7LKPC --apiIssuer 5f3b4519-83ae-4e01-8d31-f7db26f68290 \
119-
--notarization-info $$( jq -r '.["RequestUUID"]' < dist/SLIP39-$(VERSION).notarization ) \
162+
--apiKey $(APIKEY) --apiIssuer $(APIISSUER) \
163+
--notarization-info $$( jq -r '.["notarization-upload"]["RequestUUID"]' $< ) \
120164
| tee -a $@
121165

166+
dist/SLIP39.zip.notarization: dist/SLIP39.zip
167+
jq -r '.["notarization-upload"]["RequestUUID"]' $@ 2>/dev/null \
168+
|| xcrun altool --notarize-app -f $< \
169+
--team-id ZD8TVTCXDS \
170+
--primary-bundle-id ca.kundert.perry.SLIP39 \
171+
--apiKey $(APIKEY) --apiIssuer $(APIISSUER) \
172+
--output-format json \
173+
> $@
174+
175+
dist/SLIP39.zip.notarization-status: dist/SLIP39.zip.notarization FORCE
176+
xcrun altool \
177+
--apiKey $(APIKEY) --apiIssuer $(APIISSUER) \
178+
--notarization-info $$( jq -r '.["notarization-upload"]["RequestUUID"]' $< ) \
179+
| tee -a $@
122180

123181

124-
#(cd dist; zip -r SLIP39.app-$(VERSION).zip SLIP39.app)
125-
# Create a ZIP archive suitable for notarization.
126-
dist/SLIP39-$(VERSION).app.zip: dist/SLIP39.app FORCE
182+
183+
#
184+
# Package the macOS App as a Zip file for Notarization
185+
#
186+
# o Create a ZIP archive suitable for notarization.
187+
#
188+
dist/SLIP39.zip: dist/SLIP39.app
127189
rm -f $@
128190
# grep -q "CFBundleVersion" "$</Contents/Info.plist" || sed -i "" -e 's:<dict>:<dict>\n\t<key>CFBundleVersion</key>\n\t<string>0.0.0</string>:' "$</Contents/Info.plist"
129191
# sed -i "" -e "s:0.0.0:$(VERSION):" "$</Contents/Info.plist"
@@ -139,29 +201,126 @@ dist/SLIP39-$(VERSION).app.zip: dist/SLIP39.app FORCE
139201
/usr/bin/ditto -c -k --keepParent "$<" "$@"
140202
@ls -last dist
141203

204+
# Submit the macOS App Zip for notarization
205+
# o Must first set up an app-specific password at appleid.apple.com/account/manage
206+
# o This will produce a UUID; produces the same log of errors as the pkg flow, above...
207+
# - For each binary/library: "The binary is not signed with a valid Developer ID certificate."
208+
dist/SLIP39.zip-submit: dist/SLIP39.zip
209+
xcrun notarytool submit $< --wait --apple-id [email protected] --team-id ZD8TVTCXDS --password efzr-sigp-muun-oowc
210+
xcrun notarytool log 0bcc1c61-f5bb-4131-b412-557c3c027e9b --apple-id [email protected] --team-id ZD8TVTCXDS --password efzr-sigp-muun-oowc
211+
212+
#
213+
# The macOS gui APP
214+
#
142215
# Rebuild the gui App; ensure we discard any partial/prior build and gui artifacts The --onefile
143216
# approach doesn't seem to work, as we need to sign things after packaging. We need to customize
144217
# the SLIP39.spec file (eg. for version), so we do not target SLIP39.py (which would re-generate it
145218
# without our additions)
146219
#
147220
# Additional .spec file configurations:
148221
# - https://developer.apple.com/documentation/bundleresources/information_property_list/lsminimumsystemversion
149-
dist/SLIP39.app: SLIP39.spec images/SLIP39.icns
222+
#
223+
# o The codesign --verify succeeds w/ the '3rd Party Mac Developer Application ...', but not the spctl --assess?
224+
#
225+
.PHONY: dist/SLIP39.app-signed
226+
dist/SLIP39.app-signed: dist/SLIP39.app \
227+
dist/SLIP39.app-checkids
228+
@echo "\n\n*** Verifying codesigning of $<..."
229+
codesign --verify -v $< \
230+
|| ( echo "!!! Unable to verify codesign: "; codesign --verify -vv $<; false )
231+
spctl --assess --type install --context context:primary-signature -vvv $< || \
232+
spctl --assess --type execute --context context:primary-signature -vvv $< || \
233+
spctl --assess --type open --context context:primary-signature -vvv $< || true
234+
235+
.PHONY: dist/SLIP39.app-checkids
236+
dist/SLIP39.app-checkids: SLIP39.spec
237+
@echo "\n\n*** Checking Developer/Installer IDs for $(TEAMID) in $<..."
238+
security find-identity -vp macappstore
239+
security find-identity -vp macappstore | grep "$(DEVID)" \
240+
|| ( echo "!!! Unable to find Developer ID for signing: $(DEVID)"; false )
241+
security find-identity -vp macappstore | grep "$(PKGID)" \
242+
|| ( echo "!!! Unable to find Installer ID for signing: $(PKGID)"; false )
243+
244+
# Not necessary?
245+
# --options=runtime --timestamp
246+
#
247+
# For details on Signing Apps:
248+
# See: https://developer.apple.com/library/archive/technotes/tn2318/_index.html
249+
250+
# * In order for code signing to succeed, your code signing key(s) MUST have all of their dependent
251+
# (issuer) keys downloaded to your Keychain, from https://www.apple.com/certificateauthority.
252+
# - Use Keychain Access, right-click on your signing key and click Evaluate "...".
253+
# - Find each dependent key, and look at its SHA fingerprint, and then see if you have
254+
# that one in your System keychain, downloading all the named keys from apple 'til
255+
# you find the one with the matching fingerprint. Grr... Repeat 'til check-signature works.
256+
dist/SLIP39.app: SLIP39.spec \
257+
SLIP39.metadata/entitlements.plist \
258+
images/SLIP39.icns
259+
@echo "\n\n*** Rebuilding $@..."
150260
rm -rf build $@*
151261
sed -I "" -E "s/version=.*/version='$(VERSION)',/" $<
152262
sed -I "" -E "s/'CFBundleVersion':.*/'CFBundleVersion':'$(VERSION)',/" $<
153263
pyinstaller --noconfirm $<
264+
echo "Checking signature (pyinstaller signed)..."; ./SLIP39.metadata/check-signature $@ || true
265+
codesign --verify $@
266+
codesign --deep --force \
267+
--all-architectures --options=runtime --timestamp \
268+
--sign "$(DEVID)" \
269+
$@
270+
echo "Checking signature (app code signed)..."; ./SLIP39.metadata/check-signature $@ || true
271+
codesign --verify $@
272+
codesign --deep --force \
273+
--all-architectures --options=runtime --timestamp \
274+
--entitlements ./SLIP39.metadata/entitlements.plist \
275+
--sign "$(DEVID)" \
276+
$@
277+
echo "Checking signature (app code + entitlements signed w/ $(DEVID))..."; ./SLIP39.metadata/check-signature $@ || true
278+
codesign --verify $@
279+
codesign --deep --force \
280+
--all-architectures --options=runtime --timestamp \
281+
--entitlements ./SLIP39.metadata/entitlements.plist \
282+
--sign "$(DEVIDLOC)" \
283+
$@
284+
echo "Checking signature (app code + entitlements signed w/ $(DEVIDLOC))..."; ./SLIP39.metadata/check-signature $@ || true
285+
codesign --verify $@
286+
touch $@ # try to avoid unnecessary rebuilding
287+
288+
#
289+
# Only used for initial creation of SLIP39.spec; it must be customized, so this target cannot be
290+
# used to achieve a complete, operational SLIP39.spec file!
291+
#
292+
# Roughly, change:
293+
#
294+
# app = BUNDLE(coll,
295+
# name='SLIP39.app',
296+
# - icon=None,
297+
# + icon='images/SLIP39.icns',
298+
# + version='6.4.1',
299+
# + info_plist={
300+
# + 'CFBundleVersion':'6.4.1',
301+
# + 'LSApplicationCategoryType':'public.app-category.utilities',
302+
# + 'LSMinimumSystemVersion':'10.15.0',
303+
# + })
304+
# +
305+
# bundle_identifier='ca.kundert.perry.SLIP39')
154306

155-
# Only used for initial creation of SLIP39.spec.
156307
SLIP39.spec: SLIP39.py
308+
@echo "\n\n!!! Rebuilding $@; Must be manually edited..."
157309
pyinstaller --noconfirm --windowed \
158310
--codesign-identity "$(DEVID)" \
159311
--osx-bundle-identifier "$(BUNDLEID)" \
160312
--osx-entitlements-file ./SLIP39.metadata/entitlements.plist \
161313
--collect-data shamir_mnemonic \
162314
$<
315+
false
163316

317+
#
318+
# macOS Icons
319+
#
320+
# Requires a source images/SLIP39.png at least 1024x1024
321+
#
164322
# See: https://stackoverflow.com/questions/12306223/how-to-manually-create-icns-files-using-iconutil
323+
#
165324
images/SLIP39.icns: images/SLIP39.iconset
166325
iconutil --convert icns -o $@ $<
167326

@@ -180,10 +339,13 @@ images/SLIP39.iconset: images/SLIP39.png
180339
sips -z 1024 1024 $< --out $@/[email protected]
181340

182341

342+
#
343+
# Pypi pip packaging
344+
#
183345
# Support uploading a new version of slip32 to pypi. Must:
184346
# o advance __version__ number in slip32/version.py
185347
# o log in to your pypi account (ie. for package maintainer only)
186-
348+
#
187349
upload-check:
188350
@$(PY3) -m twine --version \
189351
|| ( echo "\n*** Missing Python modules; run:\n\n $(PY3) -m pip install --upgrade twine\n" \

SLIP39.metadata/check-signature

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
#!/bin/bash
2+
3+
# Copyright (c) 2011-2014 Apple Inc. All Rights Reserved.
4+
5+
# IMPORTANT NOTE: This file is licensed only for use on Apple-branded
6+
# computers and is subject to the terms and conditions of the Apple Software
7+
# License Agreement accompanying the package this file is a part of.
8+
# You may not port this file to another platform without Apple's written consent.
9+
10+
>&2 echo "(c) 2014 Apple Inc. All rights reserved."
11+
12+
bundle_installer_requirements='(anchor apple generic and
13+
certificate 1[subject.CN] = "Apple Software Update Certification Authority") or
14+
(anchor apple generic and certificate leaf[field.1.2.840.113635.100.6.1.10] exists) or
15+
(anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] exists and
16+
(certificate leaf[field.1.2.840.113635.100.6.1.14] or
17+
certificate leaf[field.1.2.840.113635.100.6.1.13]))'
18+
19+
app_requirements='(anchor apple) or
20+
(anchor apple generic and certificate leaf[field.1.2.840.113635.100.6.1.9] exists) or
21+
(anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] exists
22+
and certificate leaf[field.1.2.840.113635.100.6.1.13] exists)'
23+
24+
codesign=/usr/bin/codesign
25+
26+
build_version=$(sw_vers -buildVersion)
27+
v1=$(sed 's/^\([0-9]*\).*/\1/' <<< $build_version)
28+
v2=$(sed 's/^[0-9]*\([A-Z]\).*/\1/' <<< $build_version)
29+
30+
if [[ "$v1" -lt 13 || ( "$v1" -eq 13 && "$v2" < "F" ) ]]; then
31+
>&2 echo "This tool requires OS X Version 10.9.5 or higher."
32+
exit 3
33+
fi
34+
35+
ok=1
36+
for target; do
37+
use_codesign=1
38+
39+
if [[ $target == *.pkg || $target == *.mpkg ]]; then
40+
if [[ -d $target ]]; then
41+
>&2 echo "${target}: Warning: bundle installers are deprecated, please use regular installer packages."
42+
requirements=$bundle_installer_requirements
43+
else
44+
use_codesign=0
45+
46+
pkgutil_output=$(pkgutil --check-signature "$target" 2>&1)
47+
result=$?
48+
49+
[ $result -ne 0 ] && >&2 echo $pkgutil_output
50+
fi
51+
else
52+
requirements=$app_requirements
53+
fi
54+
55+
if [[ $use_codesign -eq 1 ]]; then
56+
$codesign -v --deep -R="${requirements}" "$target"
57+
result=$?
58+
59+
if [[ $result -eq 3 ]]; then
60+
>&2 echo "${target}: The target is not signed with Developer ID or by the Mac App Store."
61+
fi
62+
fi
63+
64+
[ $# -ne 1 ] && echo -n "${target}: "
65+
if [[ $result -eq 0 ]]; then
66+
echo YES
67+
else
68+
echo NO
69+
ok=0
70+
fi
71+
done
72+
73+
[ $ok -eq 1 ] && exit 0 || exit 2

SLIP39.metadata/entitlements.plist

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
33
<plist version="1.0">
44
<dict>
5-
<key>com.apple.security.app-sandbox</key>
6-
<true/>
5+
<key>com.apple.security.app-sandbox</key> <true/>
6+
<key>com.apple.security.files.user-selected.read-write</key> <true/>
7+
<key>com.apple.security.cs.allow-unsigned-executable-memory</key> <true/>
8+
<key>com.apple.security.cs.disable-executable-page-protection</key> <true/>
79
</dict>
810
</plist>

SLIP39.spec

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ exe = EXE(pyz,
3636
console=False,
3737
disable_windowed_traceback=False,
3838
target_arch=None,
39-
codesign_identity='Developer ID Application: Perry Kundert (ZD8TVTCXDS)',
39+
codesign_identity='3rd Party Mac Developer Application: Perry Kundert (ZD8TVTCXDS)',
4040
entitlements_file='SLIP39.metadata/entitlements.plist' )
4141
coll = COLLECT(exe,
4242
a.binaries,
@@ -49,11 +49,11 @@ coll = COLLECT(exe,
4949
app = BUNDLE(coll,
5050
name='SLIP39.app',
5151
icon='images/SLIP39.icns',
52-
bundle_identifier='ca.kundert.perry.SLIP39',
53-
version='6.4.1',
52+
version='6.5.3',
5453
info_plist={
55-
'CFBundleVersion':'6.4.1',
56-
'LSApplicationCategoryType':'public.app-category.utilities',
54+
'CFBundleVersion':'6.5.3',
55+
'LSApplicationCategoryType':'public.app-category.finance',
5756
'LSMinimumSystemVersion':'10.15.0',
58-
})
57+
},
58+
bundle_identifier='ca.kundert.perry.SLIP39')
5959

0 commit comments

Comments
 (0)