Flutter应用完整性校验插件app_integrity_checker的使用

发布于 1周前 作者 yuanlaile 来自 Flutter

Flutter应用完整性校验插件app_integrity_checker的使用

app_integrity_checker

Flutter插件,用于验证应用程序的完整性并在运行时检测是否被篡改。

对于iOS,部分完整性检查基于IOSSecuritySuite

开始使用

安装

可以通过以下命令安装:

$ flutter pub add app_integrity_checker

或者在pubspec.yaml文件中添加依赖项:

dependencies:
  app_integrity_checker: ^1.0.5

平台配置

  • Android:无需额外配置。
  • iOS:无需额外配置。

使用方法

以下是基本的使用示例:

import 'package:app_integrity_checker/app_integrity_checker.dart';

// 获取应用的Checksum值(SHA256)
String checksum = await AppIntegrityChecker.getchecksum() ?? "checksum retrieval failed";     
// 获取应用的签名值(SHA256)
String signature = await AppIntegrityChecker.getsignature() ?? "signature retrieval failed";  

输出说明

Android输出

  • Checksum (SHA-256):此值基于原生代码的校验和,不包括Dart代码。建议与应用签名一起使用,例如将校验和值与应用签名在服务器端进行验证。该值会在每次构建时发生变化,如果对原生代码进行了修改或篡改。
  • Signature (SHA-256):此值基于应用签名证书,如果签名证书被更改或篡改(如反编译后重新编译代码或更换发布/调试证书),该值会改变。只要使用相同的签名证书,该值不会随每次构建而变化。

iOS输出

  • Checksum (SHA-256):对于物理iOS设备,输出一个24字符的字符串;对于模拟器或非Arm64架构设备,仅前8个字符有效。
    • 前8个字符:Dart代码的校验和。可能会随着每次构建而变化,如果Dart代码被篡改也会变化。
    • 中间8个字符:原生Swift代码的校验和(仅限Arm64)。如果对原生代码进行了修改或篡改,该值会变化。
    • 后8个字符:IOSSecuritySuite库的校验和(仅限Arm64)。如果对IOSSecuritySuite库进行了修改或篡改,该值会变化。
    • 根据需求可以选择使用部分或全部校验和值。
  • Signature (SHA-256):此值基于应用代码签名,当上传到App Store时,由于苹果会替换开发者证书并使用自己的证书进行代码签名,该值会发生变化。根据需求适当使用。

示例代码

下面是一个完整的示例,展示了如何在Flutter应用中集成app_integrity_checker插件,并显示应用的Checksum和签名信息。

import 'package:flutter/material.dart';
import 'dart:async';
import 'package:flutter/services.dart';
import 'package:app_integrity_checker/app_integrity_checker.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
  String _checksum = "";
  String _signature = "";

  @override
  void initState() {
    super.initState();
    initPlatformState();
    WidgetsBinding.instance.addObserver(this);
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    switch (state) {
      case AppLifecycleState.resumed:
        initPlatformState();
        break;
      case AppLifecycleState.paused:
      case AppLifecycleState.inactive:
      case AppLifecycleState.detached:
      case AppLifecycleState.hidden:
        break;
    }
  }

  // Platform messages are asynchronous, so we initialize in an async method.
  Future<void> initPlatformState() async {
    String checksum = "";
    String signature = "";
    // Platform messages may fail, so we use a try/catch PlatformException.
    // We also handle the message potentially returning null.
    try {
      checksum = await AppIntegrityChecker.getchecksum() ??
          "checksum retrieval failed";
      signature = await AppIntegrityChecker.getsignature() ??
          "signature retrieval failed";
    } on PlatformException {
      //platform call failed
    }

    // If the widget was removed from the tree while the asynchronous platform
    // message was in flight, we want to discard the reply rather than calling
    // setState to update our non-existent appearance.
    if (!mounted) return;

    setState(() {
      _checksum = checksum;
      _signature = signature;
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Plugin example app'),
        ),
        body: Column(children: [
          Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.center,
              children: [
                const SizedBox(height: 150),
                const Text('App Checksum Value'),
                const SizedBox(height: 10),
                Text('$_checksum\n'),
                const SizedBox(height: 20),
                const Text('App Signature Value'),
                const SizedBox(height: 10),
                Text('$_signature\n'),
              ],
            ),
          )
        ]),
      ),
    );
  }
}

这个示例代码创建了一个简单的Flutter应用程序,它在启动时以及每次应用从后台恢复时获取并显示应用的Checksum和签名信息。通过这种方式,您可以确保应用的完整性和安全性。


更多关于Flutter应用完整性校验插件app_integrity_checker的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter应用完整性校验插件app_integrity_checker的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter应用中使用app_integrity_checker插件进行完整性校验的代码示例。这个插件可以帮助你确保你的应用没有被篡改。

首先,确保你已经将app_integrity_checker插件添加到你的Flutter项目中。你可以在pubspec.yaml文件中添加以下依赖项:

dependencies:
  flutter:
    sdk: flutter
  app_integrity_checker: ^x.y.z  # 请替换为最新版本号

然后运行flutter pub get来安装插件。

接下来,你可以在Flutter应用中使用该插件。以下是一个简单的示例,展示如何在应用启动时检查应用的完整性:

import 'package:flutter/material.dart';
import 'package:app_integrity_checker/app_integrity_checker.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: IntegrityCheckerScreen(),
    );
  }
}

class IntegrityCheckerScreen extends StatefulWidget {
  @override
  _IntegrityCheckerScreenState createState() => _IntegrityCheckerScreenState();
}

class _IntegrityCheckerScreenState extends State<IntegrityCheckerScreen> {
  String result = "";

  @override
  void initState() {
    super.initState();
    _checkAppIntegrity();
  }

  Future<void> _checkAppIntegrity() async {
    try {
      // 假设你有一个哈希文件 `app_hash.json` 放置在应用的资源目录中
      // 该文件包含应用的预期哈希值
      String hashFilePath = "assets/app_hash.json";
      
      // 加载哈希文件
      final String hashFileContent = await rootBundle.loadString(hashFilePath);
      
      // 初始化完整性检查器
      final AppIntegrityChecker checker = AppIntegrityChecker.fromJson(hashFileContent);
      
      // 执行完整性检查
      final bool isIntegrityOk = await checker.checkIntegrity();
      
      // 更新UI
      setState(() {
        result = isIntegrityOk ? "App integrity is OK." : "App integrity is compromised!";
      });
    } catch (e) {
      // 处理异常
      setState(() {
        result = "Failed to check app integrity: ${e.toString()}";
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("App Integrity Checker"),
      ),
      body: Center(
        child: Text(result),
      ),
    );
  }
}

app_hash.json 示例

你需要在assets文件夹中创建一个app_hash.json文件,该文件包含你应用的预期哈希值。例如:

{
  "files": [
    {
      "path": "lib/main.dart",
      "hash": "sha256-your_main_dart_file_hash_here"
    },
    {
      "path": "AndroidManifest.xml",
      "hash": "sha256-your_android_manifest_file_hash_here"
    },
    // 你可以继续添加其他需要校验的文件
  ]
}

请注意,你需要计算每个文件的哈希值,并将其填入app_hash.json文件中。

计算文件哈希值

你可以使用命令行工具来计算文件的哈希值。例如,在Linux或macOS上,你可以使用sha256sum命令:

sha256sum path/to/your/file

在Windows上,你可以使用PowerShell命令:

Get-FileHash -Path "path\to\your\file" -Algorithm SHA256

将计算出的哈希值复制并粘贴到app_hash.json文件中。

注意事项

  1. 确保你的pubspec.yaml文件中包含了app_hash.json文件的资源引用:

    flutter:
      assets:
        - assets/app_hash.json
    
  2. 在生产环境中,请确保你的哈希文件是安全的,避免被篡改。

这样,你就可以在Flutter应用中使用app_integrity_checker插件进行完整性校验了。

回到顶部