之前有多个游戏遇到关于签名错误的问题,加上有些游戏开发不熟悉Android签名校验的机制以及打包的方法,就专门总结了一下,现在整理一下。 首先放上官方文档链接:http://developer.android.com/tools/publishing/app-signing.html
就是只有信息的发送者才能产生的别人无法伪造的一段数字串,这段数字串同时也是对信息的发送者发送信息真实性的一个有效证明。数字签名是个加密的过程,数字签名验证是个解密的过程。
最简单直接的回答: 系统要求的。
通俗的解答:
Android系统要求每一个Android应用程序必须要经过数字签名才能够安装到系统中,也就是说如果一个Android应用程序没有经过数字签名,是没有办法安装到系统中的!
装逼的解答:
在Android 系统中,所有安装到系统的应用程序都必有一个数字证书,此数字证书用于标识应用程序的作者和在应用程序之间建立信任关系,如果一个permission的protectionLevel为signature,那么就只有那些跟该permission所在的程序拥有同一个数字证书的应用程序才能取得该权限。
数字证书的私钥保存在程序开发者的手中。Android将数字证书用来在应用程序的作者和应用程序之间建立信任关系,不是用来决定最终用户可以安装哪些应用程序。这个数字证书并不需要权威的数字证书签名机构认证,它只是用来让应用程序包自我认证的。
在调试模式下,ADT会自动的使用debug密钥为应用程序签名,因此我们可以直接运行程序。
debug密钥:一个名为debug.keystore的文件,android默认的debug.keystore的信息如下:
Keystore name: “debug.keystore”
Keystore password: “android”
Key alias: “androiddebugkey”
Key password: “android”
CN: “CN=Android Debug,O=Android,C=US”
存放位置:C:\Users\用户名.android\debug.keystore
debug签名的两个风险:
发布程序时,开发者需要使用自己的数字证书给apk包签名。使用自己的数字证书给APK签名有两种方法。将在下文描述。
私钥目前主要是通过 keytool 生成,事例如下:
生成命令:
keytool -genkey -keystore debug.keystore -alias bihe0832 -keypass android -keyalg RSA -validity 40000
常用参数含义:
非常用参数含义:
查看命令:
keytool -list -v -keystore debug.keystore
使用事例:
➜ AndroidAppFactory git:(master) keytool -list -v -keystore debug.keystore
输入密钥库口令:
密钥库类型: JKS
密钥库提供方: SUN
您的密钥库包含 1 个条目
别名: androiddebugkey
创建日期: 2015年1月19日
条目类型: PrivateKeyEntry
证书链长度: 1
证书[1]:
所有者: CN=Android Debug, O=Android, C=US
发布者: CN=Android Debug, O=Android, C=US
序列号: 54bc748d
生效时间: Mon Jan 19 11:05:49 CST 2015, 失效时间: Wed Jan 11 11:05:49 CST 2045
证书指纹:
SHA1: F1:61:47:EC:C2:98:F4:F2:ED:DE:B5:5E:C9:4B:62:92:2F:52:BE:2C
SHA256: 3A:DB:9E:16:EE:E3:84:81:63:91:F7:CE:A0:FF:F0:BF:24:8F:F2:C3:00:EA:06:97:2B:83:8B:AA:95:FF:48:8A
签名算法名称: SHA1withRSA (弱)
主体公共密钥算法: 1024 位 RSA 密钥 (弱)
版本: 3
*******************************************
*******************************************
查看命令:
keytool -list -rfc --keystore debug.keystore | openssl x509 -inform pem -pubkey
使用事例:
➜ AndroidAppFactory git:(master) keytool -list -rfc --keystore ./debug.keystore | openssl x509 -inform pem -pubkey
输入密钥库口令: android
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCU1yjobRCWKk70XfM3lYM/Vsb9
eTNs8wavDOrH2VHi471/WtW+vuvXWdeF2NmvciVU7y+E6qf561rA7hdx5iDi4z7K
vvCri6ySiXM7Dq+4UBL3FT1V4kqLtvzjNIKs2Cp2HIRI/DAwgD6lOKseApSPj5Kw
iFxe35iwTAYDr9EykQIDAQAB
-----END PUBLIC KEY-----
-----BEGIN CERTIFICATE-----
MIIB5TCCAU6gAwIBAgIEVLx0jTANBgkqhkiG9w0BAQUFADA3MQswCQYDVQQGEwJV
UzEQMA4GA1UEChMHQW5kcm9pZDEWMBQGA1UEAxMNQW5kcm9pZCBEZWJ1ZzAeFw0x
NTAxMTkwMzA1NDlaFw00NTAxMTEwMzA1NDlaMDcxCzAJBgNVBAYTAlVTMRAwDgYD
VQQKEwdBbmRyb2lkMRYwFAYDVQQDEw1BbmRyb2lkIERlYnVnMIGfMA0GCSqGSIb3
DQEBAQUAA4GNADCBiQKBgQCU1yjobRCWKk70XfM3lYM/Vsb9eTNs8wavDOrH2VHi
471/WtW+vuvXWdeF2NmvciVU7y+E6qf561rA7hdx5iDi4z7KvvCri6ySiXM7Dq+4
UBL3FT1V4kqLtvzjNIKs2Cp2HIRI/DAwgD6lOKseApSPj5KwiFxe35iwTAYDr9Ey
kQIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAEYAcZE2H9kwJELwIOSB1ezTTvYGvdZw
R2gYm1gnQhWtUxGS05iewhTv8GynPWxuRVyEAOZdrIy1EP+ToPlyD9COgU61pyEs
bcWbp7WFBxC/+V0XazOJ0PbPpECTzJLYnd/By7rQK8SkkVimm9rufiTnZCdzKQgZ
+WvQ/Jv7n2cU
-----END CERTIFICATE-----
如果要使用APK 查看加密信息,可以参考下面的链接:应用信息及Keystore信息获取 - AAF
目前使用keytool签名有两种方式,一种是java提供的jarsigner,另一种是安卓官方提供的apksigner,这里分别介绍一下。不过需要注意的是目前Android已经在逐渐淘汰基于 jarsigner 的 Android V1 签名模式,因此如非必需,建议使用基于 apksigner的 Android V2 签名方式签名apk。关于 Android V2 签名的更多文章,请参考个人的另一篇文章:关于Android的APK Signature Scheme v2签名相关的资料汇总
签名命令:
jarsigner -verbose -keystore bihe0832.keystore -signedjar agsdkdemo_signed.apk -digestalg SHA1 -sigalg SHA1withDSA agsdkdemo.apk bihe0832 -storepass mypassword
参数含义:
-keystore bihe0832.keystore
: 密钥库位置-signedjar agsdkdemo_signed.apk
:签名后产生的文件-digestalg SHA1 -sigalg SHA1withDSA
:私钥算法agsdkdemo.apk
:要签名的文件demo.apkbihe0832
:私钥的alias-storepass mypassword
:私钥密码,其中mypassword即为密码注意事项:android工程的bin目录下的demo.apk默认是已经使用debug用户签名的,所以不能使用上述步骤对此文件再次签名。正确步骤应该是:在工程点击右键->Anroid Tools-Export Unsigned Application Package导出的apk采用上述步骤签名。
签名命令:
$ANDROID_HOME/build-tools/25.0.1/apksigner sign --ks ~/lib/bihe0832.keystore ./debug-ysdk.apk
$ANDROID_HOME/build-tools/25.0.1/apksigner sign --ks ~/lib/bihe0832.keystore --out ./debug-ysdk-singned.apk --ks-pass pass:mypassword ./debug-ysdk.apk
参数含义:
sign
:给应用签名--ks ~/lib/bihe0832.keystore
: 密钥库位置--out ./debug-ysdk-singned.apk
: 签名后应用--ks-pass pass:mypassword
: 文字格式的私钥密码,其中mypassword即为密码./debug-ysdk.apk
: 要签名的应用注意事项: apksigner是Android官方提供的签名及校验工具,从Android SDK Build Tools的24.0.3版本开始支持,具体路径在SDK目录的build-tools目录下。
Eclipse直接能导出带签名的最终apk,非常方便,推荐使用,步骤如下:
导出
选择工程:选择你要导出apk的工程
创建密钥库keystore,输入密钥库导出位置和密码,要记住密码
填写密钥库信息,填写一些apk文件的密码,使用期限和组织单位的信息
输入生成带签名的apk文件的位置。
jarsigner: 找不到XXXX的证书链。XXXX必须引用包含私有密钥和相应的公共密钥证书链的有效密钥库密钥条目。
出现该错误是因为在命令输入的最后一个参数填写的是签名私钥的alias,而不是私钥的文件名称
jarsigner: 无法对 jar 进行签名: java.util.zip.ZipException: invalid entry compressed size (expected 19384 but got 19942 bytes)
出现该错误的原因是因为对一个已经使用DEBUG权限的数字签名的包,使用jarsigner再次签名导致的,建议用V2重新签名或者导出一个未签名的apk重新签名即可,如果一定要对当前包重新签名,可以选择将文件修改为.zip后缀,然后解压缩,删除META-INF
目录,然后再次压缩为.zip并修改扩展名为.apk后再次签名
jarsigner 错误: java.security.NoSuchAlgorithmException: unrecognized algorithm name: RSAwithDSA
出现该错误的原因是私钥算法与签名算法(命令中的-sigalg 参数的值)不兼容,直接使用keytool去查看私钥使用的算法修改即可,命令示例如下:
➜ readhub git:(master) keytool -list -v -keystore bihe0832.keystore
输入密钥库口令:
……
证书指纹:
……
签名算法名称: SHA1withDSA
……
jarsigner: 无法对 jar 进行签名: 无法对jar进行签名:java.util.zip.ZipException: invalid entry compressed size (expected xxx but got xxx bytes)
出现该错误的原因是由于资源文件造成的,对于android开发来说应该检查res文件夹中的文件,逐个排查。当然也可以可以通过升级系统的JDK和JRE版本来解决。
安装apk过程中出现:adb: failed to install 2.apk: Failure [INSTALL_PARSE_FAILED_NO_CERTIFICATES: Failed to collect certificates from XXX.apk: Attempt to get length of null array]
使用adb安装时出现该错误是因为应用没有签名,需要先对apk签名之后再尝试安装
安装apk过程中出现:adb: failed to install test.apk: Failure [INSTALL_PARSE_FAILED_NO_CERTIFICATES: Failed to collect certificates from XXX.apk: META-INF/CERT.SF has invalid digest for XXX.xml in XXX.apk]
出现该的原因是由于使用jarsigner 方式签名时JDK的版本问题造成的,可以通过升级系统的JDK和JRE版本来解决。
安装apk过程中出现:adb: failed to install test-singend.apk: Failure [INSTALL_FAILED_UPDATE_INCOMPATIBLE: Package com.bihe0832.getsignature signatures do not match the previously installed version; ignoring!]
出现该错误的原因是因为设备上已经安装了一个同包名但是签名并不一致的apk,需要卸载原有apk重新安装新签名的apk。
安装apk过程中出现:adb: failed to install test-singend.apk: Failure [INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES]
出现该错误的原因是因为设备上已经安装了一个同包名但是签名并不一致的apk,并且已经安装的应用使用Android的debug签名文件来签名,即将安装的应用使用自定义签名文件签名,需要卸载原有apk重新安装新签名的apk。