android apk完整性检测的实现思路和代码实现-kb88凯时官网登录

来自:网络
时间:2024-06-09
阅读:
免费资源网,https://freexyz.cn/

需求和背景

行业相关,对安全性较高的程序一般都需要添加完整性检测的功能,以防止程序被篡改,从而导致安全问题的发生。
相关的支付应用项目今年也做了好几个,这些程序也都已通过了行业相关安全标准的认证。

实现

下面来分享android app完整性校验的实现思路和代码实现。

通过sp判断当前是否是第一次安装apk,第一次安装默认apk是从市场下载安装,默认认为是没有被篡改过的。可以不用检查,只计算当前的hash值并保存到文件中。

可以在application中执行,计算apk的hash值并写文件的操作是耗时操作,记得开子线程进行。

 
    private boolean integritycheckresult = false;
    private boolean isfirstrun;//可以通过文件保存,例如sp
   @override
    public void oncreate() {
        super.oncreate();
           threadpoolmanager.getinstance().runinbackground(new runnable() {
            @override
            public void run() {
                //检测apk完整性
                if (isfirstrun){//skip and calculate apk's hash
                    securitymanager.getinstance().checkintegrity(true);
                    integritycheckresult = true;
                }else {
                    integritycheckresult = securitymanager.getinstance().checkintegrity(false);
                }
            }
        });
	 public boolean isintegritycheckresult() {
        return integritycheckresult;
    }

在入口activity中判断是否完整性校验通过,假如不通过,可以弹窗提示然后锁定app,让用户重新在安全的平台重新下载安装。当前app无法使用,存在安全问题。

  @override
    protected void oncreate(bundle savedinstancestate) {
        super.oncreate(savedinstancestate);
        setcontentview(r.layout.activity_main);
        if (app.getapp().isintegritycheckresult()) {
            log.d(tag, "oncreate: checkintegrity success");
        } else {
            log.d(tag, "oncreate: checkintegrity failed");
        }
    }

安全管理类

新建一个安全管理类,用于管理所有和安全相关的类

public class securitymanager {
    //做一个单例
    private static securitymanager instance = null;
    private final integrity integrity;
    private securitymanager(){
        integrity = new integrity();
    }
    public static synchronized securitymanager getinstance() {
        if (instance == null)
            instance = new securitymanager();
        return instance;
    }
    public boolean checkintegrity(boolean isfirstinstall) {
        return integrity.checkintegrity(isfirstinstall);
    }
}

实现完整性检测类的接口

public interface iintegrity {
    boolean checkapkintegrity();
}

完整性检测实现类:

public class integrity implements iintegrity {
  public boolean checkintegrity(boolean isfirstinstall) {
        if (isfirstinstall) {
            calcandsaveapksohash();
            return true;
        } else {
            return comparehashswithlasttime();
        }
    }
  private void calcandsaveapksohash() {
        file apk = new file(baseapplication.getappcontext().getpackagecodepath());
        byte[] apkhash = hashcalculator.calculatehashbytes(apk, hashcalculator.sha_256);
        fileutils.writebytestofile(filepath   apk_hash_file, apkhash);
    }
 private boolean comparehashswithlasttime() {
        //检测apk so
        return checkapkintegrity();
    }
  @override
    public boolean checkapkintegrity() {
        if (buildconfig.debug) {
            log.w(tag, "debug version,skip apk‘s hash verification");
            return true;
        }
        try {
            string apkpath = baseapplication.getappcontext().getpackagecodepath();
            byte[] originalapkhash = fileutils.readfiletobytes(filepath   apk_hash_file);
            return calcsrcandcomparewithlasthash(originalapkhash, new file(apkpath));
        } catch (ioexception e) {
            log.e(tag, "checkapkandlibs: ", e);
        }
        return false;
    }
    /**
     * 计算明文数据并和上一次hash进行比较
     *
     * @param dechashbytes 明文hash数据
     * @param decsrc 明文源数据
     */
    private static boolean calcsrcandcomparewithlasthash(byte[] dechashbytes, file decsrc) {
        string dechash = utils.bcd2str(dechashbytes);
        //计算解密ksn的hash
        string calchash = hashcalculator.calculatehash(decsrc, hashcalculator.sha_256);
        logutils.i(tag,
                "calculate hash = "   utils.bcd2str(
                        hashcalculator.calculatehashbytes(decsrc, hashcalculator.sha_256)));
        return dechash.equalsignorecase(calchash);
    }
}

相关工具类

这个只是工具类,方便获取application ,只要获取context即可,可以随意发挥。

public class baseapplication extends application {
 private static baseapplication mbaseapplication ;
  mbaseapplication = this;
}
 public static baseapplication getappcontext(){
        return mbaseapplication;
    }

编码转换工具:

  @nonnull
    public static string bcd2str(@nullable byte[] b, int length) {
        if (b == null) {
            return "";
        }
        stringbuilder sb = new stringbuilder(length * 2);
        for (int i = 0; i < length;   i) {
            sb.append(array_of_char[((b[i] & 0xf0) >>> 4)]);
            sb.append(array_of_char[(b[i] & 0xf)]);
        }
        return sb.tostring();
    }

hash计算器

  @nonnull
    public static string bcd2str(@nullable byte[] b, int length) {
        if (b == null) {
            return "";
        }
        stringbuilder sb = new stringbuilder(length * 2);
        for (int i = 0; i < length;   i) {
            sb.append(array_of_char[((b[i] & 0xf0) >>> 4)]);
            sb.append(array_of_char[(b[i] & 0xf)]);
        }
        return sb.tostring();
    }

文件工具类

    /**
     * 文件锁定(file locking)
     * 强制刷新缓冲(force flushing buffer):
     */
    public static boolean writebytestofile(string filepath, byte[] bytes) {
        try (fileoutputstream fos = new fileoutputstream(filepath)) {
            fos.write(bytes);
            // 获取文件锁定
            filechannel filechannel = fos.getchannel();
            try (filelock filelock = filechannel.lock()) {
                // 强制刷新缓冲
                filechannel.force(true);
            }
            return true;
        } catch (ioexception e) {
            logutils.e(e);
            return false;
        }
    }
免费资源网,https://freexyz.cn/
返回顶部
顶部
网站地图