hash
hash(哈希)算法是指将任意长度的文本,通过一个算法后得到一个固定长度的文本(也可能是二进制数据),哈希其实是一种思想,所有符合这种思想的算法都可以称之为哈希算法(不如MD5,sha1,sha256)
哈希算法具有以下特点:
1. 相同的源文本,通过算法得到的结果必然相同
2. 不同的原文本,通过算法得到的结果必然不同(也有散列碰撞的情况不过概率很小)
3. 无法从结果反推出源文本
hash的应用:1.用户密码的加密2.搜索引擎3.版权/云盘秒传功能4、数字签名
数字签名
实际上数字签名就是把非对称加密算法(RSA)和HASH算法结合起来用,比如我们有一篇文章需要传输,先用hash算法对文章运算得到hash值然后再用RSA私钥对hash值加密得到密文,这个密文就是这篇文章的数字签名,接收方用公钥解密数字签名得到发送方生成的hash 然后对文章进行hash运算得到hash值 这个值对比如果一致说明文章没有被篡改过,不一致则说明文章被篡改了,数字签名可以快速验证文本的完整性和合法性。
数字证书
现实生活中的证书
证书说到底其实就是一个证明,像我们的毕业证书,学位证书就是教育局颁发给我们用来证明我们学历文凭的,证书的组成部分:
- 证书获得者:张三
- 内容:完成大学教育考试合格顺利毕业
- 盖章:教育部的钢印
然后张三就可以去那着证书去找工作了,用人单位查看证书内容和钢印,来验证证书的真伪和判断张三的学历
不过现在有好多刻章办证的也能做出来钢印的效果,这样用人单位就很难判断证书的真伪了
数字证书:用数字签名实现的证书
数字证书就是通过数字签名实现的数字化证书,在证书的组成部分中还加入了其他信息比如证书有效期等。
跟现实生活中的签发机构一样,数字证书的签发机构也有若干,并有不同的用处。比如苹果公司就可以签发跟苹果公司有关的证书,而跟web访问有关的证书则是又几家公认的机构进行签发。这些签发机构称为CA(Certificate Authority)。
对于被签发人,通常都是企业或开发者。比如需要开发iOS的应用程序,需要从苹果公司获得相关的证书。这些申请通常是企业或者开发者个人提交给CA的。当然申请所需要的材料、资质和费用都各不相同,是由这些CA制定的,比如苹果要求99或者299的费用。
之所以要申请证书,当然是为了被验证。毕业证书的验证方一般是用人单位;web应用相关的SSL证书的验证方通常是浏览器;iOS各种证书的验证方是iOS设备。我们之所以必须从CA处申请证书,就是因为CA已经将整个验证过程规定好了。对于iOS,iOS系统已经将这个验证过程固化在系统中了,除非越狱,否则无法绕过。
证书的授权链
数字证书可能还包括证书链信息。举个例子:如果你要申请休假1周,需要你的上司审批,你的上司需要他的上司同意,最终需要大老板同意,那么这一层层的授权,形成了一个授权链,大老板是授权链的根(root),中间这些环节分别是被更接近root的人授权的。
我们从苹果MC(Member Center)中获得的证书实际也是一个包含有证书链的证书,其中的根是苹果的CA。我们获得的证书实际上是在告诉iOS设备:我们的证书是被苹果CA签过名的合法的证书。而iOS设备在执行app前,首先要先验证CA的签名是否合法,然后再通过证书中我们的公钥验证程序是否的确是我们发布的,且中途没有对程序进行过篡改。
苹果的应用签名
苹果为什么要搞应用签名
在苹果iOS系统出来之前,主流的操作系统Windows、安卓都不会限制应用程序的来源,随便什么地方来的应用都可以安装,这就造成了盗版引用泛滥,恶意程序横行,苹果为了解决这个问题也为了保证系统的安全性,必须对安装的APP有绝对的控制权(也可能是为了收取每年$$99、$299这笔开发账号费用)。
如果只是这样事情会很简单
我们的iPhone中和苹果服务器中存在着一对RSA秘钥(iPhone中存公钥public key 苹果服务器中存私钥private key )
直接把我们提交上去的app生成一个用私钥签名的数字证书,每次安装应用时再用iPhone上的公钥验签,通过验证的才给安装就行了。
但实际情况要复杂的多,我们开发时调试应用、企业证书分发的应用也需要能安装到手机上,这样上面的办法就行不通了,苹果给出的答案是双重签名
双重签名流程
如下图
流程如下:
- 把Mac电脑中的公钥M(M:代表Mac)包装成CSR文件在MC中向苹果请求证书
- 苹果服务器把CSR中的公钥M取出来跟MC中的开发者账号信息一起打包并使用苹果服务器的私钥A(A:代表Apple )进行签名打包成证书
- 把证书包装成描述文件并使用私钥A签名
- 在开发时,编译完一个 APP 后,用本地的私钥 M(今后你导出的P12) 对这个 APP 进行签名,同时把第三步得到的证书一起打包进 APP 里,安装到手机上。
- 在安装时,iOS 系统取得证书,通过系统内置的公钥 A,去验证证书的数字签名是否正确。
- 验证证书后确保了公钥M 是苹果认证过的,再用公钥 M 去验证 APP 的签名,这里就间接验证了这个 APP 安装行为是否经过苹果官方允许。
接下来对每一步详细说明:
什么是CSR文件(CertificateSigningRequest.certSigningRequest)
CSR文件(CertificateSigningRequest.certSigningRequest)这个文件是我们从钥匙串申请来的为后面申请证书准备的,在MC中提交该文件向苹果申请证书,这个文件主要包括两部分内容:
1、申请者的信息,使用私钥M加密
2、申请者的公钥M,申请者使用的私钥M对应的公钥M
3、摘要算法(hash算法),RSA算法
我们可以用openssl来解析文件中的内容看看到底是个啥:
openssl asn1parse -i -in CertificateSigningRequest.certSigningRequest
0:d=0 hl=4 l= 638 cons: SEQUENCE
4:d=1 hl=4 l= 358 cons: SEQUENCE
8:d=2 hl=2 l= 1 prim: INTEGER :00
11:d=2 hl=2 l= 57 cons: SEQUENCE
13:d=3 hl=2 l= 22 cons: SET
15:d=4 hl=2 l= 20 cons: SEQUENCE
17:d=5 hl=2 l= 9 prim: OBJECT :emailAddress
28:d=5 hl=2 l= 7 prim: IA5STRING :xxx.com
37:d=3 hl=2 l= 18 cons: SET
39:d=4 hl=2 l= 16 cons: SEQUENCE
41:d=5 hl=2 l= 3 prim: OBJECT :commonName
46:d=5 hl=2 l= 9 prim: UTF8STRING :宋XX
57:d=3 hl=2 l= 11 cons: SET
59:d=4 hl=2 l= 9 cons: SEQUENCE
61:d=5 hl=2 l= 3 prim: OBJECT :countryName
66:d=5 hl=2 l= 2 prim: PRINTABLESTRING :CN
70:d=2 hl=4 l= 290 cons: SEQUENCE
74:d=3 hl=2 l= 13 cons: SEQUENCE
76:d=4 hl=2 l= 9 prim: OBJECT :rsaEncryption
87:d=4 hl=2 l= 0 prim: NULL
89:d=3 hl=4 l= 271 prim: BIT STRING
364:d=2 hl=2 l= 0 cons: cont [ 0 ]
366:d=1 hl=2 l= 13 cons: SEQUENCE
368:d=2 hl=2 l= 9 prim: OBJECT :sha256WithRSAEncryption
379:d=2 hl=2 l= 0 prim: NULL
381:d=1 hl=4 l= 257 prim: BIT STRING
可以看到文件包含了我的信息,并标明使用了sha256摘要算法和RSA公钥加密算法。苹果的MC在拿到这个后,将这个信息记录下来,并签发出相关的证书。这里,苹果实际无需验证我的信息,因为如果我不交钱就没办法上传这个文件,也就得不到证书。
在MC中申请的证书是什么
苹果取出CertificateSigningRequest.certSigningRequest中的公钥,然后将我的MC账号信息和我提交的公钥封装在证书中,并进行数字签名。以开发证书为例,以开发证书为例我们用openssl打开看一下内容:
openssl x509 -inform der -in ios_development.cer -noout -text
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 8261114673414944075 (0x72a56006b5aa354b)
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=US, O=Apple Inc., OU=Apple Worldwide Developer Relations, CN=Apple Worldwide Developer Relations Certification Authority
Validity
Not Before: Jun 15 06:59:13 2020 GMT
Not After : Jun 15 06:59:13 2021 GMT
Subject: UID=H34NZV9396, CN=iPhone Developer: shen dongqu (J4NH894YDN), OU=X8H9B4P8L2, O=ZhongChu NanJing ZhiHuiWuLiu KeJi CO.LTD, C=CN
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
00:cd:58:f1:21:b2:82:95:e6:7a:4c:72:70:9d:06:
12:97:ed:a0:5c:d2:43:e0:f8:96:33:34:ef:a2:62:
6e:59:fc:e3:b0:08:5b:0b:9c:d6:4b:37:1e:22:46:
32:71:67:b4:ca:14:4a:94:a6:4f:46:b7:b6:f8:bd:
e6:8e:f9:f6:a5:0a:9a:24:7f:0d:71:d0:c7:c4:19:
be:f9:a4:de:42:1f:22:e2:17:ed:3c:13:00:9c:62:
d5:ea:6d:86:9d:6c:6c:90:ae:ea:55:24:f0:00:08:
ed:17:cd:d3:cf:40:6d:a7:11:22:c3:cc:24:e0:4a:
70:9a:36:8b:ea:f4:e0:42:4c:68:28:69:b0:fa:9b:
58:59:ae:58:c3:c2:25:2a:07:ac:c2:ad:53:55:f9:
3b:fe:ac:7d:9b:cf:e2:15:ff:c9:e7:eb:ec:27:9a:
e3:e9:34:47:d3:1f:68:92:28:14:26:68:0c:13:34:
53:ce:a3:03:a8:db:af:2b:3e:2f:45:59:73:6b:42:
23:f2:db:81:b3:e4:11:56:3f:2a:db:96:5e:a1:83:
32:75:b5:c9:be:1f:bb:9f:49:62:af:63:c8:11:f7:
a2:ae:a6:25:2e:69:c5:ff:73:6c:20:da:62:de:0a:
27:0d:24:af:da:30:37:ad:d1:7f:97:5a:06:4a:23:
fa:53
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints: critical
CA:FALSE
X509v3 Authority Key Identifier:
keyid:88:27:17:09:A9:B6:18:60:8B:EC:EB:BA:F6:47:59:C5:52:54:A3:B7
Authority Information Access:
OCSP - URI:http://ocsp.apple.com/ocsp03-wwdr01
X509v3 Certificate Policies:
Policy: 1.2.840.113635.100.5.1
User Notice:
Explicit Text: Reliance on this certificate by any party assumes acceptance of the then applicable standard terms and conditions of use, certificate policy and certification practice statements.
CPS: http://www.apple.com/certificateauthority/
X509v3 Extended Key Usage: critical
Code Signing
X509v3 Subject Key Identifier:
5C:FF:A1:74:3A:8C:64:9B:38:35:7A:D4:14:53:6E:05:F2:00:1A:55
X509v3 Key Usage: critical
Digital Signature
1.2.840.113635.100.6.1.2: critical
..
Signature Algorithm: sha256WithRSAEncryption
79:99:29:82:ed:80:3b:5a:6f:f6:5f:53:d0:7b:79:29:0f:46:
40:a2:e4:c8:3f:f5:c9:09:0b:7a:ec:f9:be:9e:50:6a:fa:83:
9e:c0:78:74:77:eb:6d:7b:21:df:ca:36:91:79:9a:71:0e:bb:
a6:41:fb:0a:71:58:b4:b7:b4:f5:00:a0:bb:ca:60:ef:4d:56:
82:53:ce:38:8d:55:37:ec:65:b1:13:bd:2d:5c:5c:e9:59:65:
58:d0:c7:bf:be:84:99:31:77:32:80:a2:57:e1:f4:54:46:7e:
ad:f2:46:fe:6c:ed:d9:9f:e0:50:b8:91:a1:14:e2:48:dd:2f:
37:80:02:93:db:93:50:27:07:c7:83:ae:b6:5b:4d:ab:dd:41:
e4:bd:80:21:30:c1:c4:f8:bf:41:f3:e6:0f:5d:6a:39:56:cd:
0a:d4:ab:27:d3:0f:ae:97:d1:a1:a4:b3:c7:8a:3b:d8:6a:28:
49:92:76:6f:4c:06:75:96:73:4d:24:bf:50:65:31:80:73:08:
dd:87:74:6e:b9:9e:e2:0a:0f:25:37:a5:4e:72:4a:e5:c6:93:
9a:36:8c:ac:a6:1e:1f:74:58:e7:20:5b:1f:e5:31:6c:96:34:
d8:50:b9:b3:92:72:1a:57:9a:e6:c3:dc:3c:c2:f9:53:27:90:
2b:2b:60:39
Data域即为证书的实际内容,与Data域平级的Signature Algorithm实际就是苹果的CA的公钥,而摘要的签名应该没有显示出来。Data域下一级的内容就是我的苹果账号信息,其中最为重要的是我的公钥,这个公钥与我本机的私钥是对应的。当我们双击安装完证书后,KeyChain会自动将这对密钥关联起来,所以在KeyChain中可以看到类似的效果:
[图片上传失败...(image-9f53db-1613977335577)]
程序跑到真机上的时候就是用这个私钥M给程序包签名的,而公钥M会随着描述文件(.mobileprovision)一起打进app中。
所以,就算你有证书,但是如果没有对应的私钥是没有用的。而团队开发则需要通过.p12文件把这个私钥分享给团队其他成员。
iOS授权和描述文件
有了证书苹果可以确保app是自己授权的开发者提交的以及app的完整性,但是这样只能确保本app是安全的,并不能细化到APP所使用的某些服务是被苹果认可的,不如APNS推送,定位等,而且证书也无法限制调试版应用的装机规模,于是苹果推出了mobileprovision描述文件。可以使用命令查看mobileprovision:
security cms -D -I embedded.mobileprovision
mobileprovision文件包含:
- AppId。每个app必须在MC中创建一个对应的AppId。规则不累述了。
- 使用哪些证书。上面说了,不同类型的证书就代表了不同的发布方式,还包括一些功能的能否使用(比如APN)
- 功能授权列表
- 可安装的设备列表。对于AdHoc方式发布的app或者真机调试时,会有一个列表,这个列表里面是iOS设备的UDID,每台iOS设备出厂的UDID都不同,所以可以用来标识设备。可通过iTunes连接设备,或者http://fir.im/udid这里获取
-
苹果的签名!
注意5,这里的签名是苹果签的,跟我们的私钥没有关系。也就是说mobileprovision文件是苹果签名的,我们除了从MC中获取,别无他法。也不能再获取后随意篡改(比如添加别的设备)。因此上面的1-4就被苹果牢牢的控制在手里,所有的规则都必须由苹果来制定和约束。
最终程序包变成了这个样子:
应用重签名
iOS程序最终都会以.ipa文件导出,先来了解一下ipa文件的结构:
事实上,ipa文件只是一个zip包,可以使用如下命令解压:
/usr/bin/unzip -q xxx.ipa -d <destination>
解压后,得到上图的Payload目录,下面是个子目录,其中的内容如下:
- 资源文件,例如图片、html、等等。
- _CodeSignature/CodeResources。这是一个plist文件,可用文本查看,其中的内容就是是程序包中(不包括Frameworks)所有文件的签名。注意这里是所有文件。意味着你的程序一旦签名,就不能更改其中任何的东西,包括资源文件和可执行文件本身。iOS系统会检查这些签名。
- 可执行文件。此文件跟资源文件一样需要签名。
- 一个mobileprovision文件.打包的时候使用的,从MC上生成的。
- Frameworks。程序引用的非系统自带的Frameworks,每个Frameworks其实就是一个app,其中的结构应该和app差不多,也包含签名信息CodeResources文件
重签名工具:codesign
需要砸过壳的ipa包(可以在PP助手里下载,也可以在越狱手机里自己砸壳)
相关命令:
- codesign -vv -d XXX.app 查看app包的签名信息
- security find-identity -v -p codesigning 列举出电脑中安装过的证书
- otool -l XXX (> ~/Desktop/111.txt 重定向输出 | grep cry 查询条件) 查看MachO文件的信息(器重cryptid标识是否加密0标识没有加密已经砸过壳了,其他值已经加密,是appStore加密的用的对称加密算法,程序运行的时候iPhone手机会把包解密到手机内存中,加密是为了应用代码安全防止逆向工程师查看应用的汇编代码)
- codesign -fs "证书名称" XXX 使用“证书” 重签 XXX(--no-strict --entitlements=XXX.plist 该参数使用权限文件XXX.plist进行重签)
- security cms -Di embedded.mobileprovision 查看描述文件信息
- Zip –ry 输出文件 输入文件 将输入文件压缩为输出文件(例如Zip -ry XXX.ipa Payload )
重签步骤:
- 删除调无法重签的东西包括1.插件Plugins文件夹下的所有插件2.Watch目录下的文件(因为免费的证书功能没有那么强大,签不动这些东西)
- 签Frameworks目录下的frameworks(查看MachO文件是否有可执行权限(黑色表示有权限 白色标识没有权限 没有的话 chmod + x MachO名称))
- 添加描述文件(需要新建一个工程build一下去.app中把embedded.mobileprovision复制粘贴到MachO同级目录下)
- 修改info.plist中的bundleId 改成跟描述文件里的一致
- 签名整个app包(需要用到证书和第三步中描述文件的授权信息,授权信息就是描述文件中Entitlements字段,复制到一个新的plist里就行)
- 重新打包
搞个流程图:
iOS设备如何验证app是否合法
关键的几个点:
- 解压ipa
- 取出embedded.mobileprovision,通过签名校验是否被篡改过
2.1 其中有几个证书的公钥,其中开发证书和发布证书用于校验签名
2.2 BundleId
2.3 授权列表 - 校验所有文件的签名,包括Frameworks
- 比对Info.plist里面的BundleId是否符合embedded.mobileprovision文件中的
利用Xcode进行重签
使用Xcode重签会简单很多
步骤:
- 使用Xcode新建一个同名工程(跟需要重签的.app同名 不同名的话Xcode会再自动生成一个同名的MachO文件,需要重签的MachO会被忽略),build一下,然后把Products目录下的.app替换成需要重签的.app包
- 删除无法重签的
- 重签Framews下的文件
然后直接运行Xcode会自动重签安装到手机上,.app包中info.plist的BundleId会被Xcode自动修改,方便的一批
小知识点使用Xcode调试手机上正在运行的应用数据线连接手机Xcode选择Debug -> Attach to Process -> 应用名 等待Xcode状态变为Running 就可以调试了
有时候重签的时候会报错提示:resource fork, Finder information, or similar detritus not allowed
这个cd到.app所在的目录执行命令:xattr -rc .
就可以了