Skip to content

Commit a47c3d0

Browse files
authored
refactor: normalize bigint literals and reuse common helpers (#714)
1 parent 984914a commit a47c3d0

File tree

14 files changed

+248
-205
lines changed

14 files changed

+248
-205
lines changed

packages/chacha20poly1305/src/chacha/_poly1305.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,16 +47,16 @@ function u8to16(a: Uint8Array, i: number) {
4747
// function poly1305_small(msg: Uint8Array, key: Uint8Array): Uint8Array {
4848
// abytes(msg);
4949
// abytes(key, 32, "key");
50-
// const POW_2_130_5 = BigInt(2) ** BigInt(130) - BigInt(5); // 2^130-5
51-
// const POW_2_128_1 = BigInt(2) ** BigInt(128) - BigInt(1); // 2^128-1
52-
// const CLAMP_R = BigInt("0x0ffffffc0ffffffc0ffffffc0fffffff");
50+
// const POW_2_130_5 = 2n ** 130n - 5n; // 2^130-5
51+
// const POW_2_128_1 = 2n ** 128n - 1n; // 2^128-1
52+
// const CLAMP_R = 0x0ffffffc0ffffffc0ffffffc0fffffffn;
5353
// const r = bytesToNumberLE(key.subarray(0, 16)) & CLAMP_R;
5454
// const s = bytesToNumberLE(key.subarray(16));
5555
// // Process by 16 byte chunks
56-
// let acc = BigInt(0);
56+
// let acc = 0n;
5757
// for (let i = 0; i < msg.length; i += 16) {
5858
// const m = msg.subarray(i, i + 16);
59-
// const n = bytesToNumberLE(m) | (BigInt(1) << BigInt(8 * m.length));
59+
// const n = bytesToNumberLE(m) | (1n << (8n * mLen)); // mLen: bigint
6060
// acc = ((acc + n) * r) % POW_2_130_5;
6161
// }
6262
// const res = (acc + s) & POW_2_128_1;

packages/chacha20poly1305/src/chacha/utils.ts

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
* Utilities for hex, bytes, CSPRNG.
1212
* @module
1313
*/
14+
import { hexToNumber, numberToBigint } from "@hpke/common";
15+
16+
export { hexToNumber };
1417

1518
/** Checks if something is Uint8Array. Be careful: nodejs Buffer will return true. */
1619
export function isBytes(a: unknown): a is Uint8Array {
@@ -187,14 +190,6 @@ export function hexToBytes(hex: string): Uint8Array {
187190
return array;
188191
}
189192

190-
// Used in micro
191-
export function hexToNumber(hex: string): bigint {
192-
if (typeof hex !== "string") {
193-
throw new Error("hex string expected, got " + typeof hex);
194-
}
195-
return BigInt(hex === "" ? "0" : "0x" + hex); // Big Endian
196-
}
197-
198193
// Used in ff1
199194
// BE: Big Endian, LE: Little Endian
200195
export function bytesToNumberBE(bytes: Uint8Array): bigint {
@@ -472,8 +467,8 @@ export function u64Lengths(
472467
abool(isLE);
473468
const num = new Uint8Array(16);
474469
const view = createView(num);
475-
view.setBigUint64(0, BigInt(aadLength), isLE);
476-
view.setBigUint64(8, BigInt(dataLength), isLE);
470+
view.setBigUint64(0, numberToBigint(aadLength), isLE);
471+
view.setBigUint64(8, numberToBigint(dataLength), isLE);
477472
return num;
478473
}
479474

packages/common/mod.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ export {
5050
loadSubtleCrypto,
5151
xor,
5252
} from "./src/utils/misc.ts";
53+
export { hexToNumber, numberToBigint } from "./src/utils/noble.ts";
5354

5455
export { hmac } from "./src/hash/hmac.ts";
5556
export { sha256, sha384, sha512 } from "./src/hash/sha2.ts";

packages/common/src/consts.ts

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,22 @@ export const MINIMUM_PSK_LENGTH = 32;
1010
export const EMPTY: Uint8Array = /* @__PURE__ */ new Uint8Array(0);
1111

1212
// Common BigInt constants
13-
export const N_0 = /* @__PURE__ */ BigInt(0);
14-
export const N_1 = /* @__PURE__ */ BigInt(1);
15-
export const N_2 = /* @__PURE__ */ BigInt(2);
16-
export const N_7 = /* @__PURE__ */ BigInt(7);
17-
export const N_32 = /* @__PURE__ */ BigInt(32);
18-
export const N_256 = /* @__PURE__ */ BigInt(256);
19-
export const N_0x71 = /* @__PURE__ */ BigInt(0x71);
13+
export const N_0 = 0n;
14+
export const N_1 = 1n;
15+
export const N_2 = 2n;
16+
export const N_7 = 7n;
17+
export const N_32 = 32n;
18+
export const N_256 = 256n;
19+
export const N_0x71 = 0x71n;
20+
21+
export const BYTE_TO_BIGINT_256: readonly bigint[] = /* @__PURE__ */ (() => {
22+
const out = new Array<bigint>(256);
23+
let i = 0;
24+
let value = 0n;
25+
while (i < 256) {
26+
out[i] = value;
27+
i++;
28+
value += 1n;
29+
}
30+
return out;
31+
})();

packages/common/src/curve/montgomery.ts

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -69,21 +69,19 @@ export function montgomery(curveDef: CurveType): MontgomeryECDH {
6969
if (!is25519 && type !== "x448") throw new Error("invalid type");
7070
const randomBytes_ = rand || randomBytesAsync;
7171

72-
const montgomeryBits = is25519 ? 255 : 448;
72+
const montgomeryBits = is25519 ? 255n : 448n;
7373
const fieldLen = is25519 ? 32 : 56;
74-
const Gu = is25519 ? BigInt(9) : BigInt(5);
74+
const Gu = is25519 ? 9n : 5n;
7575
// RFC 7748 #5:
7676
// The constant a24 is (486662 - 2) / 4 = 121665 for curve25519/X25519 and
7777
// (156326 - 2) / 4 = 39081 for curve448/X448
7878
// const a = is25519 ? 156326n : 486662n;
79-
const a24 = is25519 ? BigInt(121665) : BigInt(39081);
79+
const a24 = is25519 ? 121665n : 39081n;
8080
// RFC: x25519 "the resulting integer is of the form 2^254 plus
8181
// eight times a value between 0 and 2^251 - 1 (inclusive)"
8282
// x448: "2^447 plus four times a value between 0 and 2^445 - 1 (inclusive)"
83-
const minScalar = is25519 ? N_2 ** BigInt(254) : N_2 ** BigInt(447);
84-
const maxAdded = is25519
85-
? BigInt(8) * N_2 ** BigInt(251) - N_1
86-
: BigInt(4) * N_2 ** BigInt(445) - N_1;
83+
const minScalar = is25519 ? N_2 ** 254n : N_2 ** 447n;
84+
const maxAdded = is25519 ? 8n * N_2 ** 251n - N_1 : 4n * N_2 ** 445n - N_1;
8785
const maxScalar = minScalar + maxAdded + N_1; // (inclusive)
8886
const modP = (n: bigint) => mod(n, P);
8987
const GuBytes = encodeU(Gu);
@@ -152,7 +150,7 @@ export function montgomery(curveDef: CurveType): MontgomeryECDH {
152150
let x_3 = u;
153151
let z_3 = N_1;
154152
let swap = N_0;
155-
for (let t = BigInt(montgomeryBits - 1); t >= N_0; t--) {
153+
for (let t = montgomeryBits - 1n; t >= N_0; t--) {
156154
const k_t = (k >> t) & N_1;
157155
swap ^= k_t;
158156
({ x_2, x_3 } = cswap(swap, x_2, x_3));

packages/common/src/hash/md.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,14 @@
1111
* Internal Merkle-Damgard hash utils.
1212
* @module
1313
*/
14-
import { abytes, aexists, aoutput, clean, createView } from "../utils/noble.ts";
14+
import {
15+
abytes,
16+
aexists,
17+
aoutput,
18+
clean,
19+
createView,
20+
numberToBigint,
21+
} from "../utils/noble.ts";
1522
import type { Hash } from "./hash.ts";
1623

1724
/** Choice: a ? b : c */
@@ -111,7 +118,7 @@ export abstract class HashMD<T extends HashMD<T>> implements Hash<T> {
111118
// Note: sha512 requires length to be 128bit integer, but length in JS will overflow before that
112119
// You need to write around 2 exabytes (u64_max / 8 / (1024**6)) for this to happen.
113120
// So we just write lowest 64 bits of that value.
114-
view.setBigUint64(blockLen - 8, BigInt(this.length * 8), isLE);
121+
view.setBigUint64(blockLen - 8, numberToBigint(this.length * 8), isLE);
115122
this.process(view, 0);
116123
const oview = createView(out);
117124
const len = this.outputLen;

packages/common/src/hash/sha2.ts

Lines changed: 81 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -211,87 +211,87 @@ export class _SHA256 extends SHA2_32B<_SHA256> {
211211
// First 32 bits of the fractional parts of the cube roots of the first 80 primes 2..409
212212
const K512 = /* @__PURE__ */ (() =>
213213
u64.split([
214-
"0x428a2f98d728ae22",
215-
"0x7137449123ef65cd",
216-
"0xb5c0fbcfec4d3b2f",
217-
"0xe9b5dba58189dbbc",
218-
"0x3956c25bf348b538",
219-
"0x59f111f1b605d019",
220-
"0x923f82a4af194f9b",
221-
"0xab1c5ed5da6d8118",
222-
"0xd807aa98a3030242",
223-
"0x12835b0145706fbe",
224-
"0x243185be4ee4b28c",
225-
"0x550c7dc3d5ffb4e2",
226-
"0x72be5d74f27b896f",
227-
"0x80deb1fe3b1696b1",
228-
"0x9bdc06a725c71235",
229-
"0xc19bf174cf692694",
230-
"0xe49b69c19ef14ad2",
231-
"0xefbe4786384f25e3",
232-
"0x0fc19dc68b8cd5b5",
233-
"0x240ca1cc77ac9c65",
234-
"0x2de92c6f592b0275",
235-
"0x4a7484aa6ea6e483",
236-
"0x5cb0a9dcbd41fbd4",
237-
"0x76f988da831153b5",
238-
"0x983e5152ee66dfab",
239-
"0xa831c66d2db43210",
240-
"0xb00327c898fb213f",
241-
"0xbf597fc7beef0ee4",
242-
"0xc6e00bf33da88fc2",
243-
"0xd5a79147930aa725",
244-
"0x06ca6351e003826f",
245-
"0x142929670a0e6e70",
246-
"0x27b70a8546d22ffc",
247-
"0x2e1b21385c26c926",
248-
"0x4d2c6dfc5ac42aed",
249-
"0x53380d139d95b3df",
250-
"0x650a73548baf63de",
251-
"0x766a0abb3c77b2a8",
252-
"0x81c2c92e47edaee6",
253-
"0x92722c851482353b",
254-
"0xa2bfe8a14cf10364",
255-
"0xa81a664bbc423001",
256-
"0xc24b8b70d0f89791",
257-
"0xc76c51a30654be30",
258-
"0xd192e819d6ef5218",
259-
"0xd69906245565a910",
260-
"0xf40e35855771202a",
261-
"0x106aa07032bbd1b8",
262-
"0x19a4c116b8d2d0c8",
263-
"0x1e376c085141ab53",
264-
"0x2748774cdf8eeb99",
265-
"0x34b0bcb5e19b48a8",
266-
"0x391c0cb3c5c95a63",
267-
"0x4ed8aa4ae3418acb",
268-
"0x5b9cca4f7763e373",
269-
"0x682e6ff3d6b2b8a3",
270-
"0x748f82ee5defb2fc",
271-
"0x78a5636f43172f60",
272-
"0x84c87814a1f0ab72",
273-
"0x8cc702081a6439ec",
274-
"0x90befffa23631e28",
275-
"0xa4506cebde82bde9",
276-
"0xbef9a3f7b2c67915",
277-
"0xc67178f2e372532b",
278-
"0xca273eceea26619c",
279-
"0xd186b8c721c0c207",
280-
"0xeada7dd6cde0eb1e",
281-
"0xf57d4f7fee6ed178",
282-
"0x06f067aa72176fba",
283-
"0x0a637dc5a2c898a6",
284-
"0x113f9804bef90dae",
285-
"0x1b710b35131c471b",
286-
"0x28db77f523047d84",
287-
"0x32caab7b40c72493",
288-
"0x3c9ebe0a15c9bebc",
289-
"0x431d67c49c100d4c",
290-
"0x4cc5d4becb3e42b6",
291-
"0x597f299cfc657e2a",
292-
"0x5fcb6fab3ad6faec",
293-
"0x6c44198c4a475817",
294-
].map((n) => BigInt(n))))();
214+
0x428a2f98d728ae22n,
215+
0x7137449123ef65cdn,
216+
0xb5c0fbcfec4d3b2fn,
217+
0xe9b5dba58189dbbcn,
218+
0x3956c25bf348b538n,
219+
0x59f111f1b605d019n,
220+
0x923f82a4af194f9bn,
221+
0xab1c5ed5da6d8118n,
222+
0xd807aa98a3030242n,
223+
0x12835b0145706fben,
224+
0x243185be4ee4b28cn,
225+
0x550c7dc3d5ffb4e2n,
226+
0x72be5d74f27b896fn,
227+
0x80deb1fe3b1696b1n,
228+
0x9bdc06a725c71235n,
229+
0xc19bf174cf692694n,
230+
0xe49b69c19ef14ad2n,
231+
0xefbe4786384f25e3n,
232+
0x0fc19dc68b8cd5b5n,
233+
0x240ca1cc77ac9c65n,
234+
0x2de92c6f592b0275n,
235+
0x4a7484aa6ea6e483n,
236+
0x5cb0a9dcbd41fbd4n,
237+
0x76f988da831153b5n,
238+
0x983e5152ee66dfabn,
239+
0xa831c66d2db43210n,
240+
0xb00327c898fb213fn,
241+
0xbf597fc7beef0ee4n,
242+
0xc6e00bf33da88fc2n,
243+
0xd5a79147930aa725n,
244+
0x06ca6351e003826fn,
245+
0x142929670a0e6e70n,
246+
0x27b70a8546d22ffcn,
247+
0x2e1b21385c26c926n,
248+
0x4d2c6dfc5ac42aedn,
249+
0x53380d139d95b3dfn,
250+
0x650a73548baf63den,
251+
0x766a0abb3c77b2a8n,
252+
0x81c2c92e47edaee6n,
253+
0x92722c851482353bn,
254+
0xa2bfe8a14cf10364n,
255+
0xa81a664bbc423001n,
256+
0xc24b8b70d0f89791n,
257+
0xc76c51a30654be30n,
258+
0xd192e819d6ef5218n,
259+
0xd69906245565a910n,
260+
0xf40e35855771202an,
261+
0x106aa07032bbd1b8n,
262+
0x19a4c116b8d2d0c8n,
263+
0x1e376c085141ab53n,
264+
0x2748774cdf8eeb99n,
265+
0x34b0bcb5e19b48a8n,
266+
0x391c0cb3c5c95a63n,
267+
0x4ed8aa4ae3418acbn,
268+
0x5b9cca4f7763e373n,
269+
0x682e6ff3d6b2b8a3n,
270+
0x748f82ee5defb2fcn,
271+
0x78a5636f43172f60n,
272+
0x84c87814a1f0ab72n,
273+
0x8cc702081a6439ecn,
274+
0x90befffa23631e28n,
275+
0xa4506cebde82bde9n,
276+
0xbef9a3f7b2c67915n,
277+
0xc67178f2e372532bn,
278+
0xca273eceea26619cn,
279+
0xd186b8c721c0c207n,
280+
0xeada7dd6cde0eb1en,
281+
0xf57d4f7fee6ed178n,
282+
0x06f067aa72176fban,
283+
0x0a637dc5a2c898a6n,
284+
0x113f9804bef90daen,
285+
0x1b710b35131c471bn,
286+
0x28db77f523047d84n,
287+
0x32caab7b40c72493n,
288+
0x3c9ebe0a15c9bebcn,
289+
0x431d67c49c100d4cn,
290+
0x4cc5d4becb3e42b6n,
291+
0x597f299cfc657e2an,
292+
0x5fcb6fab3ad6faecn,
293+
0x6c44198c4a475817n,
294+
]))();
295295
const SHA512_Kh = /* @__PURE__ */ (() => K512[0])();
296296
const SHA512_Kl = /* @__PURE__ */ (() => K512[1])();
297297

packages/common/src/hash/sha3.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,9 @@ for (let round = 0, R = N_1, x = 1, y = 0; round < 24; round++) {
5353
SHA3_ROTL.push((((round + 1) * (round + 2)) / 2) % 64);
5454
// Iota
5555
let t = N_0;
56-
for (let j = 0; j < 7; j++) {
56+
for (let j = 0n; j < 7n; j++) {
5757
R = ((R << N_1) ^ ((R >> N_7) * N_0x71)) % N_256;
58-
if (R & N_2) t ^= N_1 << ((N_1 << BigInt(j)) - N_1);
58+
if (R & N_2) t ^= N_1 << ((N_1 << j) - N_1);
5959
}
6060
_SHA3_IOTA.push(t);
6161
}

packages/common/src/hash/u64.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,17 @@
1111
* @todo re-check https://issues.chromium.org/issues/42212588
1212
* @module
1313
*/
14-
import { N_32 } from "../consts.ts";
14+
import { BYTE_TO_BIGINT_256, N_32 } from "../consts.ts";
1515

16-
const U32_MASK64 = /* @__PURE__ */ BigInt(2 ** 32 - 1);
16+
const U32_MASK64 = 0xffff_ffffn;
17+
18+
function u32ToBig(n: number): bigint {
19+
const u = n >>> 0;
20+
return (BYTE_TO_BIGINT_256[(u >>> 24) & 0xff] << 24n) |
21+
(BYTE_TO_BIGINT_256[(u >>> 16) & 0xff] << 16n) |
22+
(BYTE_TO_BIGINT_256[(u >>> 8) & 0xff] << 8n) |
23+
BYTE_TO_BIGINT_256[u & 0xff];
24+
}
1725

1826
function fromBig(
1927
n: bigint,
@@ -43,7 +51,7 @@ function split(lst: bigint[], le = false): Uint32Array[] {
4351
}
4452

4553
const toBig = (h: number, l: number): bigint =>
46-
(BigInt(h >>> 0) << N_32) | BigInt(l >>> 0);
54+
(u32ToBig(h) << N_32) | u32ToBig(l);
4755
// for Shift in [0, 32)
4856
const shrSH = (h: number, _l: number, s: number): number => h >>> s;
4957
const shrSL = (h: number, l: number, s: number): number =>

0 commit comments

Comments
 (0)