Skip to content

feat(core): use @noble/ciphers/aes for mobile compat#152

Merged
andrascodes merged 1 commit into
mainfrom
andras/feat-core-use-noble-ciphers-aes-for-mobile-compat
May 5, 2026
Merged

feat(core): use @noble/ciphers/aes for mobile compat#152
andrascodes merged 1 commit into
mainfrom
andras/feat-core-use-noble-ciphers-aes-for-mobile-compat

Conversation

@andrascodes
Copy link
Copy Markdown
Collaborator

@andrascodes andrascodes commented May 5, 2026

This PR is part of a stack created with Aviator.

Make HPKE seal work in non-WebCrypto runtimes (React Native)

Summary

The OTP_V3 HPKE seal in packages/core/src/utils/hpke.ts used crypto.subtle.importKey / crypto.subtle.encrypt for AES-256-GCM. React
Native's Hermes runtime has no Web Crypto, so any RN consumer hits Cannot read property 'importKey' of undefined during auth({ type: 'otp', mode: 'verifyOtp' }).

This swaps the AES-GCM step for the pure-JS gcm from @noble/ciphers, matching the rest of the file (already on @noble/curves +
@noble/hashes).

Changes

  • packages/core/package.json — add @noble/ciphers: ^2.2.0 (aligned with the existing @noble/curves / @noble/hashes v2.2.0).
  • packages/core/src/utils/hpke.ts
    • Import gcm from @noble/ciphers/aes.js.
    • Replace aesGcmSeal (Web Crypto, async) with a one-liner over gcm(key, nonce, aad).encrypt(plaintext).
    • Drop the toArrayBuffer helper (only existed to satisfy BufferSource typing for crypto.subtle).
    • hpkeSealP256 keeps its Promise return type for callsite stability, even though seal is now synchronous.

Wire-format compatibility

@noble/ciphers's gcm returns ciphertext || tag (16-byte tag appended) — identical to crypto.subtle.encrypt with tagLength: 128 and to
Turnkey's Go Sealer.Seal. AAD shape (enc || pkR) and HPKE info ("turnkey_hpke") are unchanged, so the sealed bundle is bit-identical to
the previous implementation.

Tests

All existing HPKE / encryptOtpAttempt tests pass unchanged (10 tests across hpke.test.ts and encryptOtpAttempt.test.ts), including
round-trip decryption via the reference impl — confirming byte-level compatibility with the prior Web Crypto path.

Compatibility

  • Browsers / Node: behavior unchanged.
  • React Native (Hermes): now works without polyfills.
  • No public API changes; no consumer code changes required.

Copy link
Copy Markdown
Collaborator

@SahilVasava SahilVasava left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@andrascodes andrascodes merged commit de3b369 into main May 5, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants