鸿蒙新特性实战:cryptoFramework 密码学工具箱 — Hash摘要、AES加解密与HMAC认证码
引言
在现代应用开发中,数据安全是一个不可回避的话题。无论是用户密码的存储、敏感数据的传输,还是接口参数的签名验证,都离不开密码学算法的支撑。HarmonyOS NEXT 通过 @ohos.security.cryptoFramework 模块为开发者提供了一套完整的密码学能力,涵盖消息摘要(Hash)、对称加密(AES)、消息认证码(HMAC)、非对称加密(RSA)、数字签名等全方位的安全功能。
本文将以一个密码学工具箱的实战 Demo 为线索,深入讲解 cryptoFramework 的核心 API 和使用模式。与上一篇文章介绍的 zlib 压缩引擎类似,cryptoFramework 也遵循"创建实例 → 初始化 → 更新数据 → 获取结果"的管道式操作模式,但它在算法丰富度和安全场景覆盖面上要广阔得多。
读完本文,你将掌握:
- 消息摘要(MD5/SHA) 的计算方法及7种算法对比
- AES 对称加密 的加密/解密流程及5种模式切换
- HMAC 消息认证码 的生成与验证
- DataBlob 数据容器 在密码学 API 中的核心作用
- 同步 vs 异步 API 的选择策略
环境与权限
cryptoFramework 属于 CryptoArchitectureKit 工具包,自 API 9 开始提供,API 11 起支持跨平台,API 12 起支持原子化服务。本文基于 API 24 (HarmonyOS NEXT) 编写,使用同步 API(xxxSync 系列方法)。
cryptoFramework 不需要申请任何权限,直接导入即可使用:
import cryptoFramework from '@ohos.security.cryptoFramework';
这是密码学 API 相比传感器、蓝牙等功能模块的一大优势——零权限门槛,开箱即用。
核心数据结构:DataBlob
在深入各个算法之前,必须先理解 cryptoFramework 的通用数据容器——DataBlob。它是整个密码学框架的数据交换基础,所有输入输出都通过它来传递。
interface DataBlob {
data: Uint8Array;
}
DataBlob 本质上是 Uint8Array 的包装。字符串与 DataBlob 之间的转换是所有操作的第一步。我们使用 @kit.ArkTS 中的 util.TextEncoder / util.TextDecoder 来完成:
import { util } from '@kit.ArkTS';
// 字符串 → Uint8Array → DataBlob
function stringToUint8(str: string): Uint8Array {
let encoder = new util.TextEncoder();
return encoder.encodeInto(str);
}
// DataBlob → Uint8Array → 字符串
function uint8ToString(buf: Uint8Array): string {
let decoder = new util.TextDecoder();
return decoder.decodeToString(buf);
}
实际使用时只需将 Uint8Array 放入对象字面量即可创建 DataBlob:
let dataBlob: cryptoFramework.DataBlob = { data: this.stringToUint8('Hello HarmonyOS') };
一、消息摘要(Hash):MD5、SHA 系列与 SM3
消息摘要算法(又称哈希算法)将任意长度的数据映射为固定长度的"指纹"。cryptoFramework 支持 7 种摘要算法:
| 算法 | 摘要长度 | 安全性 | 典型用途 |
|---|---|---|---|
| MD5 | 128 bit (16 B) | 已破解,不推荐安全场景 | 文件完整性校验、非安全去重 |
| SHA-1 | 160 bit (20 B) | 已弱化 | 遗留系统兼容 |
| SHA-224 | 224 bit (28 B) | 中等 | 资源受限场景 |
| SHA-256 | 256 bit (32 B) | 高 | 区块链、证书、签名 |
| SHA-384 | 384 bit (48 B) | 很高 | 高安全场景 |
| SHA-512 | 512 bit (64 B) | 最高 | 高安全场景、HMAC |
| SM3 | 256 bit (32 B) | 高 | 国密标准,政务金融 |
同步 Hash 计算(三步走)
cryptoFramework 的 Hash 流程遵循统一的"创建 → 更新 → 摘要"三步模式:
// 步骤1:创建消息摘要实例
let md: cryptoFramework.Md = cryptoFramework.createMd('SHA256');
// 步骤2:更新数据(可多次调用处理大块数据)
md.updateSync({ data: this.stringToUint8('Hello HarmonyOS!') });
// 步骤3:获取摘要结果
let result: cryptoFramework.DataBlob = md.digestSync();
// result.data 是 Uint8Array,转为十六进制字符串展示
let hexString = this.bufToHex(result.data);
// 输出:32字节的SHA-256摘要
Uint8Array → 十六进制字符串
摘要结果是一段二进制数据,展示时通常转为十六进制:
bufToHex(buf: Uint8Array): string {
let sb = '';
for (let i = 0; i < buf.length; i++) {
let h = (buf[i] & 0xFF).toString(16);
if (h.length === 1) sb += '0';
sb += h;
}
return sb;
}
批量对比:7种算法一键测试
Demo 中提供了"批量对比"功能,对同一段文本依次运行 7 种算法,同时记录每种算法的输出长度和计算耗时,让开发者直观感受不同算法的特点:
batchHash(): void {
let inputData = this.stringToUint8(this.textInput);
for (let a = 0; a < this.algos.length; a++) {
let algo = this.algos[a];
let md: cryptoFramework.Md = cryptoFramework.createMd(algo);
let start = Date.now();
md.updateSync({ data: inputData });
let result: cryptoFramework.DataBlob = md.digestSync();
let elapsed = Date.now() - start;
// 记录算法名、耗时、摘要长度...
}
}
Md 接口完整方法列表
interface Md {
update(input: DataBlob, callback: AsyncCallback<void>): void; // 异步更新
update(input: DataBlob): Promise<void>; // Promise更新
updateSync(input: DataBlob): void; // 同步更新(推荐)
digest(callback: AsyncCallback<DataBlob>): void; // 异步摘要
digest(): Promise<DataBlob>; // Promise摘要
digestSync(): DataBlob; // 同步摘要(推荐)
getMdLength(): number; // 获取摘要长度
}
对于 Demo 场景,同步 API 代码更简洁。生产环境中处理大文件(如几百MB的视频),建议使用异步 Promise 版以避免阻塞主线程。
二、AES 对称加密:5种模式的加密/解密往返
cryptoFramework 的 Cipher(密码器)模块提供完整的对称加密能力。支持的对称算法包括 AES128、AES192、AES256,以及国密 SM4。本文 Demo 聚焦最常用的 AES,提供 5 种配置模式:
| 模式 | transformation 参数 | 密钥长度 | 填充方式 |
|---|---|---|---|
| AES128-ECB | AES128|ECB|PKCS7 |
16 B | PKCS7 |
| AES128-CBC | AES128|CBC|PKCS7 |
16 B | PKCS7 |
| AES128-CTR | AES128|CTR|NoPadding |
16 B | 无填充(流式) |
| AES192-ECB | AES192|ECB|PKCS7 |
24 B | PKCS7 |
| AES256-ECB | AES256|ECB|PKCS7 |
32 B | PKCS7 |
transformation 参数的格式为 算法|模式|填充方式,三个部分用 | 连接。
加密/解密六步流程
完整的 AES 加解密往返包含 6 个核心步骤:
aesEncryptDecrypt(): void {
let transformation = 'AES128|ECB|PKCS7'; // 算法|模式|填充
let keyStr = this.keyInput;
// 1. 准备密钥(将字符串填充/截断到算法需要的长度)
let keyBuf = this.stringToUint8(keyStr);
let paddedKey = new Uint8Array(16); // AES128 = 16 bytes
for (let i = 0; i < 16; i++) {
paddedKey[i] = keyBuf[i % keyBuf.length];
}
// 2. 创建对称密钥生成器
let symKeyGen: cryptoFramework.SymKeyGenerator =
cryptoFramework.createSymKeyGenerator('AES128');
// 3. 从字节数据转换为 SymKey 对象
let symKey: cryptoFramework.SymKey =
symKeyGen.convertKeySync({ data: paddedKey });
// 4. 创建 Cipher 并初始化为加密模式
let cipher: cryptoFramework.Cipher = cryptoFramework.createCipher(transformation);
let iv: cryptoFramework.IvParamsSpec = {
algName: 'IvParamsSpec',
iv: { data: paddedKey } // ECB模式不需要IV,为统一接口仍传入
};
cipher.initSync(cryptoFramework.CryptoMode.ENCRYPT_MODE, symKey, iv);
// 5. 执行加密(doFinal = 完成并输出)
let cipherResult: cryptoFramework.DataBlob =
cipher.doFinalSync({ data: this.stringToUint8(this.textInput) });
// 6. 重新初始化并解密,验证往返正确性
let decipher: cryptoFramework.Cipher = cryptoFramework.createCipher(transformation);
decipher.initSync(cryptoFramework.CryptoMode.DECRYPT_MODE, symKey, iv);
let plainResult: cryptoFramework.DataBlob =
decipher.doFinalSync({ data: cipherResult.data });
let roundtrip = (this.uint8ToString(plainResult.data) === this.textInput);
// roundtrip === true 说明加解密往返正确
}


关键要点
1) CryptoMode 枚举
enum CryptoMode {
ENCRYPT_MODE, // 加密模式
DECRYPT_MODE // 解密模式
}
同一个 Cipher 实例在 doFinal 之后不可重复使用。如果需要解密,必须创建新的 Cipher 实例,并以 DECRYPT_MODE 重新 init。
2) IV(初始化向量)参数
CBC/CTR 等模式使用 IV 增加随机性,保证同一明文每次产生不同密文。ECB 模式不使用 IV,但 initSync 的第三个参数 params 在 ECB 模式下可传入 null。Demo 中为统一接口风格,对 ECB 也传入了一个占位 IV。
3) 密钥长度与算法的对应
AES128→ 16 bytes (128 bits)AES192→ 24 bytes (192 bits)AES256→ 32 bytes (256 bits)
Demo 中自动从 transformation 字符串中提取密钥长度要求,并用取模循环方式填充用户输入的任意长度密钥:
let keyAlg = transformation.split('|')[0]; // 'AES128'
let keyBytesNeeded = parseInt(keyAlg.substring(3)) / 8; // 128/8 = 16
let paddedKey = new Uint8Array(keyBytesNeeded);
for (let i = 0; i < keyBytesNeeded; i++) {
paddedKey[i] = keyBuf[i % keyBuf.length];
}
三、HMAC 消息认证码:带密钥的哈希
HMAC(Hash-based Message Authentication Code)在哈希算法的基础上引入密钥,同时验证数据的完整性和真实性。接收方只有持相同密钥才能生成一致的 HMAC 值,有效防止中间人篡改。
cryptoFramework 为 HMAC 提供了与 Md 完全一致的三步式 API:
computeHmac(): void {
// 1. 准备对称密钥(HMAC需要共享密钥)
let keyBuf = this.stringToUint8(this.keyInput);
let padded = new Uint8Array(16);
for (let i = 0; i < 16; i++) { padded[i] = keyBuf[i % keyBuf.length]; }
let symKeyGen: cryptoFramework.SymKeyGenerator =
cryptoFramework.createSymKeyGenerator('AES128');
let symKey: cryptoFramework.SymKey =
symKeyGen.convertKeySync({ data: padded });
// 2. 创建Mac实例并初始化
let mac: cryptoFramework.Mac = cryptoFramework.createMac('HMAC|SHA256');
mac.initSync(symKey);
// 3. 更新数据并获取结果
mac.updateSync({ data: this.stringToUint8(this.textInput) });
let macResult: cryptoFramework.DataBlob = mac.doFinalSync();
this.hmacOutput = this.bufToHex(macResult.data);
}
HMAC 的算法名称格式为 HMAC|摘要算法,例如:
HMAC|SHA1HMAC|SHA256HMAC|SHA384HMAC|SHA512
四、API 全景概览
cryptoFramework 的模块结构层次分明,下图展示了核心类与创建函数的关系:
cryptoFramework (namespace)
├── createMd(algName) ──────────────→ Md ──→ updateSync() + digestSync()
├── createMac(algName) ─────────────→ Mac ─→ initSync() + updateSync() + doFinalSync()
├── createCipher(transformation) ───→ Cipher → initSync() + doFinalSync()
├── createSymKeyGenerator(algName) ─→ SymKeyGenerator ─→ generateSymKeySync() + convertKeySync()
├── createRandom() ─────────────────→ Random ─→ generateRandomSync()
├── createSign(algName) ────────────→ Sign ──→ initSync() + signSync()
├── createVerify(algName) ──────────→ Verify → initSync() + verifySync()
├── createKeyAgreement(algName) ────→ KeyAgreement ─→ generateSecretSync()
└── createAsyKeyGenerator(algName) ─→ AsyKeyGenerator ─→ generateKeyPairSync()
本文 Demo 聚焦最常用的前 4 个模块(Md、Cipher、Mac、SymKeyGenerator),它们已经覆盖了日常开发 90% 的密码学需求。
五、实战 Demo:密码学工具箱
页面结构
Demo 页面 CryptoFrameworkPage.ets 采用"输入区 + 三大功能面板 + 历史记录"的卡片式布局:
密码学工具箱
├── 状态栏 — 实时反馈当前操作结果
├── 输入区
│ ├── 文本输入框(3000字上限)
│ └── AES密钥输入框(自动填充至所需长度)
├── 消息摘要 (Hash) 面板
│ ├── 7种算法横向选择(MD5/SHA1/SHA224/SHA256/SHA384/SHA512/SM3)
│ ├── 计算Hash 按钮 — 对输入文本执行选中算法
│ ├── 批量对比 按钮 — 对同一输入执行全部7种算法
│ └── 结果展示区 — 十六进制摘要 + 耗时
├── AES 对称加密面板
│ ├── 5种模式选择(AES128-ECB/CBC/CTR, AES192-ECB, AES256-ECB)
│ ├── 加密并解密 按钮 — 执行完整的加密→解密往返
│ ├── 密文展示(hex格式,前40字符预览)
│ └── 解密验证结果(对比原文,显示"通过/失败")
├── HMAC 消息认证码面板
│ ├── 计算 HMAC-SHA256 按钮
│ └── MAC值展示(hex格式)
├── 摘要/认证记录 — 最近8次Hash和HMAC操作
├── 加解密记录 — 最近8次AES操作及往返验证状态
└── 核心API参考 — 12个关键API速查表
4 个交互点
- 算法选择与单次Hash — 点击7种算法标签切换,输入文本后计算Hash,实时显示摘要和耗时
- 批量算法对比 — 一键对同一文本执行全部7种算法,记录在历史面板中直观对比摘要长度和速度
- AES加解密往返 — 选择5种模式之一点击加密,自动执行解密并验证往返正确性(对比原文)
- HMAC认证码生成 — 用密钥对输入文本生成MAC,展示键控哈希与普通哈希的区别
核心代码位置
完整代码在 dev/entry/src/main/ets/pages/CryptoFrameworkPage.ets(约 380 行),路由已注册为 pages/CryptoFrameworkPage。
六、同步 vs 异步 API 的选择
cryptoFramework 为每个操作提供了 3 种调用方式:Callback 异步、Promise 异步、同步(Sync)。以 Md.digest 为例:
// 方式1:Callback 异步
md.digest((err, result) => {
if (err) { console.error('digest failed'); return; }
let hex = bufToHex(result.data);
});
// 方式2:Promise 异步
md.digest().then((result) => {
let hex = bufToHex(result.data);
}).catch((err) => { console.error('digest failed'); });
// 方式3:同步(Demo 推荐)
let result: cryptoFramework.DataBlob = md.digestSync();
let hex = bufToHex(result.data);
选择策略:
| 场景 | 推荐方式 | 原因 |
|---|---|---|
| 小数据(< 1 KB) | 同步 Sync | 代码简洁,阻塞时间可忽略 |
| 中等数据(1 KB - 1 MB) | Promise 异步 | 避免UI卡顿,保持响应 |
| 大数据(> 1 MB) | Promise 异步 + update 分块 | 利用 update 逐块处理,内存友好 |
| Worker 线程 | 同步 Sync | Worker 不阻塞主线程,Sync 更简单 |
七、常见问题与排查
1. “algName is invalid” 错误
算法名称字符串区分大小写且不能有额外空格。标准算法名称为:
正确: 'SHA256', 'AES128|ECB|PKCS7', 'HMAC|SHA256'
错误: 'sha256', 'AES128|ECB|PKCS7 '(尾部有空格)
2. doFinalSync 只能调用一次
每个 Md/Cipher/Mac 实例的 doFinalSync / digestSync 只能调用一次。如果需要重复计算,必须创建新实例:
// 错误 —— 重复使用同一个Md
let md = cryptoFramework.createMd('SHA256');
md.digestSync();
md.digestSync(); // 抛出异常!
// 正确 —— 每次创建新实例
let md1 = cryptoFramework.createMd('SHA256');
md1.updateSync({ data: data1 });
let result1 = md1.digestSync();
let md2 = cryptoFramework.createMd('SHA256');
md2.updateSync({ data: data2 });
let result2 = md2.digestSync();
3. AES 加解密往返验证失败
如果解密后的明文与原文本不一致,检查以下几点:
- 加密和解密使用的
transformation参数是否完全一致 - 加密和解密的 IV 是否一致
- 密钥是否一致(是否被意外截断或补零)
- 密文在传输过程中是否被修改(如错误的反序列化)
4. cipher.init: params is null
ECB/CTR 等不需要 IV 的模式,initSync 的第三个参数 params 可传入 null。但对于 CBC 模式,必须提供 IvParamsSpec。
八、安全最佳实践
1. 密码存储:绝不用 MD5
MD5 和 SHA-1 已被证明存在碰撞漏洞。存储用户密码时,应使用 SHA-256 + 随机盐值 或专门的密钥派生函数。
// 不安全的密码存储
let hash = cryptoFramework.createMd('MD5');
hash.updateSync({ data: passwordData });
let result = hash.digestSync(); // MD5 易碰撞
// 更好的做法(简化示意)
let hash = cryptoFramework.createMd('SHA256');
let salt = cryptoFramework.createRandom().generateRandomSync(16); // 随机盐
let combined = new Uint8Array(salt.data.length + passwordData.data.length);
combined.set(salt.data, 0);
combined.set(passwordData.data, salt.data.length);
hash.updateSync({ data: combined });
let result = hash.digestSync();
// 存储 salt + result
2. IV 必须随机且不重复
CBC 模式下,每次加密都应使用新的随机 IV。重复使用相同 IV 会泄露明文模式:
let random = cryptoFramework.createRandom();
let iv = random.generateRandomSync(16); // 16字节随机IV
3. ECB 模式的局限性
ECB 模式下相同的明文块产生相同的密文块,可能泄露数据模式。对于包含重复结构的数据(如 JSON、XML),应优先使用 CBC 或 CTR 模式。
4. 密钥管理
Demo 中的密钥输入仅供演示。生产环境中,密钥应:
- 使用
cryptoFramework.createRandom().generateRandomSync()生成 - 存储在系统安全区域(如 HUKS 密钥管理服务)
- 绝不明文硬编码在代码中
- 使用后及时从内存清除
九、与其它平台对比
如果你有 Android 或 iOS 开发经验,以下对照表可帮助理解:
| 功能 | HarmonyOS cryptoFramework | Android javax.crypto | iOS CryptoKit |
|---|---|---|---|
| 消息摘要 | createMd('SHA256').digestSync() |
MessageDigest.getInstance("SHA-256").digest() |
SHA256.hash(data:) |
| AES加密 | createCipher('AES128|CBC|PKCS7') |
Cipher.getInstance("AES/CBC/PKCS5Padding") |
AES.GCM.seal() |
| HMAC | createMac('HMAC|SHA256') |
Mac.getInstance("HmacSHA256") |
HMAC<SHA256>.authenticationCode() |
| 对称密钥生成 | createSymKeyGenerator('AES256').generateSymKeySync() |
KeyGenerator.getInstance("AES").generateKey() |
SymmetricKey(size:) |
可以看到,HarmonyOS 的 API 设计融合了 Android 的灵活性(字符串参数指定算法)和 iOS 的类型安全性(强类型接口),同时加入了国密算法(SM3、SM4)的原生支持,这是其它平台不具备的独特优势。
十、总结
cryptoFramework 是 HarmonyOS NEXT 密码学能力的核心入口,它提供了:
- 7种摘要算法 — MD5、SHA-1/224/256/384/512、SM3,覆盖国际标准和国密
- AES对称加密 — AES128/192/256 × ECB/CBC/CTR 多种组合
- HMAC认证码 — 基于SHA-256的键控哈希,验证完整性和真实性
- 统一的管道式API — 所有模块遵循"创建→初始化→更新→完成"四步模式
- 同步/异步双轨支持 — 小数据用 Sync,大文件用 Promise,灵活切换
- 零权限门槛 — 无需申请任何系统权限即可使用
与 zlib 压缩引擎一样,cryptoFramework 也体现了 HarmonyOS API 设计的统一哲学:用 createXxx() 创建实例,用 xxxSync() 完成同步操作,用 DataBlob 传递二进制数据。掌握这一个模式,就能触类旁通地驾驭整个框架。
下一篇文章我们将继续探索 HarmonyOS NEXT 的其它新特性,敬请期待。
更多推荐


所有评论(0)