Apk签名就是对我们的apk加了一个校验参数,防止apk被掉包。一开始做Android开发,就接触到了apk签名;后来在微信开放平台、申请ysdk的参数,需要填写apk签名的md5值和sha256值;就想整理一下,也分享给其它小伙伴们。
一、v1、v2签名的理解:
v1:在v1中只对未压缩的文件内容进行了验证,所以在APK签名之后可以进行很多修改——文件可以移动,甚至可以重新压缩。即可以对签名后的文件在进行处理
v2:v2签名验证了归档中的所有字节,而不是单独的ZIP条目,如果您在构建过程中有任何定制任务,包括篡改或处理APK文件,请确保禁用它们,否则您可能会使v2签名失效,从而使您的APKs与Android 7.0和以上版本不兼容。
google官方文档解释:一个APK可以同时由v1和v2签名同时签署,所以它仍然可以向后兼容以前的Android版本。
使用经验总结:
一定可行的方案: 只使用 v1 方案
不一定可行的方案:同时使用 v1 和 v2 方案
对 7.0 以下一定不行的方案:只使用 v2 方案
1, 如果要支持 Android 7.0 以下版本,那么尽量同时选择两种签名方式,但是一旦遇到签名问题,可以只使用 v1 签名方案
2,如果需要对签名后的信息做处理修改,那就使用v1签名方案
3,如果最后遇到各种不同的问题,可以不勾选v1和v2,直接打包签名
二、命令行查看apk是v1或v2签名
apksigner verify -v demo.apk
三、jks与keystore生成,以及命令行查看签名信息
Eclipse默认生成的签名文件是keystore格式,而Android Studio生成的是jks格式,二者只是签名格式的不同;
keytool -v -list -keystore demo.jks
用代码获取md5值和sha256值
public static String getSign(Context context, String packageName) {
String signValidString = "";
try {
@SuppressLint("PackageManagerGetSignatures")
PackageInfo packageInfo = context.getPackageManager().getPackageInfo(packageName, PackageManager.*GET_SIGNATURES*);
signValidString = *getSignValidString*(packageInfo.signatures[0].toByteArray(), "MD5"); //参数可以填"SHA1"、"SHA256"
} catch (Exception e) {
}
return signValidString;
}
private static String getSignValidString(byte[] paramArrayOfByte, String signType) throws NoSuchAlgorithmException {
MessageDigest localMessageDigest = MessageDigest.*getInstance*(signType);
localMessageDigest.update(paramArrayOfByte);
return *toHexString*(localMessageDigest.digest()); //转为16进制显示,实现略去
}
四、命令行生成签名文件
keytool -genkeypair -alias csdemo -keyalg RSA -validity 400 -keystore demo.keystore
命令行对未签名的apk签名
jarsigner -verbose -keystore demo.keystore -signedjar test_sign.apk Test.apk csdemo
重签名
进行重签名时,会报错java.util.zip.ZipException: invalid entry compressed size (expected 41278 but got 42575bytes) bytes)。如何解决呢?就是要重签名的apk后缀改成zip,打开后删除里面的META-INF目录,然后重新改成apk后缀,再进行签名就可以了。