Android 代码获取apk和app的签名信息

最近有需求是需要获取未安装的apk和已经安装的app的签名信息。记录一下代码。

1、命令读取签名信息

keytool -printcert -jarfile xxx.apk

测试如下:
在这里插入图片描述

2、代码获取签名信息

测试如下:
在这里插入图片描述
可以看到命令读取的签名信息和代码获取的是一样的,证明代码获取的没有问题。

apk MD5:7815c5174154b7ce33f023602106ecc6 是获取的apk的签名信息
app MD5:7815c5174154b7ce33f023602106ecc6 是获取的app的签名信息

代码如下:

import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.Signature;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.cert.Certificate;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

public class SignUtil {

    /**
     * 从 apk 中获取 MD5 签名信息
     *
     * @param apkPath
     * @return
     * @throws Exception
     */
    public static String getApkSignatureMD5(String apkPath) throws Exception {
        byte[] bytes = SignUtil.getSignaturesFromApk(apkPath);
        String sign = hexDigest(bytes, "MD5");
        return sign;
    }

    public static String getApkSignatureSHA1(String apkPath) throws Exception {
        byte[] bytes = getSignaturesFromApk(apkPath);
        String sign = hexDigest(bytes, "SHA1");
        return sign;
    }

    public static String getApkSignatureSHA256(String apkPath) throws Exception {
        byte[] bytes = getSignaturesFromApk(apkPath);
        String sign = hexDigest(bytes, "SHA256");
        return sign;
    }

    /**
     * 获取已经安装的 app 的 MD5 签名信息
     *
     * @param context
     * @param pkgName
     * @return
     */
    public static String getAppSignatureMD5(Context context, String pkgName) {
        return getAppSignature(context, pkgName, "MD5");
    }

    public static String getAppSignatureSHA1(Context context, String pkgName) {
        return getAppSignature(context, pkgName, "SHA1");
    }

    public static String getAppSignatureSHA256(Context context, String pkgName) {
        return getAppSignature(context, pkgName, "SHA256");
    }

    public static String getAppSignature(Context context, String pkgName, String algorithm) {
        try {
            PackageInfo packageInfo = context.getPackageManager().getPackageInfo(
                    pkgName, PackageManager.GET_SIGNATURES);
            Signature[] signs = packageInfo.signatures;
            Signature sign = signs[0];
            String signStr = hexDigest(sign.toByteArray(), algorithm);
            return signStr;
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     * 从APK中读取签名
     *
     * @param apkPath
     * @return
     * @throws IOException
     */
    public static byte[] getSignaturesFromApk(String apkPath) throws IOException {
        File file = new File(apkPath);
        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) {
                    return c.getEncoded();
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;
    }

    /**
     * 加载签名
     *
     * @param jarFile
     * @param je
     * @param readBuffer
     * @return
     */
    public 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) {
            e.printStackTrace();
        }
        return null;
    }

    public static String hexDigest(byte[] bytes, String algorithm) {
        MessageDigest md5;
        try {
            md5 = MessageDigest.getInstance(algorithm);
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
        byte[] md5Bytes = md5.digest(bytes);
        StringBuffer hexValue = new StringBuffer();
        for (int i = 0; i < md5Bytes.length; i++) {
            int val = ((int) md5Bytes[i]) & 0xff;
            if (val < 16) {
                hexValue.append("0");
            }
            hexValue.append(Integer.toHexString(val));
        }
        return hexValue.toString();
    }

}
  • 7
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
Android系统中,要获取已安装的apk文件,可以使用以下步骤: 1. 首先,要获取apk文件,需要先获取应用的包名。可以使用PackageManager类来获取应用程序的信息。例如,可以使用getInstalledPackages()方法获取已安装应用的列表,然后通过遍历列表来获取每个应用程序的包名。 2. 获取包名后,可以通过PackageManager类的getApplicationInfo()方法来获取应用程序的详细信息,包括其数据目录。 3. 在应用程序详细信息中,可以通过applicationInfo.sourceDir来获取apk文件的路径。该路径可以用于读取apk文件的内容或者进行一些其他操作。 例如,可以使用以下代码片段来获取已安装应用的apk文件路径: PackageManager packageManager = getPackageManager(); List<PackageInfo> packageList = packageManager.getInstalledPackages(0); for(PackageInfo packageInfo : packageList) { ApplicationInfo appInfo = packageManager.getApplicationInfo(packageInfo.packageName, 0); String apkPath = appInfo.sourceDir; // 可以使用apkPath来进行apk文件的相关操作 } 需要注意的是,为了获取已安装应用的详细信息,需要在AndroidManifest.xml文件中添加相应的权限。例如,<uses-permission android:name="android.permission.GET_PACKAGE_SIZE" />可以用于获取应用程序的大小,而<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />可以用于读取外部存储的应用文件。 总之,通过PackageManager类和ApplicationInfo类,可以获取已安装应用的详细信息,包括apk文件的路径。根据这些信息,可以对apk文件进行一些操作,如读取内容或进行备份等。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值