Android apk完整性检测的实现思路和代码实现

 更新时间:2023年12月22日 10:12:31   作者:Shujie_L  
这篇文章主要介绍了Android apk完整性检测的实现思路和代码实现,本文通过示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧

需求和背景

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

实现

下面来分享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;
        }
    }

到此这篇关于Android apk完整性检测的实现思路和实现过程全记录的文章就介绍到这了,更多相关Android apk完整性检测内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Flutter实现仿京东商品详情底部操作栏

    Flutter实现仿京东商品详情底部操作栏

    这篇文章主要为大家详细介绍了Flutter如何仿京东实现商品详情底部操作栏,文中的示例代码讲解详细,具有一定的学习价值,感兴趣的小伙伴可以了解一下
    2023-06-06
  • android开发教程之startActivityForResult使用方法

    android开发教程之startActivityForResult使用方法

    这篇文章主要介绍了android开发教程之startActivityForResult使用方法,需要的朋友可以参考下
    2014-03-03
  • 2021最新Android笔试题总结美团Android岗职能要求

    2021最新Android笔试题总结美团Android岗职能要求

    这篇文章主要介绍了2021最新Android笔试题总结以及美团Android岗职能要求,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-08-08
  • Android studio实现动态背景页面

    Android studio实现动态背景页面

    这篇文章主要为大家详细介绍了Android studio实现动态背景页面,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-04-04
  • Flutter时间轴Timeline的实现

    Flutter时间轴Timeline的实现

    时间轴在很多地方都可以用的到,本文介绍了Flutter时间轴Timeline的实现,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-05-05
  • 解决Android 源码编译错误的问题

    解决Android 源码编译错误的问题

    这篇文章主要介绍了解决Android 源码编译错误的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-03-03
  • Android Camera是否支持变焦的判断方法总结

    Android Camera是否支持变焦的判断方法总结

    这篇文章主要介绍了Android Camera是否支持变焦的判断方法总结,本文总结了调节摄像头焦距编程中遇到的一些问题和解决方法,需要的朋友可以参考下
    2015-04-04
  • 详解flutter如何实现局部导航管理

    详解flutter如何实现局部导航管理

    这篇文章主要为大家介绍了详解flutter如何实现局部导航管理示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-01-01
  • 简单谈谈我的Android屏幕适配之路

    简单谈谈我的Android屏幕适配之路

    我相信Android碎片化问题是让所有的Android开发者都比较头疼的问题.尤其是屏幕适配这一块儿.想要自己的app在不同的设备上面都有一个比较好的显示效果.就必须做好相应的屏幕适配.
    2017-11-11
  • 多语言切换在Androidx失效的踩坑解决记录

    多语言切换在Androidx失效的踩坑解决记录

    这篇文章主要为大家介绍了多语言切换在Androidx失效的踩坑解决记录详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-01-01

最新评论