代码重签名
签名机制
iOS签名需要用到codesign这个命令,了解这个命令的用法可以增加我们对签名机制的了解
最简单的情况是用可签名的证书对文件进行签名
codesign -s "iPhone Distribution: Xiaoxuan Chen (CXJ8TF54LW)" mix.sh
使用证书签名可以确认身份和代码的完整性,但是应用运行还会受到其他的一些限制,在签名的时候可以指定应用的权限。
codesign -fs "iPhone Distribution: Qinda Zhuang (287VV6UT6R)" --entitlements=/Users/wangxuefeng/Desktop/CITest/entitlements.plist Live.app
在entitlements.plist中存放了应用的权限。
我们没有直接创建entitlements.plist,但是当我们修改应用的权限的时候,比如开启推送,entitlements会随之更改。entitlements信息保存在provisioning profiles中,
- codesign 通过codesign可以对OS X 和 iOS系统中任何可执行二进制文件设置签名,设置签名需要证书和密钥,保证文件不被篡改
- entitlements entitlements授权机制决定了哪些系统资源在什么情况下允许被一个应用使用,比如可以使用推送、可以调试,针对沙盒配置
- provisioning profiles 在整个代码签名和沙盒机制中有一个组成部分将签名,授权和沙盒联系了起来,那就是配置文件。
重签名
- 准备新的证书和provisioning profiles
签名会用到证书和密钥,授权机制会用到entitlements.plist,和证书相匹配的provisioning profiles当然也少不了。
entitlements.plist可以从provisioning profiles中导出,所以准备一个可签名的证书和相应的provisioning profiles就可以。
- 删除旧的签名
iOS 应用的签名是针对.app进行的,因此签名相关的文件都存放在.app里面。
移除已有文件签名:应用程序的签名都放在一个文件里面 _CodeSignatue/CodeResources,由于这个文件在签名过程中会重新生成,因此不移除也是可以的。
移除provisioning profiles: provisioning profiles会被copy到应用中,名称为embedded.mobileprovision,删除这个文件
CFBundleIdentifier
# 修改 Plist,Plist路径必须为绝对路径
defaults write /Users/wangxuefeng/Desktop/ci/Live.app/info.plist "CFBundleName" "小爱Top"
defaults write /Users/wangxuefeng/Desktop/ci/Live.app/info.plist "CFBundleDisplayName" "小爱Top"
defaults write /Users/wangxuefeng/Desktop/ci/Live.app/info.plist "CFBundleIdentifier" "com.fungo.loveshowtop"
# 重签名 iPhone Distribution: Qinda Zhuang (287VV6UT6R) 在钥匙串中对应的证书只有一个,否则不能这么写
codesign -f -s "iPhone Distribution: Qinda Zhuang (287VV6UT6R)" --entitlements entitlements.plist Live.app
#验证签名
codesign --verify Live.app
#获取签名详情
codesign -vv -d Live.app
#获取主机上所有可用于签名的证书
security find-identity -v -p codesigning
#导出entitlements.plist
security cms -D -i Live.app/embedded.mobileprovision > t_entitlements_full.plist
/usr/libexec/PlistBuddy -x -c 'Print:Entitlements' t_entitlements_full.plist > entitlements.plist
resign.sh
workspace=~/Desktop/CITest
payloadDirectory=${workspace}/Payload
entitlementsPlistPath=${workspace}/entitlements.plist
rm -rf payloadDirectory
mkdir payloadDirectory
cp -r $1 Payload
provisioningFile=$3
appName=Live.app
appBundlePath=${payloadDirectory}/${appName}
appBundleInfoPlist=${appBundlePath}/Info.plist
appBundleProvisioningFilePath=${appBundlePath}/embedded.mobileprovision
#删除info.plist中的CFBundleResourceSpecification这一项
defaults delete $appBundleInfoPlist "CFBundleResourceSpecification"
#删除原有的embedded.mobileprovision
rm $appBundleProvisioningFilePath
#将新的embedded.mobileprovision复制到app中
cp -R "${3}" $appBundleProvisioningFilePath
#解析新的embedded.mobileprovision
security cms -D -i $appBundleProvisioningFilePath > ${workspace}/t_entitlements_full.plist
/usr/libexec/PlistBuddy -x -c 'Print:Entitlements' ${workspace}/t_entitlements_full.plist > ${entitlementsPlistPath}
#解析appID
applicationIdentifier=`defaults read ${entitlementsPlistPath} "application-identifier"`
newBundleId=${applicationIdentifier#*.}
#确保文件可执行
bundleExecutable=`defaults read $appBundleInfoPlist "CFBundleExecutable"`
chmod 755 ${appBundlePath}/${bundleExecutable}
#改变bundleid,以.app .appex结尾的文件中的info.plist都需要修改
oldBundleId=`defaults read ${appBundleInfoPlist} "CFBundleIdentifier"`
# if $newBundleId != $oldBundleId then
echo changing Bundle id $appBundleInfoPlist $newBundleId
defaults write $appBundleInfoPlist "CFBundleIdentifier" $newBundleId
# fi
#签名
for file in `ls $appBundlePath/Frameworks`
do
codesign -vvv -fs "$2" --no-strict --entitlements=${entitlementsPlistPath} $appBundlePath/Frameworks/$file
done
codesign -vvv -fs "$2" --no-strict --entitlements=${entitlementsPlistPath} $appBundlePath
#测试签名结果
codesign -v $appBundlePath
调用
sh resign.sh /Users/wangxuefeng/Desktop/ci/Release-iphones/Live.app "iPhone Distribution: Qinda Zhuang (287VV6UT6R)" /Users/wangxuefeng/Library/MobileDevice/Provisioning\ Profiles/1fb19f15-021a-40ac-9f4f-d33fe1a1d138.mobileprovision