React Native for OpenHarmony 实战:三方库 react-native-crypto-js 的鸿蒙化适配指南
react-native-crypto-js 是 crypto-js 在 RN 生态里的一个常用入口包:MD5、HMAC-MD5、AES 口令式加解密,做本地数据摘要、接口签名、配置加密时会用到。
它和"需要把 iOS/Android 实现换成鸿蒙实现"的那类库不一样——它是纯 JavaScript,没有原生代码,所以在鸿蒙上不需要原生适配。但这个交付版本有一个值得单独讲的点:它确实改过 JS。
上游 npm 包导出了 HmacMD5,可它一调用就抛 TypeError —— 因为打包时把 HMAC 依赖的内部模块裁掉了。交付版用 CryptoJS 已有原语按 RFC 2104 把这段实现补齐了。
所以本文要讲清四件事:怎么判断一个库"要不要原生适配"、上游那个 bug 长什么样、交付版的补丁怎么验证、以及这个包实际支持哪些算法(不能按 README 猜)。
环境准备:本文不重复环境搭建步骤。RNOH(React Native for OpenHarmony)开发环境的完整配置见官方开发者指南:
https://atomgit.com/CPF-RN/docs/blob/main/开发者指南/02-搭建准备/环境初始化.md
一、先说结论:不需要原生适配,但需要一处 JS 修复
| 项 | 结论 |
|---|---|
| 需要原生适配吗 | ❌ 不需要(无 harmony/、无原生代码、无依赖、无 harmony.autolinking) |
| 需要 HAR / ohpm / autolinking / 权限吗 | ❌ 都不需要 |
| 需要 JS 层修复吗 | ✅ 需要 —— 上游 bundle 的 HmacMD5 一调用就抛 TypeError |
"不需要原生适配"和"不需要动代码"是两件事。 一个纯 JS 库也可能因为打包裁剪、平台分支、历史 bug 而在运行时不可用——这类问题不解决,接进来照样跑不起来。
二、判定过程:三步判断一个 RN 库要不要鸿蒙原生适配
这个方法在选库阶段就能用,不用先装进来:
第一步:看 package.json 有没有 harmony 字段
npm view <包名> harmony --json
有 harmony.autolinking(ohPackageName / etsPackageClassName / cppPackageClassName / cmakeLibraryTargetName 那四个名字)的,一定是带原生实现的包,必须走 link-harmony + ohpm + hvigor。
react-native-crypto-js 的情况:
$ npm view react-native-crypto-js version main dependencies --json
{ "version": "1.0.0", "main": "CryptoJS.js" } # 无 harmony、无 dependencies
第二步:看仓库里有没有 harmony/
$ git clone https://atomgit.com/oh-react-native/react-native-crypto-js.git
$ ls react-native-crypto-js
CryptoJS.js package.json LICENSE
README.OpenHarmony.md README.OpenHarmony_CN.md
spec.json RN_react-native-crypto-js+代码检查报告.md __tests__/
没有 harmony/、没有 src/ —— 全部实现就是根目录那一个 CryptoJS.js(124 行的压缩 bundle)。
第三步:读代码里有没有原生调用或平台分支
搜三个关键词就够了:
NativeModules/TurboModuleRegistry—— 有的话在调原生Platform.OS—— 有的话在按平台分叉行为requireNativeComponent—— 有的话是原生视图
CryptoJS.js 里一个都没有,纯字符串与位运算。
spec.json 也把性质写明了:
{
"implementation": "pure JavaScript; no native module or HAR required",
"upstreamCommit": "f9bf05dbc6f92400f53204776ad968d20d305ac2"
}
一个容易误判的点:包里有
android/或ios/目录,不代表"有原生实现"。很多库把平台工程放进包里但实际不参与 RN 运行。判断要看有没有被 JS 侧真实调用——第一步的harmony.autolinking是最可靠的信号。
三、上游那个 bug:导出了,却一调就炸
先复现:
const CryptoJS = require('react-native-crypto-js'); // npm 上游 1.0.0
typeof CryptoJS.HmacMD5; // "function" ← 看起来是有的
CryptoJS.HmacMD5('message', 'secret');
// TypeError: Cannot read properties of undefined (reading 'init')
同一个 bundle 的 MD5 完全正常:
CryptoJS.MD5('abc').toString();
// "900150983cd24fb0d6963f7d28e17f72"
所以问题只出在 HMAC 接线:上游打包时把 CryptoJS.algo.HMAC 这类内部模块裁掉了,却忘了把依赖它的 HmacMD5 helper 一起裁掉,于是留下一个**"导出了但一用就炸"的 API**。
这类问题为什么值得警惕? 因为它是"检查存在性通不过"的反面——你对 typeof CryptoJS.HmacMD5 === 'function' 的检查会通过,甚至做静态检查、做类型定义都不会报错。只有真的调用一次才会暴露。
四、交付版怎么修的
交付版与 npm 上游做逐字节 diff,差异只有两类:
上游 CryptoJS.js [16744 字节] SHA256 = C31A3E861F66C1EE23C207B96540B9B5D813DDEFA4E8AF11D7CAE62EAE7A4DB8
交付 CryptoJS.js [17784 字节] SHA256 = 95E43C0117E3E6AADDA6CA43ED8F2BD86F7DD14F2E44589624D87D370280CE21
1 file changed, 27 insertions(+), 9 deletions(-) # 9 行删除是版权注释去行尾空格
新增的就是 18 行 HmacMD5:
// The upstream bundle omits the internal HMAC module although it exports the
// helper. Implement the documented MD5 HMAC using the bundled primitives.
CryptoJS.HmacMD5 = function (message, secret) {
var WordArray = CryptoJS.lib.WordArray;
var Utf8 = CryptoJS.enc.Utf8;
var key = typeof secret === 'string' ? Utf8.parse(secret) : secret;
if (key.sigBytes > 64) key = CryptoJS.MD5(key);
key = key.clone();
key.clamp();
var keyWords = key.words.slice(0);
while (keyWords.length < 16) keyWords.push(0);
var innerWords = keyWords.map(function (word) { return word ^ 0x36363636; });
var outerWords = keyWords.map(function (word) { return word ^ 0x5c5c5c5c; });
var messageWordArray = typeof message === 'string' ? Utf8.parse(message) : message;
var inner = CryptoJS.MD5(WordArray.create(innerWords, 64).concat(messageWordArray));
return CryptoJS.MD5(WordArray.create(outerWords, 64).concat(inner));
};
这就是 RFC 2104 定义的 HMAC:
HMAC(K, m) = H( (K ⊕ opad) ‖ H( (K ⊕ ipad) ‖ m ) )
对照着看每一行都在做什么:
| 代码 | RFC 2104 里的含义 |
|---|---|
if (key.sigBytes > 64) key = CryptoJS.MD5(key) | 密钥长于分组长度时,先做一次摘要(MD5 的分组长度是 64 字节) |
while (keyWords.length < 16) keyWords.push(0) | 密钥补零到 64 字节(16 个字) |
word ^ 0x36363636 | ipad = 0x36 重复 |
word ^ 0x5c5c5c5c | opad = 0x5c 重复 |
内层 MD5(ipad ‖ m),外层 MD5(opad ‖ 内层) | 嵌套结构 |
它没有另造算法,而是复用 bundle 里已有的 CryptoJS.MD5 和 WordArray ——在一个被裁剪过的 bundle 里,这是最小侵入的修法。
补丁正确性怎么验
补丁是手写的,就必须独立验证。我用 Node 的 crypto.createHmac('md5') 逐例比对:
密钥长度:0, 1, 3, 4, 5, 15, 16, 20, 63, 64, 65, 80, 128, 200, 4097 字节
消息:'' / 'a' / 'message' / 'Harmony RN' / '鸿蒙 RN' / 200 字节长消息
结果:90/90 与 Node HMAC-MD5 一致
特意覆盖了两个容易实现错的边界:
- 密钥长度 64 与 65 —— 分组长度是 64,64 字节不该被摘要、65 字节必须被摘要,改错一边就会在 65 字节上露馅;
- 密钥长度 0 —— 空密钥按标准补零。
为什么不直接信那个新增的注释? 因为注释说的是"用已有原语实现文档化的 MD5 HMAC"——它是意图,不是证据。90 组独立比对才是证据。
五、能力边界:不能按 README 猜测支持
这个包有个很容易踩的预期差。上游 README 里列了 SHA 系列、PBKDF2、DES 等算法,但这个 npm 包并没有导出它们。
逐个探测 19 个名字:
| 名称 | 上游 | 交付 |
|---|---|---|
MD5 / HmacMD5 | function | function |
AES / enc / lib / mode / pad / algo | object | object |
SHA1 / SHA256 / SHA512 | undefined | undefined |
HmacSHA1 / HmacSHA256 / HmacSHA512 | undefined | undefined |
PBKDF2 | undefined | undefined |
DES / TripleDES / RC4 / Rabbit | undefined | undefined |
在 bundle 里搜关键词也印证了:SHA256、PBKDF2、DES、TripleDES、HmacSHA 出现次数都是 0,而 MD5 出现 9 次、AES 出现 2 次。
所以这个包实际只有三个能力:MD5、HmacMD5、AES。交付版因此在 README 里明确写了"不能按 README 猜测支持",并声明能力范围就是这三项。
这是很实用的一条经验:第三方库的 README 描述的是作者的意图或上游完整版的形态,而你 npm install 装到的可能是裁剪过的子集。判断一个算法能不能用,typeof 一下比读 README 可靠。
六、接入宿主:零原生接线
对照带 harmony/ 的库,这个库少了整整一排接线动作:
| 接线项 | 带原生实现的库 | react-native-crypto-js |
|---|---|---|
npm install + package.json 加依赖 | 需要 | 需要(这个躲不掉) |
react-native link-harmony | 需要 | 不需要 |
工程级 harmony/oh-package.json5 加 HAR | 需要 | 不需要 |
模块级 harmony/entry/oh-package.json5 加 HAR | 需要 | 不需要 |
harmony/entry/src/main/ets/RNOHPackagesFactory.ets 注册 Package | 需要 | 不需要 |
ohos.permission.* 权限声明 | 视库而定 | 不需要 |
metro.config.js 的 watchFolders | 需要 | 本次需要一行(原因见下) |
实测一:link-harmony 跳过了它
$ node_modules\.bin\react-native link-harmony --verbose
...
info updated 4 file(s), linked 5 libraries, skipped 1 libraries
linked 5 libraries 与加入它之前完全一样,react-native-crypto-js 不在列表里——因为它没有 harmony.autolinking 声明。
实测二:Metro 的重定向清单里也没有它
[INFO] Redirected imports to 5 harmony-specific third-party package(s):
[INFO] • <已接入的带鸿蒙实现的包> → <同名鸿蒙实现>
…
清单里没有 react-native-crypto-js。
注意:这里"不在清单里"才是对的。Metro 的这个重定向是给"有鸿蒙变体"的包准备的(把某个包名解析到它的鸿蒙实现),纯 JS 库没有鸿蒙变体可重定向,出现在清单里反而说明有问题。
实测三:模块级 oh-package.json5 一个字没动
构建照样成功,ohpm install --all 0.45 秒。
唯一需要的那一行,以及它为什么可以省
// metro.config.js
watchFolders: [
...
path.resolve(__dirname, '../react-native-crypto-js'),
],
这一行不是鸿蒙适配,而是 file: 本地依赖的通病:file: 装进 node_modules 之后是链接(Windows 上是 Junction),metro 需要一个 watchFolders 条目才认得出它的真实目录。
从 npm registry 装(装成真目录)就连这一行都不需要——真正的"零接线"。
七、验证方法:已知值向量 + 独立复算
这个库的输出是确定性的(MD5、HMAC-MD5,以及用显式 key+IV 的 AES),所以验证方式很明确:逐字节对已知值。
设备侧 100 项断言
测试页把期望值放在 cryptoVectors.json 里(由 PC 端 Node/OpenSSL 现场生成),分四组跑:
| 组 | 内容 | 断言数 | 结果 |
|---|---|---|---|
| A | MD5(7)+ HmacMD5(45)+ AES-CBC 加密/解密(12×2) | 76 | ✅ 76/76 |
| B | AES 口令模式往返、随机性、Salted__ 头、密文长度 | 5 | ✅ 5/5 |
| C | 19 个导出名的 typeof 与交付声明一致 | 19 | ✅ 19/19 |
| 合计 | 100 | ✅ 100/100 | |
| D | 上游 bundle vs 交付版对比 | 不计入 | 如实展示 |

A 组的向量设计上刻意覆盖边界:
- MD5:空串、单字符、
abc、中英文、1000 字节长文本 - HmacMD5:15 种密钥长度(0 / 1 / 3 / 4 / 5 / 15 / 16 / 20 / 63 / 64 / 65 / 80 / 128 / 200 / 4097 字节)× 3 种消息——把 HMAC 的块长边界(64)夹在中间
- AES-CBC:128/192/256 位 × 4 种明文(含空串、中文、100 字节多块),加密与解密各断言一次
AES 用显式 key + IV而不是口令,是因为口令模式每次都带随机 salt、密文不可复现;显式 key+IV 才能拿到确定值去和 OpenSSL 比对。
B 组:口令模式与密文格式
口令模式往返一致 ✅
两次加密结果不同(随机 salt)✅
密文不等于明文 ✅
密文头 8 字节 = "Salted__"(hex 53616c7465645f5f)✅
密文总长度 = 32 字节(16 字节头 + 16 字节密文块)✅
Salted__ 这个头说明它用的是 OpenSSL 兼容的口令派生格式(EVP_BytesToKey + salt)。我用库自身的 API 读这个头,不引入额外依赖:
const parsed = CryptoJS.enc.Base64.parse(ciphertext);
const head = CryptoJS.enc.Hex.stringify(
CryptoJS.lib.WordArray.create(parsed.words.slice(0, 2), 8),
); // → "53616c7465645f5f" = "Salted__"

C 组:导出能力与交付声明一致
把 19 个名字的 typeof 与交付声明逐一对照(含 11 个必须为 undefined 的名字)。断言"不存在"也是有意义的——它把交付的能力边界钉死,将来上游补包或误改都能立刻发现。

D 组:在设备上直接对比上游 bundle 与交付版
这一组是本文最有说服力的一屏。我把 npm 上游那份有 bug 的 CryptoJS.js 也拷进宿主,和设备上跑的交付版并排调用:
• 上游 npm bundle 的 HmacMD5 结果:抛错 → TypeError: Cannot read property 'init' of undefined
• 上游 npm bundle 的 MD5('abc') = 900150983cd24fb0d6963f7d28e17f72(可用)
• 交付版 HmacMD5 结果:7e0d0767775312154ba16fd3af9771a2
• 两者是否一致:否(上游不可用,交付版已修复)
这不是"我推断上游坏了",而是在同一台设备、同一个 JS 引擎上跑出来的对照结果。

PC 端独立复算
设备侧说"和期望值一致"还不够——期望值本身也要可信。所以所有期望值都由 PC 端 Node.js(底层 OpenSSL)算出,关键结论在 PC 端再复算一次:
| 检查 | 结果 |
|---|---|
上游 HmacMD5 调用 | ❌ 抛 TypeError: Cannot read properties of undefined (reading 'init') |
交付版 HmacMD5 vs Node createHmac('md5') | ✅ 90/90 一致 |
AES-128-CBC / AES-256-CBC(显式 key+IV)vs Node createCipheriv | ✅ 逐字节相同 |
MD5('Harmony RN') | ✅ b9f12de3a17ac5fb38584533d2ce5c35(与 Node 一致) |
aes-128-cbc 交付=lAUC21+ObYF3qZp45Wl3NQ3Sqkb8tOKSz8QkU1ffAww=
Node=lAUC21+ObYF3qZp45Wl3NQ3Sqkb8tOKSz8QkU1ffAww= ✓ 一致
aes-256-cbc 交付=RndHlDeJRl7ChXlsIKrF+m4SqGQeld1fE8PyuxgvZDs=
Node=RndHlDeJRl7ChXlsIKrF+m4SqGQeld1fE8PyuxgvZDs= ✓ 一致
八、真机验证
验证环境:Pura X View 模拟器,HarmonyOS 7.0.0(26.0.0) Beta2,API 26,ohos-x64。
[cryptojs-test] A. 已知值向量(MD5 / HmacMD5 / AES-CBC) -> 76/76 全部通过
[cryptojs-test] B. AES 口令模式与格式 -> 5/5 全部通过
[cryptojs-test] C. 导出能力与交付声明一致 -> 19/19 全部通过
[cryptojs-test] 口令模式密文示例:U2FsdGVkX19rwGYlEmTic2OpA/FCf9CK3hZmFzmvKok=
[cryptojs-test] 对比|上游 npm bundle 的 HmacMD5 结果:抛错 → TypeError: Cannot read property 'init' of undefined
[cryptojs-test] 对比|上游 npm bundle 的 MD5('abc') = 900150983cd24fb0d6963f7d28e17f72(可用)
[cryptojs-test] 对比|交付版 HmacMD5 结果:7e0d0767775312154ba16fd3af9771a2
[cryptojs-test] 对比|两者是否一致:否(上游不可用,交付版已修复)
设备侧行为与 PC 端完全一致 —— 这既说明"纯 JS 库不需要原生适配",也说明上游那个 bug 是打包裁剪问题,与平台无关。
编译代价:assembleHap 7 分 1 秒,HAP 从 79.99 MB 涨到 80.09 MB(约 +102 KB,其中包含两份 16.7 KB 的 bundle、27.5 KB 的向量和主 bundle 的增量)。
能力对照
| 能力 | 结果 |
|---|---|
MD5(text) | ✅ 7 组已知值一致(空串 / 单字符 / 中英文 / 1000 字节长文本) |
HmacMD5(text, key) | ✅ 45 组已知值一致(15 种密钥长度 × 3 种消息),PC 端另复算 90 组 |
AES.encrypt/decrypt(显式 key+IV) | ✅ 128/192/256 位 × 4 种明文,密文与 OpenSSL 逐字节相同 |
AES 口令模式 | ✅ 往返一致、随机 salt、OpenSSL 兼容 Salted__ 格式 |
| 导出能力 | ✅ 19 个名字的 typeof 与交付声明一致 |
| 原生接线 | ✅ 零接线(未改 oh-package.json5、未触发 autolinking) |
九、已知限制
一、只支持三个能力:MD5、HmacMD5、AES(CBC)。 上游 README 里宣称的 SHA 系列、PBKDF2、DES、TripleDES、RC4、Rabbit 在这个包里没有导出,typeof 全部是 undefined。不要按 README 规划功能。
二、AES 的口令模式用 OpenSSL 兼容格式。 密钥由口令 + 随机 salt 按 EVP_BytesToKey 派生,密文带 Salted__ 头。密钥管理与协议升级由业务负责——这个库不提供 KDF 参数选择、不提供版本协商。
三、摘要和 HMAC 是"无认证"的原语组合。 MD5 与 HMAC-MD5 本身不构成安全协议;MD5 早已不适合做抗碰撞用途,用于签名场景时应评估是否该换成更强的摘要(但本包不提供 SHA 系列)。
四、口令模式的随机数质量未评估。 实现依赖运行时的随机源;本次只验证了"两次密文不同",样本检查不等于证明随机性。
五、未测大消息吞吐。 纯 JS 实现对短文本没问题,长文本的性能未做基准测试。
六、交付版相对上游只做了两处改动。 版权注释去尾空格 + 新增 HmacMD5 实现;上游那个"导出了但缺依赖"的问题属于上游打包缺陷,本交付是在 JS 层补齐,不是改上游源码。
七、其他 ROM / 真机未验证。 适配方记录的是 OpenHarmony-7.0.0.105;本次在 HarmonyOS 7.0.0(26.0.0) Beta2 模拟器上通过。
十、常见问题
Q:这个库需要鸿蒙化适配吗?
A:不需要原生适配——它是纯 JavaScript,没有 harmony/、没有原生代码、没有依赖、没有 harmony.autolinking。但交付版确实改过 JS:补上了上游缺失的 HmacMD5 实现。所以准确说法是"不需要原生适配,但需要一处 JS 修复"。
Q:为什么 typeof CryptoJS.HmacMD5 是 function,调用却抛错?
A:因为上游打包时把 CryptoJS.algo.HMAC 这类内部模块裁掉了,但保留了对它的引用。typeof 检查、静态检查、类型定义都不会报错,只有真的调用一次才会暴露 TypeError: Cannot read properties of undefined (reading 'init')。
Q:交付版是怎么修的?会不会改坏了?
A:用 bundle 里已有的 CryptoJS.MD5 和 WordArray,按 RFC 2104 实现 HMAC-MD5(密钥超 64 字节先摘要、补零到 64 字节、ipad/opad 异或、内外双层 MD5)。正确性用 Node 的 createHmac('md5') 逐例验证:90/90 一致,覆盖密钥长度 0~4097 字节。
Q:README 里写了 SHA256、PBKDF2、DES,为什么我用不了?
A:这个 npm 包没有导出它们(typeof 全是 undefined)。README 描述的是上游完整版的形态,而你装到的是裁剪过的子集。判断某个算法能不能用,typeof 一下比读 README 可靠。
Q:为什么我在 metro.config.js 里加了一行 watchFolders?
A:这一行不是鸿蒙适配,是 file: 本地依赖的通病——file: 装进 node_modules 是链接(Junction),metro 需要 watchFolders 才认真实目录。从 npm registry 装成真目录就不需要这一行。
Q:怎么确认这个库"真的没被 autolinking 接管"?
A:两个信号:① link-harmony 输出的 linked N libraries 不应因为它增加;② Metro 的 Redirected imports to N ... 清单里不应出现它。注意这两个信号的方向——Redirected imports 是"鸿蒙变体重定向",只有带鸿蒙实现的包才该出现在里面;纯 JS 库出现在里面反而是异常。
Q:AES 的密文为什么每次都不一样?
A:口令模式下每次加密会生成随机 salt(派生密钥和 IV 用),所以同样明文 + 同样口令也会得到不同密文。这是正确行为。密文以 OpenSSL 兼容格式存储:Base64 解码后前 8 字节是 Salted__,跟着 8 字节 salt。要拿确定性密文就传显式 key + IV(本页 A 组就是这么和 OpenSSL 比对的)。
Q:AES 用的是 CBC 还是别的模式?
A:这个 bundle 里只有 CBC(配合 PKCS7 填充)。GCM、CTR 等模式未包含,也未验证。
Q:怎么确认这个交付版本是对的?
A:四层证据:① 与 npm 上游逐字节 diff,只多了注释格式和 18 行 HmacMD5;② 设备侧 100 项已知值断言全部通过(期望值由 PC 端 Node/OpenSSL 生成);③ PC 端独立复算——HMAC 90/90、AES 密文与 OpenSSL 逐字节相同;④ 把上游那份 bundle 拷进宿主做同机对比,直接看到"上游抛错 / 交付版正确"。
Q:为什么我在模拟器上编译要这么久?
A:宿主已经带有原生缓存的库,增量加一个纯 JS 库约 6~7 分钟(hvigor 会把整套流水线走一遍);全新克隆的宿主首次编译要 30~40 分钟。只改 JS 重新打包也是 6~7 分钟,所以别把 UI 微调留到最后做。
小结
这个案子有两层值得记:
第一层是"要不要适配"的判断。 三步就够了:看 package.json 有没有 harmony.autolinking、看仓库有没有 harmony/、看代码有没有原生调用。三步都无,就是纯 JS 库,能省掉整套原生接线和一个 30~40 分钟的首次编译。这个库的实际接入成本只有一行依赖(+102 KB HAP、7 分钟编译),而且从 npm 装的话连 metro.config.js 都不用改。
第二层是"不需要原生适配"≠"不需要动代码"。 上游 bundle 导出了 HmacMD5,依赖的内部 HMAC 模块却被裁掉了——typeof 是 function,一调用就 TypeError。这类问题最有欺骗性:存在性检查通不过,只有真的调用一次才会暴露。
由此还有两条方法论:
- 补丁必须独立验证,不能只看注释。 那 18 行是新写的手写实现,它的注释说明的是意图,不是证据。要证明它符合 RFC 2104,就得拿
createHmac('md5')逐例比对——而且要特意把分组长度边界(64 / 65 字节)和空密钥夹在里面,改错一边立刻露馅。 - 能力边界要实测,不能读 README。 上游 README 里列了 SHA、PBKDF2、DES,但这个包一个都没导出。第三方库的 README 描述的是作者的意图或上游完整版的形态,你装到的可能是裁剪过的子集。
最后是验证设计上的一点:把"上游 bundle"也拷进宿主、在同一台设备上并排调用,比任何"我推断上游有问题"的说明都直接。做适配时多花十分钟造一个这样的对照,比写三段解释有用。
本篇用到的库
| 项 | 内容 |
|---|---|
| 三方库 | react-native-crypto-js(上游 1.0.0,纯 JavaScript 实现) |
| 交付仓库 | https://atomgit.com/oh-react-native/react-native-crypto-js |
| 交付 TAG | 1.0.0-ohos-1.0.0 |
| 是否需要 HAR / ohpm / autolinking / 权限 | 都不需要 |
| 上游仓库 | https://github.com/imchintan/react-native-crypto-js |
| 基线 commit | f9bf05dbc6f92400f53204776ad968d20d305ac2 |
| 实际导出的能力 | MD5、HmacMD5、AES(CBC) |
| 宿主工程 | RNOH084Demo(测试页 rnAppKey = CryptoJsTestApp) |
"react-native-crypto-js": "git+https://atomgit.com/oh-react-native/react-native-crypto-js.git#1.0.0-ohos-1.0.0"
import CryptoJS from 'react-native-crypto-js';
const digest = CryptoJS.MD5('Harmony RN').toString(); // b9f12de3a17ac5fb38584533d2ce5c35
const mac = CryptoJS.HmacMD5('message', 'secret').toString(); // 7e0d0767775312154ba16fd3af9771a2
// 口令模式:每次随机 salt,密文带 OpenSSL 兼容的 Salted__ 头
const encrypted = CryptoJS.AES.encrypt('hello 鸿蒙', 'secret key 123').toString();
const text = CryptoJS.AES.decrypt(encrypted, 'secret key 123').toString(CryptoJS.enc.Utf8);
// 显式 key + IV:确定性输出,可与 OpenSSL 互操作
const ciphertext = CryptoJS.AES.encrypt(
CryptoJS.enc.Utf8.parse('HarmonyOS 鸿蒙'),
CryptoJS.enc.Hex.parse('000102030405060708090a0b0c0d0e0f'),
{iv: CryptoJS.enc.Hex.parse('101112131415161718191a1b1c1d1e1f')},
).toString();
# 换页启动测试页(force-stop 不能省,换页参数只在冷启动生效)
hdc shell aa force-stop com.rnoh084.demo
hdc shell aa start -b com.rnoh084.demo -a EntryAbility --ps rnAppKey CryptoJsTestApp
验证环境
| 项 | 版本 |
|---|---|
| React Native | 0.84.1 |
| React | 19.2.3 |
| RNOH(npm / ohpm) | @react-native-oh/react-native-harmony / @rnoh/react-native-openharmony 0.84.3 |
| Node.js | v24.14.0 |
| DevEco Studio | 26.0.0.621 |
| HarmonyOS SDK | API 26(26.0.0.32) |
| 设备 | HarmonyOS 7.0.0(26.0.0) Beta2 模拟器 Pura X View(ohos-x64) |
| 宿主 HAP 产物 | entry-default-signed.hap(80.09 MB) |
| 本次增量构建 | assembleHap 7 分 1 秒 |
| 验证规模 | 设备侧 100 项断言全通过;PC 端 HMAC 复算 90/90、AES 与 OpenSSL 逐字节一致 |
欢迎加入 CPF-RN 鸿蒙社区:https://atomgit.com/CPF-RN
React Native for OpenHarmony 组织:https://atomgit.com/oh-react-native
RN 三方库鸿蒙适配清单:https://atomgit.com/oh-react-native/rn-ohos-adaptation-overview
更多推荐




所有评论(0)