数据加密基础:对称加密(AES)在鸿蒙中的实战
各位同学,今天我们来聊聊对称加密。说白了,对称加密就是加密和解密用同一把钥匙。你想想看,就像你家的门锁,用一把钥匙锁上,也用同一把钥匙打开。AES 是目前最主流的对称加密算法,鸿蒙系统对它支持得非常好。
AES 的核心概念
AES,全称是 Advanced Encryption Standard。它有几个关键参数,我建议你记牢:
- 密钥长度:支持 128 位、192 位、256 位。我个人习惯用 256 位,安全性更高。
- 分组大小:固定 128 位,也就是 16 个字节。
- 工作模式:常见的有 ECB、CBC、GCM 等。
- 填充方式:PKCS7 是最常用的。
重要提醒:ECB 模式虽然简单,但安全性较差。我在项目中遇到过,用 ECB 加密同样的数据块,得到的密文是一样的,这很容易被攻击者利用。所以,我建议你优先选择 CBC 或 GCM 模式。
鸿蒙中的 AES 实战
鸿蒙系统提供了统一的加密框架,叫 HUKS(Harmony Universal KeyStore)。它把密钥管理、加密运算都封装好了,用起来很方便。
嗯,这里要注意:HUKS 要求密钥必须存储在安全环境中,不能直接拿到密钥的明文。这样做的好处是,即使应用被攻破,攻击者也拿不到密钥。
生成 AES 密钥
我们先来看怎么生成一个 AES 密钥。代码其实不复杂:
// 1. 构造密钥参数
let keyParam = {
keyType: huks.HuksKeyType.AES,
keyLen: huks.HuksKeyLen.HUKS_AES_KEY_SIZE_256,
keyUsage: huks.HuksKeyUsage.ENCRYPT | huks.HuksKeyUsage.DECRYPT,
keyMode: huks.HuksKeyMode.CBC,
keyPadding: huks.HuksKeyPadding.PKCS7,
};
// 2. 生成密钥
let keyAlias = "my_aes_key";
huks.generateKey(keyAlias, keyParam, (err, data) => {
if (err) {
console.error("生成密钥失败: " + err);
return;
}
console.log("密钥生成成功");
});
这段代码里,我指定了密钥类型是 AES,长度 256 位,用途是加密和解密,模式是 CBC,填充方式是 PKCS7。这些参数组合起来,就是一个比较安全的配置。
加密数据
密钥有了,接下来就是加密。加密时需要指定 IV(初始化向量)。IV 的作用是让同样的明文每次加密结果都不同。我习惯每次加密都生成一个新的随机 IV。
// 1. 准备明文数据
let plainText = "Hello, HarmonyOS!";
let plainData = new Uint8Array(plainText.length);
for (let i = 0; i < plainText.length; i++) {
plainData[i] = plainText.charCodeAt(i);
}
// 2. 生成随机 IV
let iv = new Uint8Array(16);
crypto.getRandomValues(iv);
// 3. 构造加密参数
let encryptParam = {
keyAlias: "my_aes_key",
iv: iv,
keyMode: huks.HuksKeyMode.CBC,
keyPadding: huks.HuksKeyPadding.PKCS7,
};
// 4. 执行加密
huks.encrypt(encryptParam, plainData, (err, cipherData) => {
if (err) {
console.error("加密失败: " + err);
return;
}
console.log("加密成功,密文长度: " + cipherData.length);
});
你看,加密过程很清晰。这里有个细节:IV 不需要保密,但必须保证每次加密都不同。我一般会把 IV 和密文一起存储,解密时再取出来用。
解密数据
解密是加密的逆过程。注意,解密时用的 IV 必须和加密时一样:
// 1. 构造解密参数(IV 必须和加密时一致)
let decryptParam = {
keyAlias: "my_aes_key",
iv: iv, // 从存储中取出加密时用的 IV
keyMode: huks.HuksKeyMode.CBC,
keyPadding: huks.HuksKeyPadding.PKCS7,
};
// 2. 执行解密
huks.decrypt(decryptParam, cipherData, (err, plainData) => {
if (err) {
console.error("解密失败: " + err);
return;
}
let decryptedText = String.fromCharCode.apply(null, plainData);
console.log("解密成功: " + decryptedText);
});
小技巧:我曾经在项目中遇到解密失败,排查了半天才发现是 IV 传错了。所以,我建议你把 IV 和密文打包在一起存储,比如用 JSON 格式:{"iv": "...", "cipher": "..."}。这样就不会搞混了。
常见问题与避坑指南
做 AES 加密时,有几个坑我踩过,分享给你:
- 密钥长度不匹配:生成密钥时指定了 256 位,但传入的密钥数据只有 128 位,会报错。一定要检查密钥长度。
- IV 重复使用:同一个密钥下,IV 绝对不能重复。否则,攻击者可以通过分析密文推断出明文信息。
- 填充错误:加密和解密用的填充方式必须一致。一个用 PKCS7,另一个用 NoPadding,解密就会失败。
- 密钥别名冲突:HUKS 中密钥别名是唯一的。如果重复生成同一个别名的密钥,会覆盖之前的密钥。我建议用 UUID 或时间戳作为别名的一部分。
警告:千万不要把密钥硬编码在代码里!我曾经见过有人把密钥写在 Java 代码中,结果反编译后密钥直接暴露了。正确的做法是使用 HUKS 生成密钥,或者从安全服务器获取。
性能对比
不同模式的 AES 性能差异挺大的。我整理了一个表格,供你参考:
| 模式 | 安全性 | 性能 | 适用场景 |
|---|---|---|---|
| ECB | 低 | 高 | 不推荐使用 |
| CBC | 中 | 中 | 文件加密、数据传输 |
| GCM | 高 | 中高 | 网络通信、实时数据 |
| CTR | 高 | 高 | 流式数据加密 |
我个人最推荐 GCM 模式。它不仅能加密,还能做完整性校验,防止数据被篡改。说白了,就是一次搞定加密和认证,省心又安全。
总结
好了,今天的内容就到这里。AES 加密在鸿蒙中实现起来并不复杂,关键是理解密钥管理、IV 的使用和模式选择。记住我强调的几点:用 HUKS 管理密钥、每次加密用随机 IV、优先选 GCM 模式。这样你的数据安全就有保障了。
下一章,我们会讲非对称加密 RSA 在鸿蒙中的实战,敬请期待。