微信获取apk公钥的方法(提供源代码)

记得上次在公司玩微信支付的时候,微信的商务给了一个破apk获取我们自己开发的app的公钥,非常之难用,后来自己写了一个方法,再后来找不见了,

这几天决定把腾讯的开放平台都研究个遍,提交app的时候,又需要提供公钥,那就动手吧:

不说原理直接发代码:

package com.example.navigatedemo;import java.io.ByteArrayInputStream;import java.io.File;import java.io.IOException;import java.io.InputStream;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.Method;import java.security.cert.Certificate;import java.security.cert.CertificateFactory;import java.util.ArrayList;import java.util.List;import java.util.jar.JarEntry;import java.util.jar.JarFile;import java.security.cert.X509Certificate;import android.app.Activity;import android.content.pm.PackageManager;import android.content.pm.Signature;import android.os.Bundle;import android.os.Environment;import android.util.DisplayMetrics;import android.util.Log;public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//获取签名File file=new File(Environment.getExternalStorageDirectory()+"/XXXbyfayuV1.3.apk");getAPKSignatures(Environment.getExternalStorageDirectory()+"/SOUAPP_babyfayuV1.3.apk");}/*** 从APK中读取签名* @param file* @return* @throws IOException*/private static List<String> getSignaturesFromApk(File file) throws IOException {List<String> signatures=new ArrayList<String>();JarFile jarFile=new JarFile(file);try {JarEntry je=jarFile.getJarEntry("AndroidManifest.xml");byte[] readBuffer=new byte[8192];Certificate[] certs=loadCertificates(jarFile, je, readBuffer);if(certs != null) {for(Certificate c: certs) {Log.d("maomao","publickey1:"+toCharsString(c.getPublicKey().getEncoded()));Log.d("maomao","publickey2:"+(c.getPublicKey().toString()));String sig=toCharsString(c.getEncoded());signatures.add(sig);}}} catch(Exception ex) {}return signatures;}/*** 加载签名* @param jarFile* @param je* @param readBuffer* @return*/private static Certificate[] loadCertificates(JarFile jarFile, JarEntry je, byte[] readBuffer) {try {InputStream is=jarFile.getInputStream(je);while(is.read(readBuffer, 0, readBuffer.length) != -1) {}is.close();return je != null ? je.getCertificates() : null;} catch(IOException e) {}return null;}/*** 将签名转成转成可见字符串* @param sigBytes* @return*/private static String toCharsString(byte[] sigBytes) {byte[] sig=sigBytes;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 new String(text);}public void getAPKSignatures(String apkPath) {String PATH_PackageParser = "android.content.pm.PackageParser";try {// apk包的文件路径// 这是一个Package 解释器, 是隐藏的// 构造函数的参数只有一个, apk文件的路径Class pkgParserCls = Class.forName(PATH_PackageParser);Class[] typeArgs = new Class[1];typeArgs[0] = String.class;Constructor pkgParserCt = pkgParserCls.getConstructor(typeArgs);Object[] valueArgs = new Object[1];valueArgs[0] = apkPath;Object pkgParser = pkgParserCt.newInstance(valueArgs);// 这个是与显示有关的, 里面涉及到一些像素显示等等, 我们使用默认的情况DisplayMetrics metrics = new DisplayMetrics();metrics.setToDefaults();typeArgs = new Class[4];typeArgs[0] = File.class;typeArgs[1] = String.class;typeArgs[2] = DisplayMetrics.class;typeArgs[3] = Integer.TYPE;Method pkgParser_parsePackageMtd = pkgParserCls.getDeclaredMethod("parsePackage",typeArgs);valueArgs = new Object[4];valueArgs[0] = new File(apkPath);valueArgs[1] = apkPath;valueArgs[2] = metrics;valueArgs[3] = PackageManager.GET_SIGNATURES;Object pkgParserPkg = pkgParser_parsePackageMtd.invoke(pkgParser, valueArgs);typeArgs = new Class[2];typeArgs[0] = pkgParserPkg.getClass();typeArgs[1] = Integer.TYPE;Method pkgParser_collectCertificatesMtd = pkgParserCls.getDeclaredMethod("collectCertificates",typeArgs);valueArgs = new Object[2];valueArgs[0] = pkgParserPkg;valueArgs[1] = PackageManager.GET_SIGNATURES;pkgParser_collectCertificatesMtd.invoke(pkgParser, valueArgs);// 应用程序信息包, 这个公开的, 不过有些函数, 变量没公开Field packageInfoFld = pkgParserPkg.getClass().getDeclaredField("mSignatures");Signature[] info = (Signature[]) packageInfoFld.get(pkgParserPkg);parseSignature(info[0].toByteArray());} catch (Exception e) {e.printStackTrace();}}public void parseSignature(byte[] signature) {try{CertificateFactory certFactory = CertificateFactory.getInstance("X.509");X509Certificate cert = (X509Certificate)certFactory.generateCertificate(new ByteArrayInputStream(signature));Log.i("maomao", cert.toString());//这里是打印证书,如果要公钥,使用函数cert.getPublicKey();}catch(Exception e){e.printStackTrace();} } }日志打印出来如下:

人生就像爬坡,要一步一步来。

微信获取apk公钥的方法(提供源代码)

相关文章:

你感兴趣的文章:

标签云: