我在鸿蒙上做了个加密工具,加密结果看起来像一段正常中文——聊聊 AES-GCM + 字谱替换的实现思路
·
起因:加密结果为什么非得是乱码?
去年我在整理备忘录的时候突然意识到一个问题——我把一些重要密码、私密笔记存在手机便签里,虽然手机有锁屏密码,但如果有人借我手机看个东西,顺手划到便签……
那用加密工具呢?试了几个,加密之后输出的要么是 Base64,要么是一串不可读的乱码。问题来了:一眼就能看出来"这东西被加密了",反而引起好奇心。
所以我想做一个不一样的东西:加密结果是人类可读的汉字组合,看起来就像一段普通文字,没有任何"被加密过"的痕迹。
这就是「密语盒子」的出发点。今年我把它搬到了 HarmonyOS 上,目前版本 1.2.0,已经上架华为应用市场。
核心设计:字谱替换 + AES-GCM
说白了,整个方案分两层:
底层加密:用 AES-GCM 做真正的加密,密钥通过 PBKDF2 从用户输入的密码派生。这一层保证安全性,即使有人拿到密文也没法逆向。
表层伪装:把加密后的二进制数据,通过一套"字谱"映射成汉字。字谱是可自定义的——你可以用唐诗三百首里的字,可以用菜谱里的字,甚至可以用 emoji。最终输出看起来就是一段"正常文字"。
举个例子,我输入"我的银行密码是123456",加密之后可能输出的是:
春风得意马蹄疾一日看尽长安花碧云天黄叶地秋色连波
外人看到这个,只觉得你在摘抄古诗。
鸿蒙侧的实现
在 HarmonyOS 上做这个,主要用到 ArkTS + ArkUI 构建界面,加解密部分依赖 @ohos.security.cryptoFramework 这个系统模块。
加密核心逻辑大概是这样的:
import cryptoFramework from '@ohos.security.cryptoFramework';
async function encryptWithAesGcm(plainText: string, password: string): Promise<Uint8Array> {
// PBKDF2 派生密钥
let keyGenApi = cryptoFramework.createSymKeyGenerator('AES256');
let kdfSpec: cryptoFramework.PBKDF2Spec = {
algName: 'PBKDF2',
password: password,
salt: generateRandomSalt(),
iterations: 100000,
keySize: 32
};
let symKey = await keyGenApi.generateSymKeyBySpec(kdfSpec);
// AES-GCM 加密
let cipher = cryptoFramework.createCipher('AES256|GCM|PKCS7');
let gcmParams = buildGcmParams(); // iv + aad + authTag
await cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, symKey, gcmParams);
let encData = await cipher.doFinal({ data: stringToUint8Array(plainText) });
return encData.data;
}
```
拿到加密后的字节数组之后,下一步就是字谱映射。这步的思路很简单:把字节流按固定位数切分,每一段对应字谱中的一个字符。
```arkts
function bytesToCipherText(encrypted: Uint8Array, charset: string[]): string {
let result = '';
// 每个字节映射到字谱中的一个字符(字谱长度>=256)
for (let i = 0; i < encrypted.length; i++) {
let index = encrypted[i]; // 0-255
result += charset[index];
}
return result;
}
```
这里有个取舍:如果字谱长度刚好 256,那一个字节对应一个字,输出长度等于密文字节数。如果字谱小于 256,就需要用两个字符表示一个字节,输出会变长。我最终选了让用户自定义字谱长度,界面上会实时提示"当前字谱可表示范围"和"预估输出长度"。
## 踩过的坑
说几个实际开发中遇到的问题:
**1. cryptoFramework 的 GCM 模式在某些设备上 authTag 长度有限制。** 我一开始设了 128 bit,在 Mate 60 上没问题,但有个用户反馈在某款平板上会报错。后来查了文档发现要做兼容判断,退到 96 bit 保底。
**2. 字谱编辑的体验比想象中难做。** 用户可能输入重复字符、输入空格、甚至粘贴进来带换行的文本。我做了去重、trim、以及实时校验字谱有效性的逻辑。ArkUI 的 `TextInput` 组件配合 `onChange` 回调处理这些校验还算顺手。
**3. 离线这件事很重要。** 整个加解密过程完全在本地完成,不请求任何网络。这一点我在应用描述里重点写了——做隐私工具如果还联网,谁信你?
## 多套字谱管理
这是我觉得比较有意思的功能。你可以保存多套字谱:
- 跟朋友 A 约定用"天气预报"风格的字谱
- - 跟朋友 B 约定用"菜谱"风格的字谱
- - 自己私用一套"古诗词"字谱
不同字谱加密同一段文字,输出完全不同。即使有人知道你用了密语盒子,不知道你用的哪套字谱 + 密码,依然解不出来。
我用 ArkUI 的 `List` + `ListItem` 做了字谱列表管理,支持增删改和切换默认字谱。数据存在本地 preferences 里,不走云端。
## 当前状态
说实话,这个 App 目前下载量不大。刚上架没多久,还在冷启动阶段。鸿蒙应用市场的分发逻辑跟其他平台不太一样,纯工具类如果没有搜索关键词的自然流量,前期确实比较慢。
但我觉得这个方向值得做下去。隐私类工具在鸿蒙生态里目前还挺稀缺的,大部分加密 App 还是安卓那套思路直接迁过来,没有针对 HarmonyOS 的设计语言做适配。
## 为什么选鸿蒙
一个很现实的原因:鸿蒙原生应用目前竞争没那么卷。同样一个工具类 App,在 iOS/Android 上你要跟几百个竞品抢,在 HarmonyOS 上可能同类 App 就那么几个。
另外 ArkUI 的声明式开发体验我个人觉得还行,跟 SwiftUI / Compose 类似的思路,上手成本不高。状态管理用 `@State` / `@Link` / `@Provide` 基本够用,不需要额外引入什么框架。
对了,HarmonyOS 的安全模块(cryptoFramework)封装得比我预期的好,AES/RSA/SM4 这些常见算法都有,PBKDF2 也内置了,不需要像以前在 Android 上那样自己引 BouncyCastle。
## 后续计划
- 支持分享密文时附带"字谱指纹"(不暴露字谱内容,但接收方可以校验自己的字谱是否匹配)
- - 加一个"阅后即焚"模式——解密查看一次后自动清除剪贴板
- - 适配鸿蒙的万能卡片,在桌面快速加解密
如果你也在做 HarmonyOS 开发,特别是安全/隐私方向的,欢迎交流。我在 CSDN 评论区或者私信都能看到。
更多推荐

所有评论(0)