如何使用Dart以编程方式计算APK哈希值?
Dart 端实现当前APK哈希校验方案
纯Dart无法直接获取系统沙箱内的自身APK文件路径,需要结合平台通道调用Android原生能力实现,整体逻辑不复杂,具体实现如下:
核心实现逻辑
- 原生端通过系统API拿到当前安装APK的绝对路径
- 将路径回传给Dart层,以流读取的方式计算文件SHA-256哈希(避免大文件读取导致内存溢出)
- 拿到哈希值后请求自有接口完成篡改校验
- 不建议使用MD5、SHA-1等已被证实存在碰撞风险的哈希算法,优先选SHA-256
代码实现
1. Dart层代码
首先在pubspec.yaml中添加crypto包依赖(官方维护的纯Dart哈希实现库),然后编写如下逻辑:
import 'dart:io'; import 'package:crypto/crypto.dart'; import 'package:flutter/services.dart'; class ApkIntegrityChecker { static const _channel = MethodChannel('native_apk_util'); /// 计算当前APK的SHA256值 static Future<String?> getApkSha256() async { try { // 从原生端获取APK存储路径 final String? apkPath = await _channel.invokeMethod('getCurrentApkPath'); if (apkPath == null || !await File(apkPath).exists()) return null; // 流式计算哈希,避免大文件OOM final fileStream = File(apkPath).openRead(); final digest = await sha256.bind(fileStream).first; return digest.toString(); } catch (_) { return null; } } }
2. Android原生端配置
在主Activity中注册方法通道,处理Dart端的路径获取请求,以Kotlin代码为例:
import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.engine.FlutterEngine import io.flutter.plugin.common.MethodChannel class MainActivity: FlutterActivity() { private val CHANNEL_NAME = "native_apk_util" override fun configureFlutterEngine(flutterEngine: FlutterEngine) { super.configureFlutterEngine(flutterEngine) MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL_NAME).setMethodCallHandler { call, result -> when (call.method) { "getCurrentApkPath" -> { // 直接返回当前应用APK的系统路径 result.success(applicationContext.packageCodePath) } else -> result.notImplemented() } } } }
注意事项
- 哈希计算存在百毫秒级耗时(取决于APK体积),不要在主线程UI构建逻辑中直接调用,放在后台异步执行即可
- 如果想进一步简化逻辑,也可以直接把哈希计算逻辑写在原生端,算完直接把哈希字符串回传给Dart,省去路径传输步骤
- 多渠道分发的APK如果存在渠道方重签名、注入渠道信息的情况,服务端需要存储对应渠道包的基准哈希值,避免正常包校验失败
- 校验逻辑建议做代码混淆,避免被逆向工具直接Hook绕过校验流程
内容的提问来源于stack exchange,提问作者Levi
相关产品推荐
相关产品推荐

