Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .iyarc
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,13 @@ GHSA-qffp-2rhf-9h96
# - We only use tar for packing; low risk in terms of exploitability
# - Security exception approved
GHSA-9ppj-qmqm-q256

# Excluded because:
# - CVE-2026-4258: missing point-on-curve validation in sjcl.ecc.basicKey.publicKey()
# - Transitive dependency via @bitgo/abstract-lightning > macaroon > sjcl
# - The vulnerability is in sjcl.ecc (ECDH invalid-curve attack); macaroon only uses
# sjcl.codec, sjcl.bitArray, sjcl.misc.hmac, and sjcl.hash.sha256 — no ECC operations
# - Additionally, @bitgo/sjcl (our fork) does not include sjcl.ecc at all
# - Resolved sjcl -> npm:@bitgo/sjcl@1.0.1 in root resolutions; sjcl.ecc is absent at runtime
# - No patched version of sjcl exists upstream (first_patched_version: null)
GHSA-2w8x-224x-785m
6 changes: 3 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ COPY --from=builder /tmp/bitgo/modules/abstract-lightning /var/modules/abstract-
COPY --from=builder /tmp/bitgo/modules/sdk-core /var/modules/sdk-core/
COPY --from=builder /tmp/bitgo/modules/sdk-lib-mpc /var/modules/sdk-lib-mpc/
COPY --from=builder /tmp/bitgo/modules/sdk-opensslbytes /var/modules/sdk-opensslbytes/
COPY --from=builder /tmp/bitgo/modules/secp256k1 /var/modules/secp256k1/
COPY --from=builder /tmp/bitgo/modules/sjcl /var/modules/sjcl/
COPY --from=builder /tmp/bitgo/modules/secp256k1 /var/modules/secp256k1/
COPY --from=builder /tmp/bitgo/modules/statics /var/modules/statics/
COPY --from=builder /tmp/bitgo/modules/utxo-lib /var/modules/utxo-lib/
COPY --from=builder /tmp/bitgo/modules/blake2b /var/modules/blake2b/
Expand Down Expand Up @@ -145,8 +145,8 @@ RUN cd /var/modules/abstract-lightning && yarn link && \
cd /var/modules/sdk-core && yarn link && \
cd /var/modules/sdk-lib-mpc && yarn link && \
cd /var/modules/sdk-opensslbytes && yarn link && \
cd /var/modules/secp256k1 && yarn link && \
cd /var/modules/sjcl && yarn link && \
cd /var/modules/secp256k1 && yarn link && \
cd /var/modules/statics && yarn link && \
cd /var/modules/utxo-lib && yarn link && \
cd /var/modules/blake2b && yarn link && \
Expand Down Expand Up @@ -248,8 +248,8 @@ RUN cd /var/bitgo-express && \
yarn link @bitgo/sdk-core && \
yarn link @bitgo/sdk-lib-mpc && \
yarn link @bitgo/sdk-opensslbytes && \
yarn link @bitgo/secp256k1 && \
yarn link @bitgo/sjcl && \
yarn link @bitgo/secp256k1 && \
yarn link @bitgo/statics && \
yarn link @bitgo/utxo-lib && \
yarn link @bitgo/blake2b && \
Expand Down
5 changes: 2 additions & 3 deletions modules/sdk-lib-mpc/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,11 @@
},
"devDependencies": {
"@bitgo/sdk-opensslbytes": "^2.1.0",
"@bitgo/sjcl": "^1.0.1",
"@silencelaboratories/dkls-wasm-ll-bundler": "1.2.0-pre.4",
"@types/lodash": "^4.14.151",
"@types/node": "^24.10.9",
"@types/sjcl": "1.0.34",
"nyc": "^15.0.0",
"sjcl": "1.0.8"
"nyc": "^15.0.0"
},
"peerDependencies": {
"@silencelaboratories/dkls-wasm-ll-bundler": "1.2.0-pre.4"
Expand Down
2 changes: 1 addition & 1 deletion modules/sdk-lib-mpc/test/unit/tss/ecdsa/dklsDsg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import assert from 'assert';
import { Keyshare } from '@silencelaboratories/dkls-wasm-ll-node';
import { decode } from 'cbor-x';
import * as mpcv2KeyCardData from './fixtures/mpcv2keycarddata';
import * as sjcl from 'sjcl';
import * as sjcl from '@bitgo/sjcl';
import {
DeserializedBroadcastMessage,
DeserializedDklsSignature,
Expand Down
268 changes: 268 additions & 0 deletions modules/sjcl/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,268 @@
export = sjcl;
export as namespace sjcl;

declare namespace sjcl {
export var bitArray: BitArrayStatic;
export var codec: SjclCodecs;
export var hash: SjclHashes;
export var exception: SjclExceptions;
export var cipher: SjclCiphers;
export var mode: SjclModes;
export var misc: SjclMisc;
export var random: SjclRandom;
export var prng: SjclRandomStatic;
export var keyexchange: Record<string, unknown>;
export var json: SjclJson;
export var encrypt: SjclConvenienceEncryptor;
export var decrypt: SjclConvenienceDecryptor;

// ________________________________________________________________________

interface BitArray extends Array<number> {}

interface BitArrayStatic {
/** Array slices in units of bits. */
bitSlice(a: BitArray, bstart: number, bend: number): BitArray;

/** Extract a number packed into a bit array. */
extract(a: BitArray, bstart: number, blength: number): number;

/** Concatenate two bit arrays. */
concat(a1: BitArray, a2: BitArray): BitArray;

/** Find the length of an array of bits. */
bitLength(a: BitArray): number;

/** Truncate an array. */
clamp(a: BitArray, len: number): BitArray;

/** Make a partial word for a bit array. */
partial(len: number, x: number, _end?: number): number;

/** Get the number of bits used by a partial word. */
getPartial(x: number): number;

/** Compare two arrays for equality in a predictable amount of time. */
equal(a: BitArray, b: BitArray): boolean;
}

// ________________________________________________________________________

interface SjclCodec<T> {
fromBits(bits: BitArray): T;
toBits(value: T): BitArray;
}

interface SjclCodecs {
utf8String: SjclCodec<string>;
hex: SjclCodec<string>;
bytes: SjclCodec<number[]>;
base64: SjclCodec<string>;
base64url: SjclCodec<string>;
}

// ________________________________________________________________________

interface SjclHash {
blockSize: number;
reset(): SjclHash;
update(data: BitArray | string): SjclHash;
finalize(): BitArray;
}

interface SjclHashStatic {
new (hash?: SjclHash): SjclHash;
hash(data: BitArray | string): BitArray;
}

interface SjclHashes {
sha1: SjclHashStatic;
sha256: SjclHashStatic;
sha512: SjclHashStatic;
}

// ________________________________________________________________________

interface SjclExceptions {
corrupt: SjclExceptionFactory;
invalid: SjclExceptionFactory;
bug: SjclExceptionFactory;
notReady: SjclExceptionFactory;
}

interface SjclExceptionFactory {
new (message: string): Error;
}

// ________________________________________________________________________

interface SjclCiphers {
aes: SjclCipherStatic;
}

interface SjclCipher {
encrypt(data: number[]): number[];
decrypt(data: number[]): number[];
}

interface SjclCipherStatic {
new (key: number[]): SjclCipher;
}

// ________________________________________________________________________

interface SjclModes {
gcm: SjclGCMMode;
ccm: SjclCCMMode;
ocb2: SjclOCB2Mode;
}

interface SjclGCMMode {
encrypt(prf: SjclCipher, plaintext: BitArray, iv: BitArray, adata?: BitArray, tlen?: number): BitArray;
decrypt(prf: SjclCipher, ciphertext: BitArray, iv: BitArray, adata?: BitArray, tlen?: number): BitArray;
}

interface SjclCCMMode {
encrypt(prf: SjclCipher, plaintext: BitArray, iv: BitArray, adata?: BitArray, tlen?: number): BitArray;
decrypt(prf: SjclCipher, ciphertext: BitArray, iv: BitArray, adata?: BitArray, tlen?: number): BitArray;
}

interface SjclOCB2Mode {
encrypt(
prf: SjclCipher,
plaintext: BitArray,
iv: BitArray,
adata?: BitArray,
tlen?: number,
premac?: boolean
): BitArray;
decrypt(
prf: SjclCipher,
ciphertext: BitArray,
iv: BitArray,
adata?: BitArray,
tlen?: number,
premac?: boolean
): BitArray;
pmac(prf: SjclCipher, adata: BitArray): number[];
}

// ________________________________________________________________________

interface PBKDF2Params {
iter?: number | undefined;
salt?: BitArray | undefined;
}

interface SjclMisc {
pbkdf2(
password: BitArray | string,
salt: BitArray | string,
count?: number,
length?: number,
Prff?: SjclPRFFamilyStatic
): BitArray;
hmac: SjclHMACStatic;
cachedPbkdf2(
password: string,
obj?: PBKDF2Params
): {
key: BitArray;
salt: BitArray;
};
}

class SjclPRFFamily {
encrypt(data: BitArray | string): BitArray;
}

interface SjclHMAC extends SjclPRFFamily {
mac(data: BitArray | string): BitArray;
reset(): void;
update(data: BitArray | string): void;
digest(): BitArray;
}

interface SjclPRFFamilyStatic {
new (key: BitArray): SjclPRFFamily;
}

interface SjclHMACStatic {
new (key: BitArray, Hash?: SjclHashStatic): SjclHMAC;
}

// ________________________________________________________________________

interface SjclRandom {
randomWords(nwords: number, paranoia?: number): BitArray;
setDefaultParanoia(paranoia: number, allowZeroParanoia: string): void;
addEntropy(data: number | number[] | string, estimatedEntropy: number, source: string): void;
isReady(paranoia?: number): number;
getProgress(paranoia?: number): number;
startCollectors(): void;
stopCollectors(): void;
addEventListener(name: string, cb: () => void): void;
removeEventListener(name: string, cb: () => void): void;
}

interface SjclRandomStatic {
new (defaultParanoia: number): SjclRandom;
}

// ________________________________________________________________________

interface SjclCipherParams {
v?: number | undefined;
iter?: number | undefined;
ks?: number | undefined;
ts?: number | undefined;
mode?: string | undefined;
adata?: string | undefined;
cipher?: string | undefined;
}

interface SjclCipherEncryptParams extends SjclCipherParams {
salt: BitArray;
iv: BitArray;
}

interface SjclCipherDecryptParams extends SjclCipherParams {
salt?: BitArray | undefined;
iv?: BitArray | undefined;
}

interface SjclCipherEncrypted extends SjclCipherEncryptParams {
kemtag?: BitArray | undefined;
ct: BitArray;
}

interface SjclCipherDecrypted extends SjclCipherEncrypted {
key: BitArray;
}

interface SjclConvenienceEncryptor {
(
password: BitArray | string | undefined,
plaintext: string | undefined,
params?: SjclCipherEncryptParams,
rp?: SjclCipherEncrypted
): string;
}

interface SjclConvenienceDecryptor {
(
password: BitArray | string | undefined,
ciphertext: SjclCipherEncrypted | string | undefined,
params?: SjclCipherDecryptParams,
rp?: SjclCipherDecrypted
): string;
}

interface SjclJson {
defaults: Required<SjclCipherParams>;
encrypt: SjclConvenienceEncryptor;
decrypt: SjclConvenienceDecryptor;
encode(obj: object): string;
decode(obj: string): object;
}
}
1 change: 1 addition & 0 deletions modules/sjcl/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"version": "1.0.1",
"description": "fork of Stanford Javascript Crypto Library",
"main": "sjcl.min.js",
"types": "index.d.ts",
"author": "BitGo SDK Team <sdkteam@bitgo.com>",
"license": "(BSD-2-Clause OR GPL-2.0-only)",
"repository": {
Expand Down
2 changes: 1 addition & 1 deletion modules/web-demo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,14 @@
"@bitgo/sdk-core": "^36.35.0",
"@bitgo/sdk-lib-mpc": "^10.9.0",
"@bitgo/sdk-opensslbytes": "^2.1.0",
"@bitgo/sjcl": "^1.0.1",
"@bitgo/statics": "^58.31.0",
"bitgo": "^50.28.0",
"lodash": "^4.17.15",
"react": "^18.0.0",
"react-dom": "^18.0.0",
"react-json-view": "^1.21.3",
"react-router-dom": "6.3.0",
"sjcl": "1.0.8",
"styled-components": "^5.3.5"
},
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion modules/web-demo/src/components/KeyCard/fixtures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { generateKeycard } from '@bitgo/key-card';
import { KeyCurve, coins } from '@bitgo/statics';
import { Keychain } from '@bitgo/sdk-core';
import { DklsDkg, DklsTypes } from '@bitgo/sdk-lib-mpc';
import * as sjcl from 'sjcl';
import * as sjcl from '@bitgo/sjcl';

function downloadKeycardImage(coinFamily: string): Promise<HTMLImageElement> {
return new Promise<HTMLImageElement>((resolve, reject) => {
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,8 @@
"**/tronweb/**/validator": "13.15.23",
"@isaacs/brace-expansion": "5.0.1",
"basic-ftp": ">=5.2.0",
"flatted": "3.4.0"
"flatted": "3.4.2",
"sjcl": "npm:@bitgo/sjcl@1.0.1"
},
"workspaces": [
"modules/*"
Expand Down
Loading
Loading