安卓签名文件及解析
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