证书等的概念
相关概念连接
简单说:
- keystore就是数据库,存着 证书(Certificate)
- 证书
- 拥有人的信息(公司、住址、电话、官网)
- 公钥(Public Key)
- 证书的签名(MD5、SHA1、SHA256,各种摘要算法)
- AC机构(该证书授权的机构)
获取证书指纹
- 从KeyStore里获取证书
//keytool 是JDK jre\bin下的执行文件
//从keystore中导出证书
keytool -export -keystore you-keystore -alias you-alias -file Example.cer
//获取证书中的信息
keytool -printcert -file Example.cer
- 从APK包里获取证书
- 取出APK中meta-info/CERT.RSA (将APK后缀改成zip,解压缩就行,CERT.RSA就是证书)
- 运行 keytool -printcert -file CERT.RSA (keytool是JDK bin下的可执行文件,需要在环境变量path中才能运行)
打印出來的信息
证书指纹:
MD5: CB:38:17:D9:44:74:EE:.......
SHA1: 28:3D:60:DD:C.......
SHA256: BC:C3:5D:......
签名算法名称: SHA1withRSA
Android运行时获取
public class SignatureUtils {
private static final String TAG = "SignatureUtils";
public static String[] getSha1And256(Context context) throws PackageManager.NameNotFoundException {
String[] sha = new String[2];
PackageInfo packageInfo = context.getPackageManager().getPackageInfo(
context.getPackageName(), PackageManager.GET_SIGNATURES);
//note sample just checks the first signature
if (packageInfo.signatures != null && packageInfo.signatures.length > 0) {
sha[0] = getSHA1(packageInfo.signatures[0].toByteArray());
sha[1] = getSHA256(packageInfo.signatures[0].toByteArray());
return sha;
}
return null;
}
//computed the sha1 hash of the signature
private static String getSHA1(byte[] sig) {
return getMessageDigest(sig, "SHA1", "BC");
}
private static String getSHA256(byte[] sig) {
return getMessageDigest(sig, "SHA-256", null);
}
private static String getMessageDigest(byte[] sig, String algorithm, String provider) {
String sha1 = null;
MessageDigest shaDigest;
try {
if (provider == null) {
shaDigest = MessageDigest.getInstance(algorithm);
} else {
shaDigest = MessageDigest.getInstance(algorithm, provider);
}
shaDigest.update(sig);
byte[] hashtext = shaDigest.digest();
sha1 = bytesToHex(hashtext);
LogUtil.i(TAG, "SHA" + algorithm + ": " + sha1);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchProviderException e) {
e.printStackTrace();
}
return sha1;
}
//util method to convert byte array to hex string
private static String bytesToHex(byte[] bytes) {
final char[] hexArray = { '0', '1', '2', '3', '4', '5', '6', '7', '8',
'9', 'A', 'B', 'C', 'D', 'E', 'F' };
char[] hexChars = new char[bytes.length * 2];
int v;
for (int j = 0; j < bytes.length; j++) {
v = bytes[j] & 0xFF;
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
}
}
PackageInfo.signature
packageInfo.signatures是一个Array,但实际上APK往往都是1个证书签名的。AndroidStudio提醒是有的人可能含有两个证书,一个伪造的,一个真正的证书。这样我们验证就可能出错,暂时没考虑这么多了。
Public Key
signature 是有getPublicKey,不过是hide注解了,只能FrameWork用。只能自己写getPublicKey,如下是原生方法
/**
* Returns the public key for this signature.
*
* @throws CertificateException when Signature isn't a valid X.509
* certificate; shouldn't happen.
* @hide
*/
public PublicKey getPublicKey() throws CertificateException {
final CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
final ByteArrayInputStream bais = new ByteArrayInputStream(mSignature);
final Certificate cert = certFactory.generateCertificate(bais);
return cert.getPublicKey();
}