iOS App 簽名
目的:
保證 iOS 平臺(tái)對(duì)第三方 APP 有絕對(duì)的控制權(quán),每一個(gè)安裝到 iOS 上的 APP 都是經(jīng)過蘋果官方允許的扎拣。
簽名過程
- 在你的 Mac 開發(fā)機(jī)器生成一對(duì)公私鑰赴肚,這里稱為公鑰L,私鑰L二蓝。L:Local
- 蘋果自己有固定的一對(duì)公私鑰誉券,跟上面 AppStore 例子一樣,私鑰在蘋果后臺(tái)刊愚,公鑰在每個(gè) iOS 設(shè)備上踊跟。這里稱為公鑰A,私鑰A鸥诽。A:Apple
- 把公鑰 L 傳到蘋果后臺(tái)商玫,用蘋果后臺(tái)里的私鑰 A 去簽名公鑰 L。得到一份數(shù)據(jù)包含了公鑰 L 以及其簽名牡借,把這份數(shù)據(jù)稱為證書拳昌。
- 在蘋果后臺(tái)申請(qǐng) AppID,配置好設(shè)備 ID 列表和 APP 可使用的權(quán)限钠龙,再加上第③步的證書炬藤,組成的數(shù)據(jù)用私鑰 A 簽名御铃,把數(shù)據(jù)和簽名一起組成一個(gè) Provisioning Profile 文件,下載到本地 Mac 開發(fā)機(jī)刻像。
- 在開發(fā)時(shí)畅买,編譯完一個(gè) APP 后,用本地的私鑰 L 對(duì)這個(gè) APP 進(jìn)行簽名细睡,同時(shí)把第④步得到的 Provisioning Profile 文件打包進(jìn) APP 里谷羞,文件名為 embedded.mobileprovision,把 APP 安裝到手機(jī)上溜徙。
- 在安裝時(shí)湃缎,iOS 系統(tǒng)取得證書,通過系統(tǒng)內(nèi)置的公鑰 A蠢壹,去驗(yàn)證 embedded.mobileprovision 的數(shù)字簽名是否正確嗓违,里面的證書簽名也會(huì)再驗(yàn)一遍。
- 確保了 embedded.mobileprovision 里的數(shù)據(jù)都是蘋果授權(quán)以后图贸,就可以取出里面的數(shù)據(jù)蹂季,做各種驗(yàn)證,包括用公鑰 L 驗(yàn)證APP簽名疏日,驗(yàn)證設(shè)備 ID 是否在 ID 列表上偿洁,AppID 是否對(duì)應(yīng)得上,權(quán)限開關(guān)是否跟 APP 里的 Entitlements 對(duì)應(yīng)等沟优。
概念和操作
上面的步驟對(duì)應(yīng)到我們平常具體的操作和概念是這樣的:
- 第 1 步對(duì)應(yīng)的是 keychain 里的 “從證書頒發(fā)機(jī)構(gòu)請(qǐng)求證書”涕滋,這里就本地生成了一對(duì)公私鑰,保存的 CertificateSigningRequest 就是公鑰挠阁,私鑰保存在本地電腦里宾肺。
- 第 2 步蘋果處理,不用管侵俗。
- 第 3 步對(duì)應(yīng)把 CertificateSigningRequest 傳到蘋果后臺(tái)生成證書锨用,并下載到本地。這時(shí)本地有兩個(gè)證書隘谣,一個(gè)是第 1 步生成的黔酥,一個(gè)是這里下載回來的,keychain 會(huì)把這兩個(gè)證書關(guān)聯(lián)起來洪橘,因?yàn)樗麄児借€是對(duì)應(yīng)的跪者,在XCode選擇下載回來的證書時(shí),實(shí)際上會(huì)找到 keychain 里對(duì)應(yīng)的私鑰去簽名熄求。這里私鑰只有生成它的這臺(tái) Mac 有渣玲,如果別的 Mac 也要編譯簽名這個(gè) App 怎么辦?答案是把私鑰導(dǎo)出給其他 Mac 用,在 keychain 里導(dǎo)出私鑰死嗦,就會(huì)存成 .p12 文件虱岂,其他 Mac 打開后就導(dǎo)入了這個(gè)私鑰回懦。
- 第 4 步都是在蘋果網(wǎng)站上操作,配置 AppID / 權(quán)限 / 設(shè)備等渺蒿,最后下載 Provisioning Profile 文件拗慨。
- 第 5 步 XCode 會(huì)通過第 3 步下載回來的證書(存著公鑰)陷寝,在本地找到對(duì)應(yīng)的私鑰(第一步生成的)搀捷,用本地私鑰去簽名 App星掰,并把 Provisioning Profile 文件命名為 embedded.mobileprovision 一起打包進(jìn)去。這里對(duì) App 的簽名數(shù)據(jù)保存分兩部分嫩舟,Mach-O 可執(zhí)行文件會(huì)把簽名直接寫入這個(gè)文件里氢烘,其他資源文件則會(huì)保存在 _CodeSignature 目錄下。
- 第 6 – 7 步的打包和驗(yàn)證都是 Xcode 和 iOS 系統(tǒng)自動(dòng)做的事家厌。
這里再總結(jié)一下這些概念:
- 證書:內(nèi)容是公鑰或私鑰播玖,由其他機(jī)構(gòu)對(duì)其簽名組成的數(shù)據(jù)包。
- Entitlements:包含了 App 權(quán)限開關(guān)列表饭于。
- CertificateSigningRequest:本地公鑰蜀踏。
- p12:本地私鑰,可以導(dǎo)入到其他電腦掰吕。
- Provisioning Profile:包含了 證書 / Entitlements 等數(shù)據(jù)脓斩,并由蘋果后臺(tái)私鑰簽名的數(shù)據(jù)包。
iOS APP 重簽名具體操作(手動(dòng))
干掉插件Plugins文件夾里面的內(nèi)容!
Watch 文件刪除
-
對(duì) Frameworks 進(jìn)行簽名!
`$ codesign -fs "證書" xxx.framework`
給可執(zhí)行文件執(zhí)行權(quán)限!
chmod +x WeChat
拷貝描述文件(可新建工程畴栖,獲取app包中
embedded.mobileprovision
)修改info.plist 的Bundle ID(與描述文件工程一致)
-
生成plist的權(quán)限文件
en.plist
(復(fù)制embedded.mobileprovision
權(quán)限內(nèi)容),放到Payload
目錄下<key>keychain-access-groups</key> <array> <string>X7Y****CQ.*</string> </array> <key>get-task-allow</key> <true/> <key>application-identifier</key> <string>X7Y****JCQ.*</string> <key>com.apple.developer.team-identifier</key> <string>X7Y****CQ</string>
-
簽名整個(gè)APP!
$ codesign -fs "iPhone Developer: xxxxxx (6ZBE4C573L)" --no-strict --entitlements=en.plist WeChat.app
-
打包其實(shí)就是一個(gè)zip
$ zip -ry WeChat.ipa Payload
iPhone Developer: shan jingjing (3QDN5929LL)
- 安裝到手機(jī)
Xcode
->Window
->Devices and Simulators
->Devices INSTALL APP
點(diǎn)擊+
選中WeChat.ipa
iOS APP 利用Xcode重簽名
創(chuàng)建工程八千,替換Product下的app
修改
Bundle identifier
與新建工程一致Plugins吗讶、Watch 文件刪除
-
Framework重簽名
`$ codesign -fs "證書" xxx.framework`
給可執(zhí)行文件執(zhí)行權(quán)限!
chmod +x WeChat
Xcode 運(yùn)行安裝至手機(jī)
iOS APP 腳本自動(dòng)化重簽名
- 新建工程,添加
Run Script
腳本
# ${SRCROOT} 它是工程文件所在的目錄
TEMP_PATH="${SRCROOT}/Temp"
#資源文件夾
ASSETS_PATH="${SRCROOT}/TargetAPP"
#ipa包路徑
TARGET_IPA_PATH="${ASSETS_PATH}/*.ipa"
#新建Temp文件夾
rm -rf "${SRCROOT}/Temp"
mkdir -p "${SRCROOT}/Temp"
#----------------------------------------
# 1. 解壓IPA到Temp下
unzip -oqq "$TARGET_IPA_PATH" -d "$TEMP_PATH"
# 拿到解壓的臨時(shí)的APP的路徑
TEMP_APP_PATH=$(set -- "$TEMP_PATH/Payload/"*.app;echo "$1")
# echo "路徑是:$TEMP_APP_PATH"
#----------------------------------------
# 2. 將解壓出來的.app拷貝進(jìn)入工程下
# BUILT_PRODUCTS_DIR 工程生成的APP包的路徑
# TARGET_NAME target名稱
TARGET_APP_PATH="$BUILT_PRODUCTS_DIR/$TARGET_NAME.app"
echo "app路徑:$TARGET_APP_PATH"
rm -rf "$TARGET_APP_PATH"
mkdir -p "$TARGET_APP_PATH"
cp -rf "$TEMP_APP_PATH/" "$TARGET_APP_PATH"
#----------------------------------------
# 3. 刪除extension和WatchAPP.個(gè)人證書沒法簽名Extention
rm -rf "$TARGET_APP_PATH/PlugIns"
rm -rf "$TARGET_APP_PATH/Watch"
#----------------------------------------
# 4. 更新info.plist文件 CFBundleIdentifier
# 設(shè)置:"Set : KEY Value" "目標(biāo)文件路徑"
/usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier $PRODUCT_BUNDLE_IDENTIFIER" "$TARGET_APP_PATH/Info.plist"
#----------------------------------------
# 5. 給MachO文件上執(zhí)行權(quán)限
# 拿到MachO文件的路徑
APP_BINARY=`plutil -convert xml1 -o - $TARGET_APP_PATH/Info.plist|grep -A1 Exec|tail -n1|cut -f2 -d\>|cut -f1 -d\<`
#上可執(zhí)行權(quán)限
chmod +x "$TARGET_APP_PATH/$APP_BINARY"
#----------------------------------------
# 6. 重簽名第三方 FrameWorks
TARGET_APP_FRAMEWORKS_PATH="$TARGET_APP_PATH/Frameworks"
if [ -d "$TARGET_APP_FRAMEWORKS_PATH" ];
then
for FRAMEWORK in "$TARGET_APP_FRAMEWORKS_PATH/"*
do
if test -f $FRAMEWORK
then
#簽名
/usr/bin/codesign --force --sign "$EXPANDED_CODE_SIGN_IDENTITY" "$FRAMEWORK"
fi
done
fi
命令
查看描述文件信息:$ security cms -D -i 描述文件路徑
查看APP的簽名信息
$ codesign -vv -d APP路徑(.app)
查看本機(jī)所有證書
$ security find-identity -v -p codesigning
查看可執(zhí)行文件的加密信息!
$ otool -l WeChat | grep crypt
簽名
$ codesign -fs "證書" 需要簽名的文件
參考
[toc]