Add debug logging to see received auth data
This commit is contained in:
170
node_modules/@noble/ciphers/esm/_arx.js
generated
vendored
Normal file
170
node_modules/@noble/ciphers/esm/_arx.js
generated
vendored
Normal file
@@ -0,0 +1,170 @@
|
||||
// Basic utils for ARX (add-rotate-xor) salsa and chacha ciphers.
|
||||
import { number as anumber, bytes as abytes, bool as abool } from './_assert.js';
|
||||
import { checkOpts, u32 } from './utils.js';
|
||||
/*
|
||||
RFC8439 requires multi-step cipher stream, where
|
||||
authKey starts with counter: 0, actual msg with counter: 1.
|
||||
|
||||
For this, we need a way to re-use nonce / counter:
|
||||
|
||||
const counter = new Uint8Array(4);
|
||||
chacha(..., counter, ...); // counter is now 1
|
||||
chacha(..., counter, ...); // counter is now 2
|
||||
|
||||
This is complicated:
|
||||
|
||||
- 32-bit counters are enough, no need for 64-bit: max ArrayBuffer size in JS is 4GB
|
||||
- Original papers don't allow mutating counters
|
||||
- Counter overflow is undefined [^1]
|
||||
- Idea A: allow providing (nonce | counter) instead of just nonce, re-use it
|
||||
- Caveat: Cannot be re-used through all cases:
|
||||
- * chacha has (counter | nonce)
|
||||
- * xchacha has (nonce16 | counter | nonce16)
|
||||
- Idea B: separate nonce / counter and provide separate API for counter re-use
|
||||
- Caveat: there are different counter sizes depending on an algorithm.
|
||||
- salsa & chacha also differ in structures of key & sigma:
|
||||
salsa20: s[0] | k(4) | s[1] | nonce(2) | ctr(2) | s[2] | k(4) | s[3]
|
||||
chacha: s(4) | k(8) | ctr(1) | nonce(3)
|
||||
chacha20orig: s(4) | k(8) | ctr(2) | nonce(2)
|
||||
- Idea C: helper method such as `setSalsaState(key, nonce, sigma, data)`
|
||||
- Caveat: we can't re-use counter array
|
||||
|
||||
xchacha [^2] uses the subkey and remaining 8 byte nonce with ChaCha20 as normal
|
||||
(prefixed by 4 NUL bytes, since [RFC8439] specifies a 12-byte nonce).
|
||||
|
||||
[^1]: https://mailarchive.ietf.org/arch/msg/cfrg/gsOnTJzcbgG6OqD8Sc0GO5aR_tU/
|
||||
[^2]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-xchacha#appendix-A.2
|
||||
*/
|
||||
// We can't make top-level var depend on utils.utf8ToBytes
|
||||
// because it's not present in all envs. Creating a similar fn here
|
||||
const _utf8ToBytes = (str) => Uint8Array.from(str.split('').map((c) => c.charCodeAt(0)));
|
||||
const sigma16 = _utf8ToBytes('expand 16-byte k');
|
||||
const sigma32 = _utf8ToBytes('expand 32-byte k');
|
||||
const sigma16_32 = u32(sigma16);
|
||||
const sigma32_32 = u32(sigma32);
|
||||
export const sigma = sigma32_32.slice();
|
||||
export function rotl(a, b) {
|
||||
return (a << b) | (a >>> (32 - b));
|
||||
}
|
||||
// Is byte array aligned to 4 byte offset (u32)?
|
||||
function isAligned32(b) {
|
||||
return b.byteOffset % 4 === 0;
|
||||
}
|
||||
// Salsa and Chacha block length is always 512-bit
|
||||
const BLOCK_LEN = 64;
|
||||
const BLOCK_LEN32 = 16;
|
||||
// new Uint32Array([2**32]) // => Uint32Array(1) [ 0 ]
|
||||
// new Uint32Array([2**32-1]) // => Uint32Array(1) [ 4294967295 ]
|
||||
const MAX_COUNTER = 2 ** 32 - 1;
|
||||
const U32_EMPTY = new Uint32Array();
|
||||
function runCipher(core, sigma, key, nonce, data, output, counter, rounds) {
|
||||
const len = data.length;
|
||||
const block = new Uint8Array(BLOCK_LEN);
|
||||
const b32 = u32(block);
|
||||
// Make sure that buffers aligned to 4 bytes
|
||||
const isAligned = isAligned32(data) && isAligned32(output);
|
||||
const d32 = isAligned ? u32(data) : U32_EMPTY;
|
||||
const o32 = isAligned ? u32(output) : U32_EMPTY;
|
||||
for (let pos = 0; pos < len; counter++) {
|
||||
core(sigma, key, nonce, b32, counter, rounds);
|
||||
if (counter >= MAX_COUNTER)
|
||||
throw new Error('arx: counter overflow');
|
||||
const take = Math.min(BLOCK_LEN, len - pos);
|
||||
// aligned to 4 bytes
|
||||
if (isAligned && take === BLOCK_LEN) {
|
||||
const pos32 = pos / 4;
|
||||
if (pos % 4 !== 0)
|
||||
throw new Error('arx: invalid block position');
|
||||
for (let j = 0, posj; j < BLOCK_LEN32; j++) {
|
||||
posj = pos32 + j;
|
||||
o32[posj] = d32[posj] ^ b32[j];
|
||||
}
|
||||
pos += BLOCK_LEN;
|
||||
continue;
|
||||
}
|
||||
for (let j = 0, posj; j < take; j++) {
|
||||
posj = pos + j;
|
||||
output[posj] = data[posj] ^ block[j];
|
||||
}
|
||||
pos += take;
|
||||
}
|
||||
}
|
||||
export function createCipher(core, opts) {
|
||||
const { allowShortKeys, extendNonceFn, counterLength, counterRight, rounds } = checkOpts({ allowShortKeys: false, counterLength: 8, counterRight: false, rounds: 20 }, opts);
|
||||
if (typeof core !== 'function')
|
||||
throw new Error('core must be a function');
|
||||
anumber(counterLength);
|
||||
anumber(rounds);
|
||||
abool(counterRight);
|
||||
abool(allowShortKeys);
|
||||
return (key, nonce, data, output, counter = 0) => {
|
||||
abytes(key);
|
||||
abytes(nonce);
|
||||
abytes(data);
|
||||
const len = data.length;
|
||||
if (!output)
|
||||
output = new Uint8Array(len);
|
||||
abytes(output);
|
||||
anumber(counter);
|
||||
if (counter < 0 || counter >= MAX_COUNTER)
|
||||
throw new Error('arx: counter overflow');
|
||||
if (output.length < len)
|
||||
throw new Error(`arx: output (${output.length}) is shorter than data (${len})`);
|
||||
const toClean = [];
|
||||
// Key & sigma
|
||||
// key=16 -> sigma16, k=key|key
|
||||
// key=32 -> sigma32, k=key
|
||||
let l = key.length, k, sigma;
|
||||
if (l === 32) {
|
||||
k = key.slice();
|
||||
toClean.push(k);
|
||||
sigma = sigma32_32;
|
||||
}
|
||||
else if (l === 16 && allowShortKeys) {
|
||||
k = new Uint8Array(32);
|
||||
k.set(key);
|
||||
k.set(key, 16);
|
||||
sigma = sigma16_32;
|
||||
toClean.push(k);
|
||||
}
|
||||
else {
|
||||
throw new Error(`arx: invalid 32-byte key, got length=${l}`);
|
||||
}
|
||||
// Nonce
|
||||
// salsa20: 8 (8-byte counter)
|
||||
// chacha20orig: 8 (8-byte counter)
|
||||
// chacha20: 12 (4-byte counter)
|
||||
// xsalsa20: 24 (16 -> hsalsa, 8 -> old nonce)
|
||||
// xchacha20: 24 (16 -> hchacha, 8 -> old nonce)
|
||||
// Align nonce to 4 bytes
|
||||
if (!isAligned32(nonce)) {
|
||||
nonce = nonce.slice();
|
||||
toClean.push(nonce);
|
||||
}
|
||||
const k32 = u32(k);
|
||||
// hsalsa & hchacha: handle extended nonce
|
||||
if (extendNonceFn) {
|
||||
if (nonce.length !== 24)
|
||||
throw new Error(`arx: extended nonce must be 24 bytes`);
|
||||
extendNonceFn(sigma, k32, u32(nonce.subarray(0, 16)), k32);
|
||||
nonce = nonce.subarray(16);
|
||||
}
|
||||
// Handle nonce counter
|
||||
const nonceNcLen = 16 - counterLength;
|
||||
if (nonceNcLen !== nonce.length)
|
||||
throw new Error(`arx: nonce must be ${nonceNcLen} or 16 bytes`);
|
||||
// Pad counter when nonce is 64 bit
|
||||
if (nonceNcLen !== 12) {
|
||||
const nc = new Uint8Array(12);
|
||||
nc.set(nonce, counterRight ? 0 : 12 - nonce.length);
|
||||
nonce = nc;
|
||||
toClean.push(nonce);
|
||||
}
|
||||
const n32 = u32(nonce);
|
||||
runCipher(core, sigma, k32, n32, data, output, counter, rounds);
|
||||
while (toClean.length > 0)
|
||||
toClean.pop().fill(0);
|
||||
return output;
|
||||
};
|
||||
}
|
||||
//# sourceMappingURL=_arx.js.map
|
||||
1
node_modules/@noble/ciphers/esm/_arx.js.map
generated
vendored
Normal file
1
node_modules/@noble/ciphers/esm/_arx.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
41
node_modules/@noble/ciphers/esm/_assert.js
generated
vendored
Normal file
41
node_modules/@noble/ciphers/esm/_assert.js
generated
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
function number(n) {
|
||||
if (!Number.isSafeInteger(n) || n < 0)
|
||||
throw new Error(`positive integer expected, not ${n}`);
|
||||
}
|
||||
function bool(b) {
|
||||
if (typeof b !== 'boolean')
|
||||
throw new Error(`boolean expected, not ${b}`);
|
||||
}
|
||||
export function isBytes(a) {
|
||||
return (a instanceof Uint8Array ||
|
||||
(a != null && typeof a === 'object' && a.constructor.name === 'Uint8Array'));
|
||||
}
|
||||
function bytes(b, ...lengths) {
|
||||
if (!isBytes(b))
|
||||
throw new Error('Uint8Array expected');
|
||||
if (lengths.length > 0 && !lengths.includes(b.length))
|
||||
throw new Error(`Uint8Array expected of length ${lengths}, not of length=${b.length}`);
|
||||
}
|
||||
function hash(hash) {
|
||||
if (typeof hash !== 'function' || typeof hash.create !== 'function')
|
||||
throw new Error('hash must be wrapped by utils.wrapConstructor');
|
||||
number(hash.outputLen);
|
||||
number(hash.blockLen);
|
||||
}
|
||||
function exists(instance, checkFinished = true) {
|
||||
if (instance.destroyed)
|
||||
throw new Error('Hash instance has been destroyed');
|
||||
if (checkFinished && instance.finished)
|
||||
throw new Error('Hash#digest() has already been called');
|
||||
}
|
||||
function output(out, instance) {
|
||||
bytes(out);
|
||||
const min = instance.outputLen;
|
||||
if (out.length < min) {
|
||||
throw new Error(`digestInto() expects output buffer of length at least ${min}`);
|
||||
}
|
||||
}
|
||||
export { number, bool, bytes, hash, exists, output };
|
||||
const assert = { number, bool, bytes, hash, exists, output };
|
||||
export default assert;
|
||||
//# sourceMappingURL=_assert.js.map
|
||||
1
node_modules/@noble/ciphers/esm/_assert.js.map
generated
vendored
Normal file
1
node_modules/@noble/ciphers/esm/_assert.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"_assert.js","sourceRoot":"","sources":["../src/_assert.ts"],"names":[],"mappings":"AAAA,SAAS,MAAM,CAAC,CAAS;IACvB,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,EAAE,CAAC,CAAC;AAChG,CAAC;AAED,SAAS,IAAI,CAAC,CAAU;IACtB,IAAI,OAAO,CAAC,KAAK,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,EAAE,CAAC,CAAC;AAC5E,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,CAAU;IAChC,OAAO,CACL,CAAC,YAAY,UAAU;QACvB,CAAC,CAAC,IAAI,IAAI,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,WAAW,CAAC,IAAI,KAAK,YAAY,CAAC,CAC5E,CAAC;AACJ,CAAC;AAED,SAAS,KAAK,CAAC,CAAyB,EAAE,GAAG,OAAiB;IAC5D,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;IACxD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC;QACnD,MAAM,IAAI,KAAK,CAAC,iCAAiC,OAAO,mBAAmB,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;AAC3F,CAAC;AAQD,SAAS,IAAI,CAAC,IAAU;IACtB,IAAI,OAAO,IAAI,KAAK,UAAU,IAAI,OAAO,IAAI,CAAC,MAAM,KAAK,UAAU;QACjE,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;IACnE,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACvB,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AACxB,CAAC;AAED,SAAS,MAAM,CAAC,QAAa,EAAE,aAAa,GAAG,IAAI;IACjD,IAAI,QAAQ,CAAC,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;IAC5E,IAAI,aAAa,IAAI,QAAQ,CAAC,QAAQ;QAAE,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;AACnG,CAAC;AAED,SAAS,MAAM,CAAC,GAAQ,EAAE,QAAa;IACrC,KAAK,CAAC,GAAG,CAAC,CAAC;IACX,MAAM,GAAG,GAAG,QAAQ,CAAC,SAAS,CAAC;IAC/B,IAAI,GAAG,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CAAC,yDAAyD,GAAG,EAAE,CAAC,CAAC;IAClF,CAAC;AACH,CAAC;AAED,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;AACrD,MAAM,MAAM,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;AAC7D,eAAe,MAAM,CAAC"}
|
||||
287
node_modules/@noble/ciphers/esm/_micro.js
generated
vendored
Normal file
287
node_modules/@noble/ciphers/esm/_micro.js
generated
vendored
Normal file
@@ -0,0 +1,287 @@
|
||||
/*! noble-ciphers - MIT License (c) 2023 Paul Miller (paulmillr.com) */
|
||||
// prettier-ignore
|
||||
import { createView, setBigUint64, wrapCipher, bytesToHex, concatBytes, equalBytes, hexToNumber, numberToBytesBE, } from './utils.js';
|
||||
import { createCipher, rotl } from './_arx.js';
|
||||
import { bytes as abytes } from './_assert.js';
|
||||
/*
|
||||
noble-ciphers-micro: more auditable, but slower version of salsa20, chacha & poly1305.
|
||||
Implements the same algorithms that are present in other files, but without
|
||||
unrolled loops (https://en.wikipedia.org/wiki/Loop_unrolling).
|
||||
*/
|
||||
function bytesToNumberLE(bytes) {
|
||||
return hexToNumber(bytesToHex(Uint8Array.from(bytes).reverse()));
|
||||
}
|
||||
function numberToBytesLE(n, len) {
|
||||
return numberToBytesBE(n, len).reverse();
|
||||
}
|
||||
function salsaQR(x, a, b, c, d) {
|
||||
x[b] ^= rotl((x[a] + x[d]) | 0, 7);
|
||||
x[c] ^= rotl((x[b] + x[a]) | 0, 9);
|
||||
x[d] ^= rotl((x[c] + x[b]) | 0, 13);
|
||||
x[a] ^= rotl((x[d] + x[c]) | 0, 18);
|
||||
}
|
||||
// prettier-ignore
|
||||
function chachaQR(x, a, b, c, d) {
|
||||
x[a] = (x[a] + x[b]) | 0;
|
||||
x[d] = rotl(x[d] ^ x[a], 16);
|
||||
x[c] = (x[c] + x[d]) | 0;
|
||||
x[b] = rotl(x[b] ^ x[c], 12);
|
||||
x[a] = (x[a] + x[b]) | 0;
|
||||
x[d] = rotl(x[d] ^ x[a], 8);
|
||||
x[c] = (x[c] + x[d]) | 0;
|
||||
x[b] = rotl(x[b] ^ x[c], 7);
|
||||
}
|
||||
function salsaRound(x, rounds = 20) {
|
||||
for (let r = 0; r < rounds; r += 2) {
|
||||
salsaQR(x, 0, 4, 8, 12);
|
||||
salsaQR(x, 5, 9, 13, 1);
|
||||
salsaQR(x, 10, 14, 2, 6);
|
||||
salsaQR(x, 15, 3, 7, 11);
|
||||
salsaQR(x, 0, 1, 2, 3);
|
||||
salsaQR(x, 5, 6, 7, 4);
|
||||
salsaQR(x, 10, 11, 8, 9);
|
||||
salsaQR(x, 15, 12, 13, 14);
|
||||
}
|
||||
}
|
||||
function chachaRound(x, rounds = 20) {
|
||||
for (let r = 0; r < rounds; r += 2) {
|
||||
chachaQR(x, 0, 4, 8, 12);
|
||||
chachaQR(x, 1, 5, 9, 13);
|
||||
chachaQR(x, 2, 6, 10, 14);
|
||||
chachaQR(x, 3, 7, 11, 15);
|
||||
chachaQR(x, 0, 5, 10, 15);
|
||||
chachaQR(x, 1, 6, 11, 12);
|
||||
chachaQR(x, 2, 7, 8, 13);
|
||||
chachaQR(x, 3, 4, 9, 14);
|
||||
}
|
||||
}
|
||||
function salsaCore(s, k, n, out, cnt, rounds = 20) {
|
||||
// prettier-ignore
|
||||
const y = new Uint32Array([
|
||||
s[0], k[0], k[1], k[2], // "expa" Key Key Key
|
||||
k[3], s[1], n[0], n[1], // Key "nd 3" Nonce Nonce
|
||||
cnt, 0, s[2], k[4], // Pos. Pos. "2-by" Key
|
||||
k[5], k[6], k[7], s[3], // Key Key Key "te k"
|
||||
]);
|
||||
const x = y.slice();
|
||||
salsaRound(x, rounds);
|
||||
for (let i = 0; i < 16; i++)
|
||||
out[i] = (y[i] + x[i]) | 0;
|
||||
}
|
||||
// prettier-ignore
|
||||
export function hsalsa(s, k, i, o32) {
|
||||
const x = new Uint32Array([
|
||||
s[0], k[0], k[1], k[2],
|
||||
k[3], s[1], i[0], i[1],
|
||||
i[2], i[3], s[2], k[4],
|
||||
k[5], k[6], k[7], s[3]
|
||||
]);
|
||||
salsaRound(x, 20);
|
||||
let oi = 0;
|
||||
o32[oi++] = x[0];
|
||||
o32[oi++] = x[5];
|
||||
o32[oi++] = x[10];
|
||||
o32[oi++] = x[15];
|
||||
o32[oi++] = x[6];
|
||||
o32[oi++] = x[7];
|
||||
o32[oi++] = x[8];
|
||||
o32[oi++] = x[9];
|
||||
}
|
||||
function chachaCore(s, k, n, out, cnt, rounds = 20) {
|
||||
// prettier-ignore
|
||||
const y = new Uint32Array([
|
||||
s[0], s[1], s[2], s[3], // "expa" "nd 3" "2-by" "te k"
|
||||
k[0], k[1], k[2], k[3], // Key Key Key Key
|
||||
k[4], k[5], k[6], k[7], // Key Key Key Key
|
||||
cnt, n[0], n[1], n[2], // Counter Counter Nonce Nonce
|
||||
]);
|
||||
const x = y.slice();
|
||||
chachaRound(x, rounds);
|
||||
for (let i = 0; i < 16; i++)
|
||||
out[i] = (y[i] + x[i]) | 0;
|
||||
}
|
||||
// prettier-ignore
|
||||
export function hchacha(s, k, i, o32) {
|
||||
const x = new Uint32Array([
|
||||
s[0], s[1], s[2], s[3],
|
||||
k[0], k[1], k[2], k[3],
|
||||
k[4], k[5], k[6], k[7],
|
||||
i[0], i[1], i[2], i[3],
|
||||
]);
|
||||
chachaRound(x, 20);
|
||||
let oi = 0;
|
||||
o32[oi++] = x[0];
|
||||
o32[oi++] = x[1];
|
||||
o32[oi++] = x[2];
|
||||
o32[oi++] = x[3];
|
||||
o32[oi++] = x[12];
|
||||
o32[oi++] = x[13];
|
||||
o32[oi++] = x[14];
|
||||
o32[oi++] = x[15];
|
||||
}
|
||||
/**
|
||||
* salsa20, 12-byte nonce.
|
||||
*/
|
||||
export const salsa20 = /* @__PURE__ */ createCipher(salsaCore, {
|
||||
allowShortKeys: true,
|
||||
counterRight: true,
|
||||
});
|
||||
/**
|
||||
* xsalsa20, 24-byte nonce.
|
||||
*/
|
||||
export const xsalsa20 = /* @__PURE__ */ createCipher(salsaCore, {
|
||||
counterRight: true,
|
||||
extendNonceFn: hsalsa,
|
||||
});
|
||||
/**
|
||||
* chacha20 non-RFC, original version by djb. 8-byte nonce, 8-byte counter.
|
||||
*/
|
||||
export const chacha20orig = /* @__PURE__ */ createCipher(chachaCore, {
|
||||
allowShortKeys: true,
|
||||
counterRight: false,
|
||||
counterLength: 8,
|
||||
});
|
||||
/**
|
||||
* chacha20 RFC 8439 (IETF / TLS). 12-byte nonce, 4-byte counter.
|
||||
*/
|
||||
export const chacha20 = /* @__PURE__ */ createCipher(chachaCore, {
|
||||
counterRight: false,
|
||||
counterLength: 4,
|
||||
});
|
||||
/**
|
||||
* xchacha20 eXtended-nonce. https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-xchacha
|
||||
*/
|
||||
export const xchacha20 = /* @__PURE__ */ createCipher(chachaCore, {
|
||||
counterRight: false,
|
||||
counterLength: 8,
|
||||
extendNonceFn: hchacha,
|
||||
});
|
||||
/**
|
||||
* 8-round chacha from the original paper.
|
||||
*/
|
||||
export const chacha8 = /* @__PURE__ */ createCipher(chachaCore, {
|
||||
counterRight: false,
|
||||
counterLength: 4,
|
||||
rounds: 8,
|
||||
});
|
||||
/**
|
||||
* 12-round chacha from the original paper.
|
||||
*/
|
||||
export const chacha12 = /* @__PURE__ */ createCipher(chachaCore, {
|
||||
counterRight: false,
|
||||
counterLength: 4,
|
||||
rounds: 12,
|
||||
});
|
||||
const POW_2_130_5 = BigInt(2) ** BigInt(130) - BigInt(5);
|
||||
const POW_2_128_1 = BigInt(2) ** BigInt(16 * 8) - BigInt(1);
|
||||
const CLAMP_R = BigInt('0x0ffffffc0ffffffc0ffffffc0fffffff');
|
||||
const _0 = BigInt(0);
|
||||
const _1 = BigInt(1);
|
||||
// Can be speed-up using BigUint64Array, but would be more complicated
|
||||
export function poly1305(msg, key) {
|
||||
abytes(msg);
|
||||
abytes(key);
|
||||
let acc = _0;
|
||||
const r = bytesToNumberLE(key.subarray(0, 16)) & CLAMP_R;
|
||||
const s = bytesToNumberLE(key.subarray(16));
|
||||
// Process by 16 byte chunks
|
||||
for (let i = 0; i < msg.length; i += 16) {
|
||||
const m = msg.subarray(i, i + 16);
|
||||
const n = bytesToNumberLE(m) | (_1 << BigInt(8 * m.length));
|
||||
acc = ((acc + n) * r) % POW_2_130_5;
|
||||
}
|
||||
const res = (acc + s) & POW_2_128_1;
|
||||
return numberToBytesLE(res, 16);
|
||||
}
|
||||
function computeTag(fn, key, nonce, ciphertext, AAD) {
|
||||
const res = [];
|
||||
if (AAD) {
|
||||
res.push(AAD);
|
||||
const leftover = AAD.length % 16;
|
||||
if (leftover > 0)
|
||||
res.push(new Uint8Array(16 - leftover));
|
||||
}
|
||||
res.push(ciphertext);
|
||||
const leftover = ciphertext.length % 16;
|
||||
if (leftover > 0)
|
||||
res.push(new Uint8Array(16 - leftover));
|
||||
// Lengths
|
||||
const num = new Uint8Array(16);
|
||||
const view = createView(num);
|
||||
setBigUint64(view, 0, BigInt(AAD ? AAD.length : 0), true);
|
||||
setBigUint64(view, 8, BigInt(ciphertext.length), true);
|
||||
res.push(num);
|
||||
const authKey = fn(key, nonce, new Uint8Array(32));
|
||||
return poly1305(concatBytes(...res), authKey);
|
||||
}
|
||||
/**
|
||||
* xsalsa20-poly1305 eXtended-nonce (24 bytes) salsa.
|
||||
*/
|
||||
export const xsalsa20poly1305 = /* @__PURE__ */ wrapCipher({ blockSize: 64, nonceLength: 24, tagLength: 16 }, function xsalsa20poly1305(key, nonce) {
|
||||
abytes(key);
|
||||
abytes(nonce);
|
||||
return {
|
||||
encrypt: (plaintext) => {
|
||||
abytes(plaintext);
|
||||
const m = concatBytes(new Uint8Array(32), plaintext);
|
||||
const c = xsalsa20(key, nonce, m);
|
||||
const authKey = c.subarray(0, 32);
|
||||
const data = c.subarray(32);
|
||||
const tag = poly1305(data, authKey);
|
||||
return concatBytes(tag, data);
|
||||
},
|
||||
decrypt: (ciphertext) => {
|
||||
abytes(ciphertext);
|
||||
if (ciphertext.length < 16)
|
||||
throw new Error('encrypted data must be at least 16 bytes');
|
||||
const c = concatBytes(new Uint8Array(16), ciphertext);
|
||||
const authKey = xsalsa20(key, nonce, new Uint8Array(32));
|
||||
const tag = poly1305(c.subarray(32), authKey);
|
||||
if (!equalBytes(c.subarray(16, 32), tag))
|
||||
throw new Error('invalid poly1305 tag');
|
||||
return xsalsa20(key, nonce, c).subarray(32);
|
||||
},
|
||||
};
|
||||
});
|
||||
/**
|
||||
* Alias to xsalsa20-poly1305
|
||||
*/
|
||||
export function secretbox(key, nonce) {
|
||||
const xs = xsalsa20poly1305(key, nonce);
|
||||
return { seal: xs.encrypt, open: xs.decrypt };
|
||||
}
|
||||
export const _poly1305_aead = (fn) => (key, nonce, AAD) => {
|
||||
const tagLength = 16;
|
||||
const keyLength = 32;
|
||||
abytes(key, keyLength);
|
||||
abytes(nonce);
|
||||
return {
|
||||
encrypt: (plaintext) => {
|
||||
abytes(plaintext);
|
||||
const res = fn(key, nonce, plaintext, undefined, 1);
|
||||
const tag = computeTag(fn, key, nonce, res, AAD);
|
||||
return concatBytes(res, tag);
|
||||
},
|
||||
decrypt: (ciphertext) => {
|
||||
abytes(ciphertext);
|
||||
if (ciphertext.length < tagLength)
|
||||
throw new Error(`encrypted data must be at least ${tagLength} bytes`);
|
||||
const passedTag = ciphertext.subarray(-tagLength);
|
||||
const data = ciphertext.subarray(0, -tagLength);
|
||||
const tag = computeTag(fn, key, nonce, data, AAD);
|
||||
if (!equalBytes(passedTag, tag))
|
||||
throw new Error('invalid poly1305 tag');
|
||||
return fn(key, nonce, data, undefined, 1);
|
||||
},
|
||||
};
|
||||
};
|
||||
/**
|
||||
* chacha20-poly1305 12-byte-nonce chacha.
|
||||
*/
|
||||
export const chacha20poly1305 = /* @__PURE__ */ wrapCipher({ blockSize: 64, nonceLength: 12, tagLength: 16 }, _poly1305_aead(chacha20));
|
||||
/**
|
||||
* xchacha20-poly1305 eXtended-nonce (24 bytes) chacha.
|
||||
* With 24-byte nonce, it's safe to use fill it with random (CSPRNG).
|
||||
*/
|
||||
export const xchacha20poly1305 = /* @__PURE__ */ wrapCipher({ blockSize: 64, nonceLength: 24, tagLength: 16 }, _poly1305_aead(xchacha20));
|
||||
//# sourceMappingURL=_micro.js.map
|
||||
1
node_modules/@noble/ciphers/esm/_micro.js.map
generated
vendored
Normal file
1
node_modules/@noble/ciphers/esm/_micro.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
264
node_modules/@noble/ciphers/esm/_poly1305.js
generated
vendored
Normal file
264
node_modules/@noble/ciphers/esm/_poly1305.js
generated
vendored
Normal file
@@ -0,0 +1,264 @@
|
||||
import { exists as aexists, bytes as abytes, output as aoutput } from './_assert.js';
|
||||
import { toBytes } from './utils.js';
|
||||
// Poly1305 is a fast and parallel secret-key message-authentication code.
|
||||
// https://cr.yp.to/mac.html, https://cr.yp.to/mac/poly1305-20050329.pdf
|
||||
// https://datatracker.ietf.org/doc/html/rfc8439
|
||||
// Based on Public Domain poly1305-donna https://github.com/floodyberry/poly1305-donna
|
||||
const u8to16 = (a, i) => (a[i++] & 0xff) | ((a[i++] & 0xff) << 8);
|
||||
class Poly1305 {
|
||||
constructor(key) {
|
||||
this.blockLen = 16;
|
||||
this.outputLen = 16;
|
||||
this.buffer = new Uint8Array(16);
|
||||
this.r = new Uint16Array(10);
|
||||
this.h = new Uint16Array(10);
|
||||
this.pad = new Uint16Array(8);
|
||||
this.pos = 0;
|
||||
this.finished = false;
|
||||
key = toBytes(key);
|
||||
abytes(key, 32);
|
||||
const t0 = u8to16(key, 0);
|
||||
const t1 = u8to16(key, 2);
|
||||
const t2 = u8to16(key, 4);
|
||||
const t3 = u8to16(key, 6);
|
||||
const t4 = u8to16(key, 8);
|
||||
const t5 = u8to16(key, 10);
|
||||
const t6 = u8to16(key, 12);
|
||||
const t7 = u8to16(key, 14);
|
||||
// https://github.com/floodyberry/poly1305-donna/blob/e6ad6e091d30d7f4ec2d4f978be1fcfcbce72781/poly1305-donna-16.h#L47
|
||||
this.r[0] = t0 & 0x1fff;
|
||||
this.r[1] = ((t0 >>> 13) | (t1 << 3)) & 0x1fff;
|
||||
this.r[2] = ((t1 >>> 10) | (t2 << 6)) & 0x1f03;
|
||||
this.r[3] = ((t2 >>> 7) | (t3 << 9)) & 0x1fff;
|
||||
this.r[4] = ((t3 >>> 4) | (t4 << 12)) & 0x00ff;
|
||||
this.r[5] = (t4 >>> 1) & 0x1ffe;
|
||||
this.r[6] = ((t4 >>> 14) | (t5 << 2)) & 0x1fff;
|
||||
this.r[7] = ((t5 >>> 11) | (t6 << 5)) & 0x1f81;
|
||||
this.r[8] = ((t6 >>> 8) | (t7 << 8)) & 0x1fff;
|
||||
this.r[9] = (t7 >>> 5) & 0x007f;
|
||||
for (let i = 0; i < 8; i++)
|
||||
this.pad[i] = u8to16(key, 16 + 2 * i);
|
||||
}
|
||||
process(data, offset, isLast = false) {
|
||||
const hibit = isLast ? 0 : 1 << 11;
|
||||
const { h, r } = this;
|
||||
const r0 = r[0];
|
||||
const r1 = r[1];
|
||||
const r2 = r[2];
|
||||
const r3 = r[3];
|
||||
const r4 = r[4];
|
||||
const r5 = r[5];
|
||||
const r6 = r[6];
|
||||
const r7 = r[7];
|
||||
const r8 = r[8];
|
||||
const r9 = r[9];
|
||||
const t0 = u8to16(data, offset + 0);
|
||||
const t1 = u8to16(data, offset + 2);
|
||||
const t2 = u8to16(data, offset + 4);
|
||||
const t3 = u8to16(data, offset + 6);
|
||||
const t4 = u8to16(data, offset + 8);
|
||||
const t5 = u8to16(data, offset + 10);
|
||||
const t6 = u8to16(data, offset + 12);
|
||||
const t7 = u8to16(data, offset + 14);
|
||||
let h0 = h[0] + (t0 & 0x1fff);
|
||||
let h1 = h[1] + (((t0 >>> 13) | (t1 << 3)) & 0x1fff);
|
||||
let h2 = h[2] + (((t1 >>> 10) | (t2 << 6)) & 0x1fff);
|
||||
let h3 = h[3] + (((t2 >>> 7) | (t3 << 9)) & 0x1fff);
|
||||
let h4 = h[4] + (((t3 >>> 4) | (t4 << 12)) & 0x1fff);
|
||||
let h5 = h[5] + ((t4 >>> 1) & 0x1fff);
|
||||
let h6 = h[6] + (((t4 >>> 14) | (t5 << 2)) & 0x1fff);
|
||||
let h7 = h[7] + (((t5 >>> 11) | (t6 << 5)) & 0x1fff);
|
||||
let h8 = h[8] + (((t6 >>> 8) | (t7 << 8)) & 0x1fff);
|
||||
let h9 = h[9] + ((t7 >>> 5) | hibit);
|
||||
let c = 0;
|
||||
let d0 = c + h0 * r0 + h1 * (5 * r9) + h2 * (5 * r8) + h3 * (5 * r7) + h4 * (5 * r6);
|
||||
c = d0 >>> 13;
|
||||
d0 &= 0x1fff;
|
||||
d0 += h5 * (5 * r5) + h6 * (5 * r4) + h7 * (5 * r3) + h8 * (5 * r2) + h9 * (5 * r1);
|
||||
c += d0 >>> 13;
|
||||
d0 &= 0x1fff;
|
||||
let d1 = c + h0 * r1 + h1 * r0 + h2 * (5 * r9) + h3 * (5 * r8) + h4 * (5 * r7);
|
||||
c = d1 >>> 13;
|
||||
d1 &= 0x1fff;
|
||||
d1 += h5 * (5 * r6) + h6 * (5 * r5) + h7 * (5 * r4) + h8 * (5 * r3) + h9 * (5 * r2);
|
||||
c += d1 >>> 13;
|
||||
d1 &= 0x1fff;
|
||||
let d2 = c + h0 * r2 + h1 * r1 + h2 * r0 + h3 * (5 * r9) + h4 * (5 * r8);
|
||||
c = d2 >>> 13;
|
||||
d2 &= 0x1fff;
|
||||
d2 += h5 * (5 * r7) + h6 * (5 * r6) + h7 * (5 * r5) + h8 * (5 * r4) + h9 * (5 * r3);
|
||||
c += d2 >>> 13;
|
||||
d2 &= 0x1fff;
|
||||
let d3 = c + h0 * r3 + h1 * r2 + h2 * r1 + h3 * r0 + h4 * (5 * r9);
|
||||
c = d3 >>> 13;
|
||||
d3 &= 0x1fff;
|
||||
d3 += h5 * (5 * r8) + h6 * (5 * r7) + h7 * (5 * r6) + h8 * (5 * r5) + h9 * (5 * r4);
|
||||
c += d3 >>> 13;
|
||||
d3 &= 0x1fff;
|
||||
let d4 = c + h0 * r4 + h1 * r3 + h2 * r2 + h3 * r1 + h4 * r0;
|
||||
c = d4 >>> 13;
|
||||
d4 &= 0x1fff;
|
||||
d4 += h5 * (5 * r9) + h6 * (5 * r8) + h7 * (5 * r7) + h8 * (5 * r6) + h9 * (5 * r5);
|
||||
c += d4 >>> 13;
|
||||
d4 &= 0x1fff;
|
||||
let d5 = c + h0 * r5 + h1 * r4 + h2 * r3 + h3 * r2 + h4 * r1;
|
||||
c = d5 >>> 13;
|
||||
d5 &= 0x1fff;
|
||||
d5 += h5 * r0 + h6 * (5 * r9) + h7 * (5 * r8) + h8 * (5 * r7) + h9 * (5 * r6);
|
||||
c += d5 >>> 13;
|
||||
d5 &= 0x1fff;
|
||||
let d6 = c + h0 * r6 + h1 * r5 + h2 * r4 + h3 * r3 + h4 * r2;
|
||||
c = d6 >>> 13;
|
||||
d6 &= 0x1fff;
|
||||
d6 += h5 * r1 + h6 * r0 + h7 * (5 * r9) + h8 * (5 * r8) + h9 * (5 * r7);
|
||||
c += d6 >>> 13;
|
||||
d6 &= 0x1fff;
|
||||
let d7 = c + h0 * r7 + h1 * r6 + h2 * r5 + h3 * r4 + h4 * r3;
|
||||
c = d7 >>> 13;
|
||||
d7 &= 0x1fff;
|
||||
d7 += h5 * r2 + h6 * r1 + h7 * r0 + h8 * (5 * r9) + h9 * (5 * r8);
|
||||
c += d7 >>> 13;
|
||||
d7 &= 0x1fff;
|
||||
let d8 = c + h0 * r8 + h1 * r7 + h2 * r6 + h3 * r5 + h4 * r4;
|
||||
c = d8 >>> 13;
|
||||
d8 &= 0x1fff;
|
||||
d8 += h5 * r3 + h6 * r2 + h7 * r1 + h8 * r0 + h9 * (5 * r9);
|
||||
c += d8 >>> 13;
|
||||
d8 &= 0x1fff;
|
||||
let d9 = c + h0 * r9 + h1 * r8 + h2 * r7 + h3 * r6 + h4 * r5;
|
||||
c = d9 >>> 13;
|
||||
d9 &= 0x1fff;
|
||||
d9 += h5 * r4 + h6 * r3 + h7 * r2 + h8 * r1 + h9 * r0;
|
||||
c += d9 >>> 13;
|
||||
d9 &= 0x1fff;
|
||||
c = ((c << 2) + c) | 0;
|
||||
c = (c + d0) | 0;
|
||||
d0 = c & 0x1fff;
|
||||
c = c >>> 13;
|
||||
d1 += c;
|
||||
h[0] = d0;
|
||||
h[1] = d1;
|
||||
h[2] = d2;
|
||||
h[3] = d3;
|
||||
h[4] = d4;
|
||||
h[5] = d5;
|
||||
h[6] = d6;
|
||||
h[7] = d7;
|
||||
h[8] = d8;
|
||||
h[9] = d9;
|
||||
}
|
||||
finalize() {
|
||||
const { h, pad } = this;
|
||||
const g = new Uint16Array(10);
|
||||
let c = h[1] >>> 13;
|
||||
h[1] &= 0x1fff;
|
||||
for (let i = 2; i < 10; i++) {
|
||||
h[i] += c;
|
||||
c = h[i] >>> 13;
|
||||
h[i] &= 0x1fff;
|
||||
}
|
||||
h[0] += c * 5;
|
||||
c = h[0] >>> 13;
|
||||
h[0] &= 0x1fff;
|
||||
h[1] += c;
|
||||
c = h[1] >>> 13;
|
||||
h[1] &= 0x1fff;
|
||||
h[2] += c;
|
||||
g[0] = h[0] + 5;
|
||||
c = g[0] >>> 13;
|
||||
g[0] &= 0x1fff;
|
||||
for (let i = 1; i < 10; i++) {
|
||||
g[i] = h[i] + c;
|
||||
c = g[i] >>> 13;
|
||||
g[i] &= 0x1fff;
|
||||
}
|
||||
g[9] -= 1 << 13;
|
||||
let mask = (c ^ 1) - 1;
|
||||
for (let i = 0; i < 10; i++)
|
||||
g[i] &= mask;
|
||||
mask = ~mask;
|
||||
for (let i = 0; i < 10; i++)
|
||||
h[i] = (h[i] & mask) | g[i];
|
||||
h[0] = (h[0] | (h[1] << 13)) & 0xffff;
|
||||
h[1] = ((h[1] >>> 3) | (h[2] << 10)) & 0xffff;
|
||||
h[2] = ((h[2] >>> 6) | (h[3] << 7)) & 0xffff;
|
||||
h[3] = ((h[3] >>> 9) | (h[4] << 4)) & 0xffff;
|
||||
h[4] = ((h[4] >>> 12) | (h[5] << 1) | (h[6] << 14)) & 0xffff;
|
||||
h[5] = ((h[6] >>> 2) | (h[7] << 11)) & 0xffff;
|
||||
h[6] = ((h[7] >>> 5) | (h[8] << 8)) & 0xffff;
|
||||
h[7] = ((h[8] >>> 8) | (h[9] << 5)) & 0xffff;
|
||||
let f = h[0] + pad[0];
|
||||
h[0] = f & 0xffff;
|
||||
for (let i = 1; i < 8; i++) {
|
||||
f = (((h[i] + pad[i]) | 0) + (f >>> 16)) | 0;
|
||||
h[i] = f & 0xffff;
|
||||
}
|
||||
}
|
||||
update(data) {
|
||||
aexists(this);
|
||||
const { buffer, blockLen } = this;
|
||||
data = toBytes(data);
|
||||
const len = data.length;
|
||||
for (let pos = 0; pos < len;) {
|
||||
const take = Math.min(blockLen - this.pos, len - pos);
|
||||
// Fast path: we have at least one block in input
|
||||
if (take === blockLen) {
|
||||
for (; blockLen <= len - pos; pos += blockLen)
|
||||
this.process(data, pos);
|
||||
continue;
|
||||
}
|
||||
buffer.set(data.subarray(pos, pos + take), this.pos);
|
||||
this.pos += take;
|
||||
pos += take;
|
||||
if (this.pos === blockLen) {
|
||||
this.process(buffer, 0, false);
|
||||
this.pos = 0;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
destroy() {
|
||||
this.h.fill(0);
|
||||
this.r.fill(0);
|
||||
this.buffer.fill(0);
|
||||
this.pad.fill(0);
|
||||
}
|
||||
digestInto(out) {
|
||||
aexists(this);
|
||||
aoutput(out, this);
|
||||
this.finished = true;
|
||||
const { buffer, h } = this;
|
||||
let { pos } = this;
|
||||
if (pos) {
|
||||
buffer[pos++] = 1;
|
||||
// buffer.subarray(pos).fill(0);
|
||||
for (; pos < 16; pos++)
|
||||
buffer[pos] = 0;
|
||||
this.process(buffer, 0, true);
|
||||
}
|
||||
this.finalize();
|
||||
let opos = 0;
|
||||
for (let i = 0; i < 8; i++) {
|
||||
out[opos++] = h[i] >>> 0;
|
||||
out[opos++] = h[i] >>> 8;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
digest() {
|
||||
const { buffer, outputLen } = this;
|
||||
this.digestInto(buffer);
|
||||
const res = buffer.slice(0, outputLen);
|
||||
this.destroy();
|
||||
return res;
|
||||
}
|
||||
}
|
||||
export function wrapConstructorWithKey(hashCons) {
|
||||
const hashC = (msg, key) => hashCons(key).update(toBytes(msg)).digest();
|
||||
const tmp = hashCons(new Uint8Array(32));
|
||||
hashC.outputLen = tmp.outputLen;
|
||||
hashC.blockLen = tmp.blockLen;
|
||||
hashC.create = (key) => hashCons(key);
|
||||
return hashC;
|
||||
}
|
||||
export const poly1305 = wrapConstructorWithKey((key) => new Poly1305(key));
|
||||
//# sourceMappingURL=_poly1305.js.map
|
||||
1
node_modules/@noble/ciphers/esm/_poly1305.js.map
generated
vendored
Normal file
1
node_modules/@noble/ciphers/esm/_poly1305.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
217
node_modules/@noble/ciphers/esm/_polyval.js
generated
vendored
Normal file
217
node_modules/@noble/ciphers/esm/_polyval.js
generated
vendored
Normal file
@@ -0,0 +1,217 @@
|
||||
import { createView, toBytes, u32 } from './utils.js';
|
||||
import { bytes as abytes, exists as aexists, output as aoutput } from './_assert.js';
|
||||
// GHash from AES-GCM and its little-endian "mirror image" Polyval from AES-SIV.
|
||||
// Implemented in terms of GHash with conversion function for keys
|
||||
// GCM GHASH from NIST SP800-38d, SIV from RFC 8452.
|
||||
// https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf
|
||||
// GHASH modulo: x^128 + x^7 + x^2 + x + 1
|
||||
// POLYVAL modulo: x^128 + x^127 + x^126 + x^121 + 1
|
||||
const BLOCK_SIZE = 16;
|
||||
// TODO: rewrite
|
||||
// temporary padding buffer
|
||||
const ZEROS16 = /* @__PURE__ */ new Uint8Array(16);
|
||||
const ZEROS32 = u32(ZEROS16);
|
||||
const POLY = 0xe1; // v = 2*v % POLY
|
||||
// v = 2*v % POLY
|
||||
// NOTE: because x + x = 0 (add/sub is same), mul2(x) != x+x
|
||||
// We can multiply any number using montgomery ladder and this function (works as double, add is simple xor)
|
||||
const mul2 = (s0, s1, s2, s3) => {
|
||||
const hiBit = s3 & 1;
|
||||
return {
|
||||
s3: (s2 << 31) | (s3 >>> 1),
|
||||
s2: (s1 << 31) | (s2 >>> 1),
|
||||
s1: (s0 << 31) | (s1 >>> 1),
|
||||
s0: (s0 >>> 1) ^ ((POLY << 24) & -(hiBit & 1)), // reduce % poly
|
||||
};
|
||||
};
|
||||
const swapLE = (n) => (((n >>> 0) & 0xff) << 24) |
|
||||
(((n >>> 8) & 0xff) << 16) |
|
||||
(((n >>> 16) & 0xff) << 8) |
|
||||
((n >>> 24) & 0xff) |
|
||||
0;
|
||||
/**
|
||||
* `mulX_POLYVAL(ByteReverse(H))` from spec
|
||||
* @param k mutated in place
|
||||
*/
|
||||
export function _toGHASHKey(k) {
|
||||
k.reverse();
|
||||
const hiBit = k[15] & 1;
|
||||
// k >>= 1
|
||||
let carry = 0;
|
||||
for (let i = 0; i < k.length; i++) {
|
||||
const t = k[i];
|
||||
k[i] = (t >>> 1) | carry;
|
||||
carry = (t & 1) << 7;
|
||||
}
|
||||
k[0] ^= -hiBit & 0xe1; // if (hiBit) n ^= 0xe1000000000000000000000000000000;
|
||||
return k;
|
||||
}
|
||||
const estimateWindow = (bytes) => {
|
||||
if (bytes > 64 * 1024)
|
||||
return 8;
|
||||
if (bytes > 1024)
|
||||
return 4;
|
||||
return 2;
|
||||
};
|
||||
class GHASH {
|
||||
// We select bits per window adaptively based on expectedLength
|
||||
constructor(key, expectedLength) {
|
||||
this.blockLen = BLOCK_SIZE;
|
||||
this.outputLen = BLOCK_SIZE;
|
||||
this.s0 = 0;
|
||||
this.s1 = 0;
|
||||
this.s2 = 0;
|
||||
this.s3 = 0;
|
||||
this.finished = false;
|
||||
key = toBytes(key);
|
||||
abytes(key, 16);
|
||||
const kView = createView(key);
|
||||
let k0 = kView.getUint32(0, false);
|
||||
let k1 = kView.getUint32(4, false);
|
||||
let k2 = kView.getUint32(8, false);
|
||||
let k3 = kView.getUint32(12, false);
|
||||
// generate table of doubled keys (half of montgomery ladder)
|
||||
const doubles = [];
|
||||
for (let i = 0; i < 128; i++) {
|
||||
doubles.push({ s0: swapLE(k0), s1: swapLE(k1), s2: swapLE(k2), s3: swapLE(k3) });
|
||||
({ s0: k0, s1: k1, s2: k2, s3: k3 } = mul2(k0, k1, k2, k3));
|
||||
}
|
||||
const W = estimateWindow(expectedLength || 1024);
|
||||
if (![1, 2, 4, 8].includes(W))
|
||||
throw new Error(`ghash: wrong window size=${W}, should be 2, 4 or 8`);
|
||||
this.W = W;
|
||||
const bits = 128; // always 128 bits;
|
||||
const windows = bits / W;
|
||||
const windowSize = (this.windowSize = 2 ** W);
|
||||
const items = [];
|
||||
// Create precompute table for window of W bits
|
||||
for (let w = 0; w < windows; w++) {
|
||||
// truth table: 00, 01, 10, 11
|
||||
for (let byte = 0; byte < windowSize; byte++) {
|
||||
// prettier-ignore
|
||||
let s0 = 0, s1 = 0, s2 = 0, s3 = 0;
|
||||
for (let j = 0; j < W; j++) {
|
||||
const bit = (byte >>> (W - j - 1)) & 1;
|
||||
if (!bit)
|
||||
continue;
|
||||
const { s0: d0, s1: d1, s2: d2, s3: d3 } = doubles[W * w + j];
|
||||
(s0 ^= d0), (s1 ^= d1), (s2 ^= d2), (s3 ^= d3);
|
||||
}
|
||||
items.push({ s0, s1, s2, s3 });
|
||||
}
|
||||
}
|
||||
this.t = items;
|
||||
}
|
||||
_updateBlock(s0, s1, s2, s3) {
|
||||
(s0 ^= this.s0), (s1 ^= this.s1), (s2 ^= this.s2), (s3 ^= this.s3);
|
||||
const { W, t, windowSize } = this;
|
||||
// prettier-ignore
|
||||
let o0 = 0, o1 = 0, o2 = 0, o3 = 0;
|
||||
const mask = (1 << W) - 1; // 2**W will kill performance.
|
||||
let w = 0;
|
||||
for (const num of [s0, s1, s2, s3]) {
|
||||
for (let bytePos = 0; bytePos < 4; bytePos++) {
|
||||
const byte = (num >>> (8 * bytePos)) & 0xff;
|
||||
for (let bitPos = 8 / W - 1; bitPos >= 0; bitPos--) {
|
||||
const bit = (byte >>> (W * bitPos)) & mask;
|
||||
const { s0: e0, s1: e1, s2: e2, s3: e3 } = t[w * windowSize + bit];
|
||||
(o0 ^= e0), (o1 ^= e1), (o2 ^= e2), (o3 ^= e3);
|
||||
w += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.s0 = o0;
|
||||
this.s1 = o1;
|
||||
this.s2 = o2;
|
||||
this.s3 = o3;
|
||||
}
|
||||
update(data) {
|
||||
data = toBytes(data);
|
||||
aexists(this);
|
||||
const b32 = u32(data);
|
||||
const blocks = Math.floor(data.length / BLOCK_SIZE);
|
||||
const left = data.length % BLOCK_SIZE;
|
||||
for (let i = 0; i < blocks; i++) {
|
||||
this._updateBlock(b32[i * 4 + 0], b32[i * 4 + 1], b32[i * 4 + 2], b32[i * 4 + 3]);
|
||||
}
|
||||
if (left) {
|
||||
ZEROS16.set(data.subarray(blocks * BLOCK_SIZE));
|
||||
this._updateBlock(ZEROS32[0], ZEROS32[1], ZEROS32[2], ZEROS32[3]);
|
||||
ZEROS32.fill(0); // clean tmp buffer
|
||||
}
|
||||
return this;
|
||||
}
|
||||
destroy() {
|
||||
const { t } = this;
|
||||
// clean precompute table
|
||||
for (const elm of t) {
|
||||
(elm.s0 = 0), (elm.s1 = 0), (elm.s2 = 0), (elm.s3 = 0);
|
||||
}
|
||||
}
|
||||
digestInto(out) {
|
||||
aexists(this);
|
||||
aoutput(out, this);
|
||||
this.finished = true;
|
||||
const { s0, s1, s2, s3 } = this;
|
||||
const o32 = u32(out);
|
||||
o32[0] = s0;
|
||||
o32[1] = s1;
|
||||
o32[2] = s2;
|
||||
o32[3] = s3;
|
||||
return out;
|
||||
}
|
||||
digest() {
|
||||
const res = new Uint8Array(BLOCK_SIZE);
|
||||
this.digestInto(res);
|
||||
this.destroy();
|
||||
return res;
|
||||
}
|
||||
}
|
||||
class Polyval extends GHASH {
|
||||
constructor(key, expectedLength) {
|
||||
key = toBytes(key);
|
||||
const ghKey = _toGHASHKey(key.slice());
|
||||
super(ghKey, expectedLength);
|
||||
ghKey.fill(0);
|
||||
}
|
||||
update(data) {
|
||||
data = toBytes(data);
|
||||
aexists(this);
|
||||
const b32 = u32(data);
|
||||
const left = data.length % BLOCK_SIZE;
|
||||
const blocks = Math.floor(data.length / BLOCK_SIZE);
|
||||
for (let i = 0; i < blocks; i++) {
|
||||
this._updateBlock(swapLE(b32[i * 4 + 3]), swapLE(b32[i * 4 + 2]), swapLE(b32[i * 4 + 1]), swapLE(b32[i * 4 + 0]));
|
||||
}
|
||||
if (left) {
|
||||
ZEROS16.set(data.subarray(blocks * BLOCK_SIZE));
|
||||
this._updateBlock(swapLE(ZEROS32[3]), swapLE(ZEROS32[2]), swapLE(ZEROS32[1]), swapLE(ZEROS32[0]));
|
||||
ZEROS32.fill(0); // clean tmp buffer
|
||||
}
|
||||
return this;
|
||||
}
|
||||
digestInto(out) {
|
||||
aexists(this);
|
||||
aoutput(out, this);
|
||||
this.finished = true;
|
||||
// tmp ugly hack
|
||||
const { s0, s1, s2, s3 } = this;
|
||||
const o32 = u32(out);
|
||||
o32[0] = s0;
|
||||
o32[1] = s1;
|
||||
o32[2] = s2;
|
||||
o32[3] = s3;
|
||||
return out.reverse();
|
||||
}
|
||||
}
|
||||
function wrapConstructorWithKey(hashCons) {
|
||||
const hashC = (msg, key) => hashCons(key, msg.length).update(toBytes(msg)).digest();
|
||||
const tmp = hashCons(new Uint8Array(16), 0);
|
||||
hashC.outputLen = tmp.outputLen;
|
||||
hashC.blockLen = tmp.blockLen;
|
||||
hashC.create = (key, expectedLength) => hashCons(key, expectedLength);
|
||||
return hashC;
|
||||
}
|
||||
export const ghash = wrapConstructorWithKey((key, expectedLength) => new GHASH(key, expectedLength));
|
||||
export const polyval = wrapConstructorWithKey((key, expectedLength) => new Polyval(key, expectedLength));
|
||||
//# sourceMappingURL=_polyval.js.map
|
||||
1
node_modules/@noble/ciphers/esm/_polyval.js.map
generated
vendored
Normal file
1
node_modules/@noble/ciphers/esm/_polyval.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
670
node_modules/@noble/ciphers/esm/aes.js
generated
vendored
Normal file
670
node_modules/@noble/ciphers/esm/aes.js
generated
vendored
Normal file
@@ -0,0 +1,670 @@
|
||||
// prettier-ignore
|
||||
import { wrapCipher, createView, setBigUint64, equalBytes, u32, u8, } from './utils.js';
|
||||
import { ghash, polyval } from './_polyval.js';
|
||||
import { bytes as abytes } from './_assert.js';
|
||||
/*
|
||||
AES (Advanced Encryption Standard) aka Rijndael block cipher.
|
||||
|
||||
Data is split into 128-bit blocks. Encrypted in 10/12/14 rounds (128/192/256 bits). In every round:
|
||||
1. **S-box**, table substitution
|
||||
2. **Shift rows**, cyclic shift left of all rows of data array
|
||||
3. **Mix columns**, multiplying every column by fixed polynomial
|
||||
4. **Add round key**, round_key xor i-th column of array
|
||||
|
||||
Resources:
|
||||
- FIPS-197 https://csrc.nist.gov/files/pubs/fips/197/final/docs/fips-197.pdf
|
||||
- Original proposal: https://csrc.nist.gov/csrc/media/projects/cryptographic-standards-and-guidelines/documents/aes-development/rijndael-ammended.pdf
|
||||
*/
|
||||
const BLOCK_SIZE = 16;
|
||||
const BLOCK_SIZE32 = 4;
|
||||
const EMPTY_BLOCK = new Uint8Array(BLOCK_SIZE);
|
||||
const POLY = 0x11b; // 1 + x + x**3 + x**4 + x**8
|
||||
// TODO: remove multiplication, binary ops only
|
||||
function mul2(n) {
|
||||
return (n << 1) ^ (POLY & -(n >> 7));
|
||||
}
|
||||
function mul(a, b) {
|
||||
let res = 0;
|
||||
for (; b > 0; b >>= 1) {
|
||||
// Montgomery ladder
|
||||
res ^= a & -(b & 1); // if (b&1) res ^=a (but const-time).
|
||||
a = mul2(a); // a = 2*a
|
||||
}
|
||||
return res;
|
||||
}
|
||||
// AES S-box is generated using finite field inversion,
|
||||
// an affine transform, and xor of a constant 0x63.
|
||||
const sbox = /* @__PURE__ */ (() => {
|
||||
let t = new Uint8Array(256);
|
||||
for (let i = 0, x = 1; i < 256; i++, x ^= mul2(x))
|
||||
t[i] = x;
|
||||
const box = new Uint8Array(256);
|
||||
box[0] = 0x63; // first elm
|
||||
for (let i = 0; i < 255; i++) {
|
||||
let x = t[255 - i];
|
||||
x |= x << 8;
|
||||
box[t[i]] = (x ^ (x >> 4) ^ (x >> 5) ^ (x >> 6) ^ (x >> 7) ^ 0x63) & 0xff;
|
||||
}
|
||||
return box;
|
||||
})();
|
||||
// Inverted S-box
|
||||
const invSbox = /* @__PURE__ */ sbox.map((_, j) => sbox.indexOf(j));
|
||||
// Rotate u32 by 8
|
||||
const rotr32_8 = (n) => (n << 24) | (n >>> 8);
|
||||
const rotl32_8 = (n) => (n << 8) | (n >>> 24);
|
||||
// T-table is optimization suggested in 5.2 of original proposal (missed from FIPS-197). Changes:
|
||||
// - LE instead of BE
|
||||
// - bigger tables: T0 and T1 are merged into T01 table and T2 & T3 into T23;
|
||||
// so index is u16, instead of u8. This speeds up things, unexpectedly
|
||||
function genTtable(sbox, fn) {
|
||||
if (sbox.length !== 256)
|
||||
throw new Error('Wrong sbox length');
|
||||
const T0 = new Uint32Array(256).map((_, j) => fn(sbox[j]));
|
||||
const T1 = T0.map(rotl32_8);
|
||||
const T2 = T1.map(rotl32_8);
|
||||
const T3 = T2.map(rotl32_8);
|
||||
const T01 = new Uint32Array(256 * 256);
|
||||
const T23 = new Uint32Array(256 * 256);
|
||||
const sbox2 = new Uint16Array(256 * 256);
|
||||
for (let i = 0; i < 256; i++) {
|
||||
for (let j = 0; j < 256; j++) {
|
||||
const idx = i * 256 + j;
|
||||
T01[idx] = T0[i] ^ T1[j];
|
||||
T23[idx] = T2[i] ^ T3[j];
|
||||
sbox2[idx] = (sbox[i] << 8) | sbox[j];
|
||||
}
|
||||
}
|
||||
return { sbox, sbox2, T0, T1, T2, T3, T01, T23 };
|
||||
}
|
||||
const tableEncoding = /* @__PURE__ */ genTtable(sbox, (s) => (mul(s, 3) << 24) | (s << 16) | (s << 8) | mul(s, 2));
|
||||
const tableDecoding = /* @__PURE__ */ genTtable(invSbox, (s) => (mul(s, 11) << 24) | (mul(s, 13) << 16) | (mul(s, 9) << 8) | mul(s, 14));
|
||||
const xPowers = /* @__PURE__ */ (() => {
|
||||
const p = new Uint8Array(16);
|
||||
for (let i = 0, x = 1; i < 16; i++, x = mul2(x))
|
||||
p[i] = x;
|
||||
return p;
|
||||
})();
|
||||
export function expandKeyLE(key) {
|
||||
abytes(key);
|
||||
const len = key.length;
|
||||
if (![16, 24, 32].includes(len))
|
||||
throw new Error(`aes: wrong key size: should be 16, 24 or 32, got: ${len}`);
|
||||
const { sbox2 } = tableEncoding;
|
||||
const k32 = u32(key);
|
||||
const Nk = k32.length;
|
||||
const subByte = (n) => applySbox(sbox2, n, n, n, n);
|
||||
const xk = new Uint32Array(len + 28); // expanded key
|
||||
xk.set(k32);
|
||||
// 4.3.1 Key expansion
|
||||
for (let i = Nk; i < xk.length; i++) {
|
||||
let t = xk[i - 1];
|
||||
if (i % Nk === 0)
|
||||
t = subByte(rotr32_8(t)) ^ xPowers[i / Nk - 1];
|
||||
else if (Nk > 6 && i % Nk === 4)
|
||||
t = subByte(t);
|
||||
xk[i] = xk[i - Nk] ^ t;
|
||||
}
|
||||
return xk;
|
||||
}
|
||||
export function expandKeyDecLE(key) {
|
||||
const encKey = expandKeyLE(key);
|
||||
const xk = encKey.slice();
|
||||
const Nk = encKey.length;
|
||||
const { sbox2 } = tableEncoding;
|
||||
const { T0, T1, T2, T3 } = tableDecoding;
|
||||
// Inverse key by chunks of 4 (rounds)
|
||||
for (let i = 0; i < Nk; i += 4) {
|
||||
for (let j = 0; j < 4; j++)
|
||||
xk[i + j] = encKey[Nk - i - 4 + j];
|
||||
}
|
||||
encKey.fill(0);
|
||||
// apply InvMixColumn except first & last round
|
||||
for (let i = 4; i < Nk - 4; i++) {
|
||||
const x = xk[i];
|
||||
const w = applySbox(sbox2, x, x, x, x);
|
||||
xk[i] = T0[w & 0xff] ^ T1[(w >>> 8) & 0xff] ^ T2[(w >>> 16) & 0xff] ^ T3[w >>> 24];
|
||||
}
|
||||
return xk;
|
||||
}
|
||||
// Apply tables
|
||||
function apply0123(T01, T23, s0, s1, s2, s3) {
|
||||
return (T01[((s0 << 8) & 0xff00) | ((s1 >>> 8) & 0xff)] ^
|
||||
T23[((s2 >>> 8) & 0xff00) | ((s3 >>> 24) & 0xff)]);
|
||||
}
|
||||
function applySbox(sbox2, s0, s1, s2, s3) {
|
||||
return (sbox2[(s0 & 0xff) | (s1 & 0xff00)] |
|
||||
(sbox2[((s2 >>> 16) & 0xff) | ((s3 >>> 16) & 0xff00)] << 16));
|
||||
}
|
||||
function encrypt(xk, s0, s1, s2, s3) {
|
||||
const { sbox2, T01, T23 } = tableEncoding;
|
||||
let k = 0;
|
||||
(s0 ^= xk[k++]), (s1 ^= xk[k++]), (s2 ^= xk[k++]), (s3 ^= xk[k++]);
|
||||
const rounds = xk.length / 4 - 2;
|
||||
for (let i = 0; i < rounds; i++) {
|
||||
const t0 = xk[k++] ^ apply0123(T01, T23, s0, s1, s2, s3);
|
||||
const t1 = xk[k++] ^ apply0123(T01, T23, s1, s2, s3, s0);
|
||||
const t2 = xk[k++] ^ apply0123(T01, T23, s2, s3, s0, s1);
|
||||
const t3 = xk[k++] ^ apply0123(T01, T23, s3, s0, s1, s2);
|
||||
(s0 = t0), (s1 = t1), (s2 = t2), (s3 = t3);
|
||||
}
|
||||
// last round (without mixcolumns, so using SBOX2 table)
|
||||
const t0 = xk[k++] ^ applySbox(sbox2, s0, s1, s2, s3);
|
||||
const t1 = xk[k++] ^ applySbox(sbox2, s1, s2, s3, s0);
|
||||
const t2 = xk[k++] ^ applySbox(sbox2, s2, s3, s0, s1);
|
||||
const t3 = xk[k++] ^ applySbox(sbox2, s3, s0, s1, s2);
|
||||
return { s0: t0, s1: t1, s2: t2, s3: t3 };
|
||||
}
|
||||
function decrypt(xk, s0, s1, s2, s3) {
|
||||
const { sbox2, T01, T23 } = tableDecoding;
|
||||
let k = 0;
|
||||
(s0 ^= xk[k++]), (s1 ^= xk[k++]), (s2 ^= xk[k++]), (s3 ^= xk[k++]);
|
||||
const rounds = xk.length / 4 - 2;
|
||||
for (let i = 0; i < rounds; i++) {
|
||||
const t0 = xk[k++] ^ apply0123(T01, T23, s0, s3, s2, s1);
|
||||
const t1 = xk[k++] ^ apply0123(T01, T23, s1, s0, s3, s2);
|
||||
const t2 = xk[k++] ^ apply0123(T01, T23, s2, s1, s0, s3);
|
||||
const t3 = xk[k++] ^ apply0123(T01, T23, s3, s2, s1, s0);
|
||||
(s0 = t0), (s1 = t1), (s2 = t2), (s3 = t3);
|
||||
}
|
||||
// Last round
|
||||
const t0 = xk[k++] ^ applySbox(sbox2, s0, s3, s2, s1);
|
||||
const t1 = xk[k++] ^ applySbox(sbox2, s1, s0, s3, s2);
|
||||
const t2 = xk[k++] ^ applySbox(sbox2, s2, s1, s0, s3);
|
||||
const t3 = xk[k++] ^ applySbox(sbox2, s3, s2, s1, s0);
|
||||
return { s0: t0, s1: t1, s2: t2, s3: t3 };
|
||||
}
|
||||
function getDst(len, dst) {
|
||||
if (!dst)
|
||||
return new Uint8Array(len);
|
||||
abytes(dst);
|
||||
if (dst.length < len)
|
||||
throw new Error(`aes: wrong destination length, expected at least ${len}, got: ${dst.length}`);
|
||||
return dst;
|
||||
}
|
||||
// TODO: investigate merging with ctr32
|
||||
function ctrCounter(xk, nonce, src, dst) {
|
||||
abytes(nonce, BLOCK_SIZE);
|
||||
abytes(src);
|
||||
const srcLen = src.length;
|
||||
dst = getDst(srcLen, dst);
|
||||
const ctr = nonce;
|
||||
const c32 = u32(ctr);
|
||||
// Fill block (empty, ctr=0)
|
||||
let { s0, s1, s2, s3 } = encrypt(xk, c32[0], c32[1], c32[2], c32[3]);
|
||||
const src32 = u32(src);
|
||||
const dst32 = u32(dst);
|
||||
// process blocks
|
||||
for (let i = 0; i + 4 <= src32.length; i += 4) {
|
||||
dst32[i + 0] = src32[i + 0] ^ s0;
|
||||
dst32[i + 1] = src32[i + 1] ^ s1;
|
||||
dst32[i + 2] = src32[i + 2] ^ s2;
|
||||
dst32[i + 3] = src32[i + 3] ^ s3;
|
||||
// Full 128 bit counter with wrap around
|
||||
let carry = 1;
|
||||
for (let i = ctr.length - 1; i >= 0; i--) {
|
||||
carry = (carry + (ctr[i] & 0xff)) | 0;
|
||||
ctr[i] = carry & 0xff;
|
||||
carry >>>= 8;
|
||||
}
|
||||
({ s0, s1, s2, s3 } = encrypt(xk, c32[0], c32[1], c32[2], c32[3]));
|
||||
}
|
||||
// leftovers (less than block)
|
||||
// It's possible to handle > u32 fast, but is it worth it?
|
||||
const start = BLOCK_SIZE * Math.floor(src32.length / BLOCK_SIZE32);
|
||||
if (start < srcLen) {
|
||||
const b32 = new Uint32Array([s0, s1, s2, s3]);
|
||||
const buf = u8(b32);
|
||||
for (let i = start, pos = 0; i < srcLen; i++, pos++)
|
||||
dst[i] = src[i] ^ buf[pos];
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
// AES CTR with overflowing 32 bit counter
|
||||
// It's possible to do 32le significantly simpler (and probably faster) by using u32.
|
||||
// But, we need both, and perf bottleneck is in ghash anyway.
|
||||
function ctr32(xk, isLE, nonce, src, dst) {
|
||||
abytes(nonce, BLOCK_SIZE);
|
||||
abytes(src);
|
||||
dst = getDst(src.length, dst);
|
||||
const ctr = nonce; // write new value to nonce, so it can be re-used
|
||||
const c32 = u32(ctr);
|
||||
const view = createView(ctr);
|
||||
const src32 = u32(src);
|
||||
const dst32 = u32(dst);
|
||||
const ctrPos = isLE ? 0 : 12;
|
||||
const srcLen = src.length;
|
||||
// Fill block (empty, ctr=0)
|
||||
let ctrNum = view.getUint32(ctrPos, isLE); // read current counter value
|
||||
let { s0, s1, s2, s3 } = encrypt(xk, c32[0], c32[1], c32[2], c32[3]);
|
||||
// process blocks
|
||||
for (let i = 0; i + 4 <= src32.length; i += 4) {
|
||||
dst32[i + 0] = src32[i + 0] ^ s0;
|
||||
dst32[i + 1] = src32[i + 1] ^ s1;
|
||||
dst32[i + 2] = src32[i + 2] ^ s2;
|
||||
dst32[i + 3] = src32[i + 3] ^ s3;
|
||||
ctrNum = (ctrNum + 1) >>> 0; // u32 wrap
|
||||
view.setUint32(ctrPos, ctrNum, isLE);
|
||||
({ s0, s1, s2, s3 } = encrypt(xk, c32[0], c32[1], c32[2], c32[3]));
|
||||
}
|
||||
// leftovers (less than a block)
|
||||
const start = BLOCK_SIZE * Math.floor(src32.length / BLOCK_SIZE32);
|
||||
if (start < srcLen) {
|
||||
const b32 = new Uint32Array([s0, s1, s2, s3]);
|
||||
const buf = u8(b32);
|
||||
for (let i = start, pos = 0; i < srcLen; i++, pos++)
|
||||
dst[i] = src[i] ^ buf[pos];
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
/**
|
||||
* CTR: counter mode. Creates stream cipher.
|
||||
* Requires good IV. Parallelizable. OK, but no MAC.
|
||||
*/
|
||||
export const ctr = wrapCipher({ blockSize: 16, nonceLength: 16 }, function ctr(key, nonce) {
|
||||
abytes(key);
|
||||
abytes(nonce, BLOCK_SIZE);
|
||||
function processCtr(buf, dst) {
|
||||
const xk = expandKeyLE(key);
|
||||
const n = nonce.slice();
|
||||
const out = ctrCounter(xk, n, buf, dst);
|
||||
xk.fill(0);
|
||||
n.fill(0);
|
||||
return out;
|
||||
}
|
||||
return {
|
||||
encrypt: (plaintext, dst) => processCtr(plaintext, dst),
|
||||
decrypt: (ciphertext, dst) => processCtr(ciphertext, dst),
|
||||
};
|
||||
});
|
||||
function validateBlockDecrypt(data) {
|
||||
abytes(data);
|
||||
if (data.length % BLOCK_SIZE !== 0) {
|
||||
throw new Error(`aes/(cbc-ecb).decrypt ciphertext should consist of blocks with size ${BLOCK_SIZE}`);
|
||||
}
|
||||
}
|
||||
function validateBlockEncrypt(plaintext, pcks5, dst) {
|
||||
let outLen = plaintext.length;
|
||||
const remaining = outLen % BLOCK_SIZE;
|
||||
if (!pcks5 && remaining !== 0)
|
||||
throw new Error('aec/(cbc-ecb): unpadded plaintext with disabled padding');
|
||||
const b = u32(plaintext);
|
||||
if (pcks5) {
|
||||
let left = BLOCK_SIZE - remaining;
|
||||
if (!left)
|
||||
left = BLOCK_SIZE; // if no bytes left, create empty padding block
|
||||
outLen = outLen + left;
|
||||
}
|
||||
const out = getDst(outLen, dst);
|
||||
const o = u32(out);
|
||||
return { b, o, out };
|
||||
}
|
||||
function validatePCKS(data, pcks5) {
|
||||
if (!pcks5)
|
||||
return data;
|
||||
const len = data.length;
|
||||
if (!len)
|
||||
throw new Error(`aes/pcks5: empty ciphertext not allowed`);
|
||||
const lastByte = data[len - 1];
|
||||
if (lastByte <= 0 || lastByte > 16)
|
||||
throw new Error(`aes/pcks5: wrong padding byte: ${lastByte}`);
|
||||
const out = data.subarray(0, -lastByte);
|
||||
for (let i = 0; i < lastByte; i++)
|
||||
if (data[len - i - 1] !== lastByte)
|
||||
throw new Error(`aes/pcks5: wrong padding`);
|
||||
return out;
|
||||
}
|
||||
function padPCKS(left) {
|
||||
const tmp = new Uint8Array(16);
|
||||
const tmp32 = u32(tmp);
|
||||
tmp.set(left);
|
||||
const paddingByte = BLOCK_SIZE - left.length;
|
||||
for (let i = BLOCK_SIZE - paddingByte; i < BLOCK_SIZE; i++)
|
||||
tmp[i] = paddingByte;
|
||||
return tmp32;
|
||||
}
|
||||
/**
|
||||
* ECB: Electronic CodeBook. Simple deterministic replacement.
|
||||
* Dangerous: always map x to y. See [AES Penguin](https://words.filippo.io/the-ecb-penguin/).
|
||||
*/
|
||||
export const ecb = wrapCipher({ blockSize: 16 }, function ecb(key, opts = {}) {
|
||||
abytes(key);
|
||||
const pcks5 = !opts.disablePadding;
|
||||
return {
|
||||
encrypt: (plaintext, dst) => {
|
||||
abytes(plaintext);
|
||||
const { b, o, out: _out } = validateBlockEncrypt(plaintext, pcks5, dst);
|
||||
const xk = expandKeyLE(key);
|
||||
let i = 0;
|
||||
for (; i + 4 <= b.length;) {
|
||||
const { s0, s1, s2, s3 } = encrypt(xk, b[i + 0], b[i + 1], b[i + 2], b[i + 3]);
|
||||
(o[i++] = s0), (o[i++] = s1), (o[i++] = s2), (o[i++] = s3);
|
||||
}
|
||||
if (pcks5) {
|
||||
const tmp32 = padPCKS(plaintext.subarray(i * 4));
|
||||
const { s0, s1, s2, s3 } = encrypt(xk, tmp32[0], tmp32[1], tmp32[2], tmp32[3]);
|
||||
(o[i++] = s0), (o[i++] = s1), (o[i++] = s2), (o[i++] = s3);
|
||||
}
|
||||
xk.fill(0);
|
||||
return _out;
|
||||
},
|
||||
decrypt: (ciphertext, dst) => {
|
||||
validateBlockDecrypt(ciphertext);
|
||||
const xk = expandKeyDecLE(key);
|
||||
const out = getDst(ciphertext.length, dst);
|
||||
const b = u32(ciphertext);
|
||||
const o = u32(out);
|
||||
for (let i = 0; i + 4 <= b.length;) {
|
||||
const { s0, s1, s2, s3 } = decrypt(xk, b[i + 0], b[i + 1], b[i + 2], b[i + 3]);
|
||||
(o[i++] = s0), (o[i++] = s1), (o[i++] = s2), (o[i++] = s3);
|
||||
}
|
||||
xk.fill(0);
|
||||
return validatePCKS(out, pcks5);
|
||||
},
|
||||
};
|
||||
});
|
||||
/**
|
||||
* CBC: Cipher-Block-Chaining. Key is previous round’s block.
|
||||
* Fragile: needs proper padding. Unauthenticated: needs MAC.
|
||||
*/
|
||||
export const cbc = wrapCipher({ blockSize: 16, nonceLength: 16 }, function cbc(key, iv, opts = {}) {
|
||||
abytes(key);
|
||||
abytes(iv, 16);
|
||||
const pcks5 = !opts.disablePadding;
|
||||
return {
|
||||
encrypt: (plaintext, dst) => {
|
||||
const xk = expandKeyLE(key);
|
||||
const { b, o, out: _out } = validateBlockEncrypt(plaintext, pcks5, dst);
|
||||
const n32 = u32(iv);
|
||||
// prettier-ignore
|
||||
let s0 = n32[0], s1 = n32[1], s2 = n32[2], s3 = n32[3];
|
||||
let i = 0;
|
||||
for (; i + 4 <= b.length;) {
|
||||
(s0 ^= b[i + 0]), (s1 ^= b[i + 1]), (s2 ^= b[i + 2]), (s3 ^= b[i + 3]);
|
||||
({ s0, s1, s2, s3 } = encrypt(xk, s0, s1, s2, s3));
|
||||
(o[i++] = s0), (o[i++] = s1), (o[i++] = s2), (o[i++] = s3);
|
||||
}
|
||||
if (pcks5) {
|
||||
const tmp32 = padPCKS(plaintext.subarray(i * 4));
|
||||
(s0 ^= tmp32[0]), (s1 ^= tmp32[1]), (s2 ^= tmp32[2]), (s3 ^= tmp32[3]);
|
||||
({ s0, s1, s2, s3 } = encrypt(xk, s0, s1, s2, s3));
|
||||
(o[i++] = s0), (o[i++] = s1), (o[i++] = s2), (o[i++] = s3);
|
||||
}
|
||||
xk.fill(0);
|
||||
return _out;
|
||||
},
|
||||
decrypt: (ciphertext, dst) => {
|
||||
validateBlockDecrypt(ciphertext);
|
||||
const xk = expandKeyDecLE(key);
|
||||
const n32 = u32(iv);
|
||||
const out = getDst(ciphertext.length, dst);
|
||||
const b = u32(ciphertext);
|
||||
const o = u32(out);
|
||||
// prettier-ignore
|
||||
let s0 = n32[0], s1 = n32[1], s2 = n32[2], s3 = n32[3];
|
||||
for (let i = 0; i + 4 <= b.length;) {
|
||||
// prettier-ignore
|
||||
const ps0 = s0, ps1 = s1, ps2 = s2, ps3 = s3;
|
||||
(s0 = b[i + 0]), (s1 = b[i + 1]), (s2 = b[i + 2]), (s3 = b[i + 3]);
|
||||
const { s0: o0, s1: o1, s2: o2, s3: o3 } = decrypt(xk, s0, s1, s2, s3);
|
||||
(o[i++] = o0 ^ ps0), (o[i++] = o1 ^ ps1), (o[i++] = o2 ^ ps2), (o[i++] = o3 ^ ps3);
|
||||
}
|
||||
xk.fill(0);
|
||||
return validatePCKS(out, pcks5);
|
||||
},
|
||||
};
|
||||
});
|
||||
/**
|
||||
* CFB: Cipher Feedback Mode. The input for the block cipher is the previous cipher output.
|
||||
* Unauthenticated: needs MAC.
|
||||
*/
|
||||
export const cfb = wrapCipher({ blockSize: 16, nonceLength: 16 }, function cfb(key, iv) {
|
||||
abytes(key);
|
||||
abytes(iv, 16);
|
||||
function processCfb(src, isEncrypt, dst) {
|
||||
const xk = expandKeyLE(key);
|
||||
const srcLen = src.length;
|
||||
dst = getDst(srcLen, dst);
|
||||
const src32 = u32(src);
|
||||
const dst32 = u32(dst);
|
||||
const next32 = isEncrypt ? dst32 : src32;
|
||||
const n32 = u32(iv);
|
||||
// prettier-ignore
|
||||
let s0 = n32[0], s1 = n32[1], s2 = n32[2], s3 = n32[3];
|
||||
for (let i = 0; i + 4 <= src32.length;) {
|
||||
const { s0: e0, s1: e1, s2: e2, s3: e3 } = encrypt(xk, s0, s1, s2, s3);
|
||||
dst32[i + 0] = src32[i + 0] ^ e0;
|
||||
dst32[i + 1] = src32[i + 1] ^ e1;
|
||||
dst32[i + 2] = src32[i + 2] ^ e2;
|
||||
dst32[i + 3] = src32[i + 3] ^ e3;
|
||||
(s0 = next32[i++]), (s1 = next32[i++]), (s2 = next32[i++]), (s3 = next32[i++]);
|
||||
}
|
||||
// leftovers (less than block)
|
||||
const start = BLOCK_SIZE * Math.floor(src32.length / BLOCK_SIZE32);
|
||||
if (start < srcLen) {
|
||||
({ s0, s1, s2, s3 } = encrypt(xk, s0, s1, s2, s3));
|
||||
const buf = u8(new Uint32Array([s0, s1, s2, s3]));
|
||||
for (let i = start, pos = 0; i < srcLen; i++, pos++)
|
||||
dst[i] = src[i] ^ buf[pos];
|
||||
buf.fill(0);
|
||||
}
|
||||
xk.fill(0);
|
||||
return dst;
|
||||
}
|
||||
return {
|
||||
encrypt: (plaintext, dst) => processCfb(plaintext, true, dst),
|
||||
decrypt: (ciphertext, dst) => processCfb(ciphertext, false, dst),
|
||||
};
|
||||
});
|
||||
// TODO: merge with chacha, however gcm has bitLen while chacha has byteLen
|
||||
function computeTag(fn, isLE, key, data, AAD) {
|
||||
const h = fn.create(key, data.length + (AAD?.length || 0));
|
||||
if (AAD)
|
||||
h.update(AAD);
|
||||
h.update(data);
|
||||
const num = new Uint8Array(16);
|
||||
const view = createView(num);
|
||||
if (AAD)
|
||||
setBigUint64(view, 0, BigInt(AAD.length * 8), isLE);
|
||||
setBigUint64(view, 8, BigInt(data.length * 8), isLE);
|
||||
h.update(num);
|
||||
return h.digest();
|
||||
}
|
||||
/**
|
||||
* GCM: Galois/Counter Mode.
|
||||
* Good, modern version of CTR, parallel, with MAC.
|
||||
* Be careful: MACs can be forged.
|
||||
*/
|
||||
export const gcm = wrapCipher({ blockSize: 16, nonceLength: 12, tagLength: 16 }, function gcm(key, nonce, AAD) {
|
||||
abytes(nonce);
|
||||
// Nonce can be pretty much anything (even 1 byte). But smaller nonces less secure.
|
||||
if (nonce.length === 0)
|
||||
throw new Error('aes/gcm: empty nonce');
|
||||
const tagLength = 16;
|
||||
function _computeTag(authKey, tagMask, data) {
|
||||
const tag = computeTag(ghash, false, authKey, data, AAD);
|
||||
for (let i = 0; i < tagMask.length; i++)
|
||||
tag[i] ^= tagMask[i];
|
||||
return tag;
|
||||
}
|
||||
function deriveKeys() {
|
||||
const xk = expandKeyLE(key);
|
||||
const authKey = EMPTY_BLOCK.slice();
|
||||
const counter = EMPTY_BLOCK.slice();
|
||||
ctr32(xk, false, counter, counter, authKey);
|
||||
if (nonce.length === 12) {
|
||||
counter.set(nonce);
|
||||
}
|
||||
else {
|
||||
// Spec (NIST 800-38d) supports variable size nonce.
|
||||
// Not supported for now, but can be useful.
|
||||
const nonceLen = EMPTY_BLOCK.slice();
|
||||
const view = createView(nonceLen);
|
||||
setBigUint64(view, 8, BigInt(nonce.length * 8), false);
|
||||
// ghash(nonce || u64be(0) || u64be(nonceLen*8))
|
||||
ghash.create(authKey).update(nonce).update(nonceLen).digestInto(counter);
|
||||
}
|
||||
const tagMask = ctr32(xk, false, counter, EMPTY_BLOCK);
|
||||
return { xk, authKey, counter, tagMask };
|
||||
}
|
||||
return {
|
||||
encrypt: (plaintext) => {
|
||||
abytes(plaintext);
|
||||
const { xk, authKey, counter, tagMask } = deriveKeys();
|
||||
const out = new Uint8Array(plaintext.length + tagLength);
|
||||
ctr32(xk, false, counter, plaintext, out);
|
||||
const tag = _computeTag(authKey, tagMask, out.subarray(0, out.length - tagLength));
|
||||
out.set(tag, plaintext.length);
|
||||
xk.fill(0);
|
||||
return out;
|
||||
},
|
||||
decrypt: (ciphertext) => {
|
||||
abytes(ciphertext);
|
||||
if (ciphertext.length < tagLength)
|
||||
throw new Error(`aes/gcm: ciphertext less than tagLen (${tagLength})`);
|
||||
const { xk, authKey, counter, tagMask } = deriveKeys();
|
||||
const data = ciphertext.subarray(0, -tagLength);
|
||||
const passedTag = ciphertext.subarray(-tagLength);
|
||||
const tag = _computeTag(authKey, tagMask, data);
|
||||
if (!equalBytes(tag, passedTag))
|
||||
throw new Error('aes/gcm: invalid ghash tag');
|
||||
const out = ctr32(xk, false, counter, data);
|
||||
authKey.fill(0);
|
||||
tagMask.fill(0);
|
||||
xk.fill(0);
|
||||
return out;
|
||||
},
|
||||
};
|
||||
});
|
||||
const limit = (name, min, max) => (value) => {
|
||||
if (!Number.isSafeInteger(value) || min > value || value > max)
|
||||
throw new Error(`${name}: invalid value=${value}, must be [${min}..${max}]`);
|
||||
};
|
||||
/**
|
||||
* AES-GCM-SIV: classic AES-GCM with nonce-misuse resistance.
|
||||
* Guarantees that, when a nonce is repeated, the only security loss is that identical
|
||||
* plaintexts will produce identical ciphertexts.
|
||||
* RFC 8452, https://datatracker.ietf.org/doc/html/rfc8452
|
||||
*/
|
||||
export const siv = wrapCipher({ blockSize: 16, nonceLength: 12, tagLength: 16 }, function siv(key, nonce, AAD) {
|
||||
const tagLength = 16;
|
||||
// From RFC 8452: Section 6
|
||||
const AAD_LIMIT = limit('AAD', 0, 2 ** 36);
|
||||
const PLAIN_LIMIT = limit('plaintext', 0, 2 ** 36);
|
||||
const NONCE_LIMIT = limit('nonce', 12, 12);
|
||||
const CIPHER_LIMIT = limit('ciphertext', 16, 2 ** 36 + 16);
|
||||
abytes(nonce);
|
||||
NONCE_LIMIT(nonce.length);
|
||||
if (AAD) {
|
||||
abytes(AAD);
|
||||
AAD_LIMIT(AAD.length);
|
||||
}
|
||||
function deriveKeys() {
|
||||
const len = key.length;
|
||||
if (len !== 16 && len !== 24 && len !== 32)
|
||||
throw new Error(`key length must be 16, 24 or 32 bytes, got: ${len} bytes`);
|
||||
const xk = expandKeyLE(key);
|
||||
const encKey = new Uint8Array(len);
|
||||
const authKey = new Uint8Array(16);
|
||||
const n32 = u32(nonce);
|
||||
// prettier-ignore
|
||||
let s0 = 0, s1 = n32[0], s2 = n32[1], s3 = n32[2];
|
||||
let counter = 0;
|
||||
for (const derivedKey of [authKey, encKey].map(u32)) {
|
||||
const d32 = u32(derivedKey);
|
||||
for (let i = 0; i < d32.length; i += 2) {
|
||||
// aes(u32le(0) || nonce)[:8] || aes(u32le(1) || nonce)[:8] ...
|
||||
const { s0: o0, s1: o1 } = encrypt(xk, s0, s1, s2, s3);
|
||||
d32[i + 0] = o0;
|
||||
d32[i + 1] = o1;
|
||||
s0 = ++counter; // increment counter inside state
|
||||
}
|
||||
}
|
||||
xk.fill(0);
|
||||
return { authKey, encKey: expandKeyLE(encKey) };
|
||||
}
|
||||
function _computeTag(encKey, authKey, data) {
|
||||
const tag = computeTag(polyval, true, authKey, data, AAD);
|
||||
// Compute the expected tag by XORing S_s and the nonce, clearing the
|
||||
// most significant bit of the last byte and encrypting with the
|
||||
// message-encryption key.
|
||||
for (let i = 0; i < 12; i++)
|
||||
tag[i] ^= nonce[i];
|
||||
tag[15] &= 0x7f; // Clear the highest bit
|
||||
// encrypt tag as block
|
||||
const t32 = u32(tag);
|
||||
// prettier-ignore
|
||||
let s0 = t32[0], s1 = t32[1], s2 = t32[2], s3 = t32[3];
|
||||
({ s0, s1, s2, s3 } = encrypt(encKey, s0, s1, s2, s3));
|
||||
(t32[0] = s0), (t32[1] = s1), (t32[2] = s2), (t32[3] = s3);
|
||||
return tag;
|
||||
}
|
||||
// actual decrypt/encrypt of message.
|
||||
function processSiv(encKey, tag, input) {
|
||||
let block = tag.slice();
|
||||
block[15] |= 0x80; // Force highest bit
|
||||
return ctr32(encKey, true, block, input);
|
||||
}
|
||||
return {
|
||||
encrypt: (plaintext) => {
|
||||
abytes(plaintext);
|
||||
PLAIN_LIMIT(plaintext.length);
|
||||
const { encKey, authKey } = deriveKeys();
|
||||
const tag = _computeTag(encKey, authKey, plaintext);
|
||||
const out = new Uint8Array(plaintext.length + tagLength);
|
||||
out.set(tag, plaintext.length);
|
||||
out.set(processSiv(encKey, tag, plaintext));
|
||||
encKey.fill(0);
|
||||
authKey.fill(0);
|
||||
return out;
|
||||
},
|
||||
decrypt: (ciphertext) => {
|
||||
abytes(ciphertext);
|
||||
CIPHER_LIMIT(ciphertext.length);
|
||||
const tag = ciphertext.subarray(-tagLength);
|
||||
const { encKey, authKey } = deriveKeys();
|
||||
const plaintext = processSiv(encKey, tag, ciphertext.subarray(0, -tagLength));
|
||||
const expectedTag = _computeTag(encKey, authKey, plaintext);
|
||||
encKey.fill(0);
|
||||
authKey.fill(0);
|
||||
if (!equalBytes(tag, expectedTag))
|
||||
throw new Error('invalid polyval tag');
|
||||
return plaintext;
|
||||
},
|
||||
};
|
||||
});
|
||||
function isBytes32(a) {
|
||||
return (a != null &&
|
||||
typeof a === 'object' &&
|
||||
(a instanceof Uint32Array || a.constructor.name === 'Uint32Array'));
|
||||
}
|
||||
function encryptBlock(xk, block) {
|
||||
abytes(block, 16);
|
||||
if (!isBytes32(xk))
|
||||
throw new Error('_encryptBlock accepts result of expandKeyLE');
|
||||
const b32 = u32(block);
|
||||
let { s0, s1, s2, s3 } = encrypt(xk, b32[0], b32[1], b32[2], b32[3]);
|
||||
(b32[0] = s0), (b32[1] = s1), (b32[2] = s2), (b32[3] = s3);
|
||||
return block;
|
||||
}
|
||||
function decryptBlock(xk, block) {
|
||||
abytes(block, 16);
|
||||
if (!isBytes32(xk))
|
||||
throw new Error('_decryptBlock accepts result of expandKeyLE');
|
||||
const b32 = u32(block);
|
||||
let { s0, s1, s2, s3 } = decrypt(xk, b32[0], b32[1], b32[2], b32[3]);
|
||||
(b32[0] = s0), (b32[1] = s1), (b32[2] = s2), (b32[3] = s3);
|
||||
return block;
|
||||
}
|
||||
// Highly unsafe private functions for implementing new modes or ciphers based on AES
|
||||
// Can change at any time, no API guarantees
|
||||
export const unsafe = {
|
||||
expandKeyLE,
|
||||
expandKeyDecLE,
|
||||
encrypt,
|
||||
decrypt,
|
||||
encryptBlock,
|
||||
decryptBlock,
|
||||
ctrCounter,
|
||||
ctr32,
|
||||
};
|
||||
//# sourceMappingURL=aes.js.map
|
||||
1
node_modules/@noble/ciphers/esm/aes.js.map
generated
vendored
Normal file
1
node_modules/@noble/ciphers/esm/aes.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
318
node_modules/@noble/ciphers/esm/chacha.js
generated
vendored
Normal file
318
node_modules/@noble/ciphers/esm/chacha.js
generated
vendored
Normal file
@@ -0,0 +1,318 @@
|
||||
// prettier-ignore
|
||||
import { wrapCipher, createView, equalBytes, setBigUint64, } from './utils.js';
|
||||
import { poly1305 } from './_poly1305.js';
|
||||
import { createCipher, rotl } from './_arx.js';
|
||||
import { bytes as abytes } from './_assert.js';
|
||||
// ChaCha20 stream cipher was released in 2008. ChaCha aims to increase
|
||||
// the diffusion per round, but had slightly less cryptanalysis.
|
||||
// https://cr.yp.to/chacha.html, http://cr.yp.to/chacha/chacha-20080128.pdf
|
||||
/**
|
||||
* ChaCha core function.
|
||||
*/
|
||||
// prettier-ignore
|
||||
function chachaCore(s, k, n, out, cnt, rounds = 20) {
|
||||
let y00 = s[0], y01 = s[1], y02 = s[2], y03 = s[3], // "expa" "nd 3" "2-by" "te k"
|
||||
y04 = k[0], y05 = k[1], y06 = k[2], y07 = k[3], // Key Key Key Key
|
||||
y08 = k[4], y09 = k[5], y10 = k[6], y11 = k[7], // Key Key Key Key
|
||||
y12 = cnt, y13 = n[0], y14 = n[1], y15 = n[2]; // Counter Counter Nonce Nonce
|
||||
// Save state to temporary variables
|
||||
let x00 = y00, x01 = y01, x02 = y02, x03 = y03, x04 = y04, x05 = y05, x06 = y06, x07 = y07, x08 = y08, x09 = y09, x10 = y10, x11 = y11, x12 = y12, x13 = y13, x14 = y14, x15 = y15;
|
||||
for (let r = 0; r < rounds; r += 2) {
|
||||
x00 = (x00 + x04) | 0;
|
||||
x12 = rotl(x12 ^ x00, 16);
|
||||
x08 = (x08 + x12) | 0;
|
||||
x04 = rotl(x04 ^ x08, 12);
|
||||
x00 = (x00 + x04) | 0;
|
||||
x12 = rotl(x12 ^ x00, 8);
|
||||
x08 = (x08 + x12) | 0;
|
||||
x04 = rotl(x04 ^ x08, 7);
|
||||
x01 = (x01 + x05) | 0;
|
||||
x13 = rotl(x13 ^ x01, 16);
|
||||
x09 = (x09 + x13) | 0;
|
||||
x05 = rotl(x05 ^ x09, 12);
|
||||
x01 = (x01 + x05) | 0;
|
||||
x13 = rotl(x13 ^ x01, 8);
|
||||
x09 = (x09 + x13) | 0;
|
||||
x05 = rotl(x05 ^ x09, 7);
|
||||
x02 = (x02 + x06) | 0;
|
||||
x14 = rotl(x14 ^ x02, 16);
|
||||
x10 = (x10 + x14) | 0;
|
||||
x06 = rotl(x06 ^ x10, 12);
|
||||
x02 = (x02 + x06) | 0;
|
||||
x14 = rotl(x14 ^ x02, 8);
|
||||
x10 = (x10 + x14) | 0;
|
||||
x06 = rotl(x06 ^ x10, 7);
|
||||
x03 = (x03 + x07) | 0;
|
||||
x15 = rotl(x15 ^ x03, 16);
|
||||
x11 = (x11 + x15) | 0;
|
||||
x07 = rotl(x07 ^ x11, 12);
|
||||
x03 = (x03 + x07) | 0;
|
||||
x15 = rotl(x15 ^ x03, 8);
|
||||
x11 = (x11 + x15) | 0;
|
||||
x07 = rotl(x07 ^ x11, 7);
|
||||
x00 = (x00 + x05) | 0;
|
||||
x15 = rotl(x15 ^ x00, 16);
|
||||
x10 = (x10 + x15) | 0;
|
||||
x05 = rotl(x05 ^ x10, 12);
|
||||
x00 = (x00 + x05) | 0;
|
||||
x15 = rotl(x15 ^ x00, 8);
|
||||
x10 = (x10 + x15) | 0;
|
||||
x05 = rotl(x05 ^ x10, 7);
|
||||
x01 = (x01 + x06) | 0;
|
||||
x12 = rotl(x12 ^ x01, 16);
|
||||
x11 = (x11 + x12) | 0;
|
||||
x06 = rotl(x06 ^ x11, 12);
|
||||
x01 = (x01 + x06) | 0;
|
||||
x12 = rotl(x12 ^ x01, 8);
|
||||
x11 = (x11 + x12) | 0;
|
||||
x06 = rotl(x06 ^ x11, 7);
|
||||
x02 = (x02 + x07) | 0;
|
||||
x13 = rotl(x13 ^ x02, 16);
|
||||
x08 = (x08 + x13) | 0;
|
||||
x07 = rotl(x07 ^ x08, 12);
|
||||
x02 = (x02 + x07) | 0;
|
||||
x13 = rotl(x13 ^ x02, 8);
|
||||
x08 = (x08 + x13) | 0;
|
||||
x07 = rotl(x07 ^ x08, 7);
|
||||
x03 = (x03 + x04) | 0;
|
||||
x14 = rotl(x14 ^ x03, 16);
|
||||
x09 = (x09 + x14) | 0;
|
||||
x04 = rotl(x04 ^ x09, 12);
|
||||
x03 = (x03 + x04) | 0;
|
||||
x14 = rotl(x14 ^ x03, 8);
|
||||
x09 = (x09 + x14) | 0;
|
||||
x04 = rotl(x04 ^ x09, 7);
|
||||
}
|
||||
// Write output
|
||||
let oi = 0;
|
||||
out[oi++] = (y00 + x00) | 0;
|
||||
out[oi++] = (y01 + x01) | 0;
|
||||
out[oi++] = (y02 + x02) | 0;
|
||||
out[oi++] = (y03 + x03) | 0;
|
||||
out[oi++] = (y04 + x04) | 0;
|
||||
out[oi++] = (y05 + x05) | 0;
|
||||
out[oi++] = (y06 + x06) | 0;
|
||||
out[oi++] = (y07 + x07) | 0;
|
||||
out[oi++] = (y08 + x08) | 0;
|
||||
out[oi++] = (y09 + x09) | 0;
|
||||
out[oi++] = (y10 + x10) | 0;
|
||||
out[oi++] = (y11 + x11) | 0;
|
||||
out[oi++] = (y12 + x12) | 0;
|
||||
out[oi++] = (y13 + x13) | 0;
|
||||
out[oi++] = (y14 + x14) | 0;
|
||||
out[oi++] = (y15 + x15) | 0;
|
||||
}
|
||||
/**
|
||||
* hchacha helper method, used primarily in xchacha, to hash
|
||||
* key and nonce into key' and nonce'.
|
||||
* Same as chachaCore, but there doesn't seem to be a way to move the block
|
||||
* out without 25% performance hit.
|
||||
*/
|
||||
// prettier-ignore
|
||||
export function hchacha(s, k, i, o32) {
|
||||
let x00 = s[0], x01 = s[1], x02 = s[2], x03 = s[3], x04 = k[0], x05 = k[1], x06 = k[2], x07 = k[3], x08 = k[4], x09 = k[5], x10 = k[6], x11 = k[7], x12 = i[0], x13 = i[1], x14 = i[2], x15 = i[3];
|
||||
for (let r = 0; r < 20; r += 2) {
|
||||
x00 = (x00 + x04) | 0;
|
||||
x12 = rotl(x12 ^ x00, 16);
|
||||
x08 = (x08 + x12) | 0;
|
||||
x04 = rotl(x04 ^ x08, 12);
|
||||
x00 = (x00 + x04) | 0;
|
||||
x12 = rotl(x12 ^ x00, 8);
|
||||
x08 = (x08 + x12) | 0;
|
||||
x04 = rotl(x04 ^ x08, 7);
|
||||
x01 = (x01 + x05) | 0;
|
||||
x13 = rotl(x13 ^ x01, 16);
|
||||
x09 = (x09 + x13) | 0;
|
||||
x05 = rotl(x05 ^ x09, 12);
|
||||
x01 = (x01 + x05) | 0;
|
||||
x13 = rotl(x13 ^ x01, 8);
|
||||
x09 = (x09 + x13) | 0;
|
||||
x05 = rotl(x05 ^ x09, 7);
|
||||
x02 = (x02 + x06) | 0;
|
||||
x14 = rotl(x14 ^ x02, 16);
|
||||
x10 = (x10 + x14) | 0;
|
||||
x06 = rotl(x06 ^ x10, 12);
|
||||
x02 = (x02 + x06) | 0;
|
||||
x14 = rotl(x14 ^ x02, 8);
|
||||
x10 = (x10 + x14) | 0;
|
||||
x06 = rotl(x06 ^ x10, 7);
|
||||
x03 = (x03 + x07) | 0;
|
||||
x15 = rotl(x15 ^ x03, 16);
|
||||
x11 = (x11 + x15) | 0;
|
||||
x07 = rotl(x07 ^ x11, 12);
|
||||
x03 = (x03 + x07) | 0;
|
||||
x15 = rotl(x15 ^ x03, 8);
|
||||
x11 = (x11 + x15) | 0;
|
||||
x07 = rotl(x07 ^ x11, 7);
|
||||
x00 = (x00 + x05) | 0;
|
||||
x15 = rotl(x15 ^ x00, 16);
|
||||
x10 = (x10 + x15) | 0;
|
||||
x05 = rotl(x05 ^ x10, 12);
|
||||
x00 = (x00 + x05) | 0;
|
||||
x15 = rotl(x15 ^ x00, 8);
|
||||
x10 = (x10 + x15) | 0;
|
||||
x05 = rotl(x05 ^ x10, 7);
|
||||
x01 = (x01 + x06) | 0;
|
||||
x12 = rotl(x12 ^ x01, 16);
|
||||
x11 = (x11 + x12) | 0;
|
||||
x06 = rotl(x06 ^ x11, 12);
|
||||
x01 = (x01 + x06) | 0;
|
||||
x12 = rotl(x12 ^ x01, 8);
|
||||
x11 = (x11 + x12) | 0;
|
||||
x06 = rotl(x06 ^ x11, 7);
|
||||
x02 = (x02 + x07) | 0;
|
||||
x13 = rotl(x13 ^ x02, 16);
|
||||
x08 = (x08 + x13) | 0;
|
||||
x07 = rotl(x07 ^ x08, 12);
|
||||
x02 = (x02 + x07) | 0;
|
||||
x13 = rotl(x13 ^ x02, 8);
|
||||
x08 = (x08 + x13) | 0;
|
||||
x07 = rotl(x07 ^ x08, 7);
|
||||
x03 = (x03 + x04) | 0;
|
||||
x14 = rotl(x14 ^ x03, 16);
|
||||
x09 = (x09 + x14) | 0;
|
||||
x04 = rotl(x04 ^ x09, 12);
|
||||
x03 = (x03 + x04) | 0;
|
||||
x14 = rotl(x14 ^ x03, 8);
|
||||
x09 = (x09 + x14) | 0;
|
||||
x04 = rotl(x04 ^ x09, 7);
|
||||
}
|
||||
let oi = 0;
|
||||
o32[oi++] = x00;
|
||||
o32[oi++] = x01;
|
||||
o32[oi++] = x02;
|
||||
o32[oi++] = x03;
|
||||
o32[oi++] = x12;
|
||||
o32[oi++] = x13;
|
||||
o32[oi++] = x14;
|
||||
o32[oi++] = x15;
|
||||
}
|
||||
/**
|
||||
* Original, non-RFC chacha20 from DJB. 8-byte nonce, 8-byte counter.
|
||||
*/
|
||||
export const chacha20orig = /* @__PURE__ */ createCipher(chachaCore, {
|
||||
counterRight: false,
|
||||
counterLength: 8,
|
||||
allowShortKeys: true,
|
||||
});
|
||||
/**
|
||||
* ChaCha stream cipher. Conforms to RFC 8439 (IETF, TLS). 12-byte nonce, 4-byte counter.
|
||||
* With 12-byte nonce, it's not safe to use fill it with random (CSPRNG), due to collision chance.
|
||||
*/
|
||||
export const chacha20 = /* @__PURE__ */ createCipher(chachaCore, {
|
||||
counterRight: false,
|
||||
counterLength: 4,
|
||||
allowShortKeys: false,
|
||||
});
|
||||
/**
|
||||
* XChaCha eXtended-nonce ChaCha. 24-byte nonce.
|
||||
* With 24-byte nonce, it's safe to use fill it with random (CSPRNG).
|
||||
* https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-xchacha
|
||||
*/
|
||||
export const xchacha20 = /* @__PURE__ */ createCipher(chachaCore, {
|
||||
counterRight: false,
|
||||
counterLength: 8,
|
||||
extendNonceFn: hchacha,
|
||||
allowShortKeys: false,
|
||||
});
|
||||
/**
|
||||
* Reduced 8-round chacha, described in original paper.
|
||||
*/
|
||||
export const chacha8 = /* @__PURE__ */ createCipher(chachaCore, {
|
||||
counterRight: false,
|
||||
counterLength: 4,
|
||||
rounds: 8,
|
||||
});
|
||||
/**
|
||||
* Reduced 12-round chacha, described in original paper.
|
||||
*/
|
||||
export const chacha12 = /* @__PURE__ */ createCipher(chachaCore, {
|
||||
counterRight: false,
|
||||
counterLength: 4,
|
||||
rounds: 12,
|
||||
});
|
||||
const ZEROS16 = /* @__PURE__ */ new Uint8Array(16);
|
||||
// Pad to digest size with zeros
|
||||
const updatePadded = (h, msg) => {
|
||||
h.update(msg);
|
||||
const left = msg.length % 16;
|
||||
if (left)
|
||||
h.update(ZEROS16.subarray(left));
|
||||
};
|
||||
const ZEROS32 = /* @__PURE__ */ new Uint8Array(32);
|
||||
function computeTag(fn, key, nonce, data, AAD) {
|
||||
const authKey = fn(key, nonce, ZEROS32);
|
||||
const h = poly1305.create(authKey);
|
||||
if (AAD)
|
||||
updatePadded(h, AAD);
|
||||
updatePadded(h, data);
|
||||
const num = new Uint8Array(16);
|
||||
const view = createView(num);
|
||||
setBigUint64(view, 0, BigInt(AAD ? AAD.length : 0), true);
|
||||
setBigUint64(view, 8, BigInt(data.length), true);
|
||||
h.update(num);
|
||||
const res = h.digest();
|
||||
authKey.fill(0);
|
||||
return res;
|
||||
}
|
||||
/**
|
||||
* AEAD algorithm from RFC 8439.
|
||||
* Salsa20 and chacha (RFC 8439) use poly1305 differently.
|
||||
* We could have composed them similar to:
|
||||
* https://github.com/paulmillr/scure-base/blob/b266c73dde977b1dd7ef40ef7a23cc15aab526b3/index.ts#L250
|
||||
* But it's hard because of authKey:
|
||||
* In salsa20, authKey changes position in salsa stream.
|
||||
* In chacha, authKey can't be computed inside computeTag, it modifies the counter.
|
||||
*/
|
||||
export const _poly1305_aead = (xorStream) => (key, nonce, AAD) => {
|
||||
const tagLength = 16;
|
||||
abytes(key, 32);
|
||||
abytes(nonce);
|
||||
return {
|
||||
encrypt: (plaintext, output) => {
|
||||
const plength = plaintext.length;
|
||||
const clength = plength + tagLength;
|
||||
if (output) {
|
||||
abytes(output, clength);
|
||||
}
|
||||
else {
|
||||
output = new Uint8Array(clength);
|
||||
}
|
||||
xorStream(key, nonce, plaintext, output, 1);
|
||||
const tag = computeTag(xorStream, key, nonce, output.subarray(0, -tagLength), AAD);
|
||||
output.set(tag, plength); // append tag
|
||||
return output;
|
||||
},
|
||||
decrypt: (ciphertext, output) => {
|
||||
const clength = ciphertext.length;
|
||||
const plength = clength - tagLength;
|
||||
if (clength < tagLength)
|
||||
throw new Error(`encrypted data must be at least ${tagLength} bytes`);
|
||||
if (output) {
|
||||
abytes(output, plength);
|
||||
}
|
||||
else {
|
||||
output = new Uint8Array(plength);
|
||||
}
|
||||
const data = ciphertext.subarray(0, -tagLength);
|
||||
const passedTag = ciphertext.subarray(-tagLength);
|
||||
const tag = computeTag(xorStream, key, nonce, data, AAD);
|
||||
if (!equalBytes(passedTag, tag))
|
||||
throw new Error('invalid tag');
|
||||
xorStream(key, nonce, data, output, 1);
|
||||
return output;
|
||||
},
|
||||
};
|
||||
};
|
||||
/**
|
||||
* ChaCha20-Poly1305 from RFC 8439.
|
||||
* With 12-byte nonce, it's not safe to use fill it with random (CSPRNG), due to collision chance.
|
||||
*/
|
||||
export const chacha20poly1305 = /* @__PURE__ */ wrapCipher({ blockSize: 64, nonceLength: 12, tagLength: 16 }, _poly1305_aead(chacha20));
|
||||
/**
|
||||
* XChaCha20-Poly1305 extended-nonce chacha.
|
||||
* https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-xchacha
|
||||
* With 24-byte nonce, it's safe to use fill it with random (CSPRNG).
|
||||
*/
|
||||
export const xchacha20poly1305 = /* @__PURE__ */ wrapCipher({ blockSize: 64, nonceLength: 24, tagLength: 16 }, _poly1305_aead(xchacha20));
|
||||
//# sourceMappingURL=chacha.js.map
|
||||
1
node_modules/@noble/ciphers/esm/chacha.js.map
generated
vendored
Normal file
1
node_modules/@noble/ciphers/esm/chacha.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
12
node_modules/@noble/ciphers/esm/crypto.js
generated
vendored
Normal file
12
node_modules/@noble/ciphers/esm/crypto.js
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
const cr = typeof globalThis === 'object' && 'crypto' in globalThis ? globalThis.crypto : undefined;
|
||||
export function randomBytes(bytesLength = 32) {
|
||||
if (cr && typeof cr.getRandomValues === 'function')
|
||||
return cr.getRandomValues(new Uint8Array(bytesLength));
|
||||
throw new Error('crypto.getRandomValues must be defined');
|
||||
}
|
||||
export function getWebcryptoSubtle() {
|
||||
if (cr && typeof cr.subtle === 'object' && cr.subtle != null)
|
||||
return cr.subtle;
|
||||
throw new Error('crypto.subtle must be defined');
|
||||
}
|
||||
//# sourceMappingURL=crypto.js.map
|
||||
1
node_modules/@noble/ciphers/esm/crypto.js.map
generated
vendored
Normal file
1
node_modules/@noble/ciphers/esm/crypto.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"crypto.js","sourceRoot":"","sources":["../src/crypto.ts"],"names":[],"mappings":"AAGA,MAAM,EAAE,GAAG,OAAO,UAAU,KAAK,QAAQ,IAAI,QAAQ,IAAI,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;AAEpG,MAAM,UAAU,WAAW,CAAC,WAAW,GAAG,EAAE;IAC1C,IAAI,EAAE,IAAI,OAAO,EAAE,CAAC,eAAe,KAAK,UAAU;QAChD,OAAO,EAAE,CAAC,eAAe,CAAC,IAAI,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC;IACzD,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;AAC5D,CAAC;AAED,MAAM,UAAU,kBAAkB;IAChC,IAAI,EAAE,IAAI,OAAO,EAAE,CAAC,MAAM,KAAK,QAAQ,IAAI,EAAE,CAAC,MAAM,IAAI,IAAI;QAAE,OAAO,EAAE,CAAC,MAAM,CAAC;IAC/E,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;AACnD,CAAC"}
|
||||
17
node_modules/@noble/ciphers/esm/cryptoNode.js
generated
vendored
Normal file
17
node_modules/@noble/ciphers/esm/cryptoNode.js
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
// We use WebCrypto aka globalThis.crypto, which exists in browsers and node.js 16+.
|
||||
// See utils.ts for details.
|
||||
// The file will throw on node.js 14 and earlier.
|
||||
// @ts-ignore
|
||||
import * as nc from 'node:crypto';
|
||||
const cr = nc && typeof nc === 'object' && 'webcrypto' in nc ? nc.webcrypto : undefined;
|
||||
export function randomBytes(bytesLength = 32) {
|
||||
if (cr && typeof cr.getRandomValues === 'function')
|
||||
return cr.getRandomValues(new Uint8Array(bytesLength));
|
||||
throw new Error('crypto.getRandomValues must be defined');
|
||||
}
|
||||
export function getWebcryptoSubtle() {
|
||||
if (cr && typeof cr.subtle === 'object' && cr.subtle != null)
|
||||
return cr.subtle;
|
||||
throw new Error('crypto.subtle must be defined');
|
||||
}
|
||||
//# sourceMappingURL=cryptoNode.js.map
|
||||
1
node_modules/@noble/ciphers/esm/cryptoNode.js.map
generated
vendored
Normal file
1
node_modules/@noble/ciphers/esm/cryptoNode.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"cryptoNode.js","sourceRoot":"","sources":["../src/cryptoNode.ts"],"names":[],"mappings":"AAAA,oFAAoF;AACpF,4BAA4B;AAC5B,iDAAiD;AACjD,aAAa;AACb,OAAO,KAAK,EAAE,MAAM,aAAa,CAAC;AAClC,MAAM,EAAE,GAAG,EAAE,IAAI,OAAO,EAAE,KAAK,QAAQ,IAAI,WAAW,IAAI,EAAE,CAAC,CAAC,CAAE,EAAE,CAAC,SAAiB,CAAC,CAAC,CAAC,SAAS,CAAC;AAEjG,MAAM,UAAU,WAAW,CAAC,WAAW,GAAG,EAAE;IAC1C,IAAI,EAAE,IAAI,OAAO,EAAE,CAAC,eAAe,KAAK,UAAU;QAChD,OAAO,EAAE,CAAC,eAAe,CAAC,IAAI,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC;IACzD,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;AAC5D,CAAC;AAED,MAAM,UAAU,kBAAkB;IAChC,IAAI,EAAE,IAAI,OAAO,EAAE,CAAC,MAAM,KAAK,QAAQ,IAAI,EAAE,CAAC,MAAM,IAAI,IAAI;QAAE,OAAO,EAAE,CAAC,MAAM,CAAC;IAC/E,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;AACnD,CAAC"}
|
||||
149
node_modules/@noble/ciphers/esm/ff1.js
generated
vendored
Normal file
149
node_modules/@noble/ciphers/esm/ff1.js
generated
vendored
Normal file
@@ -0,0 +1,149 @@
|
||||
import { bytesToNumberBE, numberToBytesBE } from './utils.js';
|
||||
import { unsafe } from './aes.js';
|
||||
// NOTE: no point in inlining encrypt instead of encryptBlock, since BigInt stuff will be slow
|
||||
const { expandKeyLE, encryptBlock } = unsafe;
|
||||
// Format-preserving encryption algorithm (FPE-FF1) specified in NIST Special Publication 800-38G.
|
||||
// https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38G.pdf
|
||||
const BLOCK_LEN = 16;
|
||||
function mod(a, b) {
|
||||
const result = a % b;
|
||||
return result >= 0 ? result : b + result;
|
||||
}
|
||||
function NUMradix(radix, data) {
|
||||
let res = BigInt(0);
|
||||
for (let i of data)
|
||||
res = res * BigInt(radix) + BigInt(i);
|
||||
return res;
|
||||
}
|
||||
function getRound(radix, key, tweak, x) {
|
||||
if (radix > 2 ** 16 - 1)
|
||||
throw new Error(`Invalid radix: ${radix}`);
|
||||
// radix**minlen ≥ 100
|
||||
const minLen = Math.ceil(Math.log(100) / Math.log(radix));
|
||||
const maxLen = 2 ** 32 - 1;
|
||||
// 2 ≤ minlen ≤ maxlen < 2**32
|
||||
if (2 > minLen || minLen > maxLen || maxLen >= 2 ** 32)
|
||||
throw new Error('Invalid radix: 2 ≤ minlen ≤ maxlen < 2**32');
|
||||
if (x.length < minLen || x.length > maxLen)
|
||||
throw new Error('X is outside minLen..maxLen bounds');
|
||||
const u = Math.floor(x.length / 2);
|
||||
const v = x.length - u;
|
||||
const b = Math.ceil(Math.ceil(v * Math.log2(radix)) / 8);
|
||||
const d = 4 * Math.ceil(b / 4) + 4;
|
||||
const padding = mod(-tweak.length - b - 1, 16);
|
||||
// P = [1]1 || [2]1 || [1]1 || [radix]3 || [10]1 || [u mod 256]1 || [n]4 || [t]4.
|
||||
const P = new Uint8Array([1, 2, 1, 0, 0, 0, 10, u, 0, 0, 0, 0, 0, 0, 0, 0]);
|
||||
const view = new DataView(P.buffer);
|
||||
view.setUint16(4, radix, false);
|
||||
view.setUint32(8, x.length, false);
|
||||
view.setUint32(12, tweak.length, false);
|
||||
// Q = T || [0](−t−b−1) mod 16 || [i]1 || [NUMradix(B)]b.
|
||||
const PQ = new Uint8Array(P.length + tweak.length + padding + 1 + b);
|
||||
PQ.set(P);
|
||||
P.fill(0);
|
||||
PQ.set(tweak, P.length);
|
||||
const xk = expandKeyLE(key);
|
||||
const round = (A, B, i, decrypt = false) => {
|
||||
// Q = ... || [i]1 || [NUMradix(B)]b.
|
||||
PQ[PQ.length - b - 1] = i;
|
||||
if (b)
|
||||
PQ.set(numberToBytesBE(NUMradix(radix, B), b), PQ.length - b);
|
||||
// PRF
|
||||
let r = new Uint8Array(16);
|
||||
for (let j = 0; j < PQ.length / BLOCK_LEN; j++) {
|
||||
for (let i = 0; i < BLOCK_LEN; i++)
|
||||
r[i] ^= PQ[j * BLOCK_LEN + i];
|
||||
encryptBlock(xk, r);
|
||||
}
|
||||
// Let S be the first d bytes of the following string of ⎡d/16⎤ blocks:
|
||||
// R || CIPHK(R ⊕[1]16) || CIPHK(R ⊕[2]16) ...CIPHK(R ⊕[⎡d / 16⎤ – 1]16).
|
||||
let s = Array.from(r);
|
||||
for (let j = 1; s.length < d; j++) {
|
||||
const block = numberToBytesBE(BigInt(j), 16);
|
||||
for (let k = 0; k < BLOCK_LEN; k++)
|
||||
block[k] ^= r[k];
|
||||
s.push(...Array.from(encryptBlock(xk, block)));
|
||||
}
|
||||
let y = bytesToNumberBE(Uint8Array.from(s.slice(0, d)));
|
||||
s.fill(0);
|
||||
if (decrypt)
|
||||
y = -y;
|
||||
const m = i % 2 === 0 ? u : v;
|
||||
let c = mod(NUMradix(radix, A) + y, BigInt(radix) ** BigInt(m));
|
||||
// STR(radix, m, c)
|
||||
const C = Array(m).fill(0);
|
||||
for (let i = 0; i < m; i++, c /= BigInt(radix))
|
||||
C[m - 1 - i] = Number(c % BigInt(radix));
|
||||
A.fill(0);
|
||||
A = B;
|
||||
B = C;
|
||||
return [A, B];
|
||||
};
|
||||
const destroy = () => {
|
||||
xk.fill(0);
|
||||
PQ.fill(0);
|
||||
};
|
||||
return { u, round, destroy };
|
||||
}
|
||||
const EMPTY_BUF = new Uint8Array([]);
|
||||
export function FF1(radix, key, tweak = EMPTY_BUF) {
|
||||
const PQ = getRound.bind(null, radix, key, tweak);
|
||||
return {
|
||||
encrypt(x) {
|
||||
const { u, round, destroy } = PQ(x);
|
||||
let [A, B] = [x.slice(0, u), x.slice(u)];
|
||||
for (let i = 0; i < 10; i++)
|
||||
[A, B] = round(A, B, i);
|
||||
destroy();
|
||||
const res = A.concat(B);
|
||||
A.fill(0);
|
||||
B.fill(0);
|
||||
return res;
|
||||
},
|
||||
decrypt(x) {
|
||||
const { u, round, destroy } = PQ(x);
|
||||
// The FF1.Decrypt algorithm is similar to the FF1.Encrypt algorithm;
|
||||
// the differences are in Step 6, where:
|
||||
// 1) the order of the indices is reversed,
|
||||
// 2) the roles of A and B are swapped
|
||||
// 3) modular addition is replaced by modular subtraction, in Step 6vi.
|
||||
let [B, A] = [x.slice(0, u), x.slice(u)];
|
||||
for (let i = 9; i >= 0; i--)
|
||||
[A, B] = round(A, B, i, true);
|
||||
destroy();
|
||||
const res = B.concat(A);
|
||||
A.fill(0);
|
||||
B.fill(0);
|
||||
return res;
|
||||
},
|
||||
};
|
||||
}
|
||||
// Binary string which encodes each byte in little-endian byte order
|
||||
const binLE = {
|
||||
encode(bytes) {
|
||||
const x = [];
|
||||
for (let i = 0; i < bytes.length; i++) {
|
||||
for (let j = 0, tmp = bytes[i]; j < 8; j++, tmp >>= 1)
|
||||
x.push(tmp & 1);
|
||||
}
|
||||
return x;
|
||||
},
|
||||
decode(b) {
|
||||
if (b.length % 8)
|
||||
throw new Error('Invalid binary string');
|
||||
const res = new Uint8Array(b.length / 8);
|
||||
for (let i = 0, j = 0; i < res.length; i++) {
|
||||
res[i] = b[j++] | (b[j++] << 1) | (b[j++] << 2) | (b[j++] << 3);
|
||||
res[i] |= (b[j++] << 4) | (b[j++] << 5) | (b[j++] << 6) | (b[j++] << 7);
|
||||
}
|
||||
return res;
|
||||
},
|
||||
};
|
||||
export function BinaryFF1(key, tweak = EMPTY_BUF) {
|
||||
const ff1 = FF1(2, key, tweak);
|
||||
return {
|
||||
encrypt: (x) => binLE.decode(ff1.encrypt(binLE.encode(x))),
|
||||
decrypt: (x) => binLE.decode(ff1.decrypt(binLE.encode(x))),
|
||||
};
|
||||
}
|
||||
//# sourceMappingURL=ff1.js.map
|
||||
1
node_modules/@noble/ciphers/esm/ff1.js.map
generated
vendored
Normal file
1
node_modules/@noble/ciphers/esm/ff1.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
3
node_modules/@noble/ciphers/esm/index.js
generated
vendored
Normal file
3
node_modules/@noble/ciphers/esm/index.js
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
throw new Error('noble-ciphers have no entry-point: consult README for usage');
|
||||
export {};
|
||||
//# sourceMappingURL=index.js.map
|
||||
1
node_modules/@noble/ciphers/esm/index.js.map
generated
vendored
Normal file
1
node_modules/@noble/ciphers/esm/index.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,MAAM,IAAI,KAAK,CAAC,6DAA6D,CAAC,CAAC"}
|
||||
11
node_modules/@noble/ciphers/esm/package.json
generated
vendored
Normal file
11
node_modules/@noble/ciphers/esm/package.json
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"type": "module",
|
||||
"sideEffects": false,
|
||||
"browser": {
|
||||
"node:crypto": false
|
||||
},
|
||||
"node": {
|
||||
"./crypto.js": "./esm/cryptoNode.js",
|
||||
"./crypto": "./esm/cryptoNode.js"
|
||||
}
|
||||
}
|
||||
205
node_modules/@noble/ciphers/esm/salsa.js
generated
vendored
Normal file
205
node_modules/@noble/ciphers/esm/salsa.js
generated
vendored
Normal file
@@ -0,0 +1,205 @@
|
||||
import { bytes as abytes } from './_assert.js';
|
||||
import { createCipher, rotl } from './_arx.js';
|
||||
import { poly1305 } from './_poly1305.js';
|
||||
import { wrapCipher, equalBytes } from './utils.js';
|
||||
// Salsa20 stream cipher was released in 2005.
|
||||
// Salsa's goal was to implement AES replacement that does not rely on S-Boxes,
|
||||
// which are hard to implement in a constant-time manner.
|
||||
// https://cr.yp.to/snuffle.html, https://cr.yp.to/snuffle/salsafamily-20071225.pdf
|
||||
/**
|
||||
* Salsa20 core function.
|
||||
*/
|
||||
// prettier-ignore
|
||||
function salsaCore(s, k, n, out, cnt, rounds = 20) {
|
||||
// Based on https://cr.yp.to/salsa20.html
|
||||
let y00 = s[0], y01 = k[0], y02 = k[1], y03 = k[2], // "expa" Key Key Key
|
||||
y04 = k[3], y05 = s[1], y06 = n[0], y07 = n[1], // Key "nd 3" Nonce Nonce
|
||||
y08 = cnt, y09 = 0, y10 = s[2], y11 = k[4], // Pos. Pos. "2-by" Key
|
||||
y12 = k[5], y13 = k[6], y14 = k[7], y15 = s[3]; // Key Key Key "te k"
|
||||
// Save state to temporary variables
|
||||
let x00 = y00, x01 = y01, x02 = y02, x03 = y03, x04 = y04, x05 = y05, x06 = y06, x07 = y07, x08 = y08, x09 = y09, x10 = y10, x11 = y11, x12 = y12, x13 = y13, x14 = y14, x15 = y15;
|
||||
for (let r = 0; r < rounds; r += 2) {
|
||||
x04 ^= rotl(x00 + x12 | 0, 7);
|
||||
x08 ^= rotl(x04 + x00 | 0, 9);
|
||||
x12 ^= rotl(x08 + x04 | 0, 13);
|
||||
x00 ^= rotl(x12 + x08 | 0, 18);
|
||||
x09 ^= rotl(x05 + x01 | 0, 7);
|
||||
x13 ^= rotl(x09 + x05 | 0, 9);
|
||||
x01 ^= rotl(x13 + x09 | 0, 13);
|
||||
x05 ^= rotl(x01 + x13 | 0, 18);
|
||||
x14 ^= rotl(x10 + x06 | 0, 7);
|
||||
x02 ^= rotl(x14 + x10 | 0, 9);
|
||||
x06 ^= rotl(x02 + x14 | 0, 13);
|
||||
x10 ^= rotl(x06 + x02 | 0, 18);
|
||||
x03 ^= rotl(x15 + x11 | 0, 7);
|
||||
x07 ^= rotl(x03 + x15 | 0, 9);
|
||||
x11 ^= rotl(x07 + x03 | 0, 13);
|
||||
x15 ^= rotl(x11 + x07 | 0, 18);
|
||||
x01 ^= rotl(x00 + x03 | 0, 7);
|
||||
x02 ^= rotl(x01 + x00 | 0, 9);
|
||||
x03 ^= rotl(x02 + x01 | 0, 13);
|
||||
x00 ^= rotl(x03 + x02 | 0, 18);
|
||||
x06 ^= rotl(x05 + x04 | 0, 7);
|
||||
x07 ^= rotl(x06 + x05 | 0, 9);
|
||||
x04 ^= rotl(x07 + x06 | 0, 13);
|
||||
x05 ^= rotl(x04 + x07 | 0, 18);
|
||||
x11 ^= rotl(x10 + x09 | 0, 7);
|
||||
x08 ^= rotl(x11 + x10 | 0, 9);
|
||||
x09 ^= rotl(x08 + x11 | 0, 13);
|
||||
x10 ^= rotl(x09 + x08 | 0, 18);
|
||||
x12 ^= rotl(x15 + x14 | 0, 7);
|
||||
x13 ^= rotl(x12 + x15 | 0, 9);
|
||||
x14 ^= rotl(x13 + x12 | 0, 13);
|
||||
x15 ^= rotl(x14 + x13 | 0, 18);
|
||||
}
|
||||
// Write output
|
||||
let oi = 0;
|
||||
out[oi++] = (y00 + x00) | 0;
|
||||
out[oi++] = (y01 + x01) | 0;
|
||||
out[oi++] = (y02 + x02) | 0;
|
||||
out[oi++] = (y03 + x03) | 0;
|
||||
out[oi++] = (y04 + x04) | 0;
|
||||
out[oi++] = (y05 + x05) | 0;
|
||||
out[oi++] = (y06 + x06) | 0;
|
||||
out[oi++] = (y07 + x07) | 0;
|
||||
out[oi++] = (y08 + x08) | 0;
|
||||
out[oi++] = (y09 + x09) | 0;
|
||||
out[oi++] = (y10 + x10) | 0;
|
||||
out[oi++] = (y11 + x11) | 0;
|
||||
out[oi++] = (y12 + x12) | 0;
|
||||
out[oi++] = (y13 + x13) | 0;
|
||||
out[oi++] = (y14 + x14) | 0;
|
||||
out[oi++] = (y15 + x15) | 0;
|
||||
}
|
||||
/**
|
||||
* hsalsa hashing function, used primarily in xsalsa, to hash
|
||||
* key and nonce into key' and nonce'.
|
||||
* Same as salsaCore, but there doesn't seem to be a way to move the block
|
||||
* out without 25% performance hit.
|
||||
*/
|
||||
// prettier-ignore
|
||||
export function hsalsa(s, k, i, o32) {
|
||||
let x00 = s[0], x01 = k[0], x02 = k[1], x03 = k[2], x04 = k[3], x05 = s[1], x06 = i[0], x07 = i[1], x08 = i[2], x09 = i[3], x10 = s[2], x11 = k[4], x12 = k[5], x13 = k[6], x14 = k[7], x15 = s[3];
|
||||
for (let r = 0; r < 20; r += 2) {
|
||||
x04 ^= rotl(x00 + x12 | 0, 7);
|
||||
x08 ^= rotl(x04 + x00 | 0, 9);
|
||||
x12 ^= rotl(x08 + x04 | 0, 13);
|
||||
x00 ^= rotl(x12 + x08 | 0, 18);
|
||||
x09 ^= rotl(x05 + x01 | 0, 7);
|
||||
x13 ^= rotl(x09 + x05 | 0, 9);
|
||||
x01 ^= rotl(x13 + x09 | 0, 13);
|
||||
x05 ^= rotl(x01 + x13 | 0, 18);
|
||||
x14 ^= rotl(x10 + x06 | 0, 7);
|
||||
x02 ^= rotl(x14 + x10 | 0, 9);
|
||||
x06 ^= rotl(x02 + x14 | 0, 13);
|
||||
x10 ^= rotl(x06 + x02 | 0, 18);
|
||||
x03 ^= rotl(x15 + x11 | 0, 7);
|
||||
x07 ^= rotl(x03 + x15 | 0, 9);
|
||||
x11 ^= rotl(x07 + x03 | 0, 13);
|
||||
x15 ^= rotl(x11 + x07 | 0, 18);
|
||||
x01 ^= rotl(x00 + x03 | 0, 7);
|
||||
x02 ^= rotl(x01 + x00 | 0, 9);
|
||||
x03 ^= rotl(x02 + x01 | 0, 13);
|
||||
x00 ^= rotl(x03 + x02 | 0, 18);
|
||||
x06 ^= rotl(x05 + x04 | 0, 7);
|
||||
x07 ^= rotl(x06 + x05 | 0, 9);
|
||||
x04 ^= rotl(x07 + x06 | 0, 13);
|
||||
x05 ^= rotl(x04 + x07 | 0, 18);
|
||||
x11 ^= rotl(x10 + x09 | 0, 7);
|
||||
x08 ^= rotl(x11 + x10 | 0, 9);
|
||||
x09 ^= rotl(x08 + x11 | 0, 13);
|
||||
x10 ^= rotl(x09 + x08 | 0, 18);
|
||||
x12 ^= rotl(x15 + x14 | 0, 7);
|
||||
x13 ^= rotl(x12 + x15 | 0, 9);
|
||||
x14 ^= rotl(x13 + x12 | 0, 13);
|
||||
x15 ^= rotl(x14 + x13 | 0, 18);
|
||||
}
|
||||
let oi = 0;
|
||||
o32[oi++] = x00;
|
||||
o32[oi++] = x05;
|
||||
o32[oi++] = x10;
|
||||
o32[oi++] = x15;
|
||||
o32[oi++] = x06;
|
||||
o32[oi++] = x07;
|
||||
o32[oi++] = x08;
|
||||
o32[oi++] = x09;
|
||||
}
|
||||
/**
|
||||
* Salsa20 from original paper.
|
||||
* With 12-byte nonce, it's not safe to use fill it with random (CSPRNG), due to collision chance.
|
||||
*/
|
||||
export const salsa20 = /* @__PURE__ */ createCipher(salsaCore, {
|
||||
allowShortKeys: true,
|
||||
counterRight: true,
|
||||
});
|
||||
/**
|
||||
* xsalsa20 eXtended-nonce salsa.
|
||||
* With 24-byte nonce, it's safe to use fill it with random (CSPRNG).
|
||||
*/
|
||||
export const xsalsa20 = /* @__PURE__ */ createCipher(salsaCore, {
|
||||
counterRight: true,
|
||||
extendNonceFn: hsalsa,
|
||||
});
|
||||
/**
|
||||
* xsalsa20-poly1305 eXtended-nonce salsa.
|
||||
* With 24-byte nonce, it's safe to use fill it with random (CSPRNG).
|
||||
* Also known as secretbox from libsodium / nacl.
|
||||
*/
|
||||
export const xsalsa20poly1305 = /* @__PURE__ */ wrapCipher({ blockSize: 64, nonceLength: 24, tagLength: 16 }, (key, nonce) => {
|
||||
const tagLength = 16;
|
||||
abytes(key, 32);
|
||||
abytes(nonce, 24);
|
||||
return {
|
||||
encrypt: (plaintext, output) => {
|
||||
abytes(plaintext);
|
||||
// This is small optimization (calculate auth key with same call as encryption itself) makes it hard
|
||||
// to separate tag calculation and encryption itself, since 32 byte is half-block of salsa (64 byte)
|
||||
const clength = plaintext.length + 32;
|
||||
if (output) {
|
||||
abytes(output, clength);
|
||||
}
|
||||
else {
|
||||
output = new Uint8Array(clength);
|
||||
}
|
||||
output.set(plaintext, 32);
|
||||
xsalsa20(key, nonce, output, output);
|
||||
const authKey = output.subarray(0, 32);
|
||||
const tag = poly1305(output.subarray(32), authKey);
|
||||
// Clean auth key, even though JS provides no guarantees about memory cleaning
|
||||
output.set(tag, tagLength);
|
||||
output.subarray(0, tagLength).fill(0);
|
||||
return output.subarray(tagLength);
|
||||
},
|
||||
decrypt: (ciphertext) => {
|
||||
abytes(ciphertext);
|
||||
const clength = ciphertext.length;
|
||||
if (clength < tagLength)
|
||||
throw new Error('encrypted data should be at least 16 bytes');
|
||||
// Create new ciphertext array:
|
||||
// auth tag auth tag from ciphertext ciphertext
|
||||
// [bytes 0..16] [bytes 16..32] [bytes 32..]
|
||||
// 16 instead of 32, because we already have 16 byte tag
|
||||
const ciphertext_ = new Uint8Array(clength + tagLength); // alloc
|
||||
ciphertext_.set(ciphertext, tagLength);
|
||||
// Each xsalsa20 calls to hsalsa to calculate key, but seems not much perf difference
|
||||
// Separate call to calculate authkey, since first bytes contains tag
|
||||
const authKey = xsalsa20(key, nonce, new Uint8Array(32)); // alloc(32)
|
||||
const tag = poly1305(ciphertext_.subarray(32), authKey);
|
||||
if (!equalBytes(ciphertext_.subarray(16, 32), tag))
|
||||
throw new Error('invalid tag');
|
||||
const plaintext = xsalsa20(key, nonce, ciphertext_); // alloc
|
||||
// Clean auth key, even though JS provides no guarantees about memory cleaning
|
||||
plaintext.subarray(0, 32).fill(0);
|
||||
authKey.fill(0);
|
||||
return plaintext.subarray(32);
|
||||
},
|
||||
};
|
||||
});
|
||||
/**
|
||||
* Alias to xsalsa20poly1305, for compatibility with libsodium / nacl
|
||||
*/
|
||||
export function secretbox(key, nonce) {
|
||||
const xs = xsalsa20poly1305(key, nonce);
|
||||
return { seal: xs.encrypt, open: xs.decrypt };
|
||||
}
|
||||
//# sourceMappingURL=salsa.js.map
|
||||
1
node_modules/@noble/ciphers/esm/salsa.js.map
generated
vendored
Normal file
1
node_modules/@noble/ciphers/esm/salsa.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
182
node_modules/@noble/ciphers/esm/utils.js
generated
vendored
Normal file
182
node_modules/@noble/ciphers/esm/utils.js
generated
vendored
Normal file
@@ -0,0 +1,182 @@
|
||||
/*! noble-ciphers - MIT License (c) 2023 Paul Miller (paulmillr.com) */
|
||||
import { bytes as abytes, isBytes } from './_assert.js';
|
||||
// Cast array to different type
|
||||
export const u8 = (arr) => new Uint8Array(arr.buffer, arr.byteOffset, arr.byteLength);
|
||||
export const u16 = (arr) => new Uint16Array(arr.buffer, arr.byteOffset, Math.floor(arr.byteLength / 2));
|
||||
export const u32 = (arr) => new Uint32Array(arr.buffer, arr.byteOffset, Math.floor(arr.byteLength / 4));
|
||||
// Cast array to view
|
||||
export const createView = (arr) => new DataView(arr.buffer, arr.byteOffset, arr.byteLength);
|
||||
// big-endian hardware is rare. Just in case someone still decides to run ciphers:
|
||||
// early-throw an error because we don't support BE yet.
|
||||
export const isLE = new Uint8Array(new Uint32Array([0x11223344]).buffer)[0] === 0x44;
|
||||
if (!isLE)
|
||||
throw new Error('Non little-endian hardware is not supported');
|
||||
// Array where index 0xf0 (240) is mapped to string 'f0'
|
||||
const hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, '0'));
|
||||
/**
|
||||
* @example bytesToHex(Uint8Array.from([0xca, 0xfe, 0x01, 0x23])) // 'cafe0123'
|
||||
*/
|
||||
export function bytesToHex(bytes) {
|
||||
abytes(bytes);
|
||||
// pre-caching improves the speed 6x
|
||||
let hex = '';
|
||||
for (let i = 0; i < bytes.length; i++) {
|
||||
hex += hexes[bytes[i]];
|
||||
}
|
||||
return hex;
|
||||
}
|
||||
// We use optimized technique to convert hex string to byte array
|
||||
const asciis = { _0: 48, _9: 57, _A: 65, _F: 70, _a: 97, _f: 102 };
|
||||
function asciiToBase16(char) {
|
||||
if (char >= asciis._0 && char <= asciis._9)
|
||||
return char - asciis._0;
|
||||
if (char >= asciis._A && char <= asciis._F)
|
||||
return char - (asciis._A - 10);
|
||||
if (char >= asciis._a && char <= asciis._f)
|
||||
return char - (asciis._a - 10);
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* @example hexToBytes('cafe0123') // Uint8Array.from([0xca, 0xfe, 0x01, 0x23])
|
||||
*/
|
||||
export function hexToBytes(hex) {
|
||||
if (typeof hex !== 'string')
|
||||
throw new Error('hex string expected, got ' + typeof hex);
|
||||
const hl = hex.length;
|
||||
const al = hl / 2;
|
||||
if (hl % 2)
|
||||
throw new Error('padded hex string expected, got unpadded hex of length ' + hl);
|
||||
const array = new Uint8Array(al);
|
||||
for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) {
|
||||
const n1 = asciiToBase16(hex.charCodeAt(hi));
|
||||
const n2 = asciiToBase16(hex.charCodeAt(hi + 1));
|
||||
if (n1 === undefined || n2 === undefined) {
|
||||
const char = hex[hi] + hex[hi + 1];
|
||||
throw new Error('hex string expected, got non-hex character "' + char + '" at index ' + hi);
|
||||
}
|
||||
array[ai] = n1 * 16 + n2;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
export function hexToNumber(hex) {
|
||||
if (typeof hex !== 'string')
|
||||
throw new Error('hex string expected, got ' + typeof hex);
|
||||
// Big Endian
|
||||
return BigInt(hex === '' ? '0' : `0x${hex}`);
|
||||
}
|
||||
// BE: Big Endian, LE: Little Endian
|
||||
export function bytesToNumberBE(bytes) {
|
||||
return hexToNumber(bytesToHex(bytes));
|
||||
}
|
||||
export function numberToBytesBE(n, len) {
|
||||
return hexToBytes(n.toString(16).padStart(len * 2, '0'));
|
||||
}
|
||||
// There is no setImmediate in browser and setTimeout is slow.
|
||||
// call of async fn will return Promise, which will be fullfiled only on
|
||||
// next scheduler queue processing step and this is exactly what we need.
|
||||
export const nextTick = async () => { };
|
||||
// Returns control to thread each 'tick' ms to avoid blocking
|
||||
export async function asyncLoop(iters, tick, cb) {
|
||||
let ts = Date.now();
|
||||
for (let i = 0; i < iters; i++) {
|
||||
cb(i);
|
||||
// Date.now() is not monotonic, so in case if clock goes backwards we return return control too
|
||||
const diff = Date.now() - ts;
|
||||
if (diff >= 0 && diff < tick)
|
||||
continue;
|
||||
await nextTick();
|
||||
ts += diff;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @example utf8ToBytes('abc') // new Uint8Array([97, 98, 99])
|
||||
*/
|
||||
export function utf8ToBytes(str) {
|
||||
if (typeof str !== 'string')
|
||||
throw new Error(`string expected, got ${typeof str}`);
|
||||
return new Uint8Array(new TextEncoder().encode(str)); // https://bugzil.la/1681809
|
||||
}
|
||||
/**
|
||||
* @example bytesToUtf8(new Uint8Array([97, 98, 99])) // 'abc'
|
||||
*/
|
||||
export function bytesToUtf8(bytes) {
|
||||
return new TextDecoder().decode(bytes);
|
||||
}
|
||||
/**
|
||||
* Normalizes (non-hex) string or Uint8Array to Uint8Array.
|
||||
* Warning: when Uint8Array is passed, it would NOT get copied.
|
||||
* Keep in mind for future mutable operations.
|
||||
*/
|
||||
export function toBytes(data) {
|
||||
if (typeof data === 'string')
|
||||
data = utf8ToBytes(data);
|
||||
else if (isBytes(data))
|
||||
data = data.slice();
|
||||
else
|
||||
throw new Error(`Uint8Array expected, got ${typeof data}`);
|
||||
return data;
|
||||
}
|
||||
/**
|
||||
* Copies several Uint8Arrays into one.
|
||||
*/
|
||||
export function concatBytes(...arrays) {
|
||||
let sum = 0;
|
||||
for (let i = 0; i < arrays.length; i++) {
|
||||
const a = arrays[i];
|
||||
abytes(a);
|
||||
sum += a.length;
|
||||
}
|
||||
const res = new Uint8Array(sum);
|
||||
for (let i = 0, pad = 0; i < arrays.length; i++) {
|
||||
const a = arrays[i];
|
||||
res.set(a, pad);
|
||||
pad += a.length;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
export function checkOpts(defaults, opts) {
|
||||
if (opts == null || typeof opts !== 'object')
|
||||
throw new Error('options must be defined');
|
||||
const merged = Object.assign(defaults, opts);
|
||||
return merged;
|
||||
}
|
||||
// Compares 2 u8a-s in kinda constant time
|
||||
export function equalBytes(a, b) {
|
||||
if (a.length !== b.length)
|
||||
return false;
|
||||
let diff = 0;
|
||||
for (let i = 0; i < a.length; i++)
|
||||
diff |= a[i] ^ b[i];
|
||||
return diff === 0;
|
||||
}
|
||||
// For runtime check if class implements interface
|
||||
export class Hash {
|
||||
}
|
||||
/**
|
||||
* @__NO_SIDE_EFFECTS__
|
||||
*/
|
||||
export const wrapCipher = (params, c) => {
|
||||
Object.assign(c, params);
|
||||
return c;
|
||||
};
|
||||
// Polyfill for Safari 14
|
||||
export function setBigUint64(view, byteOffset, value, isLE) {
|
||||
if (typeof view.setBigUint64 === 'function')
|
||||
return view.setBigUint64(byteOffset, value, isLE);
|
||||
const _32n = BigInt(32);
|
||||
const _u32_max = BigInt(0xffffffff);
|
||||
const wh = Number((value >> _32n) & _u32_max);
|
||||
const wl = Number(value & _u32_max);
|
||||
const h = isLE ? 4 : 0;
|
||||
const l = isLE ? 0 : 4;
|
||||
view.setUint32(byteOffset + h, wh, isLE);
|
||||
view.setUint32(byteOffset + l, wl, isLE);
|
||||
}
|
||||
export function u64Lengths(ciphertext, AAD) {
|
||||
const num = new Uint8Array(16);
|
||||
const view = createView(num);
|
||||
setBigUint64(view, 0, BigInt(AAD ? AAD.length : 0), true);
|
||||
setBigUint64(view, 8, BigInt(ciphertext.length), true);
|
||||
return num;
|
||||
}
|
||||
//# sourceMappingURL=utils.js.map
|
||||
1
node_modules/@noble/ciphers/esm/utils.js.map
generated
vendored
Normal file
1
node_modules/@noble/ciphers/esm/utils.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
105
node_modules/@noble/ciphers/esm/webcrypto.js
generated
vendored
Normal file
105
node_modules/@noble/ciphers/esm/webcrypto.js
generated
vendored
Normal file
@@ -0,0 +1,105 @@
|
||||
// We use WebCrypto aka globalThis.crypto, which exists in browsers and node.js 16+.
|
||||
// node.js versions earlier than v19 don't declare it in global scope.
|
||||
// For node.js, package.js on#exports field mapping rewrites import
|
||||
// from `crypto` to `cryptoNode`, which imports native module.
|
||||
// Makes the utils un-importable in browsers without a bundler.
|
||||
// Once node.js 18 is deprecated, we can just drop the import.
|
||||
//
|
||||
// Use full path so that Node.js can rewrite it to `cryptoNode.js`.
|
||||
import { randomBytes, getWebcryptoSubtle } from '@noble/ciphers/crypto';
|
||||
import { concatBytes } from './utils.js';
|
||||
import { number, bytes as abytes } from './_assert.js';
|
||||
/**
|
||||
* Secure PRNG. Uses `crypto.getRandomValues`, which defers to OS.
|
||||
*/
|
||||
export { randomBytes, getWebcryptoSubtle };
|
||||
// Uses CSPRG for nonce, nonce injected in ciphertext
|
||||
export function managedNonce(fn) {
|
||||
number(fn.nonceLength);
|
||||
return ((key, ...args) => ({
|
||||
encrypt: (plaintext, ...argsEnc) => {
|
||||
const { nonceLength } = fn;
|
||||
const nonce = randomBytes(nonceLength);
|
||||
const ciphertext = fn(key, nonce, ...args).encrypt(plaintext, ...argsEnc);
|
||||
const out = concatBytes(nonce, ciphertext);
|
||||
ciphertext.fill(0);
|
||||
return out;
|
||||
},
|
||||
decrypt: (ciphertext, ...argsDec) => {
|
||||
const { nonceLength } = fn;
|
||||
const nonce = ciphertext.subarray(0, nonceLength);
|
||||
const data = ciphertext.subarray(nonceLength);
|
||||
return fn(key, nonce, ...args).decrypt(data, ...argsDec);
|
||||
},
|
||||
}));
|
||||
}
|
||||
// Overridable
|
||||
export const utils = {
|
||||
async encrypt(key, keyParams, cryptParams, plaintext) {
|
||||
const cr = getWebcryptoSubtle();
|
||||
const iKey = await cr.importKey('raw', key, keyParams, true, ['encrypt']);
|
||||
const ciphertext = await cr.encrypt(cryptParams, iKey, plaintext);
|
||||
return new Uint8Array(ciphertext);
|
||||
},
|
||||
async decrypt(key, keyParams, cryptParams, ciphertext) {
|
||||
const cr = getWebcryptoSubtle();
|
||||
const iKey = await cr.importKey('raw', key, keyParams, true, ['decrypt']);
|
||||
const plaintext = await cr.decrypt(cryptParams, iKey, ciphertext);
|
||||
return new Uint8Array(plaintext);
|
||||
},
|
||||
};
|
||||
const mode = {
|
||||
CBC: 'AES-CBC',
|
||||
CTR: 'AES-CTR',
|
||||
GCM: 'AES-GCM',
|
||||
};
|
||||
function getCryptParams(algo, nonce, AAD) {
|
||||
if (algo === mode.CBC)
|
||||
return { name: mode.CBC, iv: nonce };
|
||||
if (algo === mode.CTR)
|
||||
return { name: mode.CTR, counter: nonce, length: 64 };
|
||||
if (algo === mode.GCM) {
|
||||
if (AAD)
|
||||
return { name: mode.GCM, iv: nonce, additionalData: AAD };
|
||||
else
|
||||
return { name: mode.GCM, iv: nonce };
|
||||
}
|
||||
throw new Error('unknown aes block mode');
|
||||
}
|
||||
function generate(algo) {
|
||||
return (key, nonce, AAD) => {
|
||||
abytes(key);
|
||||
abytes(nonce);
|
||||
const keyParams = { name: algo, length: key.length * 8 };
|
||||
const cryptParams = getCryptParams(algo, nonce, AAD);
|
||||
return {
|
||||
// keyLength,
|
||||
encrypt(plaintext) {
|
||||
abytes(plaintext);
|
||||
return utils.encrypt(key, keyParams, cryptParams, plaintext);
|
||||
},
|
||||
decrypt(ciphertext) {
|
||||
abytes(ciphertext);
|
||||
return utils.decrypt(key, keyParams, cryptParams, ciphertext);
|
||||
},
|
||||
};
|
||||
};
|
||||
}
|
||||
export const cbc = generate(mode.CBC);
|
||||
export const ctr = generate(mode.CTR);
|
||||
export const gcm = generate(mode.GCM);
|
||||
// // Type tests
|
||||
// import { siv, gcm, ctr, ecb, cbc } from '../aes.js';
|
||||
// import { xsalsa20poly1305 } from '../salsa.js';
|
||||
// import { chacha20poly1305, xchacha20poly1305 } from '../chacha.js';
|
||||
// const wsiv = managedNonce(siv);
|
||||
// const wgcm = managedNonce(gcm);
|
||||
// const wctr = managedNonce(ctr);
|
||||
// const wcbc = managedNonce(cbc);
|
||||
// const wsalsapoly = managedNonce(xsalsa20poly1305);
|
||||
// const wchacha = managedNonce(chacha20poly1305);
|
||||
// const wxchacha = managedNonce(xchacha20poly1305);
|
||||
// // should fail
|
||||
// const wcbc2 = managedNonce(managedNonce(cbc));
|
||||
// const wecb = managedNonce(ecb);
|
||||
//# sourceMappingURL=webcrypto.js.map
|
||||
1
node_modules/@noble/ciphers/esm/webcrypto.js.map
generated
vendored
Normal file
1
node_modules/@noble/ciphers/esm/webcrypto.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"webcrypto.js","sourceRoot":"","sources":["../src/webcrypto.ts"],"names":[],"mappings":"AAAA,oFAAoF;AACpF,sEAAsE;AACtE,mEAAmE;AACnE,8DAA8D;AAC9D,+DAA+D;AAC/D,8DAA8D;AAC9D,EAAE;AACF,mEAAmE;AACnE,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AACxE,OAAO,EAAuB,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9D,OAAO,EAAE,MAAM,EAAE,KAAK,IAAI,MAAM,EAAE,MAAM,cAAc,CAAC;AAEvD;;GAEG;AACH,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,CAAC;AAe3C,qDAAqD;AACrD,MAAM,UAAU,YAAY,CAA4B,EAAK;IAC3D,MAAM,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC;IACvB,OAAO,CAAC,CAAC,GAAe,EAAE,GAAG,IAAW,EAAO,EAAE,CAAC,CAAC;QACjD,OAAO,EAAE,CAAC,SAAqB,EAAE,GAAG,OAAc,EAAE,EAAE;YACpD,MAAM,EAAE,WAAW,EAAE,GAAG,EAAE,CAAC;YAC3B,MAAM,KAAK,GAAG,WAAW,CAAC,WAAW,CAAC,CAAC;YACvC,MAAM,UAAU,GAAI,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,CAAC,OAAe,CAAC,SAAS,EAAE,GAAG,OAAO,CAAC,CAAC;YACnF,MAAM,GAAG,GAAG,WAAW,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;YAC3C,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACnB,OAAO,GAAG,CAAC;QACb,CAAC;QACD,OAAO,EAAE,CAAC,UAAsB,EAAE,GAAG,OAAc,EAAE,EAAE;YACrD,MAAM,EAAE,WAAW,EAAE,GAAG,EAAE,CAAC;YAC3B,MAAM,KAAK,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC;YAClD,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;YAC9C,OAAQ,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,CAAC,OAAe,CAAC,IAAI,EAAE,GAAG,OAAO,CAAC,CAAC;QACpE,CAAC;KACF,CAAC,CAAmB,CAAC;AACxB,CAAC;AAED,cAAc;AACd,MAAM,CAAC,MAAM,KAAK,GAAG;IACnB,KAAK,CAAC,OAAO,CAAC,GAAe,EAAE,SAAc,EAAE,WAAgB,EAAE,SAAqB;QACpF,MAAM,EAAE,GAAG,kBAAkB,EAAE,CAAC;QAChC,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,SAAS,CAAC,KAAK,EAAE,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC;QAC1E,MAAM,UAAU,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;QAClE,OAAO,IAAI,UAAU,CAAC,UAAU,CAAC,CAAC;IACpC,CAAC;IACD,KAAK,CAAC,OAAO,CAAC,GAAe,EAAE,SAAc,EAAE,WAAgB,EAAE,UAAsB;QACrF,MAAM,EAAE,GAAG,kBAAkB,EAAE,CAAC;QAChC,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,SAAS,CAAC,KAAK,EAAE,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC;QAC1E,MAAM,SAAS,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;QAClE,OAAO,IAAI,UAAU,CAAC,SAAS,CAAC,CAAC;IACnC,CAAC;CACF,CAAC;AAEF,MAAM,IAAI,GAAG;IACX,GAAG,EAAE,SAAS;IACd,GAAG,EAAE,SAAS;IACd,GAAG,EAAE,SAAS;CACN,CAAC;AAGX,SAAS,cAAc,CAAC,IAAe,EAAE,KAAiB,EAAE,GAAgB;IAC1E,IAAI,IAAI,KAAK,IAAI,CAAC,GAAG;QAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC;IAC5D,IAAI,IAAI,KAAK,IAAI,CAAC,GAAG;QAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IAC7E,IAAI,IAAI,KAAK,IAAI,CAAC,GAAG,EAAE,CAAC;QACtB,IAAI,GAAG;YAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,EAAE,KAAK,EAAE,cAAc,EAAE,GAAG,EAAE,CAAC;;YAC9D,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC;IAC5C,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;AAC5C,CAAC;AAED,SAAS,QAAQ,CAAC,IAAe;IAC/B,OAAO,CAAC,GAAe,EAAE,KAAiB,EAAE,GAAgB,EAAe,EAAE;QAC3E,MAAM,CAAC,GAAG,CAAC,CAAC;QACZ,MAAM,CAAC,KAAK,CAAC,CAAC;QACd,MAAM,SAAS,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzD,MAAM,WAAW,GAAG,cAAc,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;QACrD,OAAO;YACL,aAAa;YACb,OAAO,CAAC,SAAqB;gBAC3B,MAAM,CAAC,SAAS,CAAC,CAAC;gBAClB,OAAO,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,SAAS,EAAE,WAAW,EAAE,SAAS,CAAC,CAAC;YAC/D,CAAC;YACD,OAAO,CAAC,UAAsB;gBAC5B,MAAM,CAAC,UAAU,CAAC,CAAC;gBACnB,OAAO,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,SAAS,EAAE,WAAW,EAAE,UAAU,CAAC,CAAC;YAChE,CAAC;SACF,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACtC,MAAM,CAAC,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACtC,MAAM,CAAC,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAEtC,gBAAgB;AAChB,uDAAuD;AACvD,kDAAkD;AAClD,sEAAsE;AAEtE,kCAAkC;AAClC,kCAAkC;AAClC,kCAAkC;AAClC,kCAAkC;AAClC,qDAAqD;AACrD,kDAAkD;AAClD,oDAAoD;AAEpD,iBAAiB;AACjB,iDAAiD;AACjD,kCAAkC"}
|
||||
Reference in New Issue
Block a user