iOS双层签名
在上一章我们知道:对文件的二进制数据进行hash处理,然后又进行一次非对称加密RSA,这个过程称为签名。为什么iOSapp不能向安卓那样任意的安装到任何安卓设备?我们先来分析苹果为了维护自己的生态圈有哪些需求:
1、安装包不需要上传到APP Store,可以直接安装到手机上。(eg:1.开发的日常调试 2.企业证书app的安装)
2、苹果为了保证系统的安全性,又必须对安装的APP有绝对的控制权
- 2.1、经过苹果允许才可以安装
- 2.2、不能被滥用导致非开发APP也能被安装
苹果为了实现上述需求,苹果给出了双层签名的方案。为了理解双层签名,先了解下面几个术语的含义:
- 代码签名:代码签名是对可执行文件或者脚本进行数据签名。用来确认软件在签名后未被修改或者损坏过,和数字签名原理一样们只不过签名的数据是代码而已
- 授权文件(Entitlements):app里面的iCloud/PUSH/后台运行等一系列的权限开关文件
- 描述文件(Provisiong profile):其是对 证书、app ID、授权文件(Entitlements)、设备一个打包。为了详细说明:我这里新建了一个
KTest工程,可以看到描述文件里的许多内容,
Command + B后,如果是第一次,你应该会看到要求访问KeyChain的对话框,这其实是一次签名的过程;之后我们可以看到具体的app执行文件:
打开包后,应该可以看到以下数据
上图中 embedded.mobileprovision就是描述文件,_CodeSignature是资源文件(图片...)签名,而应用签名在
KTest可执行文件中(相当于window系统中的.exe文件),你可以用MachO应用程序打开这里不赘述了。使用终端看描述文件内部:
XXXXX@MacBook-Pro ~ % cd /Users/XXXX/Library/Developer/Xcode/DerivedData/KTest-aljwhltjgylwbnayiwdyysnxrrny/Build/Products/Debug-iphoneos/KTest.app
XXXXX@MacBook-Pro KTest.app % ls -a
. KTest
.. PkgInfo
Base.lproj _CodeSignature
Info.plist embedded.mobileprovision
XXXXX@MacBook-Pro KTest.app % security cms -Di embedded.mobileprovision
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>AppIDName</key>
<string>XC riceFun KTest</string>
<key>ApplicationIdentifierPrefix</key>
<array>
<string>TM6D7482ZM</string>
</array>
<key>CreationDate</key>
<date>2020-02-27T09:11:45Z</date>
<key>Platform</key>
<array>
<string>iOS</string>
</array>
<key>IsXcodeManaged</key>
<true/>
<key>DeveloperCertificates</key>
<array>
<data>MIIFlzCCBH+gAwIBAgIIJJmsMK8vs2kwDQYJKoZIhvcNAQELBQAwgZYxCzAJBgNVBAYTAlVTMRMwEQYDVQQKDApBcHBsZSBJbmMuMSwwKgYDVQQLDCNBcHBsZSBXb3JsZHdpZGUgRGV2ZWxvcGVyIFJlbGF0aW9uczFEMEIGA1UEAww7QXBwbGUgV29ybGR3aWRlIERldmVsb3BlciBSZWxhdGlvbnMgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTkwOTI1MDEyMDU0WhcNMjAwOTI0MDEyMDU0WjCBijEaMBgGCgmSJomT8ixkAQEMCk00U0c5NThaMkUxODA2BgNVBAMML2lQaG9uZSBEZXZlbG9wZXI6IDk5NTA2NTIyNUBxcS5jb20gKDhGNDgzNks4NzQpMRMwEQYDVQQLDApUTTZENzQ4MlpNMRAwDgYDVQQKDAfluIYg6bKNMQswCQYDVQQGEwJVUzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJ4n37M35IxjSN3IjDYdi65PANwoQJhTZVsP2H8q43pg5Dt3uEa0qLG1zy0u6HdyYabzufggUIbRX+kDOBY55vByPJrqg+lvWepMCTDPRdmwXsMqajkj+dicdT0Q1gZtqAKe7Ozx0yqyMSuMQ9l+TrDPcXhvzLPuPjDswhf5I4KdmHuTgGQu0jcb8Sbma9tpEsQs9MXrqLY54W9uITCdCySeLPQs2wE1FYeh2dFQXbxBt/8NE2mfAVQ1fhlKkdM66UZKGphP9QwnE08Brsm+AWRp6a7HRNPiueBCCQaFgHXsxKYzXSdQE5qjGVETBOn2BrSQ18tXQ/jAcyj7oEDZt18CAwEAAaOCAfEwggHtMAwGA1UdEwEB/wQCMAAwHwYDVR0jBBgwFoAUiCcXCam2GGCL7Ou69kdZxVJUo7cwPwYIKwYBBQUHAQEEMzAxMC8GCCsGAQUFBzABhiNodHRwOi8vb2NzcC5hcHBsZS5jb20vb2NzcDAzLXd3ZHIwMTCCAR0GA1UdIASCARQwggEQMIIBDAYJKoZIhvdjZAUBMIH+MIHDBggrBgEFBQcCAjCBtgyBs1JlbGlhbmNlIG9uIHRoaXMgY2VydGlmaWNhdGUgYnkgYW55IHBhcnR5IGFzc3VtZXMgYWNjZXB0YW5jZSBvZiB0aGUgdGhlbiBhcHBsaWNhYmxlIHN0YW5kYXJkIHRlcm1zIGFuZCBjb25kaXRpb25zIG9mIHVzZSwgY2VydGlmaWNhdGUgcG9saWN5IGFuZCBjZXJ0aWZpY2F0aW9uIHByYWN0aWNlIHN0YXRlbWVudHMuMDYGCCsGAQUFBwIBFipodHRwOi8vd3d3LmFwcGxlLmNvbS9jZXJ0aWZpY2F0ZWF1dGhvcml0eS8wFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwMwHQYDVR0OBBYEFLwz0fDMcctZMtx8I6cfKDHBxa2WMA4GA1UdDwEB/wQEAwIHgDATBgoqhkiG92NkBgECAQH/BAIFADANBgkqhkiG9w0BAQsFAAOCAQEAD9L5F2jYtIDQvXZVgeJL6O7MDK4j3lUzkga+Erss4ZVlGjByInDLEE2EAPIiubtmXCUjggg4YMHfVc/QRDilyu8UM9sp6+60aI4+zHseO65TYiyNuvkjN/kGxd9LXEfwlVAHZA7DX8lJY4xFQTUt16TXZfYRob/aC120Nz5SjNHySaiJVAmTy+Wka2rMpNYzxTDmgODyfCATzoblLcWkHw3PhdUsl/30IAupWPa7qZDUto1aQhLNuLuBT/DmQmzRUO22F8KgQt4jBuI/8RBcQ46OxKHhtSnrKDQzCuyg1Becyxb+UKck+w0ib4xvmX6sg9VqWdWvKxPZERHgNP+f4A==</data>
<data>MIIFrTCCBJWgAwIBAgIIJZxJAUUW2HcwDQYJKoZIhvcNAQELBQAwgZYxCzAJBgNVBAYTAlVTMRMwEQYDVQQKDApBcHBsZSBJbmMuMSwwKgYDVQQLDCNBcHBsZSBXb3JsZHdpZGUgRGV2ZWxvcGVyIFJlbGF0aW9uczFEMEIGA1UEAww7QXBwbGUgV29ybGR3aWRlIERldmVsb3BlciBSZWxhdGlvbnMgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMjAwMjI3MDkwMTQzWhcNMjEwMjI2MDkwMTQzWjCBizEaMBgGCgmSJomT8ixkAQEMCk00U0c5NThaMkUxOTA3BgNVBAMMMEFwcGxlIERldmVsb3BtZW50OiA5OTUwNjUyMjVAcXEuY29tICg4RjQ4MzZLODc0KTETMBEGA1UECwwKVE02RDc0ODJaTTEQMA4GA1UECgwH5biGIOmyjTELMAkGA1UEBhMCVVMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDr1tktqaSMj0kZdluli1/RvR04nJJuDLvAMqAM/aN5d66UZBy58mX27sgNs5GyqJ0SGSknw4ECuc9/CONY0cfjj1KR/5b4DArn1BKMRDgv5lpnWLqer/SxUvPEaXS7KWSDMfbdT+Xo6IUMjhS6my1A2foVP6Kg4f6lG1xgP7A7tdQ35/XGYKe/JaDli/QABVTV8gqMx3YZe+10PjheuLjpbaTwqixP9/gjfXv1Mj2yBlsJuDoODjy6EZBtzGAy2o2ehshk3ItZOQZ0cs/FdMKeb+EQEnTj08g4dGPsklDtUVmoSbJZjtzdbTvVPxUwBDJjJC/UNsgAFJneXpkwBNHNAgMBAAGjggIGMIICAjAMBgNVHRMBAf8EAjAAMB8GA1UdIwQYMBaAFIgnFwmpthhgi+zruvZHWcVSVKO3MD8GCCsGAQUFBwEBBDMwMTAvBggrBgEFBQcwAYYjaHR0cDovL29jc3AuYXBwbGUuY29tL29jc3AwMy13d2RyMTkwggEdBgNVHSAEggEUMIIBEDCCAQwGCSqGSIb3Y2QFATCB/jCBwwYIKwYBBQUHAgIwgbYMgbNSZWxpYW5jZSBvbiB0aGlzIGNlcnRpZmljYXRlIGJ5IGFueSBwYXJ0eSBhc3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJsZSBzdGFuZGFyZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRlIHBvbGljeSBhbmQgY2VydGlmaWNhdGlvbiBwcmFjdGljZSBzdGF0ZW1lbnRzLjA2BggrBgEFBQcCARYqaHR0cDovL3d3dy5hcHBsZS5jb20vY2VydGlmaWNhdGVhdXRob3JpdHkvMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMDMB0GA1UdDgQWBBS9kxkEzB9qDZzmlH1eyCcGnfID2DAOBgNVHQ8BAf8EBAMCB4AwEwYKKoZIhvdjZAYBAgEB/wQCBQAwEwYKKoZIhvdjZAYBDAEB/wQCBQAwDQYJKoZIhvcNAQELBQADggEBAB1AFRan1RVQrtHsmmLFBDmbupfdf0zhELtUPR6NMeMQSRZt0NaPl26wwsp+NpiAIo+I6xMlgTPrdTab2tnYu5L2/Hz7lNy8ZvodPmYP4vA31pq183fzWlt0rVzFFkckB7lqtSMSZiPXrF0x9t929wZKhEV5KYeN8hBi6/Ow3lVqDUzouGcxxqzdvY/arCZFj0E/44pCrvH9CL/IojtfogN/2Olm8h4qXVue5qMdINo3LTcNLuloGx0YCozP4eGHhbiCCw0zo+DIn7/kbQ0wevEywxCuxal/XKuoIOD9RS4syLZAs96UcbX49RkPNUIDxkAyPbAhJLk6AJJUCiGyg48=</data>
</array>
<key>Entitlements</key>
<dict>
<key>application-identifier</key>
<string>TM6D7482ZM.riceFun.KTest</string>
<key>keychain-access-groups</key>
<array>
<string>TM6D7482ZM.*</string>
</array>
<key>get-task-allow</key>
<true/>
<key>com.apple.developer.team-identifier</key>
<string>TM6D7482ZM</string>
</dict>
<key>ExpirationDate</key>
<date>2020-03-05T09:11:45Z</date>
<key>Name</key>
<string>iOS Team Provisioning Profile: riceFun.KTest</string>
<key>ProvisionedDevices</key>
<array>
<string>8d8f30d089c0920d4ab49c473da130ad4bb36b72</string>
</array>
<key>LocalProvision</key>
<true/>
<key>TeamIdentifier</key>
<array>
<string>TM6D7482ZM</string>
</array>
<key>TeamName</key>
<string>三 张</string>
<key>TimeToLive</key>
<integer>7</integer>
<key>UUID</key>
<string>92d1831f-ac22-4300-b1ee-07c3c025b631</string>
<key>Version</key>
<integer>1</integer>
</dict>
</plist>% baofan@MacBook-Pro KTest.app %
重点关注Entitlements内部的东西,在下面的内容中会用到。
了解上面几个术语之后,再看流程图:

1.在iphone和苹果appstore上面分别有一个钥公A和私钥A(天生就有)
2.app在申请证书的时候,本地电脑会先生成一对非对称加密的公钥M和私钥M。
3.公钥M会被电脑包装成CSR文件向苹果服务器
4.苹果收到CSR文件后会用私钥A对CSR文件又进行一次签名,签名后得到就是描述文件描述文件Provisiong profile,这个描述文件内部包含了设备ids,appid,权限文件...还有一个证书,而这个证书包含了用私钥A加密后的公钥M和公钥M的hash值。
5.当本地电脑拿到这个描述文件Provisiong profile后会取出里面的证书进行钥匙串访问,将证书和私钥M进行关联;
6.当app在安装的时候(或者Command + B),本地的私钥M会对app进行签名,签名的内容包括MachO文件还有刚才的从苹果服务器上申请描述文件Provisiong profile。然后将这些东西打包成一个app包,安装到iPhone手机上
7.iPhone手机拿到app包开始安装的时候,会进行验证,如果验证成功就能安装成功
- 7.1用公钥A验证描述文件Provisiong中的证书,如果验证成功就证明这个行为是苹果服务器允许的,即验证证书签名
- 7.2用公钥A解密证书拿到公钥M,然后公钥M又去解密私钥M,。一步就是验证app签名
- 7.3通过上述两步验证,到达双层签名的目的,app也就能安装了。
以上就是app双层签名的全过程。我们去看看钥匙串

注意:上述的双层签名是为了满足日常的调试和企业级的分发;如果是app store上下载,其实只需要用到私钥A和公钥A一层签名就可以了;
iOS 应用重签名
应用重签名,首先你得有一个砸过壳的app,你可以下载pp助手,在pp助手中下载你需要重签名的app;下面我将以微信.ipa为例子
Xcode应用重签名
1.新建一个你要重签名的app同名的app,如何知道app的名字?
1.1 使用The Unarchiver 这个解压缩软件解压微信.ipa,找到app包





2.获取同名工程app证书名字
2.1查看证书名字

Apple Development: xxxxxxx@qq.com (8F4836K874)后面会用到

3.删除app包中的不可签名的插件(Plugins)及应用(Watch),因为这些插件和内部的小应用无法重签名;重签名内部的库 3.1删除



codesign -fs
XXX $: cd /Users/xxxxx/Library/Developer/Xcode/DerivedData/WeChat-hihupndjuikezabwgfipnoypmvtp/Build/Products/Debug-iphoneos/WeChat.app/Frameworks
XXX /Frameworks $: codesign -fs "Apple Development: XXXXXXXX@qq.com (8F4836K874)" andromeda.framework
andromeda.framework: replacing existing signature
XXX /Frameworks $: codesign -fs "Apple Development: XXXXX@qq.com (8F4836K874)" mars.framework
mars.framework: replacing existing signature
XXX /Frameworks $: codesign -fs "Apple Development: XXXXX@qq.com (8F4836K874)" marsbridgenetwork.framework
marsbridgenetwork.framework: replacing existing signature
XXX /Frameworks $: codesign -fs "Apple Development: XXXXX@qq.com (8F4836K874)" matrixreport.framework
matrixreport.framework: replacing existing signature
XXX /Frameworks $: codesign -fs "Apple Development: XXXXX@qq.com (8F4836K874)" OpenSSL.framework
OpenSSL.framework: replacing existing signature
XXX /Frameworks $: codesign -fs "Apple Development: XXXXX@qq.com (8F4836K874)" ProtobufLite.framework
ProtobufLite.framework: replacing existing signature
4.替换工程包
4.1复制上面1.2的app包
4.2在同名工程中找到app包的位置



脚本重签名
脚本重签需要用到shell脚本,将在下一章继续说明