欢迎大家加入[开源鸿蒙跨平台开发者社区](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 实现)
- Flutter 端:
二、前置知识:SM4 算法核心概念
在写代码前,需明确 SM4 的几个关键特性,避免开发中踩坑:
- 密钥长度:固定 128 位(16 字节),生成时需确保长度合规,不可随意设置;
- 分组长度:固定 128 位,加密时会将数据按 16 字节拆分,不足则需填充(推荐 PKCS#7 填充);
- 工作模式:
- 不推荐
ECB模式(相同明文加密后密文相同,安全性低); - 推荐
CBC模式(需额外生成 16 字节 IV 向量,每次加密 IV 需不同,密文更安全);
- 不推荐
- 数据编码:加密后输出二进制数据,需用 Base64 编码转为字符串,方便存储和传输。
三、开发环境搭建
3.1 鸿蒙端环境(DevEco Studio)
- 下载并安装 DevEco Studio 4.0+,配置鸿蒙 SDK 8.0+;
- 在鸿蒙模块的
build.gradle中添加 BouncyCastle 依赖(提供 SM4 算法实现):
gradle
dependencies { // 其他依赖... implementation 'org.bouncycastle:bcprov-jdk15on:1.70' }- 配置权限:在
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 端环境
- 确保 Flutter 版本 ≥ 3.16.0,执行
flutter --version检查; - 在
pubspec.yaml中添加依赖:
yaml
dependencies: flutter: sdk: flutter # 安全存储密钥(替代 SharedPreferences,避免密钥明文存储) flutter_secure_storage: ^8.1.0 # 网络请求库(用于加密传输演示) dio: ^5.4.0 # Base64 编码(可选,Flutter 自带也可,但此库更易用) base64: ^3.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 鸿蒙端权限问题:存储 / 网络权限被拒
- 问题:加密存储时提示「权限不足」,或网络请求失败;
- 解决方案:
- 在
module.json5中配置完整的存储和网络权限(见 3.1 节); - 鸿蒙 6.0+ 需动态申请危险权限(如存储权限),可通过
ohos.permission.RuntimePermission动态申请。
- 在
6.4 跨平台数据一致性问题:Base64 编码差异
- 问题:Flutter 端 Base64 编码与鸿蒙端不一致,导致解密失败;
- 解决方案:统一使用「标准 Base64 编码」,鸿蒙端用
java.util.Base64,Flutter 端用dart:convert或base64库,避免使用 URL-Safe Base64。
七、总结与扩展
本文详细讲解了鸿蒙 Flutter 应用中集成 SM4 算法的完整流程,包括:
- 鸿蒙端 SM4 工具类实现(CBC 模式 + PKCS7 填充);
- MethodChannel 跨平台通信;
- Flutter 端密钥安全存储与加密 / 解密调用;
- 本地加密存储和网络加密传输两个核心场景。
后续扩展方向:
- 认证加密:当前 SM4 仅提供加密,可扩展为 GCM 模式(带认证标签),防止数据被篡改;
- 密钥轮换:实现密钥定期轮换机制,进一步提升安全性;
- 鸿蒙分布式能力:结合鸿蒙分布式数据管理,实现多设备间加密数据共享;
- 后端配合:本文仅覆盖客户端加密,需后端同步实现 SM4 解密逻辑(可参考客户端算法,使用相同的密钥、模式、填充方式)。
完整代码已上传至 GitHub:harmonyos-flutter-sm4-demo(替换为你的仓库地址),可直接克隆运行,如需进一步定制,可根据实际业务场景调整代码。