按照自己的理解,写下总结。
1. 数字证书
正常是由数字证书管理心发给个人或者组织的证书,相当于身份证,用来唯一识别一个发送者,这点在通过网络签署合同时很重要,避免对方抵赖合同不是他发送的。但是android 上证书是自己生成的,因为不管是谁开发的应用,默认都是允许安装的。
2. 数字签名
数字签名是用来确认发送者身份和发送信息完整性的。发送者将把原始数据摘要信息用私有进行加密,然后连同原始数据和证书一起发送接受者。接受者获取证书获取了对方身份,和公钥信息,再用公钥对加密后的数据摘要进行解密得到原始摘要信息,之后和原始数据生成的摘要比较,如果一样表明信息没有别篡改过。Android 安装应用的时候需要检查应用的完整性,所以需要用到数字签名。
3. 数据摘要及算法
数据摘要用来验证数据的完整性,理论上可以对任意长度的原始数据生成固定长度的摘要信息,而且只要原始数据一样,得到的摘要信息就一定是一样。也就是说对应任意的数据,它的摘要信息是唯一。因此可以通过摘要信息验证原始数据是否被篡改过。常用的摘要信息算法有MD5、SHA1。MD5生成的数据长度短些,SHA1生成的摘要数据长度要长些,使用更长的摘要数据应该是避免摘要重复吧。
4. 对称加密和非对称加密
对称加密使用同一个密钥加密和解密。最大缺点是密钥不好管理,比如一个公司有很客户,那么该公司和每个客户之间都会有一个密钥进行通信,如果客户很多,本公司对密钥管理起来复杂,而且客户也同时需要管理,只要一方泄露密钥,那就导致通信不安全。常用算法有DES、AES、RC2、RC3、RC5等。
非对称加密是一个共私密钥对,用私钥加密,可以用公钥解密,反之亦然。这样对公司来说只需要保存一个私钥,把公钥发布给客户就可以了。常用的算法是RSA。
5. android 数字证书和私钥
总共有那么4种类型的证书和对应私钥,其中 pem 结尾的是证书,pk8 结尾的是对应私钥。
media.pk8
media.x509.pem
platform.pk8
platform.x509.pem
shared.pk8
shared.x509.pem
testkey.pk8
testkey.x509.pem
media 是针对media/download 应用的,它们的UID需要定义成android.uid.media,platform是给平台应用的,UID是system的必须得用这个签名。如果应用需要和Contacts进程共享数据,则使用shared,它们的UID需要定义成android.uid.shared。
证书中包含了发行者信息,发行时间,证书过期时间和公钥等。
6. 如何签名或者重新签名一个APK
1). 使用 signapk
java -jar out/host/linux-x86/framework/signapk.jar build/target/product/security/platform.x509.pem build/target/product/security/platform.pk8 NoSigned.apk Signed.apk
2). 使用jarsigner , 看网上说的,自己没用过这种方式。
7. 签名流程
1)对apk里面的所有文件生成摘要信息(基于SHA1算法)并用base64 加密写到apk的META-INF/MANIFEST.MF 文件里。 为什么还要用base64加密?base64 算法是用来将非ASCII字符转成ASCII字符,适合网络传输。还有就是加密后不能直接看到明文而已,这里就算看到摘要信息似乎也无所谓。不管怎样,这个文件是用来验证apk下的文件是否完整,有没有被篡改过,我们知道修改过后它们的摘要信息就不一样了。
2)对MANIFEST.MF 文件和里面的摘要信息再次生成摘要信息并写入META-INF/CERT.SF文件。这个文件主要是防止MANIFEST.MF 被篡改。
3)对CERT.SF 生成摘要信息,并用私钥加密生成数字签名,连同公钥写入META-INF/CERT.RSA。这样安装应用的时候就可以通过这个文件取得公钥,用公钥去解密私钥得到CERT.SF文件的摘要信息,就可以验证CERT.SF的完整性。
可见android的数字签名主要是验证应用的完整性的,但是我们同时能从应用里携带的证书获取发布应用者的信息和公钥。所以如果想让我们的设备只允许安装特定开发者的应用,那么可以通过公钥来判断。比如安全方面的设备。
签名代码实现在build\tools\signapk\SignApk.java.
8. 查看某个应用的public key,先从apk 提取出CERT.RSA,然后用如下命令就可以查看了。
openssl pkcs7 -inform DER -in CERT.RSA -noout -print_certs -text