Android Studio NDK 入门教程(6)--JNI签名验证防止恶意调用

概述

根据前面的文章来看,JNI其实只实现了关键代码加密,如果别人拿到了你的Java Native方法定义和对应的so,即可完成对你so里方法的调。因为native 方法和类都是不能混淆的,混淆了方法的函数名就变了,调用的时候就找不到方法了,因此如果反编译APK可以非常容易拿到相关文件和代码。 显然我们需要一些手段来在JNI的验证请求接口的是不是我们的程序。

签名验证的原理

可以用如下图来表明加了验证之后调用JNI的逻辑,用一个isValid 来表明请求的应用是不是我们自己的应用。isValid 通过init 去初始化。
这里写图片描述

如何判别调用者的有效性

直接有效的方案就是使用签名进行判定,如果你的keystore没有泄漏,第三方破解概率几乎为零。当然这都是相对的,任何防护都会有破绽。大多数第三方的Android SDK也都通过签名来判断申请的key是否用在了你申请的应用上。因此在大多数SDK申请key的时候会让你填写SHA1,因为在程序运行的时候SDK会获取你签名的SHA1去向服务器验证,你申请的appkey和SHA1是否正确。

签名验证的实现

在代码中获取签名的SHA1

先尝试在Java代码中获取签名的SHA1

    private String getCertSHA1(Context context)
    {
        try
        {
            //获取包管理器
            PackageManager packageManager=context.getPackageManager();
            //获取包名
            String packageName=context.getPackageName();
            //获得包信息
            PackageInfo   pis = packageManager.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
            //获得签名
            Signature[] signs = pis.signatures; //签名
            //获得签名数组的第一位
            Signature sign=signs[0];
            //获得X.509证书工厂
            CertificateFactory certFactory = CertificateFactory.getInstance("X.509");

            byte[] signBytes=sign.toByteArray();
            ByteArrayInputStream byteIn=new ByteArrayInputStream(signBytes);
            //获取X509证书
            X509Certificate cert = (X509Certificate) certFactory.generateCertificate(byteIn);
            //获取证书发行者SHA1
            MessageDigest sha1=MessageDigest.getInstance("SHA1");
            byte[] certByte=cert.getEncoded();
            byte[] bs=sha1.digest (certByte);
            return toHex(bs);
        }
        catch (CertificateException e)
        {

            e.printStackTrace();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        return null;
    }

    //将Byte转换成HexString 辅助函数
     char[] cs=new char[16];
    {
        for (int i=0;i < 10;i++)
        {
            cs[i] = (char) ('0' + i);
        }
        for (int i=10;i < 16;i++)
        {
            cs[i] = (char) ('A' + i - 10);
        }
    }
    String toHex(byte[] bs)
    {
        char[] cs=new char[bs.length * 2];
        int x;
        for (int i=0;i < bs.length;i++)
        {
            x = bs[i] & 0xff;
            cs[2 * i] = this<
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值