如何检查我的应用的签名是否与我用来签名的证书的签名相匹配?
这就是我应该如何获得证书指纹:
public String getCertificateFingerprint() throws NameNotFoundException, CertificateException, NoSuchAlgorithmException {
PackageManager pm = context.getPackageManager();
String packageName =context.getPackageName();
int flags = PackageManager.GET_SIGNATURES;
PackageInfo packageInfo = null;
packageInfo = pm.getPackageInfo(packageName, flags);
Signature[] signatures = packageInfo.signatures;
byte[] cert = signatures[0].toByteArray();
InputStream input = new ByteArrayInputStream(cert);
CertificateFactory cf = null;
cf = CertificateFactory.getInstance("X509");
X509Certificate c = null;
c = (X509Certificate) cf.generateCertificate(input);
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] publicKey = md.digest(c.getPublicKey().getEncoded());
StringBuffer hexString = new StringBuffer();
for (int i = 0; i < publicKey.length; i++) {
String appendString = Integer.toHexString(0xFF & publicKey[i]);
if (appendString.length() == 1)
hexString.append("0");
hexString.append(appendString);
}
return hexString.toString();
}
这就是我应该如何获得证书的指纹:
keytool -v -list -keystore filenameandpath
我的问题是,这两个会给出不同的结果。 有人能指出我搞砸了什么吗?
答案 0 :(得分:6)
您正在计算错误数据的MD5哈希值。证书的指纹是原始证书的哈希值(MD5,SHA1,SHA256等)。即,您应该计算这些字节的哈希值:
byte[] cert = signatures[0].toByteArray();
例如,以下计算SHA1指纹,如果您愿意,只需将SHA1更改为MD5。
public String computeFingerPrint(final byte[] certRaw) {
String strResult = "";
MessageDigest md;
try {
md = MessageDigest.getInstance("SHA1");
md.update(certRaw);
for (byte b : md.digest()) {
strAppend = Integer.toString(b & 0xff, 16);
if (strAppend.length() == 1)
strResult += "0";
strResult += strAppend;
}
strResult = strResult.toUpperCase(DATA_LOCALE);
}
catch (NoSuchAlgorithmException ex) {
ex.printStackTrace();
}
return strResult;
}
答案 1 :(得分:0)
使用您的代码以“测试”模式收集设备上的指纹 - 这意味着您有临时代码将该指纹发送到日志(或其他地方)。请务必使用生产签名密钥进行测试,而不是调试密钥!
从设备的角度来看,您可以删除临时代码和其他地方,您可以将其与您之前确定为关键字的内容进行比较。
请注意,虽然您可能会这样做是为了防止有人修改您的应用并使用其他密钥重新签名,但有能力执行此操作的人也可以修改您的密钥检查。这是一个可以通过额外的混淆解决的问题,但您需要提出自己的解决方案,以尽量减少攻击者知道要查找的内容的可能性。
答案 2 :(得分:0)
您可以将apk作为zip文件打开,并从META-INF / CERT.RSA的二进制内容中过滤ascii文本,并检查是否有人将其烧录。
尝试:
final void initVerify(Certificate certificate)
来自:http://developer.android.com/reference/java/security/Signature.html
答案 3 :(得分:0)
以下代码:
c.getPublicKey().getEncoded()
应该是这样的
c.getEncoded()
我认为通过keytool检查md5是检查certfile,而不是publickey