Android签名概述
我们已经知道的是:Android对每一个Apk文件都会进行签名,在Apk文件安装时,系统会对其签名信息进行比对,判断程序的完整性,从而决定该Apk文件是否可以安装,在一定程度上达到安全的目的。
给定一个Apk文件,解压,可以看到一个META-INFO文件夹,在该文件夹下有三个文件:分别为MANIFEST.MF、CERT.SF和CERT.RSA。这三个文件分别表征以下含义:
- MANIFEST.MF:这是摘要文件。程序遍历Apk包中的所有文件(entry),对非文件夹非签名文件的文件,逐个用SHA1生成摘要信息,再用Base64进行编码。如果你改变了apk包中的文件,那么在apk安装校验时,改变后的文件摘要信息与MANIFEST.MF的检验信息不同,于是程序就不能成功安装。
说明:如果攻击者修改了程序的内容,有重新生成了新的摘要,那么就可以通过验证,所以这是一个非常简单的验证。 - CERT.SF:这是对摘要的签名文件。对前一步生成的MANIFEST.MF,使用SHA1-RSA算法,用开发者的私钥进行签名。在安装时只能使用公钥才能解密它。解密之后,将它与未加密的摘要信息(即,MANIFEST.MF文件)进行对比,如果相符,则表明内容没有被异常修改。
说明:在这一步,即使开发者修改了程序内容,并生成了新的摘要文件,但是攻击者没有开发者的私钥,所以不能生成正确的签名文件(CERT.SF)。系统在对程序进行验证的时候,用开发者公钥对不正确的签名文件进行解密,得到的结果和摘要文件(MANIFEST.MF)对应不起来,所以不能通过检验,不能成功安装文件。 - CERT.RSA文件中保存了公钥、所采用的加密算法等信息。 说明:系统对签名文件进行解密,所需要的公钥就是从这个文件里取出来的。
结论:从上面的总结可以看出,META-INFO里面的所有文件环环相扣,从而保证Android程序的安全性。(只是防止开发者的程序不被攻击者修改,如果开发者的公私钥被攻击者得到或者开发者开发出攻击程序,Android系统都无法检测出来。)
1,Android签名机制其实是对APK包完整性和发布机构唯一性的一种校验机制。
2,Android签名机制不能阻止APK包被修改,但修改后的再签名无法与原先的签名保持一致。(拥有私钥的情况除外)。
3,APK包加密的公钥就打包在APK包内,且不同的私钥对应不同的公钥。换句话言之,不同的私钥签名的APK公钥也必不相同。所以我们可以根据公钥的对比,来判断私钥是否一致。
MD5和SHA1
Android的应用程序发布出来都是需要加密的,否则就会轻易被篡改或者替换,为此才有keystore。网上解释:是Java的密钥库、用来进行通信加密用的、比如数字签名。keystore就是用来保存密钥对的,比如公钥和私钥。
也就是说keystore是用来在打包apk的时候对apk程序进行加密处理用的,也就是所谓的数字证书加密。
我们的IDE中有默认的keystore(eclipse和Android Studio),也就是数字证书,不过这个是我们run as project的时候调试用的,也就是debugkeystore,他这个是自动生成的,cmd模式下,用keytool -list -v -keystore debug.keystore可以看到其中包含的内容。所以,在正式发布apk的时候是不能用这个的,发布时候的keystore需要我们自己去生成,填写密码等一些信息生成。
接下来是sha1 md5,就是把任意长度的信息,通过一些算法,生成固定长度的字符串,只要这些信息有变动,那么生成的sha1,md5就会变化,通过这样来保护文件没有被改动过。而且根据生成的字符串是不会推算出来原来的内容的。(sha1,md5生成的字符串长度不一样)
那么这样就会根据keystore生成相应的sha1和md5,保存在manifests.mf中。
既然apk是通过数字证书来加密的,如果程序要更新的话,怎么来保证更新的程序是对的呢,那么就是通过验证数字证书是否是相同的,那怎么来保证数字证书是相同的呢,就是通过sha1,md5来保证的。
查询应用签名
在Eclipse中可以轻而易举的通过menu下的Window找到MD5和SHA1的值。
而在Android Studio中在Terminal中输入命令行(与cmd相同)
首先我们得在系统的环境变量中配置下keytool,keytool.exe是位于我们JDK安装的bin目录下。
然后通过cmd打开控制台,定位到.android文件夹下,Users/…/.android
输入keytool -list -v -keystore debug.keystore得到三种指纹证书,选取SHA1类型的证书,密匙口令是android,就可以获取到MD5和SHA1(注意如果不输入-v的话就只会出现SHA1的值)。
还有对META-INF下的CERT.RSA解析的,大同小异,就不一一说明。
在实际开发中为了避免注册时弄错签名,建议时打包后在获取apk的签名。
公钥与私钥
公钥和私钥就是俗称的不对称加密方式,是从以前的对称加密(使用用户名与密码)方式的提高。
利用一对互相匹配的密钥进行加密、解密。每个用户自己设定一把特定的仅为本人所知的私有密钥(私钥),用它进行解密和签名;同时 设定一把公共密钥(公钥)并由本人公开,为一组用户所共享,用于加密和验证签名。当发送一份保密文件时,发送方使用接收方的公钥对数据加密,而接收方则使 用自己的私钥解密,这样信息就可以安全无误地到达目的地了。通过数字的手段保证加密过程是一个不可逆过程,即只有用私有密钥才能解密. 在公开密钥密码体制中,常用的一种是RSA体制。
用户也可以采用自己的私钥对信息加以处理,由于密钥仅为本人所有,这样就产生了别人无法生成的文件,也就形成了数字签名。采用数字签名,能够确认以下两点:
(1)保证信息是由签名者自己签名发送的,签名者不能否认或难以否认;
(2)保证信息自签发后到收到为止未曾作过任何修改,签发的文件是真实文件。
使用Android Studio签名
生成jks签名文件
build->Generate Signed APK...
选择创建一个新的签名文件
依步骤下来,可在app目录下找到签好名的apk
也可在Project Stucture图形化界面中设置每次运行都是签名的apk。
选中app这个module,然后切换到singning标签栏,紧接着点击添加,然后生成release签名信息,紧接着点击”OK”
切换到Build Types标签,将Signing config选择为”release”,即将刚刚生成的release签名信息配置进去。
点击ok后,每次run project都是签名的apk。
操作完成之后,我们还可以看到app这个module的build.gradle文件多出了签名的配置信息。
结束语:本文仅用来学习记录,参考查阅。