Android: 检查签名是否一致

本文探讨了在应用市场中如何通过签名验证实现应用更新机制,包括后台提示更新与用户安装时的签名一致性检查,详细介绍了获取应用签名的MD5值及在非终端环境下解析APK签名的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

签名原理见:http://blog.youkuaiyun.com/oqqtim12/article/details/39936465

目前主要的签名应用场景,是在各大应用市场中,实现下面这个功能:

1、后台提示用户更新应用,假设应用手机上安装的应用签名与后台上传的APK签名不一致,那么不提示用户更新此应用;

2、用户在应用市场中安装应用,假设需要安装的应用签名与本地签名不一致,那么在安装前检查,发现不一致提示用户卸载本地应用,然后重新安装


可以发现,两个场景的核心都是“检测需要安装的应用签名与本地签名不一致


一、在终端上获取本地APP的签名:

        try {
            PackageInfo packageInfo = getPackageManager()
                    .getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
            String signMd5 =  MD5.toMD5(packageInfo.signatures[packageInfo.signatures.length - 1].toCharsString());
            Log.d("Sign",signMd5);
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }

这里其实只是获取一个签名的MD5值


二、在非终端上获取apk签名

    /**
     * 获取android包里面的所有证书MD5
     * @param apkFile 包文件
     * @return
     */
    public static String getSigMd5(File apkFile) {
        //解压APK文件,;略
        String unPackFile = unpack(apkFile);
        //针对使用RSA算法签名的APK,获取./META-INF/*.RSA文件
        File cerFile = getRSAFile(unPackFile);
        //针对使用DSA算法签名的APK,获取./META-INF/*.DSA文件
        if (cerFile == null )
            cerFile = getDSAFile(unPackFile);
        FileInputStream input = null;
        try {
            input = new FileInputStream(cerFile);
            PKCS7 pkcs7 = new PKCS7(input);
            Certificate[] certs = pkcs7.getCertificates();
            String eggPainSign = (new String(BytetoChars(certs[certs.length - 1].getEncoded())));
            String eggPainMd5 = MD5.toMD5(eggPainSign.getBytes());
            return eggPainMd5;
         } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (input != null) {
                try {
                    input.close();
                } catch (IOException e) {
                }
            }
        }
        return null;
    }
同样获取对应的MD5值,讲此值存储在数据库中,然后交由终端比较即可

原理是:找到METE-INF下存储签名的文件(可能是RSA或者RSA结尾),生成Certificate[]对象,取起MD5即可;同时可以发现,Signature对象其实就是在Certificate基础上做了一层封装,其中BytetoChars方法如下:

    /**
     * @param mSignature
     * @return
     */
    private static char[] BytetoChars(byte[] mSignature) {
        byte[] sig = mSignature;
        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 text;
    }
需要注意的是,目前在签名生产过程中,主要使用RSA、DSA算法,不同算法生成的签名文件后缀不同,分别是*.RSA以及*.DSA,因此需要在搜索签名文件时候需要做兼容;



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值