Skip to content

Commit 20c4a43

Browse files
committed
Update jsbt. Improve error messages and type checks.
1 parent 42d68f5 commit 20c4a43

12 files changed

Lines changed: 127 additions & 42 deletions

File tree

.github/workflows/release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ on:
55
jobs:
66
release-js:
77
name: jsbt v0.5.1
8-
uses: paulmillr/jsbt/.github/workflows/release.yml@d156c5951d47d615d673d039aa03de6b9669449f
8+
uses: paulmillr/jsbt/.github/workflows/release.yml@9a270529fbbc31451aee938da7dad227ba87f828
99
permissions:
1010
contents: read
1111
id-token: write

.github/workflows/test-slow.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,6 @@ on:
66
jobs:
77
slow:
88
name: Slow large input tests
9-
uses: paulmillr/jsbt/.github/workflows/test-custom.yml@231cc389fe2f825b6531285ad8c275584bf76588
9+
uses: paulmillr/jsbt/.github/workflows/test-custom.yml@9a270529fbbc31451aee938da7dad227ba87f828
1010
with:
1111
npm-task: test:slow

.github/workflows/test-ts.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@ on:
55
jobs:
66
test-ts:
77
name: jsbt v0.5.1
8-
uses: paulmillr/jsbt/.github/workflows/test.yml@d156c5951d47d615d673d039aa03de6b9669449f
8+
uses: paulmillr/jsbt/.github/workflows/test.yml@9a270529fbbc31451aee938da7dad227ba87f828

package-lock.json

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
"*.d.ts.map"
1111
],
1212
"devDependencies": {
13-
"@paulmillr/jsbt": "0.5.0",
13+
"@paulmillr/jsbt": "0.5.1",
1414
"@scure/base": "2.0.0",
1515
"@types/node": "25.3.0",
1616
"fast-check": "4.2.0",
@@ -22,10 +22,7 @@
2222
"bench:compare": "cd test/benchmark; npm install; node compare.ts",
2323
"build": "tsc",
2424
"build:release": "npx --no @paulmillr/jsbt esbuild test/build",
25-
"check": "npm run check:readme && npm run check:treeshake && npm run check:jsdoc",
26-
"check:readme": "npx --no @paulmillr/jsbt readme package.json",
27-
"check:treeshake": "npx --no @paulmillr/jsbt treeshake package.json test/build/out-treeshake",
28-
"check:jsdoc": "npx --no @paulmillr/jsbt tsdoc package.json",
25+
"check": "npx --no @paulmillr/jsbt check package.json",
2926
"build:clean": "rm *.{js,js.map,d.ts,d.ts.map} 2> /dev/null",
3027
"format": "prettier --write 'src/**/*.{js,ts}' 'test/**/*.{js,ts,mjs}'",
3128
"test": "node test/index.ts",

src/_arx.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@ export class _XorStreamPRG implements PRG {
370370
this.nonce = this.state.subarray(this.keyLen) as TRet<Uint8Array>;
371371
}
372372
private reseed(seed: TArg<Uint8Array>) {
373-
abytes(seed);
373+
abytes(seed, undefined, 'seed');
374374
if (!seed || seed.length === 0) throw new Error('entropy required');
375375
// Mix variable-length entropy cyclically across the whole key||nonce state, then restart the
376376
// keystream so buffered leftovers from the previous state are never reused.
@@ -380,7 +380,7 @@ export class _XorStreamPRG implements PRG {
380380
}
381381
addEntropy(seed: TArg<Uint8Array>): void {
382382
// Reject empty entropy before re-keying, otherwise a throwing call would still advance state.
383-
abytes(seed);
383+
abytes(seed, undefined, 'seed');
384384
if (seed.length === 0) throw new Error('entropy required');
385385
// Re-key from the current stream first, then mix external entropy into the fresh key||nonce
386386
// state through reseed() so stale buffered bytes are discarded.

src/aes.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -901,7 +901,8 @@ function computeTag(
901901
* import { randomBytes } from '@noble/ciphers/utils.js';
902902
* const key = randomBytes(16);
903903
* const nonce = randomBytes(12);
904-
* const cipher = gcm(key, nonce);
904+
* const aad = new TextEncoder().encode('session metadata');
905+
* const cipher = gcm(key, nonce, aad);
905906
* cipher.encrypt(new Uint8Array([1, 2, 3]));
906907
* ```
907908
*/
@@ -1026,7 +1027,8 @@ const limit = (name: string, min: number, max: number) => (value: number) => {
10261027
* import { randomBytes } from '@noble/ciphers/utils.js';
10271028
* const key = randomBytes(16);
10281029
* const nonce = randomBytes(12);
1029-
* const cipher = gcmsiv(key, nonce);
1030+
* const aad = new TextEncoder().encode('session metadata');
1031+
* const cipher = gcmsiv(key, nonce, aad);
10301032
* cipher.encrypt(new Uint8Array([1, 2, 3]));
10311033
* ```
10321034
*/

src/chacha.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -505,7 +505,8 @@ export const _poly1305_aead =
505505
* import { randomBytes } from '@noble/ciphers/utils.js';
506506
* const key = randomBytes(32);
507507
* const nonce = randomBytes(12);
508-
* const cipher = chacha20poly1305(key, nonce);
508+
* const aad = new TextEncoder().encode('session metadata');
509+
* const cipher = chacha20poly1305(key, nonce, aad);
509510
* cipher.encrypt(new Uint8Array([1, 2, 3]));
510511
* ```
511512
*/
@@ -530,7 +531,8 @@ export const chacha20poly1305: TRet<ARXCipher & { withAAD: true }> = /* @__PURE_
530531
* import { randomBytes } from '@noble/ciphers/utils.js';
531532
* const key = randomBytes(32);
532533
* const nonce = randomBytes(24);
533-
* const cipher = xchacha20poly1305(key, nonce);
534+
* const aad = new TextEncoder().encode('session metadata');
535+
* const cipher = xchacha20poly1305(key, nonce, aad);
534536
* cipher.encrypt(new Uint8Array([1, 2, 3]));
535537
* ```
536538
*/

src/ff1.ts

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*/
66
import { unsafe } from './aes.ts';
77
import {
8+
aarray,
89
abytes,
910
anumber,
1011
bytesToNumberBE,
@@ -137,9 +138,9 @@ export function FF1(
137138
key: TArg<Uint8Array>,
138139
tweak: TArg<Uint8Array> = EMPTY_BUF
139140
): { encrypt(x: number[]): number[]; decrypt(x: number[]): number[] } {
140-
anumber(radix);
141-
abytes(key);
142-
abytes(tweak);
141+
anumber(radix, 'radix');
142+
abytes(key, undefined, 'key');
143+
abytes(tweak, undefined, 'tweak');
143144
// This borrows caller key/tweak buffers by reference through the bound closure; mutating them
144145
// after construction changes later encrypt/decrypt outputs.
145146
const PQ = getRound.bind(null, radix, key, tweak);
@@ -174,7 +175,7 @@ export function FF1(
174175
// Binary wrapper uses little-endian bit order within each byte so bit 0 stays
175176
// in the first numeral slot for this library-defined byte-array surface.
176177
const binLE = {
177-
encode(bytes: TArg<Uint8Array>): number[] {
178+
encode(bytes: TArg<Uint8Array> | number[]): number[] {
178179
const x = [];
179180
for (let i = 0; i < bytes.length; i++) {
180181
for (let j = 0, tmp = bytes[i]; j < 8; j++, tmp >>= 1) x.push(tmp & 1);
@@ -214,9 +215,27 @@ export function BinaryFF1(
214215
): TRet<Cipher> {
215216
const ff1 = FF1(2, key, tweak);
216217
return {
217-
encrypt: (x: TArg<Uint8Array>): TRet<Uint8Array> =>
218-
binLE.decode(ff1.encrypt(binLE.encode(x))) as TRet<Uint8Array>,
219-
decrypt: (x: TArg<Uint8Array>): TRet<Uint8Array> =>
220-
binLE.decode(ff1.decrypt(binLE.encode(x))) as TRet<Uint8Array>,
218+
encrypt: (x: TArg<Uint8Array> | number[]): TRet<Uint8Array> => {
219+
if (Array.isArray(x)) {
220+
aarray<number>(x, 'x', (elm, title) => {
221+
anumber(elm, title);
222+
if (elm > 255) throw new RangeError(`"${title}" expected byte`);
223+
});
224+
} else {
225+
x = abytes(x, undefined, 'x');
226+
}
227+
return binLE.decode(ff1.encrypt(binLE.encode(x))) as TRet<Uint8Array>;
228+
},
229+
decrypt: (x: TArg<Uint8Array> | number[]): TRet<Uint8Array> => {
230+
if (Array.isArray(x)) {
231+
aarray<number>(x, 'x', (elm, title) => {
232+
anumber(elm, title);
233+
if (elm > 255) throw new RangeError(`"${title}" expected byte`);
234+
});
235+
} else {
236+
x = abytes(x, undefined, 'x');
237+
}
238+
return binLE.decode(ff1.decrypt(binLE.encode(x))) as TRet<Uint8Array>;
239+
},
221240
} as TRet<Cipher>;
222241
}

src/salsa.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ export const xsalsa20poly1305: TRet<ARXCipher> = /* @__PURE__ */ wrapCipher(
314314
// [0..32] [32..48] [48..]
315315
// Authenticate the ciphertext before decrypting it; on tag failure the scratch/output
316316
// buffer may already contain copied ciphertext and derived auth-key material.
317-
abytes(ciphertext);
317+
abytes(ciphertext, undefined, 'data');
318318
output = getOutput(ciphertext.length + 32, output, false);
319319
// output[0..32] is auth-key scratch, output[32..48] is passed tag,
320320
// output[48..] is ciphertext then plaintext.

0 commit comments

Comments
 (0)