Expo 标准 Web Crypto Polyfill:expo-standard-web-crypto 的 getRandomValues 实现与使用指南
Expo 标准 Web Crypto Polyfillexpo-standard-web-crypto 的 getRandomValues 实现与使用指南【免费下载链接】expoAn open-source framework for making universal native apps with React. Expo runs on Android, iOS, and the web.项目地址: https://gitcode.com/GitHub_Trending/ex/expoexpo-standard-web-crypto是 Expo 生态中面向 W3C Crypto API 的部分实现polyfill其核心价值在于让 Expo 项目能够以标准 Web API 的形式获取密码学安全的随机数。它把浏览器中的crypto.getRandomValues()语义桥接到 Expo 的原生安全随机源是编写跨端Android / iOS / Web通用加密逻辑时弥合平台差异的关键一环。读完本文你将掌握该包的安装方式、两种引用形态、底层实现原理、边界校验规则以及测试验证方法并能在自己的 Expo 应用中直接落地使用。一、包定位W3C Crypto API 的部分实现按官方 README 的定位该包是A partial implementation of the W3C Crypto API for ExpoExpo 下的 W3C Crypto API 部分实现。目前它只实现了 W3C 规范中的Crypto#getRandomValues()一个方法其余如subtle加解密、签名、摘要等并未覆盖——需要更完整 Web Crypto 能力时应结合expo-crypto的原生 API 或其他方案。从源码结构看整个包非常精简核心文件只有两个src/index.ts定义Crypto类、默认导出实例、polyfillWebCrypto()全局注入函数src/getRandomValues.tsgetRandomValues的完整实现与降级回退逻辑。packages/expo-standard-web-crypto/ ├── src/ │ ├── index.ts # Crypto 类与 polyfillWebCrypto │ ├── getRandomValues.ts # getRandomValues 核心实现 │ └── __tests__/ │ ├── getRandomValues-test.ts │ └── index-test.ts ├── README.md ├── package.json └── tsconfig.jsonpackage.json中声明该包sideEffects: false说明导入它是纯副作用无关的Tree Shaking 时可以安全地按需摇树优化同时它把expo-crypto列为peerDependenciesworkspace 版本这是使用本包的前提。二、安装先装 expo-crypto再装本包README 明确指出本包依赖expo-crypto必须先行安装。expo-crypto提供了底层真正的密码学安全随机数生成能力Android / iOS 原生桥接 Web 端基于全局crypto本包是在其之上的标准 API 封装。在 managed Expo 项目中推荐用 Expo 内置的版本匹配命令安装expo-crypto参见 expo-crypto 的安装文档npx expo install expo-crypto然后安装本包npm install expo-standard-web-crypto对于裸 RNbare React Native工程同样需要先确保expo包及 expo-modules 已按 expo-crypto 说明 正确配置iOS 侧在安装后还需执行npx pod-install完成原生依赖链接。三、两种使用方式局部实例与全局注入README 提供了两种使用形态分别应对显式引入与兼容旧代码两类场景。方式一导入 Crypto 实例import crypto from expo-standard-web-crypto;此时crypto是一个可直接调用getRandomValues()的对象const bytes new Uint8Array(16); crypto.getRandomValues(bytes); console.log(随机字节:, bytes);方式二全局定义cryptoimport { polyfillWebCrypto } from expo-standard-web-crypto; polyfillWebCrypto(); // crypto 现在已全局定义polyfillWebCrypto()适合那些直接引用全局crypto的第三方库或既有代码。从 src/index.ts 的实现可以看到它只在typeof crypto undefined时才注入export function polyfillWebCrypto(): void { if (typeof crypto undefined) { Object.defineProperty(window, crypto, { configurable: true, enumerable: true, get: () webCrypto, }); } }即如果运行时已经存在全局crypto注入函数不会覆盖它。这也呼应了 README 中的关键约定——如果你的运行时环境已经全局定义了crypto本包会直接使用该实例而不是提供自己的实现。该逻辑同样体现在默认导出中src/index.tsconst webCrypto typeof crypto ! undefined ? crypto : new Crypto();因此在 Hermes、React Native 新架构等已内建全局crypto的环境中本包实际转发的就是宿主环境自带的实现实现了有则用之、无则补上的无缝降级。四、源码级原理getRandomValues 的完整实现4.1 Crypto 类与规范对齐src/index.ts 中的Crypto类严格对齐 W3C 规范签名接收一个ArrayBufferView并原样返回它class Crypto { getRandomValuesTArray extends ArrayBufferView(values: TArray): TArray { return getRandomValues(values); } }返回同一个数组对象原地填充是 Web Crypto 规范的重要语义测试也对此做了断言expect(result).toBe(array)见 getRandomValues-test.ts。4.2 三层输入校验src/getRandomValues.ts 在写入前执行三层校验与 W3C 规范完全对齐① 必须传参——无参数时抛出TypeErrorif (arguments.length 1) { throw new TypeError( An ArrayBuffer view must be specified as the destination for the random values ); }② 必须是整数类型数组——仅接受以下 7 种 TypedArray其余含Float32Array、普通数组、普通对象、null一律抛TypeErrortype IntegerArray | Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array | Uint8ClampedArray;③ 请求字节数不得超过 65536——超出上限抛出自定义的QuotaExceededErrorconst MAX_RANDOM_BYTES 65536; if (values.byteLength MAX_RANDOM_BYTES) { throw new QuotaExceededError( The ArrayBuffer views byte length (${values.byteLength}) exceeds the number of bytes of entropy available via this API (${MAX_RANDOM_BYTES}) ); }QuotaExceededError实现了规范要求的name QuotaExceededError与code 22QUOTA_EXCEEDED_ERR见 getRandomValues.ts。65536 字节64 KiB的单次上限与浏览器实现保持一致——需要更大随机数时应分批多次调用。4.3 优先走原生安全随机源异常时降级填充阶段getRandomValues.ts采用 try/catch 策略优先调用expo-crypto的getRandomValues一旦同步桥接方法不可用例如原生模块未正确链接则捕获异常并回退到不安全实现同时打印警告try { // NOTE: Consider implementing fillRandomBytes to populate the given TypedArray directly expoCryptoGetRandomValues(values); } catch { // TODO: rethrow the error if its not due to a lack of synchronous methods console.warn(Random.getRandomBytes is not supported; falling back to insecure Math.random); return getRandomValuesInsecure(values); }务必注意回退实现getRandomValuesInsecure基于Math.random()其源码注释明确标注这是cryptographically insecure密码学上不安全的getRandomValues.ts。它的做法是新建一个覆盖目标数组底层 buffer 的Uint8Array视图逐字节写入Math.random() * 256利用 ToUint8 的向下取整语义export function getRandomValuesInsecureTArray extends IntegerArray(values: TArray): TArray { const byteView new Uint8Array(values.buffer, values.byteOffset, values.byteLength); for (let i 0; i byteView.length; i) { byteView[i] Math.random() * 256; } return values; }因此生产环境必须确保expo-crypto正确安装并完成原生链接避免静默落入不安全路径控制台出现的Random.getRandomBytes is not supported警告应视为配置错误的信号而不是可接受的常态。五、与 expo-crypto 的调用关系本包是薄封装真正提供熵源的底层是expo-crypto。在 expo-crypto 的 Crypto.ts 中getRandomValues直接把 TypedArray 转交给原生模块ExpoCrypto.getRandomValues(typedArray)并原样返回Web 平台则在 ExpoCrypto.web.ts 中转调全局getCrypto().getRandomValues(...)。完整调用链如下你的代码 → expo-standard-web-crypto 的 Crypto.getRandomValues() → src/getRandomValues.ts校验 try/catch → expo-crypto 的 getRandomValues() [expo-crypto/src/Crypto.ts](https://link.gitcode.com/i/d5a4084396b1d52f37135d108eae7fc0) → 原生ExpoCrypto.getRandomValues() Android/iOS 桥接 → WebglobalThis.crypto.getRandomValues() [ExpoCrypto.web.ts](https://link.gitcode.com/i/acff762a891f8b4a6bdd0235416111ea) → 失败降级getRandomValuesInsecure() Math.random不安全由此可见本包在架构中的角色统一入口 规范校验 异常兜底而把平台差异隔离在expo-crypto一层。六、测试验证边界行为有据可查包内自带 Jest 测试preset 为expo-module-scripts通过npm test即可运行测试文件 getRandomValues-test.ts 覆盖了以下关键契约7 种整数类型数组均被正确填充且返回的是同一个数组实例非法输入抛TypeError无参数、普通数组[]、普通对象{}、Float32Array、null全部被拒绝超限抛QuotaExceededError请求超过 65536 字节时断言error.name QuotaExceededError且error.code 22降级实现同样能填充所有整数数组。测试通过 mocksrc/mocks/expo-crypto.ts模拟底层getRandomValues验证了本包对expo-crypto的委托调用关系断言Crypto.getRandomValues恰好被调用 1 次且传入同一数组见测试第 23-24 行。七、使用建议与注意事项先装好 expo-crypto它是本包的peerDependencies缺失会导致运行时降级到Math.random不安全路径。优先使用显式导入import crypto from expo-standard-web-crypto语义清晰、利于 Tree ShakingsideEffects: false仅在必须兼容全局crypto的旧库时使用polyfillWebCrypto()。遵守 64 KiB 单次上限大块随机数请分批调用单次超限会抛QuotaExceededError。只传整数类型数组Float32Array、普通数组等都会被TypeError拒绝这是规范行为而非缺陷。生产环境留意降级警告若控制台出现falling back to insecure Math.random应立即排查原生模块链接问题切勿将警告静默吞掉。需要更完整 Web Crypto 能力时如subtle、digest、密钥生成本包仅覆盖getRandomValues可结合expo-crypto提供的哈希digestStringAsync、digest等原生 API 组合使用见 expo-crypto/src/Crypto.ts 的摘要实现。八、小结expo-standard-web-crypto以极小的代码面解决了跨端加密随机数的标准 API 缺口对外提供 W3C 语义的crypto.getRandomValues()对内委托expo-crypto的原生安全随机源并内置严格的规范校验、64 KiB 上限与异常降级。理解其实现index.ts、getRandomValues.ts和测试契约getRandomValues-test.ts你就能在 Expo 项目中写出既符合 Web 标准、又在原生端安全可靠的随机数逻辑。【免费下载链接】expoAn open-source framework for making universal native apps with React. Expo runs on Android, iOS, and the web.项目地址: https://gitcode.com/GitHub_Trending/ex/expo创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联
返回资讯列表 →