我做了一款鸿蒙加密App,加密后的密文看起来像一段正常中文——聊聊 AES-GCM + 字谱替换的实现思路
起因:加密结果为什么非得是乱码?
去年有个朋友问我:“我想把一些私密笔记存在手机便签里,但又怕被人看到,有没有什么办法?”
我说用加密工具啊。他说试过,加密完一串 Base64 或者乱码放在便签里,别人一看就知道"这条是加密过的",反而更引人注意。
这句话点醒了我。
传统加密工具的问题不在于加密强度不够,而在于加密结果本身就在宣告"我被加密了"。对于很多日常场景——比如备忘录里记个密码、朋友之间传个悄悄话——你需要的不只是"别人解不开",而是"别人根本不觉得这里有东西需要解"。
所以我做了「密语盒子」,一个鸿蒙原生的加密工具。它的核心卖点就一句话:加密结果是一段看起来完全正常的中文文字。
技术方案:AES-GCM 加密 + 自定义字谱映射
整体分两层:
底层加密用的是 AES-GCM + PBKDF2 派生密钥。这部分没什么花活,就是保证密码学层面的安全性。HarmonyOS 提供了@ohos.security.cryptoFramework模块,AES-GCM 的实现可以直接调系统能力,不需要自己搬 OpenSSL。
上层伪装才是这个 App 的灵魂。加密产生的二进制数据,通常工具会用 Base64 编码输出,我换了一种做法——用一套「字谱」做映射。
说白了,字谱就是一个字符集合,比如你可以定义一套字谱是"天地玄黄宇宙洪荒日月盈昃辰宿列张"这些字。加密后的每个字节,按索引映射到字谱中的某个汉字。最终输出的就是一串看起来像诗句、像随笔的中文文本。
关键代码大概长这样:
// 将加密后的字节数组映射到字谱字符 function bytesToCipherText(encrypted: Uint8Array, charset: string[]): string { let result = '' for (let i = 0; i < encrypted.length; i++) { // 高4位和低4位分别映射,确保字谱长度16即可覆盖 let high = (encrypted[i] >> 4) & 0x0F let low = encrypted[i] & 0x0F result += charset[high] + charset[low] } return result } ``` 这样做的好处是:字谱完全由用户自定义。你可以用《千字文》里的字,也可以用菜单上的菜名,甚至用 emoji。只要收发双方约定同一套字谱和密码,就能互相解读。 ## 鸿蒙适配过程中踩的坑 说实话做鸿蒙版比我预想的顺利一些,ArkUI 的声明式写法上手之后效率还行。但有几个地方折腾了一阵: 1. **剪贴板权限**。密语盒子的核心操作流程是"加密→复制→粘贴到别处",鸿蒙对剪贴板的管控比较严格,`pasteboard` 模块在后台状态下行为和前台不一样,我调了两天才搞清楚生命周期的影响。 2. **文本输入框的性能**。用户可能粘贴很长的密文进来解密,ArkUI 的 `TextArea` 组件在文本量大的时候渲染有点卡。最后我做了分段渲染,超过一定长度就先截断显示,点击展开全文。 3. **字谱编辑器**。这个功能我试了三种交互方案。第一版是表格填写,太笨重;第二版是自由文本输入然后自动拆分,用户反馈说搞不清哪个字对应哪个位置;最终第三版用了类似标签流的布局,每个字是一个可拖拽的 tag,直观多了。 ```arkts // 字谱编辑器 - 标签流布局 Flex({ wrap: FlexWrap.Wrap, space: { main: LengthMetrics.vp(8), cross: LengthMetrics.vp(8) } }) { ForEach(this.charsetArray, (char: string, index: number) => { Text(char) .fontSize(16) .padding({ left: 12, right: 12, top: 6, bottom: 6 }) .backgroundColor(this.selectedIndex === index ? '#4FC3F7' : '#F5F5F5') .borderRadius(16) .onClick(() => { this.selectedIndex = index }) }) } ``` ## 当前状态 密语盒子鸿蒙版 1.2.0 已经上架华为应用市场,完全免费,无广告,数据全离线不联网。 说实话,这个 App 目前下载量很小。我分析了一下,一方面是品类太小众,大部分人没有"加密后还要伪装"这个需求意识;另一方面是我之前几乎没做过推广,就是静默上架等自然流量,结果当然约等于零。 但从留存数据看,用过的人留下来的比例还不错。有几个用户在评论区说用来和对象传悄悄话,这倒是我没想到的使用场景。 ## 为什么选择做鸿蒙原生而不是跨平台 这个问题我考虑过。密语盒子的核心依赖两个能力:加密 API 和剪贴板。HarmonyOS 的 `cryptoFramework` 接口封装得比较干净,AES-GCM 支持完整,不需要额外引入第三方库。如果用 Flutter 或 RN 做跨平台,反而要桥接原生加密模块,多一层不说,还有安全审核的麻烦。 对了,鸿蒙的应用审核对加密类 App 有额外审查,提交的时候需要在备注里说明加密用途和算法类型,第一次被打回来就是因为这个没写清楚。后来补了一份算法说明文档就过了。 ## 后续计划 下个版本打算加两个东西: - **密语分享卡片**:生成一张好看的图片,密文嵌在图里,分享到社交平台更自然 - - **字谱市场**(本地的):预置几套有趣的字谱模板,比如"外卖菜单风"、"古诗词风"、"数学公式风",降低用户自己编字谱的门槛 如果你也在做 HarmonyOS 开发,或者对加密/信息隐藏这个方向感兴趣,欢迎交流。我的鸿蒙开发笔记后续也会陆续整理发出来。