安卓签名文件及解析
1. Android Studio默认的apk打包文件地址
用户根目录/.android/debug.keystore
Android Studio - debug keystore
Where the debug.keystore in Android Studio
Eclipse ADT基本一致:Windows->Preference->Android->Build 可以查看
2. 通过keytool计算apk的签名
对于jdk7及以上版本可以直接通过如下命令
keytool -list -printcert -jarfile apk_file_path
如果有keystore文件
keytool -list -keystore file_path
默认的debug.keystore密码为android
I have never set any passwords to my keystore and alias, so how are they created
如果知道keystore的alias和密码,可以显示更详细的信息
keytool -list -alias androiddebugkey -keystore debug.keystore -storepass android -keypass android -v
对于jdk7以下的版本,可以先解压apk,对目标文件META-INF/CERT.RSA计算签名
keytool -printcert -file file_path
How to find out which key was used to sign an app
How to get the certificate signing information from an Android APK
How can I verify the authenticity of an APK file I downloaded(对RSA文件有个简短的介绍)
3. 在android运行时计算apk的签名
/*
standard MessageDigest algorithms:
MD5
SHA-1
SHA-256
*/
private String getCertificateFingerprint(Context mContext, String algorithm, String packageName) {
PackageManager pm = mContext.getPackageManager();
int flags = PackageManager.GET_SIGNATURES;
PackageInfo packageInfo = null;
try {
packageInfo = pm.getPackageInfo(packageName, flags);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
if (packageInfo == null)
return null;
Signature[] signatures = packageInfo.signatures;
//此处我直接默认只有一个签名
byte[] cert = signatures[0].toByteArray();
InputStream input = new ByteArrayInputStream(cert);
CertificateFactory cf = null;
try {
cf = CertificateFactory.getInstance("X509");
} catch (CertificateException e) {
e.printStackTrace();
}
if (cf == null)
return null;
X509Certificate c = null;
try {
c = (X509Certificate) cf.generateCertificate(input);
} catch (CertificateException e) {
e.printStackTrace();
}
if (c==null)
return null;
String hexString = null;
try {
MessageDigest md = MessageDigest.getInstance(algorithm);
byte[] publicKey = md.digest(c.getEncoded());
hexString = byte2HexFormatted(publicKey);
} catch (NoSuchAlgorithmException e1) {
e1.printStackTrace();
} catch (CertificateEncodingException e) {
e.printStackTrace();
}
return hexString;
}
public static String byte2HexFormatted(byte[] arr) {
StringBuilder str = new StringBuilder(arr.length * 2);
for (int i = 0; i < arr.length; i++) {
String h = Integer.toHexString(arr[i]);
int l = h.length();
if (l == 1) h = "0" + h;
if (l > 2) h = h.substring(l - 2, l);
str.append(h.toUpperCase());
if (i < (arr.length - 1)) str.append(':');
}
return str.toString();
}Get certificate fingerprint from android app
How to read SHA and MD5 fingerprint programmatically in Android
第二个链接提及了一个开源项目 apk-parser
4. 直接通过java程序获取
1) 读取apk中的RSA签名文件
ZipFile zipFile = new ZipFile("demo-debug.apk_2.0.4.apk");
Enumeration<? extends ZipEntry> entries = zipFile.entries();
while(entries.hasMoreElements()){
ZipEntry entry = entries.nextElement();
if (entry.getName().endsWith("RSA")) {
ZipEntry entry = entries.nextElement();
//TODO with zipFile.getInputStream(entry)
}
}Read Content from Files which are inside Zip file
2) 计算RSA文件签名
public static String[] getSign(InputStream input, String algorithm) throws CertificateException, NoSuchAlgorithmException {
CertificateFactory cf = CertificateFactory.getInstance("X509");
Collection<? extends Certificate> c = cf.generateCertificates(input);
Certificate[] certs = c.toArray(new Certificate[c.size()]);
String[] hexString = new String[certs.length];
for (int i=0; i<certs.length; i++) {
X509Certificate x509Cert = (X509Certificate)certs[i];
MessageDigest md = MessageDigest.getInstance(algorithm);
byte[] publicKey = md.digest(x509Cert.getEncoded());
//byte2HexFormatted和android那边的一致
hexString[i] = byte2HexFormatted(publicKey);
}
return hexString;
}主要参考了java KeyTool源码,可以搜索printcert,其中printCertFromStream是主要需要关注的函数
private void printCertFromStream(InputStream in, PrintStream out)
相关的一个开源项目android-apk-parser