同一个公司写的两个 HAP,为什么不能直接拿对方的密钥?

做多模块应用的时候,最开始的思路很简单:把应用拆成几个 HAP,每个 HAP 各自存一份密钥。
跑了一段时间发现问题:密钥存了好几份,改一个密钥要改好几个地方。而且有的 HAP 把密钥明文存 Preferences 里,安全风险很大。
这时候才想到:既然都是同一个开发者的 HAP,能不能共享一份密钥?HUKS 的群组密钥就是干这个的。
一、先搞清楚密钥隔离是怎么回事
很多人以为:同一个开发者的应用,密钥应该互通吧?
不对。
| 同一个 HAP 自己的密钥 | 能 |
| 不同开发者的 HAP 的密钥 | 不能 |
| 同开发者不同 HAP 的密钥 | 默认不能 |
| 同 Group 同开发者的密钥 | 能 |
默认情况下,每个 HAP 的密钥是隔离的。你自己的密钥你自己用,别人的你拿不到。哪怕是同一个开发者写的不同 HAP,默认也不能互相访问。
这是安全设计,不是 bug。
二、群组密钥是什么机制
HUKS 从 API 23 开始支持群组密钥。简单说就是:
- 你给一组 HAP 划一个 Group;
- 同一个 Group 里的 HAP,只要是同一个开发者,就能共享指定的密钥;
- 不同 Group、不同开发者的,还是隔离的。
这段代码解决什么问题: 在 HUKS 中创建群组密钥。
文件: security/KeyManager.ets
用途: 跨 HAP 密钥共享
接入位置: 密钥初始化
import huks from '@ohos.security.huks';
async createGroupKey() {
const alias = 'business_shared_key';
const groupId = 'com.myapp.shared_group';
const options: huks.HuksOptions = {
properties: [
{ tag: huks.HuksTag.HUKS_TAG_ALIAS, value: alias },
{ tag: huks.HuksTag.HUKS_TAG_GROUP_ID, value: groupId },
{ tag: huks.HuksTag.HUKS_TAG_KEY_ALG, value: huks.HuksKeyAlg.HUKS_ALG_AES }
]
};
await huks.generateKeyItem(alias, options);
}
这里 Group ID 是关键。同一个 Group 里的 HAP 才能共享这个密钥。
三、为什么不能把密钥传来传去
很多人想:那我在 A HAP 里拿到密钥,传给 B HAP 不就行了?
这是最危险的做法。
| 密钥明文传 Intent | 被拦截了 |
| 密钥存 Preferences | 随便就能读 |
| 密钥硬编码在代码里 | 反编译就拿到了 |
密钥本身绝对不能出 HUKS。你只能在 HUKS 里做加解密操作,不能把密钥导出来到处传。
群组密钥的好处就是:密钥存在 HUKS 里,所有同 Group 的 HAP 都能直接用,不用把密钥传来传去。

四、加解密的流程是怎样的
拿到群组密钥之后,加解密的流程是:
整个过程密钥都在 HUKS 里,应用代码拿不到密钥本身。你只能把数据传进去,拿到结果出来。
这就是安全设计:密钥永远不离开安全环境。
五、删除 HAP 的时候要注意什么
还有个容易踩的坑:删除 HAP 的时候,共享密钥怎么办?
如果 Group 里所有 HAP 都删了,那密钥也就没用了。但如果还有 HAP 在用,你不能把密钥删了。
很多人做应用卸载的时候,没考虑共享密钥的生命周期。结果就是:删了一个 HAP,其他 HAP 解密失败了。
六、几个容易踩的坑
第一个坑:把密钥明文放 Preferences。谁都能读,等于没加密。
第二个坑:多个 HAP 各自硬编码相同 Key。改密钥要改好几个地方,容易漏。
第三个坑:把加密后的数据和密钥一起存。密钥和数据放一起,加密就没意义了。
第四个坑:Group 配置错误导致密钥不可见。Group ID 写错了,其他 HAP 根本访问不到。
第五个坑:为了跨模块使用把密钥导出到业务层。密钥出了 HUKS,安全就没保证了。

这次做跨 HAP 安全设计最大的体会是:密钥永远不能出安全环境。不要想着把密钥传来传去,要让大家都去 HUKS 里用同一个密钥。Group 机制就是干这个的——既共享,又不把密钥暴露出来。






