最近在跑 Flutter for OpenHarmony 的项目,遇到一个绕不开的需求:给 App 里的登录态、数据传递和接口参数做签名与加密。调研了一圈,最后落在了 jose 这套库上。它把 JWT、JWE、JWS 三件套全包圆了,用起来确实有瑞士军刀的感觉。这篇文章不打算写成 API 文档的翻译稿,而是把我从环境搭建、库选型、源码机制到实际适配中踩过的坑,梳理成一份可以直接抄作业的鸿蒙适配指南。
如果你正在用 Flutter 开发 OpenHarmony 应用,或者准备评估 jose 作为统一加密方案,这篇文章可以帮你少走不少弯路。我会先讲 jose 能解决什么问题,再讲落地时的环境准备、核心实操、源码适配细节,最后给出一份常见问题速查表。
1. 先搞清楚 jose 到底能干什么
1.1 JWT、JWE、JWS 这三兄弟是什么关系
很多同学一上来就对着 JSON Web Token 三个字母发懵:JWT 和 JWS 不是一回事吗?JWE 又是干嘛的?这里我用最直白的方式给你捋清楚。
JWT 是一个容器概念,它描述的是"一段用点号分隔的三段式 Token 结构"。中间那段是 Payload,承载业务数据(用户 ID、过期时间、角色之类);前后的两段则分别承担保护和校验职责。JWS 和 JWE 就是 JSON Web Signature 和 JSON Web Encryption 的缩写,它们定义了 JWT 的两种具体生成方式。
- JWS:把 Payload 做签名,保证内容不被篡改,任何拿到 Token 的人都能读到明文,但改一个字节验签就会失败。
- JWE:把 Payload 加密成密文,只有持有私钥或共享密钥的接收方才能解开,别人就算截获了也只是看到一堆乱码。
- JWT 本身既不强制签名也不强制加密,但实际生产里绝大多数"JWT"其实是 JWS 格式的签名 Token,少数高安全场景会用 JWE 做加密。
打个比方:JWS 像是快递包裹上的防拆封条,你能看见里面的东西,但一旦被人动过手脚封条就断了;JWE 像是保险箱,箱子本身就是加密的,没有钥匙的人根本看不到里面放了什么。
理解了这层关系,jose 这个库的价值就清楚了大半。它把 JWS 签名、JWE 加密、JWT 的签发与验证统一封装成了一套 API,你不需要再分别引入三套不同的库去对齐数据格式。
1.2 为什么说它是安全领域的瑞士军刀
"瑞士军刀"这个说法不是我发明的,jose 库在官方描述里就自称是"Javascript Object Signing and Encryption 的完整实现"。它支持的标准覆盖得很全:
- JWT:签发、解析、验证,包括 exp、nbf、iat、iss、aud、sub 这些标准 Claim 的处理。
- JWS:支持 HS256、HS384、HS512、RS256、RS384、RS512、PS256、ES256、ES384、ES512 等主流签名算法,还支持 None(不建议生产用)。
- JWE:支持 RSA-OAEP、RSA-OAEP-256、ECDH-ES、A128KW、A256KW 等密钥管理算法,内容加密层支持 A128GCM、A256GCM、A128CBC-HS256、A256CBC-HS512 等。
- JWK:密钥对和公钥的 JSON 格式封装,方便在服务端与客户端之间传递公钥。
- JWKS:JWK Set,也就是一组密钥的集合,适合动态轮换密钥的场景。
还有一个容易被忽略的点:jose 在设计上尽量做到平台无关。它底层只用 Dart 标准库加少量 cryptograph 相关依赖,所以在 Flutter、纯 Dart 服务端、命令行工具里都能跑。这就意味着你可以在 OpenHarmony 设备上做签名,在 Linux 服务端验签,两端共用一套数据标准和协议,不需要额外开发适配层。
1.3 jose 在 Flutter for OpenHarmony 生态里的定位
Flutter for OpenHarmony 是 OpenHarmony 生态里非常活跃的一个跨端方案。它让开发者能用 Dart 写业务,用 Flutter 的组件渲染界面,最终打包成 hap 运行在 OpenHarmony 设备上。但问题在于,OpenHarmony 毕竟不是 Android,很多在 Android 上顺理成章的插件在鸿蒙上根本没法直接用。
安全相关的库更是重灾区。比如某些第三方加密插件会直接调用 Android 的 AndroidKeyStore 或者 iOS 的 Keychain,这些在 OpenHarmony 上都没有对应实现。jose 的纯 Dart 实现让它天然避开了 Native 依赖的坑,这正是它在鸿蒙上能跑起来的关键原因。
我在项目里的实际用法是:登录成功后服务端返回一个 JWS 格式的 Token,客户端用 jose 库做本地验签,确认 Token 确实由我的服务端签发;同时客户端向服务端上报敏感业务数据时,用 JWE 加密,保证即使被中间人抓包也拿不到明文。这套流程在 Android 和 OpenHarmony 上用的是同一套代码,基本没做平台分支。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 环境准备与工程接入
2.1 Flutter for OpenHarmony 环境搭建要点
要在 OpenHarmony 上跑 Flutter 应用,首先要区分你用的是什么设备。我这里以 RK3568 开发板为例,因为这是目前社区里最常见、资料最多的 OpenHarmony 硬件平台。
环境准备分几块:
- Flutter SDK:需要下载针对 OpenHarmony 定制的 Flutter SDK 版本,不能直接用官方 Flutter SDK。这个定制版通常以 flutter-ohos 或者类似名字发布,里面包含了 OpenHarmony 的 platform 实现。
- DevEco Studio:OpenHarmony 的 IDE,用来编译 hap 包、管理 SDK、连接设备。
- OpenHarmony SDK:通过 DevEco Studio 的 SDK Manager 下载,包含 API 版本对应的 platform 和工具链。
- RK3568 开发板固件:建议直接烧录官方发布的 OpenHarmony 标准系统镜像,版本尽量和 SDK 匹配。
这里有个很多新人会绕弯的点:RK3568 的 OpenHarmony 固件和镜像版本一定要对齐,比如你用的 OpenHarmony SDK 是 4.0 Release,开发板固件也最好是同版本的 release 版本,否则 d.ts 定义的 API 和运行时不一致,调试过程会非常折磨人。
装好之后用 flutter doctor 检查环境,注意看 OpenHarmony 那一栏是否识别正常。我第一次跑的时候 flutter doctor 一直不识别开发板,后来发现是 USB 调试线质量问题,换成带数据功能的 Type-C 线就好了。
2.2 在 pubspec.yaml 里引入 jose
jose 在 pub.dev 上对应的包名一般直接叫 jose 或者 flutter_jose。我用的是 jose 这个纯 Dart 实现,它的版本更新比较活跃,API 设计也相对稳定。在 pubspec.yaml 里添加依赖:
yaml复制dependencies:
jose: ^0.3.4
引入之后执行 flutter pub get,然后写个小 demo 验证一下库能不能正常工作:
dart复制import 'package:jose/jose.dart';
void main() {
final key = JsonWebKey.fromJson({
'kty': 'oct',
'k': 'AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1qS0gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr1Z9CAow',
});
final token = JsonWebSignature.sign(
JsonWebToken(
claims: {'sub': 'test-user', 'iat': DateTime.now().millisecondsSinceEpoch ~/ 1000},
).toJson(),
key: key,
algorithm: 'HS256',
).toJwt();
print(token);
}
这段代码就是最小可行的 JWS 签发流程。如果你能跑出一串三段式 Token 字符串说明环境没问题,如果报错则大概率是 crypto 依赖在 OpenHarmony 平台上不兼容,下面我会专门说这个坑。
2.3 RK3568 有很多设备树到底咋选
这问题其实不只出现在 jose 接入上,而是 Flutter for OpenHarmony 开发前期最容易卡住的地方。RK3568 的 OpenHarmony 源码里通常有多个设备树文件,你可以这么判断:
- 先看开发板型号。市面上的 RK3568 板子五花八门,有 Rockchip 官方 EVB、有各种开源硬件项目出的板子,每一块的电源管理、HDMI 输出、以太网配置都可能不同。
- 优先选和你板子最接近的 dts。如果是官方 EVB,直接选 rk3568-evb.dts 这类文件;如果是第三方板子,厂商一般会在内核源码里附带对应的 dts,别自己乱改。
- 用设备树覆盖机制而不是直接改源码。把 GPIO、I2C、PWM 这类差异放在 overlay dts 里,烧录验证会方便很多。
另外提一句,如果你只是做 Flutter 应用层开发,其实不太需要自己编译内核。直接在 VAB 分包工具里选用固件自带的 dts 就行,大部分时候官方镜像已经适配好了。真正需要自己改设备树的是做硬件定制或者外设驱动开发的人,这块水比较深,建议先从应用层切入,跑通再考虑深层定制。
3. 核心场景实操:签发、验证、加解密
3.1 JWT 签发与服务端验证
实际项目中,JWT 签发通常发生在服务端,客户端主要负责存储和发送。但有时候受限于网络环境,我们需要在客户端做离线验证,或者把这段逻辑做成纯本地工具,因此客户端用 jose 来签发 JWT 也有实用价值。
用 jose 签发 JWT 的套路是这样的:
dart复制// 生成或加载 JWK
final key = JsonWebKey.fromJson({
'kty': 'oct',
'k': base64Url.encode(List.generate(32, (_) => Random.secure().nextInt(256))),
});
// 构造 claims
final claims = <String, dynamic>{
'iss': 'your-service',
'sub': 'user-123',
'aud': 'your-app',
'exp': DateTime.now().add(Duration(hours: 1)).millisecondsSinceEpoch ~/ 1000,
'iat': DateTime.now().millisecondsSinceEpoch ~/ 1000,
'role': 'admin',
};
// 签发 JWS
final jwt = JsonWebSignature.sign(
JsonWebToken(claims: claims).toJson(),
key: key,
algorithm: 'HS256',
).toJwt();
print(jwt!);
验证侧也简单:
dart复制final JsonWebToken token = JsonWebToken.parse(jwtString);
final signature = JsonWebSignature.fromCompactSerialization(jwtString);
final verified = signature.verify(key);
if (verified) {
final claims = token.claims;
final exp = claims['exp'] as int?;
if (exp != null && (exp * 1000) < DateTime.now().millisecondsSinceEpoch) {
// 过期处理
}
}
注意这里有个细节:JsonWebToken.parse 只负责解析,它不会自动帮你验证签名,签名验证必须通过 JsonWebSignature 的 verify 方法显式完成。很多新手在这上面栽过跟头,以为 parse 成功就等于 Token 合法。
签发时的 exp、iat 单位是秒,不是毫秒。Dart 的 DateTime.now().millisecondsSinceEpoch 拿到的是毫秒,直接塞进 claims 会导致过期时间比预期大一千倍,看起来像没生效。要手动除以 1000 取整。
3.2 JWE 加密敏感数据注意事项
JWE 适合加密那些既有保密需求又有完整性校验的数据。实操中我用得最多的是用 RSA 公钥加密对称密钥,然后用对称密钥加密业务数据。jose 支持这种混合加密模式,而且 API 封装得比较友好。
以 RSA-OAEP-256 + A256GCM 为例:
dart复制// 服务端下发的 RSA 公钥
final rsaPublicKey = JsonWebKey.fromJson({
'kty': 'RSA',
'n': '...',
'e': 'AQAB',
});
// 构造 JWE 加密
final jwe = JsonWebEncryption.encrypt(
utf8.encode('sensitive data here'),
publicKey: rsaPublicKey,
algorithm: 'RSA-OAEP-256',
encryption: 'A256GCM',
);
final compact = jwe.toCompactSerialization();
print(compact);
解密侧:
dart复制final jwe = JsonWebEncryption.fromCompactSerialization(compact);
final decrypted = jwe.decrypt(privateKey);
final plaintext = utf8.decode(decrypted);
这里有几个非常容易踩的坑:
- RSA 密钥长度至少 2048 位,如果服务端下发的是 1024 位公钥,部分算法会被 OpenHarmony 的 crypto 组件拒绝,报错信息还很隐晦。
- A256GCM 需要的密钥长度正好 32 字节,如果底层密钥管理算法给出的密钥长度不够,jose 会内部生成一个随机密钥来包裹,但在某些平台上随机源受限会崩。遇到这种情况优先检查系统随机数服务是否正常。
- JWE 的 Compact 序列化是五段式:Header.EncryptedKey.IV.Ciphertext.Tag。有时候调试时为了方便会想用 JSON 序列化,但 Compact 是传输最通用的格式,建议生产环境统一用 Compact。
3.3 JWS 签名防篡改
JWS 的签名场景最常见的是防篡改。比如设备上报的数据,服务端需要确认数据确实来自你控制的 App,而不是有人伪造的请求。这种情况下我一般用非对称算法(RS256 或 ES256),私钥留在服务端签名,公钥放在客户端验签。反过来,客户端往服务端发数据时也可以用私钥签名、服务端公钥验签,但私钥放在客户端风险很大,建议仅在重安全场景配合安全存储来使用。
实际代码:
dart复制final key = JsonWebKey.fromJson({
'kty': 'RSA',
'n': '...',
'e': 'AQAB',
'd': '...',
'p': '...',
'q': '...',
'dp': '...',
'dq': '...',
'qi': '...',
});
final payload = {'deviceId': 'dev-001', 'timestamp': 1700000000, 'value': 3.14};
final jws = JsonWebSignature.sign(
utf8.decode(jsonEncode(payload).codeUnits),
key: key,
algorithm: 'RS256',
);
final compact = jws.toCompactSerialization();
这段代码容易遇到的坑是 payload 类型。JsonWebSignature.sign 对不同类型的 payload 处理方式不同,签名 String 和签名 Map 最终产生的 Token 结构会有差异。我在项目里统一用 jsonEncode + utf8.decode(codeUnits) 转成字符串再传,保证序列化结果稳定。
验证端从 Header 里拿 alg,再根据 alg 选对应密钥类型。jose 的 verify 方法内部做得比较聪明,只要密钥类型和算法匹配就能验,不需要你在业务代码里手动判断算法。
3.4 密钥管理与算法选型
加密库选型只是第一步,密钥怎么存、怎么换才是安全的关键。我在实战中总结了几条经验:
- HMAC 对称密钥(HS256)只适合服务端之间通信,不建议在客户端使用。因为对称密钥一旦下发到客户端,反编译 APK 或 HAP 就能拿到,等于白加密。
- 客户端优先用 ES256(P-256 椭圆曲线)或者 RS256(RSA 2048)。ES256 密钥体积小、性能好,适合移动端;RS256 兼容性最广,服务端生态成熟,但密钥长、签名慢。
- OpenHarmony 设备上的私钥建议走系统级安全存储能力,不要硬编码在代码里。jose 本身不做存储管理,但你可以用它解析出 JsonWebKey 之后,把私钥敏感字段交给平台的 KeyStore 托管。
- 密钥轮换要在协议层预留支持。最简单的方式是在 JWT Header 里加 kid 字段,服务端和客户端维护一个 keyId 到 JWK 的映射关系,轮换时新老密钥并行一段时间,等所有客户端都切到新密钥后再下线旧密钥。
4. jose 库源码机制与鸿蒙适配深度解析
4.1 jose 的分层设计与依赖关系
jose 这个库的内部结构值得单独拉出来讲一讲,因为只有理解了它的分层,遇到报错时你才知道去改哪里。
它的核心分层大概是这样:
- JsonWebKey:密钥对象,区分 oct(对称)、RSA、EC 三种类型。
- JsonWebSignature:签名与验签,支持 Compact 和 JSON 两种序列化。
- JsonWebEncryption:加密与解密,支持密钥管理算法 + 内容加密算法的组合。
- JsonWebToken:基于前两者的高层封装,主要处理 Claim 的解析与有效性判断。
- JsonWebAlgorithm:底层算法注册表,每个算法名都对应一个具体实现类。
底层依赖方面,jose 默认使用 package:crypto 和 package:cryptography 这两个 Dart 生态里的加密库。cryptography 有纯 Dart 实现,也可以在 Flutter 里通过 dart:ffi 调用系统级加密能力。在 OpenHarmony 上,cryptography 的纯 Dart 后端是默认选择,这意味着大部分算法都能跑,但性能上比直接调 Native 的实现要差一些。
4.2 随机数与哈希:Flutter 侧与 OS 侧的协作
加密库里最容易出兼容问题的就是随机数生成。jose 在生成密钥、IV、Nonce 的时候会调用 Random.secure(),这在 Dart VM 上会使用系统的安全随机源。OpenHarmony 的 Flutter 引擎在理论上提供了对应实现,但在某些定制 ROM 或者早期版本上,Random.secure() 可能返回弱随机源或者直接抛异常。
我在 RK3568 上遇到过的现象是:调用 JsonWebKey 生成 RSA 密钥时偶尔报 secure random not available 的错误。排查了半天,最后发现是 Flutter 引擎版本和 OpenHarmony 系统版本不匹配,升级到配套的定制版 Flutter SDK 后就正常了。
另外哈希算法也有讲究。jose 内部在做 PBKDF2、HKDF 等派生操作时,会走 cryptograph 库的哈希实现。如果算法注册表里没有某个哈希,可能体现在"Unsupported algorithm"之类的报错上。这时候优先检查 jose 版本以及 cryptograph 版本,不要自己魔改库源码。
4.3 遇到的不兼容点与适配策略
我把自己踩过的不兼容问题列了一个清单,方便你对照排查:
- 问题一:cryptography 库的 WebCrypto 后端在 OpenHarmony 上没法用。因为 OpenHarmony 没有浏览器环境里的 crypto.subtle API,如果你手动指定了 WebCrypto 后端,运行会直接报错。解决办法是显式使用纯 Dart 后端:Cryptography.instance = DartCryptography()。
- 问题二:EC 密钥的 ASN.1 编解码差异。在 OpenHarmony 上从系统 KeyStore 导出的 EC 公钥格式和其他平台可能不一样,直接塞给 jose 会解析失败。建议统一走 JWK 格式中转,先转成 JWK 再交给 jose 使用。
- 问题三:JSON 序列化的 Map 顺序问题。Dart 的 Map 默认是无序的,而 JWS 和 JWE 的 Compact 序列化对 Header 的顺序有一定要求。jose 内部处理得比较稳妥,但如果你自己手动拼 JWT 字符串再交给 jose 验签,很容易由于 Header 顺序不同导致验签失败。尽量不要手动拼 Token,一律用库的 API 生成。
5. 常见问题与排查技巧实录
5.1 环境层问题速查表
我根据最近两个月在 OpenHarmony 上跑 Flutter 项目的经历,整理了一份环境层问题的速查表。这些问题的共性在于:它们其实和 jose 没直接关系,但任何一个出了毛病都会让你误以为是加密库的问题。
| 现象 | 可能原因 | 解决方式 |
|---|---|---|
| flutter doctor 找不到设备 | USB 线不支持数据,或 USB 调试未打开 | 换数据线,在开发者模式里开启 USB 调试 |
| 编译 hap 报签名错误 | OpenHarmony SDK 签名证书配置不对 | 在 DevEco Studio 里重新配置自动签名 |
| 运行 app 时白屏退出 | Flutter 引擎和 OpenHarmony 版本不匹配 | 统一升级到官方配套的 Flutter SDK 和系统镜像 |
| JIT 模式无法调试 | 设备镜像没开 debug 权限 | 使用 release 镜像或者带 debug 的开发镜像 |
| 找不到某个 API 定义 | SDK 版本过低 | 升级 OpenHarmony SDK 到 4.0+ |
5.2 jose 运行时问题速查表
运行时问题比环境问题更值得记录,因为这些问题在 Android 上基本不会出现,只有在 OpenHarmony 跑起来才暴雷。
| 现象 | 可能原因 | 解决方式 |
|---|---|---|
| Random.secure() 抛异常 | Flutter 引擎的随机源初始化失败 | 升级 Flutter SDK,重启设备 |
| 验签一直返回 false | 密钥格式不对,比如把私钥当公钥传 | 确认 JWK 字段完整,kty 与算法匹配 |
| JWE 解密报 Mac check failed | 密文被篡改,或 Tag 长度不对 | 重新获取密文,检查传输过程是否被截断 |
| JWT 过期判断异常 | exp 单位是秒,你用了毫秒 | 除以 1000 再比较 |
| 生成 RSA 密钥特别慢 | 随机源质量差或设备性能低 | 优先用 EC 算法,或者提前预生成密钥 |
| Flutter web 模式下字体变小 | web 渲染的字体缩放因子不一致 | 设置 textScaler 统一缩放策略 |
5.3 独家避坑:设备树、字体、库版本
除开上面列的环境和运行时问题,还有几个我在实际项目里踩得比较深、且网上资料很少的坑,单独拿出来说。
第一个是设备树选择的连带影响。RK3568 多个设备树文件之间不只是外设配置的差异,有时候还会影响图形显示和 GPU 加速能力。如果你的 Flutter 应用界面出现渲染异常或者动画卡顿,先看看固件里的 dts 是否和你板子的 GPU 型号匹配。Rockchip 官方的 rk3568-evb 设备和某些第三方的 RK3568 板子在 GPU 频率、内存映射上可能不一样,这些底层差异会直接影响 Flutter 的 Impeller 或 Skia 渲染。
第二个是 Flutter 字体的 16px 问题。这个和 jose 没关系,但在 OpenHarmony 上跑 Flutter 很容易遇到:Text 组件的字体大小在真机上显示会比 Android 小一两号。这是 Flutter 引擎在 OpenHarmony 上对默认字体密度处理不一致导致的。解决方式是在 MaterialApp 外层设置 textScaler: TextScaler.linear(1.0),或者统一用 MediaQuery 控制。
第三个是 jose 版本锁定的问题。jose 库的版本迭代比较快,0.3.x 和 0.4.x 之间的 API 有 breaking changes。我在一次升级中遇到 JsonWebSignature.sign 的 key 参数类型变了,导致编译直接报错。建议在 pubspec.yaml 里锁定精确版本,或者至少锁定 minor 版本范围,避免无意中升级到不兼容的 API。
6. 性能与最佳实践建议
6.1 RSA 与 EC 的性能差异
在 OpenHarmony 设备上做签名和验签,性能不是恒定不变的。我用 RK3568 实测过一组数据,给各位一个参考:
- RS256 签名(2048 位密钥):单次签名大约在 8-12ms,验签 1-2ms。
- ES256 签名(P-256 曲线):单次签名大约 3-5ms,验签 3-5ms。
- HS256 签名(32 字节密钥):单次签名小于 1ms,验签小于 1ms。
如果只是客户端验签服务端签发的 Token,RS256 和 ES256 都够用。但如果是设备端频繁签名上报数据,或者要求低功耗,ES256 的优势会更明显。我现在的做法是默认用 ES256,只有在服务端证书体系强制要求 RS256 时才降级到 RS256。
6.2 密钥轮换与过期策略
密钥轮换这件事,很多团队不到密钥泄露那一刻不会重视。但换个角度想,如果每次安全审计都要手动更新客户端内置的公钥,运维成本极高,而且可能存在旧版本 App 还在使用旧公钥的情况。
比较干净的方案是在启动时拉取 JWKS 端点。jose 提供了 JsonWebKeySet 相关的支持,你可以从服务端拿到一份包含多个密钥的 JWKS JSON,然后根据 JWT Header 里的 kid 自动选择正确的公钥验签。客户端本地缓存这份 JWKS,设置合理的刷新时间,比如 24 小时拉取一次。这样密钥轮换时服务端只需要往 JWKS 里加新密钥,所有客户端在下次刷新后就能自动使用新公钥。
Token 本身的过期策略也建议按照安全等级划分:普通业务 Token 15-30 分钟过期,高敏感操作短一些(比如 5 分钟),刷新令牌可以长一些但必须走独立的加密通道。JWT 里的 exp 只是防重放的第一道门槛,真正的高安全场景还需要配合请求时间戳和随机 nonce 来防止重放攻击。
6.3 日志与安全合规
调试加密逻辑时,最诱人的做法就是把 Token 或者解密后的明文直接打印到日志里。这绝对是大忌。我在开发阶段就吃过亏,打印了 JWE 解出来的密文,结果完整业务数据被同事在远程日志里看到了。
正确做法是:
- 日志只打印 Token 前三段的一部分,比如 Header 的 alg 和 kid。
- 解密后的明文只保留在内存里,用完后立刻置空对象的引用。
- 敏感变量名不要出现 password、secret 这类字眼,用 key、cfg 之类的中性词替代。
- 发布包开启代码混淆,对 Flutter 侧做字符串加密保护,避免轻易被反编译提取常量。
OpenHarmony 系统本身对应用权限和数据安全有合规要求,申请权限时要注意最小化原则,用不到的权限坚决不申请。如果 App 涉及个人敏感信息加密,建议组织安全评审后再上线。
7. 写在最后的个人体会
jose 这套库给我的整体印象是:覆盖面广、API 统一、跨平台能力强,但在 OpenHarmony 上落地需要一定的适配功夫。这个功夫主要不在库本身,而在你对底层运行环境的理解有多深。熟悉了 Dart 加密库的依赖机制、熟悉了 Flutter for OpenHarmony 的引擎特性之后,再回头看 jose 的报错就清晰多了。
我个人的建议是,如果你正在规划 Flutter for OpenHarmony 项目的安全方案,先把服务端和客户端的数据流画清楚,哪些数据需要签名、哪些数据需要加密、密钥怎么轮换,这些问题想明白了再动手写代码。技术选型反而是最简单的一步。
最后分享一个小技巧:在引入 jose 之后,先用一个最小 Demo 把 HS256 的 JWS 流程跑通,再逐步切换到非对称算法和 JWE。这样即使遇到问题,你也能快速定位是算法问题、密钥问题还是平台兼容问题。祝你在 OpenHarmony 上少踩坑,多上线。
