签名原理见:http://blog.youkuaiyun.com/oqqtim12/article/details/39936465
目前主要的签名应用场景,是在各大应用市场中,实现下面这个功能:
1、后台提示用户更新应用,假设应用手机上安装的应用签名与后台上传的APK签名不一致,那么不提示用户更新此应用;
2、用户在应用市场中安装应用,假设需要安装的应用签名与本地签名不一致,那么在安装前检查,发现不一致提示用户卸载本地应用,然后重新安装
可以发现,两个场景的核心都是“检测需要安装的应用签名与本地签名不一致”
一、在终端上获取本地APP的签名:
try {
PackageInfo packageInfo = getPackageManager()
.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
String signMd5 = MD5.toMD5(packageInfo.signatures[packageInfo.signatures.length - 1].toCharsString());
Log.d("Sign",signMd5);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
这里其实只是获取一个签名的MD5值
二、在非终端上获取apk签名
/**
* 获取android包里面的所有证书MD5
* @param apkFile 包文件
* @return
*/
public static String getSigMd5(File apkFile) {
//解压APK文件,;略
String unPackFile = unpack(apkFile);
//针对使用RSA算法签名的APK,获取./META-INF/*.RSA文件
File cerFile = getRSAFile(unPackFile);
//针对使用DSA算法签名的APK,获取./META-INF/*.DSA文件
if (cerFile == null )
cerFile = getDSAFile(unPackFile);
FileInputStream input = null;
try {
input = new FileInputStream(cerFile);
PKCS7 pkcs7 = new PKCS7(input);
Certificate[] certs = pkcs7.getCertificates();
String eggPainSign = (new String(BytetoChars(certs[certs.length - 1].getEncoded())));
String eggPainMd5 = MD5.toMD5(eggPainSign.getBytes());
return eggPainMd5;
} catch (Exception e) {
e.printStackTrace();
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
}
}
}
return null;
}
同样获取对应的MD5值,讲此值存储在数据库中,然后交由终端比较即可
原理是:找到METE-INF下存储签名的文件(可能是RSA或者RSA结尾),生成Certificate[]对象,取起MD5即可;同时可以发现,Signature对象其实就是在Certificate基础上做了一层封装,其中BytetoChars方法如下:
/**
* @param mSignature
* @return
*/
private static char[] BytetoChars(byte[] mSignature) {
byte[] sig = mSignature;
final int N = sig.length;
final int N2 = N * 2;
char[] text = new char[N2];
for (int j = 0; j<N; j++) {
byte v = sig[j];
int d = (v >> 4)&0xf;
text[j * 2] = (char) (d>=10 ? ('a' + d - 10) : ('0' + d));
d = v&0xf;
text[j * 2 + 1] = (char) (d>=10 ? ('a' + d - 10) : ('0' + d));
}
return text;
}
需要注意的是,目前在签名生产过程中,主要使用RSA、DSA算法,不同算法生成的签名文件后缀不同,分别是*.RSA以及*.DSA,因此需要在搜索签名文件时候需要做兼容;