签名的作用

应用签名的主要作用有两个,第一个是检验安装包是否被修改,第二个是用于确认签名者的身份。

签名时需要一个密钥文件,同一个密钥文件签名出来的 apk,它的签名身份信息是一样的,使用不同的密钥文件的话,签名身份信息自然不一样。并且除非能拿到开发者的密钥文件,不然只靠签名信息文件,是很难在修改过的 apk 文件上伪造出原签名身份信息的。

签名的意义

当我们修改了一个 apk 后,不重新签名,直接安装的话你会发现无法安装(除非你修改了系统),为什么呢?其实就是因为上面提到的签名第一个作用,系统根据原有的签名检测到 apk 被修改了,于是拒绝安装。

但是重新签名不就可以安装了,那签名又有什么意义?这就是签名的第二个作用了,用于确认签名者的身份。

在第一次安装 apk 时,系统压根不知道这个应用的作者是谁,所以它只能检验安装包是否被修改。但是,如果系统已经安装了这个应用,当你覆盖安装时,系统会把已安装和正在安装的 apk 的签名者信息进行对比,如果不一致,也会拒绝安装。

要解决这个问题很简单,把已安装的应用卸载了,然后就可以安装我们重新签名的应用了。

安装 apk 时,签名的作用到这里大概就结束了。是否觉得签名好像依然没什么意义?其实不是。

首先应用可能会在启动时检测它的签名身份信息,如果发现被改了,就直接退出,这就是我们所说的签名校验。

另外一个就是,假设你做了一个十分流行的软件,但被别人修改了并植入木马,造成了非常大的影响,如果警察找上门怎么办?很简单,只要把官方版和木马版的签名身份进行对比,就可以证明你的清白了。

这段摘自网上一位师傅的话,回过来找出处没找见,尴尬…

数据摘要、数字签名、数字证书

阮一峰老师的翻译:http://www.ruanyifeng.com/blog/2011/08/what_is_a_digital_signature

Android 的签名机制流程图:

Pasted Graphic 1.tiff

.keystore 签名文件

使用 keytool 工具创建以 .keystore 为后缀的签名文件,keytool是jdk自带的工具:

keyalg参数可指定RSA、DSA…加密算法,在已签名apk压缩包中的META-INF文件夹中会有 .RSA、.DSA 相应后缀的文件;

[Go0s]: ~/Desktop 
➜  keytool -genkey -storepass "111111" -alias "Go0s" -keypass "111111" -keystore debuggable.keystore -keyalg RSA -keysize 2048 -validity 10000
您的名字与姓氏是什么?
  [Unknown]:  Go0s
您的组织单位名称是什么?
  [Unknown]:  Go0s
您的组织名称是什么?
  [Unknown]:  Go0s
您所在的城市或区域名称是什么?
  [Unknown]:  Go0s
您所在的省/市/自治区名称是什么?
  [Unknown]:  Go0s
该单位的双字母国家/地区代码是什么?
  [Unknown]:  Go0s
CN=Go0s, OU=Go0s, O=Go0s, L=Go0s, ST=Go0s, C=Go0s是否正确?
  [否]:  y

jarsigner 签名工具

jarsigner签名工具,也是自带的工具,签名证书是keytool生成的 .keystore 后缀文件:

[Go0s]: ~/Desktop 
➜  jarsigner -verbose -keystore debuggable.keystore -storepass "111111" re1-e7e4ad1a-R.apk Go0s 
  正在添加: META-INF/MANIFEST.MF
  正在添加: META-INF/GO0S.SF
  正在添加: META-INF/GO0S.RSA
  正在签名: AndroidManifest.xml
  正在签名: classes.dex
  正在签名: lib/armeabi/libplokm.so
  正在签名: res/drawable-hdpi-v4/bck_sign.png
  正在签名: res/drawable-hdpi-v4/ic_launcher.png
  正在签名: res/drawable-mdpi-v4/ic_launcher.png
  正在签名: res/drawable-xhdpi-v4/ic_launcher.png
  正在签名: res/drawable-xxhdpi-v4/ic_launcher.png
  正在签名: res/layout/activity_seclreg.xml
  正在签名: res/menu/seclreg.xml
  正在签名: resources.arsc
  jar 已签名。
  警告: 
  未提供 -tsa 或 -tsacert, 此 jar 没有时间戳。如果没有时间戳, 则在签名者证书的到期日期 (2045-06-19) 或以后的任何撤销日期之后, 用户可能无法验证此 jar。

.pk8、.x509.pem 签名文件

这里使用keytool提取以 .pk8,.x509.pem 为后缀格式的签名文件;

说明两种签名文件格式是可以相互转换的;

1、转换key的格式,控制台会提示debuggable.keystore的密码以及输出tmp.p12的密码,输入正确之后将会生成tmp.p12文件。

[Go0s]: ~/Desktop 
➜  keytool -importkeystore -srckeystore debuggable.keystore -destkeystore tmp.p12 -srcstoretype JKS -deststoretype PKCS12
输入目标密钥库口令:  
再次输入新口令: 
输入源密钥库口令:  
已成功导入别名 go0s 的条目。
已完成导入命令: 1 个条目成功导入, 0 个条目失败或取消

2、将PKCS12格式的key dump为可直接阅读的文本,dump过程中也会提示输入密码,正确输入之后可阅读的token会存储在tmp.rsa.pem中。

[Go0s]: ~/Desktop 
➜  openssl pkcs12 -in tmp.p12 -nodes -out tmp.rsa.pem
Enter Import Password:
MAC verified OK

3、用文本编辑器打开tmp.rsa.pem,将从

-----BEGIN PRIVATE KEY-----
...
-----END PRIVATE KEY-----

这一段(包含这两个tag)的文本复制出来,新建为文件Go0s.rsa.pem

将从

-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----

这一段(包含这两个tag)的文本复制出来,新建为文件Go0s.x509.pem (签名时用到的公钥)

4、转换,生成pk8格式的私钥。

[Go0s]: ~/Desktop 
➜  openssl pkcs8 -topk8 -outform DER -in Go0s.rsa.pem -inform PEM -out Go0s.pk8 -nocrypt  

signapk.jar 工具

signapk.jar签名工具,签名证书是以 .pk8,.x509.pem 为后缀的签名文件:

java -jar signapk.jar  Go0s.x509.pem  Go0s.pk8  源.apk  源-S.apk

All

jarsign:自带,使用keystore格式签名文件,META-INF中SF、RSA文件使用别名;

signapk:使用pk8、x509.pem格式签名文件,META-INF中固定使用CERT;

大多数自动签名工具都是使用这两种。