Android签名验证简介
来源:互联网 发布:淘宝产品摄影技巧大全 编辑:程序博客网 时间:2024/05/23 18:32
Android签名验证简介
- 博客分类:
- JAVA
- Android
Android原生自带了个安装器(packages\apps\PackageInstaller),
通过其中的源码PackageParser.java (frameworks\base\core\java\android\content\pm)
我们大概就能知道其签名验证机制的验证过程。
其中主要涉及2个函数:
函数1
- public boolean collectCertificates(Package pkg, int flags) {
- pkg.mSignatures = null;
- WeakReference<byte[]> readBufferRef;
- byte[] readBuffer = null;
- synchronized (mSync) {
- readBufferRef = mReadBuffer;
- if (readBufferRef != null) {
- mReadBuffer = null;
- readBuffer = readBufferRef.get();
- }
- if (readBuffer == null) {
- readBuffer = new byte[8192];
- readBufferRef = new WeakReference<byte[]>(readBuffer);
- }
- }
- try {
- JarFile jarFile = new JarFile(mArchiveSourcePath);
- Certificate[] certs = null;
- if ((flags&PARSE_IS_SYSTEM) != 0) {
- // If this package comes from the system image, then we
- // can trust it... we'll just use the AndroidManifest.xml
- // to retrieve its signatures, not validating all of the
- // files.
- JarEntry jarEntry = jarFile.getJarEntry(ANDROID_MANIFEST_FILENAME);
- certs = loadCertificates(jarFile, jarEntry, readBuffer);
- if (certs == null) {
- Slog.e(TAG, "Package " + pkg.packageName
- + " has no certificates at entry "
- + jarEntry.getName() + "; ignoring!");
- jarFile.close();
- mParseError = PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES;
- return false;
- }
- if (DEBUG_JAR) {
- Slog.i(TAG, "File " + mArchiveSourcePath + ": entry=" + jarEntry
- + " certs=" + (certs != null ? certs.length : 0));
- if (certs != null) {
- final int N = certs.length;
- for (int i=0; i<N; i++) {
- Slog.i(TAG, " Public key: "
- + certs[i].getPublicKey().getEncoded()
- + " " + certs[i].getPublicKey());
- }
- }
- }
- } else {
- Enumeration<JarEntry> entries = jarFile.entries();
- final Manifest manifest = jarFile.getManifest();
- while (entries.hasMoreElements()) {
- final JarEntry je = entries.nextElement();
- if (je.isDirectory()) continue;
- final String name = je.getName();
- if (name.startsWith("META-INF/"))
- continue;
- if (ANDROID_MANIFEST_FILENAME.equals(name)) {
- final Attributes attributes = manifest.getAttributes(name);
- pkg.manifestDigest = ManifestDigest.fromAttributes(attributes);
- }
- final Certificate[] localCerts = loadCertificates(jarFile, je, readBuffer);
- if (DEBUG_JAR) {
- Slog.i(TAG, "File " + mArchiveSourcePath + " entry " + je.getName()
- + ": certs=" + certs + " ("
- + (certs != null ? certs.length : 0) + ")");
- }
- if (localCerts == null) {
- Slog.e(TAG, "Package " + pkg.packageName
- + " has no certificates at entry "
- + je.getName() + "; ignoring!");
- jarFile.close();
- mParseError = PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES;
- return false;
- } else if (certs == null) {
- certs = localCerts;
- } else {
- // Ensure all certificates match.
- for (int i=0; i<certs.length; i++) {
- boolean found = false;
- for (int j=0; j<localCerts.length; j++) {
- if (certs[i] != null &&
- certs[i].equals(localCerts[j])) {
- found = true;
- break;
- }
- }
- if (!found || certs.length != localCerts.length) {
- Slog.e(TAG, "Package " + pkg.packageName
- + " has mismatched certificates at entry "
- + je.getName() + "; ignoring!");
- jarFile.close();
- mParseError = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
- return false;
- }
- }
- }
- }
- }
- jarFile.close();
- synchronized (mSync) {
- mReadBuffer = readBufferRef;
- }
- if (certs != null && certs.length > 0) {
- final int N = certs.length;
- pkg.mSignatures = new Signature[certs.length];
- for (int i=0; i<N; i++) {
- pkg.mSignatures[i] = new Signature(
- certs[i].getEncoded());
- }
- } else {
- Slog.e(TAG, "Package " + pkg.packageName
- + " has no certificates; ignoring!");
- mParseError = PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES;
- return false;
- }
- } catch (CertificateEncodingException e) {
- Slog.w(TAG, "Exception reading " + mArchiveSourcePath, e);
- mParseError = PackageManager.INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING;
- return false;
- } catch (IOException e) {
- Slog.w(TAG, "Exception reading " + mArchiveSourcePath, e);
- mParseError = PackageManager.INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING;
- return false;
- } catch (RuntimeException e) {
- Slog.w(TAG, "Exception reading " + mArchiveSourcePath, e);
- mParseError = PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION;
- return false;
- }
- return true;
- }
- private Certificate[] loadCertificates(JarFile jarFile, JarEntry je,
- byte[] readBuffer) {
- try {
- // We must read the stream for the JarEntry to retrieve
- // its certificates.
- InputStream is = new BufferedInputStream(jarFile.getInputStream(je));
- while (is.read(readBuffer, 0, readBuffer.length) != -1) {
- // not using
- }
- is.close();
- return je != null ? je.getCertificates() : null;
- } catch (IOException e) {
- Slog.w(TAG, "Exception reading " + je.getName() + " in "
- + jarFile.getName(), e);
- } catch (RuntimeException e) {
- Slog.w(TAG, "Exception reading " + je.getName() + " in "
- + jarFile.getName(), e);
- }
- return null;
- }
实例1
- package edu.edut.robin.utils;
- import java.io.ByteArrayInputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import java.security.PublicKey;
- import java.security.cert.Certificate;
- import java.security.cert.CertificateFactory;
- import java.security.cert.X509Certificate;
- import java.util.jar.JarEntry;
- import java.util.jar.JarFile;
- import android.content.Context;
- import android.content.pm.PackageInfo;
- import android.content.pm.PackageManager;
- import android.content.pm.PackageManager.NameNotFoundException;
- import android.util.Base64;
- public class SigntureUtil
- {
- final static String TAG = "Signture";
- public static String[] getPublicKeyString(PackageInfo pi)
- {
- PublicKey pubKeys[] = getPublicKey(pi);
- if (pubKeys == null || pubKeys.length == 0)
- {
- return null;
- }
- String[] strPubKeys = new String[pubKeys.length];
- for (int i = 0; i < pubKeys.length; i++)
- strPubKeys[i] = Base64.encodeToString(pubKeys[i].getEncoded(),
- Base64.DEFAULT);
- return strPubKeys;
- }
- private static PublicKey[] getPublicKey(PackageInfo pi)
- {
- try
- {
- if (pi.signatures == null || pi.signatures.length == 0)
- {
- return null;
- }
- PublicKey[] publicKeys = new PublicKey[pi.signatures.length];
- for (int i = 0; i < publicKeys.length; i++)
- {
- byte[] signature = pi.signatures[i].toByteArray();
- CertificateFactory certFactory = CertificateFactory
- .getInstance("X.509");
- InputStream is = new ByteArrayInputStream(signature);
- X509Certificate cert = (X509Certificate) certFactory
- .generateCertificate(is);
- publicKeys[i] = cert.getPublicKey();
- }
- } catch (Exception ex)
- {
- }
- return null;
- }
- private static PublicKey[] getInstalledAppPublicKey(Context context,
- String packageName)
- {
- PackageManager pm = context.getPackageManager();
- PackageInfo pi;
- try
- {
- pi = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
- if (pi != null && pi.versionName != null)
- {
- return getPublicKey(pi);
- }
- } catch (NameNotFoundException e)
- {
- // not installed
- return null;
- } catch (Exception e)
- {
- e.printStackTrace();
- }
- return null;
- }
- private static Certificate[] loadCertificates(JarFile jarFile, JarEntry je)
- {
- try
- {
- // We must read the stream for the JarEntry to retrieve
- // its certificates.
- byte[] readBuffer = new byte[1024];
- InputStream is = jarFile.getInputStream(je);
- while (is.read(readBuffer, 0, readBuffer.length) != -1)
- ;
- is.close();
- return (je != null) ? je.getCertificates() : null;
- } catch (IOException e)
- {
- e.printStackTrace();
- }
- return null;
- }
- public static boolean verifySignature(Context context, String packageName,
- String filePath)
- {
- boolean verifyed = true;
- try
- {
- PublicKey[] installedAppPubKeys = getInstalledAppPublicKey(context,
- packageName);
- if (installedAppPubKeys == null||installedAppPubKeys.length==0)
- {
- // package not installed
- return true;
- }
- JarFile jarFile = new JarFile(filePath);
- verifyed = false;
- JarEntry je = jarFile.getJarEntry("classes.dex");
- Certificate[] certs = loadCertificates(jarFile, je);
- if (certs != null && certs.length > 0)
- {
- for (int i = 0; i < certs.length; i++)
- {
- PublicKey pubKey = certs[i].getPublicKey();
- for(int j=0;j<installedAppPubKeys.length;j++)
- {
- if (pubKey.equals(installedAppPubKeys[j]))
- {
- verifyed = true;
- break;
- }
- }
- if(verifyed)
- break;
- }
- } else
- {
- verifyed = true;
- }
- jarFile.close();
- } catch (Exception e)
- {
- verifyed = true;
- }
- return verifyed;
- }
- }
关于java本身的数字签名和数字证书请参考《Java中的数字签名和数字证书》和《Jar文件的数字签名》
结束
0 0
- Android签名验证简介
- Android签名验证简介
- Android签名验证简介
- Android 签名验证
- Android 签名验证机制
- 破解android签名验证
- Android验证apk签名
- android JNI 验证签名
- android 签名验证
- Android应用程序签名简介
- Android签名简介
- Android签名简介
- android jni签名验证(一)
- android jni签名验证(二)
- Android签名验证原理解析
- 【转载】Android应用程序签名简介
- Android签名机制之---签名验证过程详解
- Android签名机制之---签名验证过程详解
- 讲故事,学(Java)设计模式—桥接模式
- cvReleaseImage出错问题
- leetcode:Delete Node in a Linked List 【Java】
- Ubuntu Sun JDK 安装
- #ifndef/#define/#endif使用详解
- Android签名验证简介
- poj3061
- cuda在vs2008中编程无法识别的外部符号(gpu加速的配置)
- 算法基础 - 树状数组(binary indexed tree)
- JAVA基础之IO操作
- 002.Java中有没有goto?
- uva10048 (floyd & kruskal)
- Adapter模式实战-重构鸿洋的Android建行圆形菜单
- 文章标题