一、前言
又是过了好长时间,没写文章的双手都有点难受了。今天是圣诞节,还是得上班。因为前几天有一个之前的同事,在申请微信SDK的时候,遇到签名的问题,问了我一下,结果把我难倒了。。我说Android中的签名大家都会熟悉的,就是为了安全,不让别人修改你的apk,但是我们真正的有了解多少呢?所以准备两篇文章好好介绍一下Android中签名机制。
在说道Android签名之前,我们需要了解的几个知识点
1、数据摘要(数据指纹)、签名文件,证书文件
2、jarsign工具签名和signapk工具签名
3、keystore文件和pk8文件,x509.pem文件的关系
4、如何手动的签名apk
上面介绍的四个知识点,就是今天介绍的核心,我们来一一看这些问题。
二、准备知识
首先来看一下数据摘要,签名文件,证书文件的知识点
1、数据摘要
这个知识点很好理解,百度百科即可,其实他也是一种算法,就是对一个数据源进行一个算法之后得到一个摘要,也叫作数据指纹,不同的数据源,数据指纹肯定不一样,就和人一样。
消息摘要算法(Message Digest Algorithm)是一种能产生特殊输出格式的算法,其原理是根据一定的运算规则对原始数据进行某种形式的信息提取,被提取出的信息就被称作原始数据的消息摘要。
著名的摘要算法有RSA公司的MD5算法和SHA-1算法及其大量的变体。
消息摘要的主要特点有:
1)无论输入的消息有多长,计算出来的消息摘要的长度总是固定的。例如应用MD5算法摘要的消息有128个比特位,用SHA-1算法摘要的消息最终有160比特位的输出。
2)一般来说(不考虑碰撞的情况下),只要输入的原始数据不同,对其进行摘要以后产生的消息摘要也必不相同,即使原始数据稍有改变,输出的消息摘要便完全不同。但是,相同的输入必会产生相同的输出。
3)具有不可逆性,即只能进行正向的信息摘要,而无法从摘要中恢复出任何的原始消息。
2、签名文件和证书
签名文件和证书是成对出现了,二者不可分离,而且我们后面通过源码可以看到,这两个文件的名字也是一样的,只是后缀名不一样。
其实数字签名的概念很简单。大家知道,要确保可靠通信,必须要解决两个问题:首先,要确定消息的来源确实是其申明的那个人;其次,要保证信息在传递的过程中不被第三方篡改,即使被篡改了,也可以发觉出来。
所谓数字签名,就是为了解决这两个问题而产生的,它是对前面提到的非对称加密技术与数字摘要技术的一个具体的应用。
对于消息的发送者来说,先要生成一对公私钥对,将公钥给消息的接收者。
如果消息的发送者有一天想给消息接收者发消息,在发送的信息中,除了要包含原始的消息外,还要加上另外一段消息。这段消息通过如下两步生成:
1)对要发送的原始消息提取消息摘要;
2)对提取的信息摘要用自己的私钥加密。
通过这两步得出的消息,就是所谓的原始信息的数字签名。
而对于信息的接收者来说,他所收到的信息,将包含两个部分,一是原始的消息内容,二是附加的那段数字签名。他将通过以下三步来验证消息的真伪:
1)对原始消息部分提取消息摘要,注意这里使用的消息摘要算法要和发送方使用的一致;
2)对附加上的那段数字签名,使用预先得到的公钥解密;
3)比较前两步所得到的两段消息是否一致。如果一致,则表明消息确实是期望的发送者发的,且内容没有被篡改过;相反,如果不一致,则表明传送的过程中一定出了问题,消息不可信。
通过这种所谓的数字签名技术,确实可以有效解决可靠通信的问题。如果原始消息在传送的过程中被篡改了,那么在消息接收者那里,对被篡改的消息提取的摘要肯定和原始的不一样。并且,由于篡改者没有消息发送方的私钥,即使他可以重新算出被篡改消息的摘要,也不能伪造出数字签名。
所以,综上所述,数字签名其实就是只有信息的发送者才能产生的别人无法伪造的一段数字串,这段数字串同时也是对信息的发送者发送信息真实性的一个有效证明。
不知道大家有没有注意,前面讲的这种数字签名方法,有一个前提,就是消息的接收者必须要事先得到正确的公钥。如果一开始公钥就被别人篡改了,那坏人就会被你当成好人,而真正的消息发送者给你发的消息会被你视作无效的。而且,很多时候根本就不具备事先沟通公钥的信息通道。那么如何保证公钥的安全可信呢?这就要靠数字证书来解决了。
所谓数字证书,一般包含以下一些内容:
证书的发布机构(Issuer)
证书的有效期(Validity)
消息发送方的公钥
证书所有者(Subject)
数字签名所使用的算法
数字签名
可以看出,数字证书其实也用到了数字签名技术。只不过要签名的内容是消息发送方的公钥,以及一些其它信息。但与普通数字签名不同的是,数字证书中签名者不是随随便便一个普通的机构,而是要有一定公信力的机构。这就好像你的大学毕业证书上签名的一般都是德高望重的校长一样。一般来说,这些有公信力机构的根证书已经在设备出厂前预先安装到了你的设备上了。所以,数字证书可以保证数字证书里的公钥确实是这个证书的所有者的,或者证书可以用来确认对方的身份。数字证书主要是用来解决公钥的安全发放问题。
综上所述,总结一下,数字签名和签名验证的大体流程如下图所示:
3、jarsign和signapk工具
了解到完了签名中的三个文件的知识点之后,下面继续来看看Android中签名的两个工具:jarsign和signapk
关于这两个工具开始的时候很容易混淆,感觉他们两到底有什么区别吗?
其实这两个工具很好理解,jarsign是Java本生自带的一个工具,他可以对jar进行签名的。而signapk是后面专门为了Android应用程序apk进行签名的工具,他们两的签名算法没什么区别,主要是签名时使用的文件不一样,这个就要引出第三个问题了。
4、keystore文件和pk8,x509.pem文件的区别
我们上面了解到了jarsign和signapk两个工具都可以进行Android中的签名,那么他们的区别在于签名时使用的文件不一样
jarsign工具签名时使用的是keystore文件
signapk工具签名时使用的是pk8,x509.pem文件
其中我们在使用Eclipse工具写程序的时候,出Debug包的时候,默认用的是jarsign工具进行签名的,而且Eclipse中有一个默认签名文件:
我们可以看到这个默认签名的keystore文件,当然我们可以选择我们自己指定的keystore文件。
这里还有一个知识点:
我们看到上面有MD5和SHA1的摘要,这个就是keystore文件中私钥的数据摘要,这个信息也是我们在申请很多开发平台账号的时候需要填入的信息,比如申请百度地图,微信SDK等,会需要填写应用的MD5或者是SHA1信息。
5、手动的签名Apk包
1》使用keytool和jarsigner来进行签名
当然,我们在正式签名处release包的时候,我们需要创建一个自己的keystore文件:
这里我们可以对keystore文件起自己的名字,而且后缀名也是无关紧要的。创建完文件之后,也会生成MD5和SHA1的值,这个值可以不用记录的,可以通过命令查看keystore文件的MD5和SHA1的值。
keytool -list -keystore debug.keystore
当然我们都知道这个keytstore文件的重要性,说白了就相当于你的银行卡密码。你懂得。
这里我们看到用Eclipse自动签名和生成一个keystore文件,我们也可以使用keytool工具生成一个keystore文件。这个方法网上有,这里就不做太多的介绍了。然后我们可以使用jarsign来对apk包进行签名了。
我们可以手动的生成一个keystore文件:
keytool -genkeypair -v -keyalg DSA -keysize 1024 -sigalg SHA1withDSA -validity 20000 -keystore D:\jiangwei.keystore -alias jiangwei -keypass jiangwei -storepass jiangwei
这个命令有点长,有几个重要的参数需要说明:
-alias是定义别名,这里为debug
-keyalg是规定签名算法,这里是DSA,这里的算法直接关系到后面apk中签名文件的后缀名,到后面会详细说明
在用jarsigner工具进行签名
jarsigner -verbose -sigalg SHA1withDSA -digestalg SHA1 -keystore D:\jiangwei.keystore -storepass jiangwei D:\123.apk jiangwei