Flutter鸿蒙 原生 cryptoFramework 不支持 DES 的替代方案

欢迎大家加入开源鸿蒙跨平台社区

一、问题现象

在 HarmonyOS 上使用官方 @ohos.security.cryptoFramework 实现 DES 加密时,会遇到以下情况之一:

  • 找不到 DES 相关算法常量
  • 调用 createCipher('DES|CBC|PKCS7') 报错或不支持
  • 文档中仅列出 3DES、AES 等算法,无 DES

1.1 典型错误

import { cryptoFramework } from '@kit.CryptoArchitectureKit';

// ❌ DES 不在支持列表中
let cipherAlgName = 'DES|CBC|PKCS7';
let cipher = cryptoFramework.createCipher(cipherAlgName);
// 报错:Algorithm DES is not supported

二、根本原因

2.1 HarmonyOS 安全策略

HarmonyOS 的 cryptoFramework 出于安全合规考虑,仅支持以下对称加密算法(以 API 12 为例):

算法 支持情况 说明
AES ✅ 支持 128/192/256 位
3DES ✅ 支持 即 TDES
DES 不支持 已视为弱算法,从 API 中移除
SM4 ✅ 支持 国密算法

DES 密钥仅 56 位有效,易受暴力破解,NIST 等机构已不建议在新系统中使用。因此 HarmonyOS 原生不提供 DES 支持。

2.2 业务兼容性需求

许多存量系统、第三方接口仍使用 DES,Flutter 插件需在 Android/iOS/HarmonyOS 上保持一致的加密结果。因此必须在不依赖原生 DES 的前提下,在 HarmonyOS 上实现等效算法。


三、替代方案:使用 @ohos/crypto-js

3.1 方案选型

方案 优点 缺点
原生 cryptoFramework 性能好、系统级支持 不支持 DES
@ohos/crypto-js 支持 DES、与 Web 版兼容、易集成 纯 JS 实现,大数据量略慢
自实现 DES 无第三方依赖 工作量大、易出错、维护成本高

推荐:使用 @ohos/crypto-js,它是 crypto-js 的 OpenHarmony 移植版,支持 DES/CBC/Pkcs7,与 Android 的 DES/CBC/PKCS5Padding 在 8 字节分组下等效。

3.2 依赖配置

ohos/oh-package.json5 中添加:

{
  "name": "flutter_des",
  "version": "1.0.0",
  "description": "DES plugin",
  "dependencies": {
    "@ohos/crypto-js": "^2.0.4"
  }
}

执行 ohpm install 安装依赖。

3.3 算法等效性说明

平台 算法写法 实际效果
Android DES/CBC/PKCS5Padding 8 字节分组,PKCS5 与 PKCS7 等效
iOS/macOS kCCAlgorithmDES, kCCOptionPKCS7Padding 同上
HarmonyOS (crypto-js) DES/CBC/Pkcs7 与 Android 结果一致

CryptoJS 默认使用 CBC 模式和 Pkcs7 填充,配置 { iv: ivWA } 即可,无需额外指定 mode 和 padding。


四、完整实现示例

4.1 加密

import { CryptoJS } from '@ohos/crypto-js';

function encrypt(data: string, key: string, iv: string): Uint8Array | null {
  try {
    let keyWA = CryptoJS.enc.Utf8.parse(key);
    let ivWA = CryptoJS.enc.Utf8.parse(iv);
    // 默认 CBC + Pkcs7,与 Android PKCS5Padding 等效
    let encrypted = CryptoJS.DES.encrypt(data, keyWA, { iv: ivWA });
    return wordArrayToBytes(encrypted.ciphertext);
  } catch (e) {
    return null;
  }
}

4.2 解密

function decryptFromHex(hexStr: string, key: string, iv: string): string | null {
  try {
    let wordArray = CryptoJS.enc.Hex.parse(hexStr);
    let base64Str = CryptoJS.enc.Base64.stringify(wordArray);
    let keyWA = CryptoJS.enc.Utf8.parse(key);
    let ivWA = CryptoJS.enc.Utf8.parse(iv);
    let decrypted = CryptoJS.DES.decrypt(base64Str, keyWA, { iv: ivWA });
    return decrypted.toString(CryptoJS.enc.Utf8);
  } catch (e) {
    return "";
  }
}

4.3 WordArray 转 Uint8Array

CryptoJS 内部使用 WordArray(32 位字数组),需转换为 Uint8Array 才能与 Flutter 的 Uint8List 对接:

function wordArrayToBytes(wa: CryptoJS.lib.WordArray): Uint8Array {
  let words = wa.words;
  let sigBytes = wa.sigBytes;
  let u8 = new Uint8Array(sigBytes);
  let offset = 0;
  for (let i = 0; i < words.length && offset < sigBytes; i++) {
    let word = words[i];
    u8[offset++] = (word >>> 24) & 0xff;
    if (offset < sigBytes) u8[offset++] = (word >>> 16) & 0xff;
    if (offset < sigBytes) u8[offset++] = (word >>> 8) & 0xff;
    if (offset < sigBytes) u8[offset++] = word & 0xff;
  }
  return u8;
}

五、跨平台结果一致性验证

使用相同明文、密钥、IV 在 Android 与 HarmonyOS 上加密,结果应完全一致:

// Dart 测试
final plain = 'hello';
final key = '12345678';
final iv = '01234567';

// Android 与 HarmonyOS 的 encryptToHex 结果应相同
final hex = await FlutterDes().encryptToHex(plain, key, iv: iv);
// 例如:'XXXXXXXX'(两平台一致)

建议编写单元测试,对比各平台的 hex/base64 输出。


六、性能与安全建议

6.1 性能

  • crypto-js 为纯 JavaScript 实现,大数据量(如 >1MB)时性能不如原生
  • 可考虑在 Dart 层做分块加密,或对超大 payload 给出提示

6.2 安全

  • DES 仅用于兼容存量系统,新业务建议使用 AES-256
  • 密钥、IV 需安全存储,避免硬编码

七、方案对比总结

维度 原生 cryptoFramework @ohos/crypto-js
DES 支持 ❌ 不支持 ✅ 支持
3DES/AES ✅ 支持 ✅ 支持
性能 高(原生) 中(JS)
集成难度 低(若支持 DES)
跨平台一致性 - 与 Android/iOS 一致

结论:在 HarmonyOS 上实现 DES,当前唯一可行且推荐的方式是使用 @ohos/crypto-js


八、参考资料

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐