一、什么是签名?
-
是确保消息来源的真实性
-
是确保消息不会被第三方篡改
1.基本信息基础必备
1.1 消息摘要
消息摘要,又称数字摘要 或 数字指纹. 简单来说,消息摘要就是在消息数据上,执行一个单向的 Hash 函数,生成一个固定长度的Hash值,这个Hash值即是消息摘要。
正是由于以上特点,消息摘要算法被广泛应用在“数字签名”领域,作为对明文的摘要算法。著名的消息摘要算法有 RSA 公司的 MD5 算法和 SHA-1 算法及其大量的变体。
SHA-256 是 SHA-1 的升级版,现在 Android 签名使用的默认算法都已经升级到 SHA-256 了。
消息摘要的这种特性,很适合来验证数据的完整性。比如:在网络传输过程中下载一个大文件 BigFile,我们会同时从网络下载 BigFile 和 BigFile.md5,BigFile.md5 保存 BigFile 的摘要,我们在本地生成 BigFile 的消息摘要和 BigFile.md5 比较,如果内容相同,则表示下载过程正确。
注意,消息摘要只能保证消息的完整性,并不能保证消息的不可篡改性。
1.2 数字签名
先了解一下RAS
-
加密:公钥加密,私钥解密的过程,称为“加密”。因为公钥是公开的,任何公钥持有者都可以将想要发送给私钥持有者的信息进行加密后发送,而这个信息只有私钥持有者才能解密。
-
签名: 私钥加密,公钥解密的过程,称为“签名”。它和加密有什么区别呢?因为公钥是公开的,所以任何持有公钥的人都能解密私钥加密过的密文,所以这个过程并不能保证消息的安全性,但是它却能保证消息来源的准确性和不可否认性,也就是说,如果使用公钥能正常解密某一个密文,那么就能证明这段密文一定是由私钥持有者发布的,而不是其他第三方发布的,并且私钥持有者不能否认他曾经发布过该消息。故此将该过程称为“签名”。
总结:
1、如何确保消息来源的真实性?
其实就是保证我们APP应用的唯一性质,方案就是上面给大家介绍的数字签名,使用RSA的私钥进行签名,来保证我们项目的唯一性,真实质。
2、保证APP应用来源的真实性实现方案?
-
单纯的数字签名也可以成功签名的一种验证方案。但是比较耗时。因为它会把所有的文件进行加密解密,这个过程是很耗时的
2.针对方案以进行优化
-
先摘要算法对所有文件消息进行摘要。
-
再把摘要值用信源的私钥加密。
-
几乎所有的数字签名方案都要和快速高效的摘要算法(Hash函数)一起使用,当公钥算法与摘要算法结合起来使用时,便构成了一种有效地数字签名方案。
最终采用数字签名是非对称加密技术 + 消息摘要技术的结合。
3.如何保证公钥不被篡改呢?
-
上面技术使用的前提是大家都先得到正确的公钥。如果公钥被篡改了,那么正确的公钥也会不能解密的。
-
使用数字证书,来保证我们公钥的唯一性。
3.1 数字证书
数字证书是一个经证书授权(Certificate Authentication)中心数字签名的包含公钥拥有者信息以及公钥的文件。数字证书的格式普遍采用的是 X.509 V3 国际标准,一个标准的 X.509 数字证书通常包含以下内容:
总结:
-
证书里面有公钥
-
使用的签名算法( 哈希值生成算法)
-
对证书的数字签名,把证书和数字指纹放在一起,在使用证书的时候,根据签名算法计算一下证书的数字指纹,如果数字指纹对的上,就说没有纂改过
数字签名和签名验证的大体流程(签名文件和和验签)
签名流程总结:
-
首先对项目的文件通过摘要算法,获取hash值,在通过签名者私钥进行签名。
-
把签名文件(认证证书) 和 签名 合并成签名
验证流程:
-
得到签名文件,拿到签体,然后得到摘要算法获取hash值
-
使用签名的公钥解密散列值 hash值, 跟1比较, 一直说明签名有效
2.1 签名工具
2.1.1Android 应用的签名工具有两种:
-
jarsigner:jdk 自带的签名工具,可以对 jar 进行签名。使用 keystore 文件进行签名。生成的签名文件默认使用 keystore 的别名命名。
-
signAPK:Android sdk 提供的专门用于 Android 应用的签名工具。使用 pk8、x509.pem 文件进行签名。其中 pk8 是私钥文件,x509.pem 是含有公钥的文件。生成的签名文件统一使用“CERT”命名。
2.1.2 签名过程
首先我们任意选取一个签名后的 APK(Sample-release.APK)解压
MANIFEST.MF
该文件中保存的内容其实就是逐一遍历 APK 中的所有条目,如果是目录就跳过,如果是一个文件,就用 SHA1(或者 SHA256)消息摘要算法提取出该文件的摘要然后进行 BASE64 编码后,作为“SHA1-Digest”属性的值写入到 MANIFEST.MF 文件中的一个块中。该块有一个“Name”属性, 其值就是该文件在 APK 包中的路径。
CERT.SF
-
SHA1-Digest-Manifest-Main-Attributes:对 MANIFEST.MF 头部的块做 SHA1(或者SHA256)后再用 Base64 编码
-
SHA1-Digest-Manifest:对整个 MANIFEST.MF 文件做 SHA1(或者 SHA256)后再用 Base64 编码
-
SHA1-Digest:对 MANIFEST.MF 的各个条目做 SHA1(或者 SHA256)后再用 Base64 编码
CERT.RSA
这里会把之前生成的 CERT.SF 文件,用私钥计算出签名, 然后将签名以及包含公钥信息的数字证书一同写入 CERT.RSA 中保存。这里要注意的是,Android APK 中的 CERT.RSA 证书是自签名的,并不需要这个证书是第三方权威机构发布或者认证的,用户可以在本地机器自行生成这个自签名证书。Android 目前不对应用证书进行 CA 认证。
综上所述,一个APK完整的签名过程
2.3 签名校验过程
签名验证是发生在APK的安装过程中,一共分为三步:
-
检查 APK 中包含的所有文件,对应的摘要值与 MANIFEST.MF 文件中记录的值一致。
-
使用证书文件(RSA 文件)检验签名文件(SF 文件)没有被修改过。
-
使用签名文件(SF 文件)检验 MF 文件没有被修改过。
综上所述,一个完整的签名验证过程如下所示:
APK V1 和 V2签名的区别
v1 签名有两个地方可以改进:
-
签名校验速度慢
校验过程中需要对apk中所有文件进行摘要计算,在 APK 资源很多、性能较差的机器上签名校验会花费较长时间,导致安装速度慢。
-
完整性保障不够
META-INF 目录用来存放签名,自然此目录本身是不计入签名校验过程的,可以随意在这个目录中添加文件,比如一些快速批量打包方案就选择在这个目录中添加渠道文件。
从 Android 7.0 开始,Android 支持了一套全新的 V2 签名机制
签名将验证归档中的所有字节,而不是单个 ZIP 条目。
简单来说,v2 签名模式在原先 APK 块中增加了一个新的块(签名块),新的块存储了签名,摘要,签名算法,证书链,额外属性等信息
优点: 1、速度快 2、完整性保证提高。
7.0之前 V1签名
7.0之后 v1 V2签名 ,先签V1 后签V2