Android签名机制
什么是Android签名
了解 HTTPS 通信的同学都知道,在消息通信时,必须至少解决两个问题:一是确保消息来源的真实性,二是确保消息不会被第三方篡改。
同理,在安装 apk 时,同样也需要确保 apk 来源的真实性,以及 apk 没有被第三方篡改。为了解决这一问题,Android官方要求开发者对 apk 进行签名,而签名就是对apk进行加密的过程。要了解如何实现签名,需要了解两个基本概念:消息摘要、数字签名和数字证书。
消息摘要
消息摘要(Message Digest),又称数字摘要(Digital Digest)或数字指纹(Finger Print)。简单来说,消息摘要就是在消息数据上,执行一个单向的 Hash 函数,生成一个固定长度的Hash值,这个Hash值即是消息摘要。
上面提到的的加密 Hash 函数就是消息摘要算法。它有以下特征:
无论输入的消息有多长,计算出来的消息摘要的长度总是固定的。
例如:应用 MD5 算法摘要的消息有128个比特位,用 SHA-1 算法摘要的消息最终有 160 比特位的输出,SHA-1 的变体可以产生 192 比特位和 256 比特位的消息摘要。一般认为,摘要的最终输出越长,该摘要算法就越安全。
消息摘要看起来是「随机的」。
这些比特看上去是胡乱的杂凑在一起的。可以用大量的输入来检验其输出是否相同,一般,不同的输入会有不同的输出,而且输出的摘要消息可以通过随机性检验。但是,一个摘要并不是真正随机的,因为用相同的算法对相同的消息求两次摘要,其结果必然相同;而若是真正随机的,则无论如何都是无法重现的。因此消息摘要是「伪随机的」。
消息摘要函数是单向函数,即只能进行正向的信息摘要,而无法从摘要中恢复出任何的消息,甚至根本就找不到任何与原信息相关的信息。
当然,可以采用强力攻击的方法,即尝试每一个可能的信息,计算其摘要,看看是否与已有的摘要相同,如果这样做,最终肯定会恢复出摘要的消息。但实际上,要得到的信息可能是无穷个消息之一,所以这种强力攻击几乎是无效的。
好的摘要算法,没有人能从中找到「碰撞」。或者说,无法找到两条消息,使它们的摘要相同。
虽然「碰撞」是肯定存在的(由于长明文生成短摘要的 Hash 必然会产生碰撞)。即对于给定的一个摘要,不可能找到一条信息使其摘要正好是给定的。
正是由于以上特点,消息摘要算法被广泛应用在「数字签名」领域,作为对明文的摘要算法。著名的消息摘要算法有 RSA 公司的 MD5 算法和 SHA-1 算法及其大量的变体。SHA-256 是 SHA-1 的升级版,现在 Android 签名使用的默认算法都已经升级到 SHA-256 了。
正是因为消息摘要具有这种特性,很适合来验证数据的完整性。比如:在网络传输过程中下载一个大文件 BigFile,我们会同时从网络下载 BigFile 和 BigFile.md5,BigFile.md5 保存 BigFile 的摘要,我们在本地生成 BigFile 的消息摘要和 BigFile.md5 比较,如果内容相同,则表示下载过程正确。
数字签名
数字签名的作用就是保证信息传输的完整性、发送者的身份认证、防止交易中的抵赖发生。数字签名技术是将摘要信息用发送者的私钥加密,与原文一起传送给接收者。接收者只有用发送者的公钥才能解密被加密的摘要信息然后用HASH函数对收到的原文产生一个摘要信息,与解密的摘要信息对比。如果相同,则说明收到的信息是完整的,在传输过程中没有被修改,否则说明信息被修改过,因此数字签名能够验证信息的完整性。
如 RSA 作为数字签名方案使用时,它的使用流程如下:这种签名实际上就是用信源的私钥加密消息,加密后的消息即成了签体;而用对应的公钥进行验证,若公钥解密后的消息与原来的消息相同,则消息是完整的,否则消息不完整。