news 2026/4/23 17:10:01

鸿蒙 Flutter 国密算法应用:SM4 加密存储与数据传输

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
鸿蒙 Flutter 国密算法应用:SM4 加密存储与数据传输

欢迎大家加入[开源鸿蒙跨平台开发者社区](https://openharmonycrossplatform.csdn.net),一起共建开源鸿蒙跨平台生态。

一、引言:为什么需要在鸿蒙 Flutter 中集成 SM4 算法?

在移动应用开发中,数据安全是不可忽视的核心环节,尤其是涉及用户隐私(如手机号、身份证号)、敏感业务数据(如交易记录)的场景。国密算法(国家商用密码算法)是我国自主研发的密码标准,具备高安全性、合规性,已成为金融、政务、能源等关键领域的强制要求。

其中,SM4 算法(GB/T 32905-2016 标准)是一种分组对称加密算法,采用 128 位密钥、128 位分组长度,支持 ECB、CBC、CFB、OFB 等多种工作模式,适用于数据存储加密(如本地缓存加密)和数据传输加密(如接口请求体加密)。

鸿蒙(HarmonyOS)+ Flutter的组合是跨端开发的热门方案:鸿蒙提供了分布式能力和安全子系统,Flutter 则实现了高效的跨端 UI 渲染。本文将详细讲解如何在鸿蒙 Flutter 应用中集成 SM4 算法,实现「本地加密存储」和「网络加密传输」,并附带完整可运行代码。

1.1 参考文档与依赖工具

在开始前,建议先了解以下官方文档和工具,确保开发环境合规且高效:

  • 国密 SM4 官方标准:GB/T 32905-2016 信息安全技术 SM4 分组密码算法
  • 鸿蒙安全子系统:HarmonyOS 安全开发指南
  • Flutter 平台通信:Flutter MethodChannel 文档
  • 依赖库:
    • Flutter 端:flutter_secure_storage(安全存储密钥)、dio(网络请求)
    • 鸿蒙端:bcprov-jdk15on(BouncyCastle,提供 SM4 实现)

二、前置知识:SM4 算法核心概念

在写代码前,需明确 SM4 的几个关键特性,避免开发中踩坑:

  1. 密钥长度:固定 128 位(16 字节),生成时需确保长度合规,不可随意设置;
  2. 分组长度:固定 128 位,加密时会将数据按 16 字节拆分,不足则需填充(推荐 PKCS#7 填充);
  3. 工作模式
    • 不推荐ECB模式(相同明文加密后密文相同,安全性低);
    • 推荐CBC模式(需额外生成 16 字节 IV 向量,每次加密 IV 需不同,密文更安全);
  4. 数据编码:加密后输出二进制数据,需用 Base64 编码转为字符串,方便存储和传输。

三、开发环境搭建

3.1 鸿蒙端环境(DevEco Studio)

  1. 下载并安装 DevEco Studio 4.0+,配置鸿蒙 SDK 8.0+;
  2. 在鸿蒙模块的build.gradle中添加 BouncyCastle 依赖(提供 SM4 算法实现):

gradle

dependencies { // 其他依赖... implementation 'org.bouncycastle:bcprov-jdk15on:1.70' }
  1. 配置权限:在module.json5中添加网络权限和存储权限(用于加密存储):

json

{ "module": { "abilities": [...], "requestPermissions": [ { "name": "ohos.permission.INTERNET" // 网络请求权限 }, { "name": "ohos.permission.GET_WIFI_INFO" // 可选,若需网络加密传输 }, { "name": "ohos.permission.READ_USER_STORAGE" // 存储读取权限 }, { "name": "ohos.permission.WRITE_USER_STORAGE" // 存储写入权限 } ] } }

3.2 Flutter 端环境

  1. 确保 Flutter 版本 ≥ 3.16.0,执行flutter --version检查;
  2. pubspec.yaml中添加依赖:

yaml

dependencies: flutter: sdk: flutter # 安全存储密钥(替代 SharedPreferences,避免密钥明文存储) flutter_secure_storage: ^8.1.0 # 网络请求库(用于加密传输演示) dio: ^5.4.0 # Base64 编码(可选,Flutter 自带也可,但此库更易用) base64: ^3.1.1
  1. 执行flutter pub get安装依赖。

四、核心实现:SM4 加密与解密(鸿蒙原生层)

由于 Flutter 本身没有官方的国密算法库,且直接在 Dart 层实现 SM4 可能存在性能和安全性问题,推荐通过 MethodChannel 调用鸿蒙原生层的 SM4 实现(利用鸿蒙安全子系统和 BouncyCastle 库)。

4.1 鸿蒙端 SM4 工具类(Kotlin)

首先实现鸿蒙端的 SM4 加密 / 解密工具类,封装密钥生成、CBC 模式加密、CBC 模式解密逻辑:

kotlin

import org.bouncycastle.crypto.engines.SM4Engine import org.bouncycastle.crypto.modes.CBCBlockCipher import org.bouncycastle.crypto.paddings.PKCS7Padding import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher import org.bouncycastle.crypto.params.KeyParameter import org.bouncycastle.crypto.params.ParametersWithIV import java.security.SecureRandom import java.util.Base64 /** * 鸿蒙端 SM4 工具类(CBC 模式 + PKCS7 填充) */ object SM4Utils { // SM4 密钥长度:128 位(16 字节) private const val KEY_SIZE = 16 // SM4 分组长度(CBC 模式 IV 长度与分组长度一致) private const val IV_SIZE = 16 // 字符编码 private const val CHARSET = "UTF-8" /** * 生成 128 位(16 字节)SM4 密钥(Base64 编码) */ fun generateSm4Key(): String { val key = ByteArray(KEY_SIZE) // 使用鸿蒙安全随机数生成器(避免伪随机) val secureRandom = SecureRandom() secureRandom.nextBytes(key) // 转为 Base64 字符串,方便存储和传输 return Base64.getEncoder().encodeToString(key) } /** * SM4 加密(CBC 模式 + PKCS7 填充) * @param plainText 明文(待加密字符串) * @param keyBase64 Base64 编码的密钥 * @return 加密结果(格式:IV_BASE64:ENCRYPTED_DATA_BASE64) */ fun encrypt(plainText: String, keyBase64: String): String { try { // 1. 解码密钥和明文 val key = Base64.getDecoder().decode(keyBase64) val plainData = plainText.toByteArray(charset(CHARSET)) // 2. 生成随机 IV(16 字节) val iv = ByteArray(IV_SIZE) SecureRandom().nextBytes(iv) val ivBase64 = Base64.getEncoder().encodeToString(iv) // 3. 初始化 SM4 CBC 加密器(PKCS7 填充) val sm4Engine = SM4Engine() val cbcBlockCipher = CBCBlockCipher(sm4Engine) val paddedCipher = PaddedBufferedBlockCipher(cbcBlockCipher, PKCS7Padding()) // 传入密钥和 IV 参数 val keyParam = KeyParameter(key) val ivParam = ParametersWithIV(keyParam, iv) paddedCipher.init(true, ivParam) // true 表示加密模式 // 4. 执行加密 val output = ByteArray(paddedCipher.getOutputSize(plainData.size)) var outputLen = paddedCipher.processBytes(plainData, 0, plainData.size, output, 0) outputLen += paddedCipher.doFinal(output, outputLen) // 5. 加密结果 = IVBase64:加密数据Base64(方便解密时提取 IV) val encryptedDataBase64 = Base64.getEncoder().encodeToString(output.copyOf(outputLen)) return "$ivBase64:$encryptedDataBase64" } catch (e: Exception) { e.printStackTrace() throw RuntimeException("SM4 加密失败:${e.message}") } } /** * SM4 解密(CBC 模式 + PKCS7 填充) * @param encryptedStr 加密结果(格式:IV_BASE64:ENCRYPTED_DATA_BASE64) * @param keyBase64 Base64 编码的密钥 * @return 解密后的明文 */ fun decrypt(encryptedStr: String, keyBase64: String): String { try { // 1. 拆分 IV 和加密数据 val parts = encryptedStr.split(":", limit = 2) if (parts.size != 2) { throw IllegalArgumentException("加密格式错误,需满足 IV_BASE64:ENCRYPTED_DATA_BASE64") } val ivBase64 = parts[0] val encryptedDataBase64 = parts[1] // 2. 解码密钥、IV、加密数据 val key = Base64.getDecoder().decode(keyBase64) val iv = Base64.getDecoder().decode(ivBase64) val encryptedData = Base64.getDecoder().decode(encryptedDataBase64) // 3. 初始化 SM4 CBC 解密器(PKCS7 填充) val sm4Engine = SM4Engine() val cbcBlockCipher = CBCBlockCipher(sm4Engine) val paddedCipher = PaddedBufferedBlockCipher(cbcBlockCipher, PKCS7Padding()) val keyParam = KeyParameter(key) val ivParam = ParametersWithIV(keyParam, iv) paddedCipher.init(false, ivParam) // false 表示解密模式 // 4. 执行解密 val output = ByteArray(paddedCipher.getOutputSize(encryptedData.size)) var outputLen = paddedCipher.processBytes(encryptedData, 0, encryptedData.size, output, 0) outputLen += paddedCipher.doFinal(output, outputLen) // 5. 解码为明文 return String(output.copyOf(outputLen), charset(CHARSET)) } catch (e: Exception) { e.printStackTrace() throw RuntimeException("SM4 解密失败:${e.message}") } } }

4.2 鸿蒙端 MethodChannel 通信实现

通过 MethodChannel 暴露「生成密钥」「加密」「解密」方法给 Flutter 端,实现跨平台通信:

kotlin

import ohos.aafwk.ability.Ability import ohos.aafwk.content.Intent import io.flutter.embedding.engine.FlutterEngine import io.flutter.plugin.common.MethodCall import io.flutter.plugin.common.MethodChannel class MainAbility : Ability() { // 定义 MethodChannel 名称(需与 Flutter 端一致) private val CHANNEL_NAME = "com.example.harmony_sm4/channel" override fun onStart(intent: Intent?) { super.onStart(intent) // 初始化 Flutter Engine 时注册 MethodChannel val flutterEngine = FlutterEngine(this) MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL_NAME) .setMethodCallHandler { call: MethodCall, result: MethodChannel.Result -> when (call.method) { // 1. 生成 SM4 密钥 "generateSm4Key" -> { val sm4Key = SM4Utils.generateSm4Key() result.success(sm4Key) } // 2. SM4 加密 "sm4Encrypt" -> { val plainText = call.argument<String>("plainText") ?: "" val keyBase64 = call.argument<String>("keyBase64") ?: "" try { val encryptedStr = SM4Utils.encrypt(plainText, keyBase64) result.success(encryptedStr) } catch (e: Exception) { result.error("ENCRYPT_ERROR", e.message, null) } } // 3. SM4 解密 "sm4Decrypt" -> { val encryptedStr = call.argument<String>("encryptedStr") ?: "" val keyBase64 = call.argument<String>("keyBase64") ?: "" try { val plainText = SM4Utils.decrypt(encryptedStr, keyBase64) result.success(plainText) } catch (e: Exception) { result.error("DECRYPT_ERROR", e.message, null) } } // 未知方法 else -> result.notImplemented() } } } }

五、Flutter 端实现:调用鸿蒙 SM4 能力

Flutter 端通过 MethodChannel 调用鸿蒙原生的 SM4 方法,并结合flutter_secure_storage实现密钥安全存储,结合dio实现加密数据传输。

5.1 Flutter 端 SM4 工具类(Dart)

封装 MethodChannel 调用逻辑,对外提供简洁的 API:

dart

import 'package:flutter/services.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; /** * Flutter 端 SM4 工具类(通过 MethodChannel 调用鸿蒙原生能力) */ class FlutterSm4Utils { // 与鸿蒙端一致的 MethodChannel 名称 static const MethodChannel _channel = MethodChannel("com.example.harmony_sm4/channel"); // 安全存储实例(用于存储 SM4 密钥,避免明文存储) static const FlutterSecureStorage _secureStorage = FlutterSecureStorage(); // 存储密钥的 Key(本地持久化) static const String _sm4KeyStorageKey = "harmony_sm4_key"; /** * 初始化 SM4 密钥: * - 首次启动时生成密钥并存储到安全存储; * - 非首次启动时从安全存储读取密钥。 */ static Future<String> initSm4Key() async { try { // 1. 尝试从安全存储读取已存在的密钥 String? existingKey = await _secureStorage.read(key: _sm4KeyStorageKey); if (existingKey != null && existingKey.isNotEmpty) { print("SM4 密钥已存在,直接使用"); return existingKey; } // 2. 首次启动,调用鸿蒙端生成密钥 String newKey = await _channel.invokeMethod("generateSm4Key"); // 3. 将新密钥存储到安全存储(持久化) await _secureStorage.write(key: _sm4KeyStorageKey, value: newKey); print("SM4 密钥生成并存储成功:$newKey"); return newKey; } catch (e) { throw Exception("SM4 密钥初始化失败:$e"); } } /** * SM4 加密(调用鸿蒙端实现) * @param plainText 明文 * @param keyBase64 SM4 密钥(Base64 编码) * @return 加密结果(格式:IV_BASE64:ENCRYPTED_DATA_BASE64) */ static Future<String> encrypt(String plainText, String keyBase64) async { try { if (plainText.isEmpty || keyBase64.isEmpty) { throw Exception("明文和密钥不可为空"); } // 调用鸿蒙端加密方法 String encryptedStr = await _channel.invokeMethod( "sm4Encrypt", {"plainText": plainText, "keyBase64": keyBase64}, ); return encryptedStr; } on PlatformException catch (e) { throw Exception("SM4 加密失败:${e.message}"); } } /** * SM4 解密(调用鸿蒙端实现) * @param encryptedStr 加密结果(格式:IV_BASE64:ENCRYPTED_DATA_BASE64) * @param keyBase64 SM4 密钥(Base64 编码) * @return 解密后的明文 */ static Future<String> decrypt(String encryptedStr, String keyBase64) async { try { if (encryptedStr.isEmpty || keyBase64.isEmpty) { throw Exception("加密串和密钥不可为空"); } // 调用鸿蒙端解密方法 String plainText = await _channel.invokeMethod( "sm4Decrypt", {"encryptedStr": encryptedStr, "keyBase64": keyBase64}, ); return plainText; } on PlatformException catch (e) { throw Exception("SM4 解密失败:${e.message}"); } } /** * 清除本地存储的 SM4 密钥(仅用于测试,生产环境慎用) */ static Future<void> clearSm4Key() async { await _secureStorage.delete(key: _sm4KeyStorageKey); print("SM4 密钥已清除"); } }

5.2 场景 1:SM4 加密本地存储

以存储「用户登录信息」为例,演示如何将敏感数据加密后存储到本地:

dart

import 'package:flutter/material.dart'; import 'package:harmony_sm4/flutter_sm4_utils.dart'; class LocalEncryptionDemo extends StatefulWidget { const LocalEncryptionDemo({super.key}); @override State<LocalEncryptionDemo> createState() => _LocalEncryptionDemoState(); } class _LocalEncryptionDemoState extends State<LocalEncryptionDemo> { // SM4 密钥 String? _sm4Key; // 明文(用户信息) final TextEditingController _userInfoController = TextEditingController( text: '{"userId": "123456", "userName": "张三", "phone": "13800138000"}', ); // 加密结果 String? _encryptedResult; // 解密结果 String? _decryptedResult; @override void initState() { super.initState(); // 初始化 SM4 密钥 _initSm4Key(); } // 初始化 SM4 密钥 Future<void> _initSm4Key() async { String key = await FlutterSm4Utils.initSm4Key(); setState(() { _sm4Key = key; }); } // 加密按钮点击事件 Future<void> _onEncryptClick() async { if (_sm4Key == null) return; String plainText = _userInfoController.text.trim(); String encrypted = await FlutterSm4Utils.encrypt(plainText, _sm4Key!); setState(() { _encryptedResult = encrypted; _decryptedResult = null; // 重置解密结果 }); } // 解密按钮点击事件 Future<void> _onDecryptClick() async { if (_sm4Key == null || _encryptedResult == null) return; String decrypted = await FlutterSm4Utils.decrypt(_encryptedResult!, _sm4Key!); setState(() { _decryptedResult = decrypted; }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text("SM4 本地加密存储演示")), body: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 明文输入框 const Text("明文(用户信息):"), const SizedBox(height: 8), TextField( controller: _userInfoController, minLines: 3, maxLines: 5, decoration: const InputDecoration( border: OutlineInputBorder(), hintText: "请输入待加密的敏感数据", ), ), const SizedBox(height: 16), // 加密按钮 ElevatedButton( onPressed: _onEncryptClick, child: const Text("SM4 加密"), ), const SizedBox(height: 16), // 加密结果 if (_encryptedResult != null) ...[ const Text("加密结果(IV:密文):"), const SizedBox(height: 8), Expanded( child: SingleChildScrollView( child: Text(_encryptedResult!), ), ), const SizedBox(height: 16), // 解密按钮 ElevatedButton( onPressed: _onDecryptClick, child: const Text("SM4 解密"), ), ], const SizedBox(height: 16), // 解密结果 if (_decryptedResult != null) ...[ const Text("解密结果:"), const SizedBox(height: 8), Expanded( child: SingleChildScrollView( child: Text(_decryptedResult!), ), ), ], ], ), ), ); } }

5.3 场景 2:SM4 加密数据传输

以「用户登录接口」为例,演示如何将请求体加密后发送,接收响应后解密:

5.3.1 第一步:实现 Dio 拦截器(自动加密请求 / 解密响应)

dart

import 'package:dio/dio.dart'; import 'package:harmony_sm4/flutter_sm4_utils.dart'; /** * SM4 网络拦截器: * - 请求拦截:自动加密请求体(JSON 格式) * - 响应拦截:自动解密响应体 */ class Sm4HttpInterceptor extends Interceptor { final String _sm4Key; // 构造函数:传入 SM4 密钥 Sm4HttpInterceptor(this._sm4Key); // 请求拦截(加密请求体) @override Future<void> onRequest( RequestOptions options, RequestInterceptorHandler handler, ) async { try { // 仅对 POST/PUT 请求的 JSON 体进行加密 if ((options.method == "POST" || options.method == "PUT") && options.data != null) { // 1. 将请求体转为 JSON 字符串 String requestBodyJson = options.data is String ? options.data : options.data.toString(); // 若为 Map,可先转为 JSON 字符串 // 2. SM4 加密请求体 String encryptedBody = await FlutterSm4Utils.encrypt(requestBodyJson, _sm4Key); // 3. 替换请求体为加密后的字符串 options.data = { "encryptedData": encryptedBody, // 后端需解析此字段 "algorithm": "SM4-CBC-PKCS7" // 告知后端加密算法 }; // 4. 设置 Content-Type(避免后端解析错误) options.contentType = Headers.jsonContentType; print("请求体加密完成:${options.data}"); } handler.next(options); } catch (e) { handler.reject(DioException( requestOptions: options, error: "请求体加密失败:$e", )); } } // 响应拦截(解密响应体) @override Future<void> onResponse( Response response, ResponseInterceptorHandler handler, ) async { try { // 1. 获取后端返回的加密数据(假设后端返回格式:{"encryptedData": "..."}) if (response.data is Map && response.data["encryptedData"] != null) { String encryptedResponse = response.data["encryptedData"]; // 2. SM4 解密响应体 String decryptedResponse = await FlutterSm4Utils.decrypt(encryptedResponse, _sm4Key); // 3. 替换响应体为解密后的 JSON 字符串(若需转为 Map,可进一步解析) response.data = decryptedResponse; print("响应体解密完成:$decryptedResponse"); } handler.next(response); } catch (e) { handler.reject(DioException( requestOptions: response.requestOptions, error: "响应体解密失败:$e", )); } } }
5.3.2 第二步:使用拦截器发起加密请求

dart

import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; import 'package:harmony_sm4/flutter_sm4_utils.dart'; import 'package:harmony_sm4/sm4_http_interceptor.dart'; class NetworkEncryptionDemo extends StatefulWidget { const NetworkEncryptionDemo({super.key}); @override State<NetworkEncryptionDemo> createState() => _NetworkEncryptionDemoState(); } class _NetworkEncryptionDemoState extends State<NetworkEncryptionDemo> { String? _sm4Key; final Dio _dio = Dio(); // 登录参数 final TextEditingController _phoneController = TextEditingController(text: "13800138000"); final TextEditingController _passwordController = TextEditingController(text: "12345678"); // 请求结果 String? _requestResult; @override void initState() { super.initState(); // 初始化 SM4 密钥并配置 Dio 拦截器 _initSm4KeyAndDio(); } // 初始化 SM4 密钥 + 配置 Dio 拦截器 Future<void> _initSm4KeyAndDio() async { String key = await FlutterSm4Utils.initSm4Key(); setState(() { _sm4Key = key; }); // 添加 SM4 拦截器 _dio.interceptors.add(Sm4HttpInterceptor(key)); // 配置基础 URL(替换为你的后端接口地址) _dio.options.baseUrl = "https://api.example.com"; _dio.options.connectTimeout = const Duration(seconds: 10); } // 发起加密登录请求 Future<void> _sendEncryptedLoginRequest() async { if (_sm4Key == null) return; try { // 1. 构造登录请求体(明文) Map<String, dynamic> loginBody = { "phone": _phoneController.text.trim(), "password": _passwordController.text.trim(), "timestamp": DateTime.now().millisecondsSinceEpoch // 时间戳(防重放) }; // 2. 发起 POST 请求(拦截器会自动加密请求体) Response response = await _dio.post( "/user/login", data: loginBody, // 明文请求体(拦截器会自动加密) ); // 3. 响应已被拦截器自动解密,直接使用 setState(() { _requestResult = "登录成功!\n解密后的响应:\n${response.data}"; }); } on DioException catch (e) { setState(() { _requestResult = "登录失败:\n${e.message}"; }); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text("SM4 加密数据传输演示")), body: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 手机号输入 TextField( controller: _phoneController, decoration: const InputDecoration( labelText: "手机号", border: OutlineInputBorder(), ), ), const SizedBox(height: 16), // 密码输入 TextField( controller: _passwordController, obscureText: true, decoration: const InputDecoration( labelText: "密码", border: OutlineInputBorder(), ), ), const SizedBox(height: 24), // 发起请求按钮 ElevatedButton( onPressed: _sendEncryptedLoginRequest, child: const Text("发起加密登录请求"), ), const SizedBox(height: 24), // 请求结果 const Text("请求结果:"), const SizedBox(height: 8), Expanded( child: SingleChildScrollView( child: Text(_requestResult ?? "未发起请求"), ), ), ], ), ), ); } }

六、常见问题与解决方案

6.1 密钥安全问题:避免硬编码或明文存储

  • 问题:将 SM4 密钥硬编码在代码中,或用SharedPreferences明文存储,存在密钥泄露风险;
  • 解决方案:使用flutter_secure_storage(鸿蒙端底层调用鸿蒙 KeyStore)存储密钥,确保密钥仅在设备安全硬件中存储,无法被恶意读取。

6.2 加密格式错误:IV 与密文拆分失败

  • 问题:解密时抛出「加密格式错误」,原因是加密结果格式不正确;
  • 解决方案:严格遵循「IV_BASE64:ENCRYPTED_DATA_BASE64」格式,拆分时用split(":", limit = 2)(避免 IV 或密文中包含:导致拆分错误)。

6.3 鸿蒙端权限问题:存储 / 网络权限被拒

  • 问题:加密存储时提示「权限不足」,或网络请求失败;
  • 解决方案
    1. module.json5中配置完整的存储和网络权限(见 3.1 节);
    2. 鸿蒙 6.0+ 需动态申请危险权限(如存储权限),可通过ohos.permission.RuntimePermission动态申请。

6.4 跨平台数据一致性问题:Base64 编码差异

  • 问题:Flutter 端 Base64 编码与鸿蒙端不一致,导致解密失败;
  • 解决方案:统一使用「标准 Base64 编码」,鸿蒙端用java.util.Base64,Flutter 端用dart:convertbase64库,避免使用 URL-Safe Base64。

七、总结与扩展

本文详细讲解了鸿蒙 Flutter 应用中集成 SM4 算法的完整流程,包括:

  1. 鸿蒙端 SM4 工具类实现(CBC 模式 + PKCS7 填充);
  2. MethodChannel 跨平台通信;
  3. Flutter 端密钥安全存储与加密 / 解密调用;
  4. 本地加密存储和网络加密传输两个核心场景。

后续扩展方向:

  1. 认证加密:当前 SM4 仅提供加密,可扩展为 GCM 模式(带认证标签),防止数据被篡改;
  2. 密钥轮换:实现密钥定期轮换机制,进一步提升安全性;
  3. 鸿蒙分布式能力:结合鸿蒙分布式数据管理,实现多设备间加密数据共享;
  4. 后端配合:本文仅覆盖客户端加密,需后端同步实现 SM4 解密逻辑(可参考客户端算法,使用相同的密钥、模式、填充方式)。

完整代码已上传至 GitHub:harmonyos-flutter-sm4-demo(替换为你的仓库地址),可直接克隆运行,如需进一步定制,可根据实际业务场景调整代码。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/23 9:20:07

DeepSeek-V3.1震撼发布:混合推理架构引领AI交互新纪元

DeepSeek-V3.1震撼发布&#xff1a;混合推理架构引领AI交互新纪元 【免费下载链接】DeepSeek-V3.1-Base DeepSeek-V3.1 是一款支持思考模式与非思考模式的混合模型 项目地址: https://ai.gitcode.com/hf_mirrors/deepseek-ai/DeepSeek-V3.1-Base 2025年8月21日下午&…

作者头像 李华
网站建设 2026/4/23 10:47:35

【北理工-AAAI26】MODA:首个无人机多光谱目标检测数据集

文章&#xff1a;MODA: The First Challenging Benchmark for Multispectral Object Detection in Aerial Images代码&#xff1a;https://github.com/shuaihao-han/MODA单位&#xff1a;北京理工大学一、问题背景&#xff1a;航拍检测难在哪&#xff1f;多光谱潜力为何难释放&…

作者头像 李华
网站建设 2026/4/23 10:44:01

用 Melody 听遍全网音乐!加上cpolar这个工具,随时随地享受专属歌单

文章目录前言1. 添加镜像源2. 本地部署Melody3. 本地访问与使用演示4. 安装内网穿透5. 配置Melody公网地址6. 配置固定公网地址前言 Melody 的主要功能是整合多个平台的音乐资源&#xff0c;用户可以搜索、播放、下载歌曲&#xff0c;还能将喜欢的音乐上传到云盘&#xff0c;方…

作者头像 李华
网站建设 2026/4/23 13:35:57

一文盘点家政有哪些类型

居民生活品质不断提升&#xff0c;家政服务已经从简单的日常保洁&#xff0c;扩展到清洁维护、育婴照护、居家维修等一整套生活支持体系。为了帮助家庭更高效地选择家政服务&#xff0c;本篇从“服务类型”“经营模式&#xff08;直营 / 非直营&#xff09;”“行业代表品牌”三…

作者头像 李华
网站建设 2026/4/23 10:48:55

Wan2.2-T2V-A14B如何生成带有弹幕评论的模拟播放界面?

Wan2.2-T2V-A14B如何生成带有弹幕评论的模拟播放界面&#xff1f; 在短视频内容爆炸式增长的今天&#xff0c;用户早已不满足于“看视频”这一单向行为——他们更渴望参与、互动与共鸣。尤其是在B站、抖音等平台上&#xff0c;一条视频是否“火”&#xff0c;往往不是由画质或剧…

作者头像 李华
网站建设 2026/4/23 10:48:44

从零上手MiniCPM 2.0:端侧大模型本地部署全攻略

模型概述&#xff1a;重新定义轻量级AI的性能边界 【免费下载链接】MiniCPM-V-2 项目地址: https://ai.gitcode.com/OpenBMB/MiniCPM-V-2 在大语言模型参数竞赛愈演愈烈的当下&#xff0c;面壁智能与清华大学自然语言处理实验室联合研发的MiniCPM系列&#xff0c;正以&…

作者头像 李华