本章简述iOS加密问题,主要涉及到哈希、对称加密、非对称加密。
这里在最开始有必要先说明一下,base64
这个东西只是个编码方案,是不能用来加密的,但是一般加密过后的数据会用base64进行表示。
根据密钥的使用方式,可以将密码分为两种:
1、 对称密码 - 加密用的密钥和解密用的密钥是相同的
2、公钥密码(非对称密码)- 加密用的密钥和解密用的密钥是不同的
在说对称密码和公钥密码之前,我们先来介绍一下hash的相关知识。
一、单向散列函数
1、概念
HASH
,又被称为消息摘要函数
message digest function,一般翻译成散列
,当然也有人直接音译成哈希
。
其原理就是把任意长度的输入数据通过散列算法变换成固定长度的输出,这个输出值就是散列值。输出的散列值,也被称为
消息摘要
message digest、指纹
fingerprint。这种转换本质上是一种压缩映射,因为散列值的空间通常远小于输入的空间,那么不同的输入经过散列算法后可能会产生相同的输出结果,所以不可能从散列值来确定唯一的输入值。
简单的说,HASH 就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。
-
特点:
- 算法是公开的;
- 对相同的数据加密,得到的结果是一样的;
- 对不同的数据加密,得到的结果是定长的。如:MD5是32个字符;
- 不能反算;
- 信息摘要,信息“指纹”,主要是用来做数据识别的。
-
用途:
- 用户密码的加密 - 直接使用MD5、MD5加盐、HMAC加密方案
- 搜索引擎;
- 版权;
- 数字签名 - 用于鉴别数字信息的方法
2、常见算法
-
MD4
、MD5
- 产生128bit的散列值,MD就是Message Digest的缩写,目前已经不安全
- Mac终端上默认可以使用md5命令
-
SHA-1
- 产生160bit的散列值,目前已经不安全
SHA-2
SHA-256、SHA-384、SHA-512,散列值长度分别是256bit、384bit、512bitSHA-3
全新标准,比起其他算法明显快很多
对于不同的数据,使用MD5以后能够得到相同的散列结果,这个叫做散列碰撞。目前破解的散列函数只有MD5,SHA1也在边缘。
MD5的基本安全有两种方式,一种是加盐,一种是使用HMAC。
- 加盐有个很严重的问题,就是盐的泄露问题无法从根本上解决,故此不推荐。
- HMAC是给定一个密钥,对明文进行加密,并且做了两次散列(32位),这种方式目前一两年在国内的使用开始增多。HMAC的客户端基本思路是用户先输入账号密码,然后本地查找密钥,如果没有密钥,就向服务器获取(账号可参考腾讯QQ设备锁,其他设备登录需要原设备同意)。用公式可表示为:
加密之后的密码 ==(原始密码 + key)HMAC
。
二、对称加密
1、概念
对称加密
算法,也叫传统加密
算法。
- 其原理很简单,就是明文通过密钥加密得到密文,密文通过密钥解密得到明文。
- 加解密的过程也很简单,明文进行加密成密文,密文进行解密成明文。常见的有DES、3DES、AES。
- 特点和用途
- 因为对称加密的运算效率高,所以通常用来对大数据进行加密。
2、常见算法
-
DES
:Data Encryption Standard 数据加密标准- DES是一种将64bit明文加密成64bit密文的对称密码算法,密钥长度是56bit
- 规格上来说,密钥长度是64bit,但每隔7bit会设置一个用于错误检查的bit,因此密钥长度实质上是56bit
- 由于DES每次只能加密64bit的数据,遇到比较大的数据,需要反复对DES加密进行迭代
- 目前已经可以在短时间内被破解,所以不建议使用
-
3DES
:使用3个不同的密钥,对相同的数据执行3次加密,强度增强- 3DES,将DES重复三次所得到的一种密码算法,也叫做三重DES
- 目前还被一些银行等机构使用,但处理速度不高,安全性逐渐暴露出问题
-
AES
:Advanced Encryption Standard 高级密码标准取代DES成为新标准的一种对称密码算法
AES的密钥长度有128、192、256bit三种
在2000年时选择Rijindael算法作为AES的实现
目前AES,已经逐步取代DES、3DES,成为首选的对称密码算法
一般来说,我们也不应该去使用任何自制的密码算法,而是应该使用AES,它经过了全世界密码学家所进行的高品质验证工作
钥匙串的加密方式就是AES加密,可以将保存的密码以明文的方式反算出来。在此提醒一下大家,保存用户密码到本地,一定要用钥匙串访问!
苹果的“生态圈”是从iOS7.0.3版本才开放给开发者的,其原生的接口都是C语言的,有第三方库可供使用SSKeyChain ,使用的时候注意在Capabities中开启 KeyChainSharring。
3、应用模式
- ECB (Electronic Code Book)
- 电子密码本模式,会将每一个数据块进行独立的加密。
- 最基本的加密模式,也就是通常理解的几码,相同的明文将永远加密成相同的密文,无初始向量。
- 容易受到密码本重放攻击,通常情况下很少用。
- CBC (Cipher Block Chaining)
- 密码分组链接模式,是使用一个密钥和一个初始化向量(IV)对数据进行加密。
- 明文被加密前,要与前面的密文进行异或运算后再加密。因此,只要选择不同的初始化向量,相同的密文加密后会形成不同的密文,这是目前应用最广泛的模式。
- CBC加密后的密文是上下文关联的,但明文的错误不会传递到后续分组。可是如果一个分组丢失,后面的分组将同步作废(同步错误)。
- 每一块数据的加密和解密都需要依赖前一块数据,因此CBC可以有效的保证密文数据的完整性。如果一个数据块在传递过程中丢失或者改变,后面的数据将无法正常解密。
- 一般这个技术用来防范一些窃听技巧。
4、终端命令
// 1> 加密过程是先加密,再base64编码
// 2> 解密过程是先base64解码,再解密
//DES(ECB)加密
(base) ➜ ~ git:(master) ✗ echo -n hello | openssl enc -des-ecb -K 616263 -nosalt | base64
hex string is too short, padding with zero bytes to length
HQr0Oij2kbo=
//DES(ECB)解密
(base) ➜ ~ git:(master) ✗ echo -n HQr0Oij2kbo= = | base64 -D | openssl enc -des-ecb -K 616263 -nosalt -d
hex string is too short, padding with zero bytes to length
hello%
//DES(CBC)加密
(base) ➜ ~ git:(master) ✗ echo -n hello | openssl enc -des-cbc -iv 0102030405060708 -K 616263 -nosalt | base64
hex string is too short, padding with zero bytes to length
alvrvb3Gz88=
//DES(CBC)解密
(base) ➜ ~ git:(master) ✗ echo -n alvrvb3Gz88= | base64 -D | openssl enc -des-cbc -iv 0102030405060708 -K 616263 -nosalt -d
hex string is too short, padding with zero bytes to length
hello%
//AES(ECB)加密
(base) ➜ ~ git:(master) ✗ echo -n hello | openssl enc -aes-128-ecb -K 616263 -nosalt | base64
hex string is too short, padding with zero bytes to length
d1QG4T2tivoi0Kiu3NEmZQ==
//AES(ECB)解密
(base) ➜ ~ git:(master) ✗ echo -n d1QG4T2tivoi0Kiu3NEmZQ== | base64 -D | openssl enc -aes-128-ecb -K 616263 -nosalt -d
hex string is too short, padding with zero bytes to length
hello%
//AES(CBC)加密 (base) ➜ ~ git:(master) ✗ echo -n hello | openssl enc -aes-128-cbc -iv 0102030405060708 -K 616263 -nosalt | base64
hex string is too short, padding with zero bytes to length
hex string is too short, padding with zero bytes to length
u3W/N816uzFpcg6pZ+kbdg==
//AES(CBC)解密
(base) ➜ ~ git:(master) ✗ echo -n u3W/N816uzFpcg6pZ+kbdg== | base64 -D | openssl enc -aes-128-cbc -iv 0102030405060708 -K 616263 -nosalt -d
hex string is too short, padding with zero bytes to length
hex string is too short, padding with zero bytes to length
hello%
5、密钥配送问题
在使用对称密码时,一定会遇到密钥配送问题。
问题场景:用户A将使用对称密码加密过的消息发送给用户B,只有将密钥也发送给用户B,用户B才能完成解密操作,读取最原始的消息。但在发送密钥的过程中,可能会被第三方用户C窃取密钥,最后用户C也能完成解密,读取到消息。
解决办法:事先共享密钥、密钥分配中心、Diffie-Hellman密钥交换、公钥密码
三、非对称加密
1、概念
非对称加密
算法(Asymmetric Cryptography),也称为公钥密码
(Public-key Cryptography),也可以叫做现代加密
算法。
自上世纪70年代出现,其加密方式比较特殊,需要两个密钥。算法是公开的,只能通过因式分解破解。涉及到的数学知识点蛮多的,比如迪菲赫尔曼一对一的密钥交换,比如任意的复合数(非质数)由一个唯一的一组质数相乘而来,比如欧拉函数等。这里感兴趣的小伙伴,可自行百度了解。
-
公钥密码中,密钥分为加密密钥、解密密钥2种,它们并不是同一个密钥。
- 加密密钥,一般是公开的,因此该密钥称为公钥(public key)
- 解密密钥,由消息接收者自己保管的,不能公开,因此也称为私钥(private key)
-
特点和用途
- 公钥和私钥是一 一对应的,是不能单独生成的,一对公钥和密钥统称为密钥对(key pair)
- 由公钥加密的密文,必须使用与该公钥对应的私钥才能解密
- 由私钥加密的密文,必须使用与该私钥对应的公钥才能解密
2、常见算法
- 目前使用最广泛的公钥密码算法是RSA
- RSA的名字,由它的3位开发者,即Ron Rivest、Adi Shamir、Leonard Adleman的姓氏首字母组成
3、终端命令
OpenSSL 是 Mac 系统自带的开源加密库,RSA 也是依赖于此才可以直接在终端进行操作。
介绍RSA算法三个常用的操作指令:
genrsa
: 生成并输出一个RSA私钥
rsautl
:使用RSA密钥进行加密、解密、签名和验证等运算
rsa
:处理RSA密钥的格式转换等问题
下面进入终端
首先,cd 到你的目录文件下。。。
(1)生成RSA私钥,密钥长度为1024bit
openssl genrsa -out private.pem 1024
此时目录文件下会生成名为 private.pem 的私钥。
(2)从私钥中提取公钥
openssl rsa -in private.pem -pubout -out public.pem
此时目录文件下会生成名为 public.pem 的公钥。
(3)可以利用终端查看公钥、私钥里面的内容(其实就是base64编码的文本)
// 查看私钥文件
cat private.pem
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQCzdalqsU4YF3MH/8ZLvTrMFRA6WYRIlPkr3B7LmeJF1GeAQl2S
J+pTOawo1EIfK3uRjVphLx5Fiotl5Gg+p2yJC7pfRZc7Vj3p0UpnDu5qhEhi2y7X
U8flrtqB/TqWGPHdXzkqMSYmA6BarzfQDzCOTi8XDyYBzhYSPEev7A5ViQIDAQAB
AoGAYBkDraRgYzo7WO84KlqcX6hv1i8VTSCpBTmMLA6tQiNpgR8IqDlDm2lorTxs
Y/CO7PQ6j4wBs89qshdLUzGoRh05nThfZs79Ud7S5ZTpyV6yg3w0RWPcsQMKVgLv
LuLbvMiYp20H5hjnvzoEV5elNODZTdJgOZMHVgynTJNIbeECQQDWYuFkcCUialNw
gEKjeIOyvq6VoAnUDx8IhmrD6LanDezoX6R4RrykuyYA6z0rTWvfbaiytJgcELha
NJpw4CGFAkEA1ks7vvNb1bHhMQD3WsKjxthAix8uqcwHEFb4xD7v5sLtF3fnk1MV
J6V+MtFTUwX8F2DfpmkvUGlH0k7kNWRhNQJBAK08zeF5dahvvukj27V5BwMDbtRd
tFN1vKAI7nFMtXwclpnX33GJx5pd2IHZlV5Oe6LaW/28TUYwhKfv5fTcSHkCQQCs
jFOFQ6r0fJBYxvBk8kixebsuymLmcdRWQdF5IzxEUTxbIz8iD0n/bHAbNxWiyjTc
FjK/af6g/sTIAKIco8DpAkBmb2SKTw9xD1amwUDehEQYsITJXUUCzlVLl/wQGt0f
s4TC/dr2E9CzK2Rq9MRT1OL53EPJeMlgJA5S36/Wn/v3
-----END RSA PRIVATE KEY-----
// 查看公钥文件
cat public.pem
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCzdalqsU4YF3MH/8ZLvTrMFRA6
WYRIlPkr3B7LmeJF1GeAQl2SJ+pTOawo1EIfK3uRjVphLx5Fiotl5Gg+p2yJC7pf
RZc7Vj3p0UpnDu5qhEhi2y7XU8flrtqB/TqWGPHdXzkqMSYmA6BarzfQDzCOTi8X
DyYBzhYSPEev7A5ViQIDAQAB
-----END PUBLIC KEY-----
(4)可以利用终端将私钥转换成明文信息
openssl rsa -in private.pem -text -out private.txt
此时目录文件下会生成名为 private.txt 的私钥明文信息文本。
// 查看私钥明文信息
cat private.txt
Private-Key: (1024 bit)
modulus:
00:b3:75:a9:6a:b1:4e:18:17:73:07:ff:c6:4b:bd:
3a:cc:15:10:3a:59:84:48:94:f9:2b:dc:1e:cb:99:
e2:45:d4:67:80:42:5d:92:27:ea:53:39:ac:28:d4:
42:1f:2b:7b:91:8d:5a:61:2f:1e:45:8a:8b:65:e4:
68:3e:a7:6c:89:0b:ba:5f:45:97:3b:56:3d:e9:d1:
4a:67:0e:ee:6a:84:48:62:db:2e:d7:53:c7:e5:ae:
da:81:fd:3a:96:18:f1:dd:5f:39:2a:31:26:26:03:
a0:5a:af:37:d0:0f:30:8e:4e:2f:17:0f:26:01:ce:
16:12:3c:47:af:ec:0e:55:89
publicExponent: 65537 (0x10001)
privateExponent:
60:19:03:ad:a4:60:63:3a:3b:58:ef:38:2a:5a:9c:
5f:a8:6f:d6:2f:15:4d:20:a9:05:39:8c:2c:0e:ad:
42:23:69:81:1f:08:a8:39:43:9b:69:68:ad:3c:6c:
63:f0:8e:ec:f4:3a:8f:8c:01:b3:cf:6a:b2:17:4b:
53:31:a8:46:1d:39:9d:38:5f:66:ce:fd:51:de:d2:
e5:94:e9:c9:5e:b2:83:7c:34:45:63:dc:b1:03:0a:
56:02:ef:2e:e2:db:bc:c8:98:a7:6d:07:e6:18:e7:
bf:3a:04:57:97:a5:34:e0:d9:4d:d2:60:39:93:07:
56:0c:a7:4c:93:48:6d:e1
prime1:
00:d6:62:e1:64:70:25:22:6a:53:70:80:42:a3:78:
83:b2:be:ae:95:a0:09:d4:0f:1f:08:86:6a:c3:e8:
b6:a7:0d:ec:e8:5f:a4:78:46:bc:a4:bb:26:00:eb:
3d:2b:4d:6b:df:6d:a8:b2:b4:98:1c:10:b8:5a:34:
9a:70:e0:21:85
prime2:
00:d6:4b:3b:be:f3:5b:d5:b1:e1:31:00:f7:5a:c2:
a3:c6:d8:40:8b:1f:2e:a9:cc:07:10:56:f8:c4:3e:
ef:e6:c2:ed:17:77:e7:93:53:15:27:a5:7e:32:d1:
53:53:05:fc:17:60:df:a6:69:2f:50:69:47:d2:4e:
e4:35:64:61:35
exponent1:
00:ad:3c:cd:e1:79:75:a8:6f:be:e9:23:db:b5:79:
07:03:03:6e:d4:5d:b4:53:75:bc:a0:08:ee:71:4c:
b5:7c:1c:96:99:d7:df:71:89:c7:9a:5d:d8:81:d9:
95:5e:4e:7b:a2:da:5b:fd:bc:4d:46:30:84:a7:ef:
e5:f4:dc:48:79
exponent2:
00:ac:8c:53:85:43:aa:f4:7c:90:58:c6:f0:64:f2:
48:b1:79:bb:2e:ca:62:e6:71:d4:56:41:d1:79:23:
3c:44:51:3c:5b:23:3f:22:0f:49:ff:6c:70:1b:37:
15:a2:ca:34:dc:16:32:bf:69:fe:a0:fe:c4:c8:00:
a2:1c:a3:c0:e9
coefficient:
66:6f:64:8a:4f:0f:71:0f:56:a6:c1:40:de:84:44:
18:b0:84:c9:5d:45:02:ce:55:4b:97:fc:10:1a:dd:
1f:b3:84:c2:fd:da:f6:13:d0:b3:2b:64:6a:f4:c4:
53:d4:e2:f9:dc:43:c9:78:c9:60:24:0e:52:df:af:
d6:9f:fb:f7
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQCzdalqsU4YF3MH/8ZLvTrMFRA6WYRIlPkr3B7LmeJF1GeAQl2S
J+pTOawo1EIfK3uRjVphLx5Fiotl5Gg+p2yJC7pfRZc7Vj3p0UpnDu5qhEhi2y7X
U8flrtqB/TqWGPHdXzkqMSYmA6BarzfQDzCOTi8XDyYBzhYSPEev7A5ViQIDAQAB
AoGAYBkDraRgYzo7WO84KlqcX6hv1i8VTSCpBTmMLA6tQiNpgR8IqDlDm2lorTxs
Y/CO7PQ6j4wBs89qshdLUzGoRh05nThfZs79Ud7S5ZTpyV6yg3w0RWPcsQMKVgLv
LuLbvMiYp20H5hjnvzoEV5elNODZTdJgOZMHVgynTJNIbeECQQDWYuFkcCUialNw
gEKjeIOyvq6VoAnUDx8IhmrD6LanDezoX6R4RrykuyYA6z0rTWvfbaiytJgcELha
NJpw4CGFAkEA1ks7vvNb1bHhMQD3WsKjxthAix8uqcwHEFb4xD7v5sLtF3fnk1MV
J6V+MtFTUwX8F2DfpmkvUGlH0k7kNWRhNQJBAK08zeF5dahvvukj27V5BwMDbtRd
tFN1vKAI7nFMtXwclpnX33GJx5pd2IHZlV5Oe6LaW/28TUYwhKfv5fTcSHkCQQCs
jFOFQ6r0fJBYxvBk8kixebsuymLmcdRWQdF5IzxEUTxbIz8iD0n/bHAbNxWiyjTc
FjK/af6g/sTIAKIco8DpAkBmb2SKTw9xD1amwUDehEQYsITJXUUCzlVLl/wQGt0f
s4TC/dr2E9CzK2Rq9MRT1OL53EPJeMlgJA5S36/Wn/v3
-----END RSA PRIVATE KEY-----
(5)通过公钥加密数据,私钥解密数据
// 生成待加密的明文文件
vi password.txt
// 输入内容保存后,查看待加密的文件内容
cat password.txt
密码:abc000
// 通过公钥进行加密,生成加密后的enc.txt文件
openssl rsautl -encrypt -in password.txt -inkey public.pem -pubin -out enc.txt
// 通过私钥进行解密,生成解密后的dec.txt文件
openssl rsautl -decrypt -in enc.txt -inkey private.pem -out dec.txt
// 查看加密后的enc.txt文件内容
cat enc.txt
?B??8Q????J)?k??t??Z3?=${? ??9?b? ??????4?M???4'??(?w{R?6?R? ??P.??y???p?u4@??E*K?r?!G?o$?
c?Dy@c???у?E???Nfe??
// 查看解密后的dec.txt文件内容,与待加密的password.txt内容一致
cat dec.txt
密码:abc000
(6)通过私钥加密数据,公钥解密数据
// 通过私钥进行加密,生成加密后的enc1.txt文件
openssl rsautl -sign -in password.txt -inkey private.pem -out enc1.txt
// 通过公钥进行解密,生成解密后的dec1.txt文件
openssl rsautl -verify -in enc1.txt -inkey public.pem -pubin -out dec1.txt
// 查看加密后的enc1.txt文件内容
cat enc1.txt
Ev???p???MH??%???M%
// 查看解密后的dec1.txt文件内容,与待加密的password.txt内容一致
cat dec1.txt
密码:abc000
3、解决密钥配送问题
由消息的接收者用户B,生成一对公钥和私钥,将公钥发给消息的发送者用户A,用户A使用公钥加密消息。
四、混合密码系统
- 对称密码的缺点:不能很好地解决密钥配送问题
- 公钥密码的缺点:加密解密速度比较慢
- 混合密码系统,是将对称密码和公钥密码的优势相结合的方法:
- 解决了公钥密码速度慢的问题
- 并通过公钥密码解决了对称密码的密钥配送问题
- 网络上的密码通信所用的SSL/TLS都运用了混合密码系统
混合密码-加密
会话密钥(session key)
- 为本次通信随机生成的临时密钥
- 作为对称密码的密钥,用于加密消息,提高速度
加密步骤(发送消息)
- 首先,消息发送者要拥有消息接收者的公钥
- 生成会话密钥,作为对称密码的密钥,加密消息
- 用消息接收者的公钥,加密会话密钥
- 将前2步生成的加密结果,一并发给消息接收者
发送出去的内容包括
- 用会话密钥加密的消息(加密方法:对称密码)
- 用公钥加密的会话密钥(加密方法:公钥密码)
混合密码-解密
- 解密步骤(收到消息)
- 消息接收者用自己的私钥解密出会话密钥
- 再用第1步解密出来的会话密钥,解密消息
- 混合密码-加密解密流程
- 用户A给用户B发送消息
- 发送过程,加密过程
- (1)用户B先生成一对公钥、私钥
- (2)用户B把公钥共享给用户A
- (3)用户A随机生成一个会话密钥(临时密钥)
- (4)用户A用会话密钥加密需要发送的消息(使用的是对称密码加密)
- (5)用户A用B的公钥加密会话密钥(使用的是公钥密码加密,也就是非对称密码加密)
- (6)用户A把第4、5步的加密结果,一并发送给B
- 接收过程,解密过程
- (1)用户B利用自己的私钥解密会话密钥(使用的是公钥密码解密,也就是非对称密码解密)
- (2)用户B利用会话密钥解密发送过来的消息(使用的是对称密码解密)
五、数字签名
1、问题场景
问题描述:如果用户A给用户B发送消息,那么用户B如何确定这段消息的真实性?因为用户A发送的内容有可能是被篡改的、或者别人伪装成用户A发送的。
解决方案:使用数字签名 - 用消息发送者用户A的私钥进行签名。签名的目的就是为了证明这个东西是你的,所以数字签名就是用于鉴别数字信息的方法。
2、实现原理
- 数字签名,其实就是将公钥密码反过来使用。在数字签名技术中,有以下2种行为:
- 生成签名:由消息的发送者完成,通过“签名密钥”生成;
- 验证签名:由消息的接收者完成,通过“验证密钥”验证。
在公钥密码中,任何人都可以使用公钥进行加密;
在数字签名中,任何人都可以使用公钥验证签名。
- 如果有人篡改了文件内容或者签名内容,那么结果肯定是签名验证失败,证明内容被篡改了。
- 数字签名仅仅是为了能够识别内容有没有被篡改,所以并不能保证数据的机密性。
- 数字签名的作用:
- 确认消息的完整性
- 识别消息是否被篡改
- 防止消息发送者否认
3、存在的问题
要正确使用签名,有一个前提:用于验证签名的公钥必须属于真正的发送者。如果遭遇了中间人攻击,那么公钥就是伪造的,所以数字签名也会失效。所以在验证签名之前,首先得先验证公钥的合法性。具体如何验证公钥的合法性,就需要使用到证书了。
六、证书
密码学中的证书,全称叫公钥证书
Public-key Certificate(PKC)。
跟其他证书(比如毕业证、驾驶证等)类似,里面有姓名、邮箱等个人信息,以及此人的公钥,也是由认证机构(Certificate Authority,CA)施加数字签名的。
-
CA就是能够认定“公钥确实属于此人”并能够生成数字签名的个人或者组织
- 有国际性组织、政府设立的组织
- 有通过提供认证服务来盈利的企业
- 个人也可以成立认证机构
七、代码签名机制
1、签名原理
代码签名
是对可执行文件或脚本进行数字签名。用来确认软件在签名后未被修改或损坏的措施。和数字签名的原理一样,只不过签名的是数据代码而已。在iOS出来之前,以前的主流操作系统(Mac/Windows)软件随便从哪里下载都能运行,系统安全存在隐患,盗版软件、病毒入侵、静默安装等。而iOS的代码签名机制就是为了解决这一的问题,它可以保证安装到用户手机上的APP都是经过Apple官方允许的。
2、简单签名
- 实现验证最简单的方式就是通过苹果官方生成一对非对称加密的公钥和私钥。
- 将私钥保存在苹果后台的App Store,将公钥保存在苹果手机的iOS系统中;
- 当上传应用到App Store时,苹果后台用私钥对App数据进行签名;
- 手机这个App后,用内置的公钥验证这个签名;
- 如果签名正确,这个App肯定是由苹果后台认证的,没有被修改过。
如果设备只能通过App Store来安装应用,那上述数字签名就可以解决了。但是实际上,iOS安装App还有其他的渠道,比如企业内部分发、或者直接进行真机调试。苹果需要开放这些方式安装应用,就无法通过简单的代码签名来办到了。
3、双重签名
- 不管是真机调试,还是发布APP,开发者都需要经过一系列复杂的步骤:
- 生成CertificateSigningRequest.certSigningRequest文件
- 获得ios_development.cer或者ios_distribution.cer证书文件
- 注册device、添加App ID
- 获得*.mobileprovision文件
对于真机调试,现在的Xcode已经自动帮开发者做了这些操作,这里每一个步骤都是有其存在的原因的。
首先这里有两个角色:一个是iOS系统,还有一个就是Mac系统。因为iOS的App开发环境在Mac系统下,所以这个依赖关系成为了苹果双层签名的基础。
(1)在Mac设备中生成非对称加密算法的一对公钥、私钥;(生成的CSR文件就是Mac设备的公钥)
(2)苹果本身有一对公私钥,Apple私钥在苹果后台,Apple公钥在iPhone手机系统中;
(3)把Mac设备的公钥和一些开发者信息,上传到苹果后台,用苹果后台里的私钥去签名Mac设备的公钥,得到一份数据包含了Mac公钥和签名的证书。这证书被包含在一个叫做Provisioning profile的描述文件中,同时描述文件中还包含了AppID、设备和授权文件Entitlements,授权文件里面设置了应用的iCloud、push、后台运行、调试器等附加的权限;
(4)用本地Mac设备中的私钥(导出的P12)对应用进行签名,同时把从苹果服务器得到的Provisioning profile文件打包进App里,文件名为embedded.mobileprovision,把App安装到手机上;
(5)安装应用时,通过手机上内置的Apple公钥,去验证证书的签名是否正确。
(6)验证证书后确保了Mac设备的公钥是经过苹果认证的,再用Mac公钥去验证App的签名,就间接验证了这个App安装行为是否经过苹果官方允许。
如果APP是从AppStore下载安装的,里面是没有mobileprovision文件的。
4、应用重签名
了解了苹果的双层签名验证机制,对应用重签名就比较好理解了,这里简单介绍下利用codesign
重签名的步骤。codesign是Xcode提供的签名工具(其实个人更偏向借助于图形界面工具进行重签名)。
- 重签步骤
- 删除插件和带有插件的.app包(比如Watch)
- 对Frameworks里面的库进行重签名
- 给可执行文件+x(可执行)权限
- 添加描述文件(新建工程,真机编译得到)
- 替换BundleID
- 通过授权文件(Entitlements)重签.app包
终端命令:
- security find-identity -v -p codesigning 列出钥匙串里可签名的证书
- codesign -fs "证书串" 文件名 强制替换签名
- chmod +x 可执行文件 给文件添加权限
- security cms -D -I ../embedded.mobileprovision 查看描述文件
- codesign -fs "证书串" --no-strict --entitlements=权限文件.plist App包
- zip -ry 输出文件 输入文件 将输入文件压缩为输出文件