feat(sdk-api): SJCL-free v1 decrypt with temp fallback - #9508
Merged
Conversation
Contributor
pranavjain97
force-pushed
the
pranavjain/wcn-43-remove-sjcl-decrypt-pr1
branch
from
August 14, 2026 18:45
72f280a to
9c43b24
Compare
pranavjain97
marked this pull request as ready for review
August 14, 2026 18:49
pranavjain97
force-pushed
the
pranavjain/wcn-43-remove-sjcl-decrypt-pr1
branch
from
August 14, 2026 19:14
9c43b24 to
7cd08ed
Compare
danielpeng1
requested changes
Aug 14, 2026
pranavjain97
force-pushed
the
pranavjain/wcn-43-remove-sjcl-decrypt-pr1
branch
from
August 14, 2026 19:43
7cd08ed to
2fab2b3
Compare
danielpeng1
reviewed
Aug 17, 2026
danielpeng1
left a comment
Contributor
There was a problem hiding this comment.
bump the CI tests are failing
Introduces decryptV1, a native (SJCL-free) replacement for v1 envelope decrypt using node:crypto on the server and crypto-browserify via the existing webpack shim in browser bundles. Byte-for-byte compatible with SJCL's envelope format. Public decrypt() wraps the native path in a temporary SJCL fallback so callers are never blocked if native fails on an unexpected envelope shape. The fallback uses a two-engine vote to decide when to warn: - Native succeeds -> return, silent - Iter cap violation -> rethrown (preserves DoS protection) - Both engines fail -> rethrow SJCL error (mapped upstream to "incorrect password"), no warn - Native fails but SJCL succeeds -> return SJCL result + console.warn (engines disagree, real signal for the operator) This design has zero false-negative risk: any envelope shape our stricter io-ts codec rejects that SJCL can still decrypt (Scenario D), and any hypothetical native bug that produces an auth-tag-like error (Scenario E), both get rescued by the fallback. decryptV1WithCrypto accepts an injected crypto module so the browser shim test can exercise the real decrypt code with crypto-browserify instead of duplicating the CCM logic. decryptV1WithFallback is exported and accepts an injected native fn so tests can trigger the fallback path deterministically without stub frameworks. An io-ts codec enforces an iter cap of 100k on v1 envelopes up front, before any KDF work runs. BitGoAPI.decrypt() adds "Unsupported state or unable to authenticate data" to the mapping that surfaces as "incorrect password", so the error contract downstream coin packages depend on stays stable. Test coverage (222 total, all passing): - Node parity tests (aes-128/256, adata, UTF-8, >64KiB L=3, 128-bit tags, 50 randomised inputs, one representative codec rejection, tampered ct, iter cap enforcement) - Browser-shim parity tests via crypto-browserify (same shape) - Real BitGo keycard fixture assertions on both engines - Fallback behavior tests including an injected-native-fn test that triggers the SJCL-rescue path deterministically TICKET: WCN-2079
pranavjain97
force-pushed
the
pranavjain/wcn-43-remove-sjcl-decrypt-pr1
branch
from
August 18, 2026 20:28
38b82a1 to
49c9cbb
Compare
zahin-mohammad
approved these changes
Aug 19, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Introduces a native (SJCL-free) v1 decrypt path in
@bitgo/sdk-apiusingnode:cryptoon the server andcrypto-browserifyvia webpack's shim in the browser. Publicdecrypt()routes v1 envelopes through the native path with atemporary
sjcl.decryptfallback so callers are never blocked if native fails on an unexpected envelope shape.Part of the ongoing SJCL migration. Also introduces an io-ts codec that validates v1 envelope shape and bounds params before any KDF work.
Behavior
node:crypto→ SJCL fallback +console.warnon native failureTest evidence
crypto-browserifynode:crypto, andcrypto-browserifyon user + backup keys from a throwaway testnet Solana walletTest plan