| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289 | /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */// 100 lines of code in the file are duplicated from noble-hashes (utils).// This is OK: `abstract` directory does not use noble-hashes.// User may opt-in into using different hashing library. This way, noble-hashes// won't be included into their bundle.const _0n = /* @__PURE__ */ BigInt(0);const _1n = /* @__PURE__ */ BigInt(1);const _2n = /* @__PURE__ */ BigInt(2);export function isBytes(a) {    return (a instanceof Uint8Array ||        (a != null && typeof a === 'object' && a.constructor.name === 'Uint8Array'));}export function abytes(item) {    if (!isBytes(item))        throw new Error('Uint8Array expected');}// 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;}export function numberToHexUnpadded(num) {    const hex = num.toString(16);    return hex.length & 1 ? `0${hex}` : hex;}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}`);}// We use optimized technique to convert hex string to byte arrayconst 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;}// BE: Big Endian, LE: Little Endianexport function bytesToNumberBE(bytes) {    return hexToNumber(bytesToHex(bytes));}export function bytesToNumberLE(bytes) {    abytes(bytes);    return hexToNumber(bytesToHex(Uint8Array.from(bytes).reverse()));}export function numberToBytesBE(n, len) {    return hexToBytes(n.toString(16).padStart(len * 2, '0'));}export function numberToBytesLE(n, len) {    return numberToBytesBE(n, len).reverse();}// Unpadded, rarely usedexport function numberToVarBytesBE(n) {    return hexToBytes(numberToHexUnpadded(n));}/** * Takes hex string or Uint8Array, converts to Uint8Array. * Validates output length. * Will throw error for other types. * @param title descriptive title for an error e.g. 'private key' * @param hex hex string or Uint8Array * @param expectedLength optional, will compare to result array's length * @returns */export function ensureBytes(title, hex, expectedLength) {    let res;    if (typeof hex === 'string') {        try {            res = hexToBytes(hex);        }        catch (e) {            throw new Error(`${title} must be valid hex string, got "${hex}". Cause: ${e}`);        }    }    else if (isBytes(hex)) {        // Uint8Array.from() instead of hash.slice() because node.js Buffer        // is instance of Uint8Array, and its slice() creates **mutable** copy        res = Uint8Array.from(hex);    }    else {        throw new Error(`${title} must be hex string or Uint8Array`);    }    const len = res.length;    if (typeof expectedLength === 'number' && len !== expectedLength)        throw new Error(`${title} expected ${expectedLength} bytes, got ${len}`);    return res;}/** * 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;}// Compares 2 u8a-s in kinda constant timeexport 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;}/** * @example utf8ToBytes('abc') // new Uint8Array([97, 98, 99]) */export function utf8ToBytes(str) {    if (typeof str !== 'string')        throw new Error(`utf8ToBytes expected string, got ${typeof str}`);    return new Uint8Array(new TextEncoder().encode(str)); // https://bugzil.la/1681809}// Bit operations/** * Calculates amount of bits in a bigint. * Same as `n.toString(2).length` */export function bitLen(n) {    let len;    for (len = 0; n > _0n; n >>= _1n, len += 1)        ;    return len;}/** * Gets single bit at position. * NOTE: first bit position is 0 (same as arrays) * Same as `!!+Array.from(n.toString(2)).reverse()[pos]` */export function bitGet(n, pos) {    return (n >> BigInt(pos)) & _1n;}/** * Sets single bit at position. */export function bitSet(n, pos, value) {    return n | ((value ? _1n : _0n) << BigInt(pos));}/** * Calculate mask for N bits. Not using ** operator with bigints because of old engines. * Same as BigInt(`0b${Array(i).fill('1').join('')}`) */export const bitMask = (n) => (_2n << BigInt(n - 1)) - _1n;// DRBGconst u8n = (data) => new Uint8Array(data); // creates Uint8Arrayconst u8fr = (arr) => Uint8Array.from(arr); // another shortcut/** * Minimal HMAC-DRBG from NIST 800-90 for RFC6979 sigs. * @returns function that will call DRBG until 2nd arg returns something meaningful * @example *   const drbg = createHmacDRBG<Key>(32, 32, hmac); *   drbg(seed, bytesToKey); // bytesToKey must return Key or undefined */export function createHmacDrbg(hashLen, qByteLen, hmacFn) {    if (typeof hashLen !== 'number' || hashLen < 2)        throw new Error('hashLen must be a number');    if (typeof qByteLen !== 'number' || qByteLen < 2)        throw new Error('qByteLen must be a number');    if (typeof hmacFn !== 'function')        throw new Error('hmacFn must be a function');    // Step B, Step C: set hashLen to 8*ceil(hlen/8)    let v = u8n(hashLen); // Minimal non-full-spec HMAC-DRBG from NIST 800-90 for RFC6979 sigs.    let k = u8n(hashLen); // Steps B and C of RFC6979 3.2: set hashLen, in our case always same    let i = 0; // Iterations counter, will throw when over 1000    const reset = () => {        v.fill(1);        k.fill(0);        i = 0;    };    const h = (...b) => hmacFn(k, v, ...b); // hmac(k)(v, ...values)    const reseed = (seed = u8n()) => {        // HMAC-DRBG reseed() function. Steps D-G        k = h(u8fr([0x00]), seed); // k = hmac(k || v || 0x00 || seed)        v = h(); // v = hmac(k || v)        if (seed.length === 0)            return;        k = h(u8fr([0x01]), seed); // k = hmac(k || v || 0x01 || seed)        v = h(); // v = hmac(k || v)    };    const gen = () => {        // HMAC-DRBG generate() function        if (i++ >= 1000)            throw new Error('drbg: tried 1000 values');        let len = 0;        const out = [];        while (len < qByteLen) {            v = h();            const sl = v.slice();            out.push(sl);            len += v.length;        }        return concatBytes(...out);    };    const genUntil = (seed, pred) => {        reset();        reseed(seed); // Steps D-G        let res = undefined; // Step H: grind until k is in [1..n-1]        while (!(res = pred(gen())))            reseed();        reset();        return res;    };    return genUntil;}// Validating curves and fieldsconst validatorFns = {    bigint: (val) => typeof val === 'bigint',    function: (val) => typeof val === 'function',    boolean: (val) => typeof val === 'boolean',    string: (val) => typeof val === 'string',    stringOrUint8Array: (val) => typeof val === 'string' || isBytes(val),    isSafeInteger: (val) => Number.isSafeInteger(val),    array: (val) => Array.isArray(val),    field: (val, object) => object.Fp.isValid(val),    hash: (val) => typeof val === 'function' && Number.isSafeInteger(val.outputLen),};// type Record<K extends string | number | symbol, T> = { [P in K]: T; }export function validateObject(object, validators, optValidators = {}) {    const checkField = (fieldName, type, isOptional) => {        const checkVal = validatorFns[type];        if (typeof checkVal !== 'function')            throw new Error(`Invalid validator "${type}", expected function`);        const val = object[fieldName];        if (isOptional && val === undefined)            return;        if (!checkVal(val, object)) {            throw new Error(`Invalid param ${String(fieldName)}=${val} (${typeof val}), expected ${type}`);        }    };    for (const [fieldName, type] of Object.entries(validators))        checkField(fieldName, type, false);    for (const [fieldName, type] of Object.entries(optValidators))        checkField(fieldName, type, true);    return object;}// validate type tests// const o: { a: number; b: number; c: number } = { a: 1, b: 5, c: 6 };// const z0 = validateObject(o, { a: 'isSafeInteger' }, { c: 'bigint' }); // Ok!// // Should fail type-check// const z1 = validateObject(o, { a: 'tmp' }, { c: 'zz' });// const z2 = validateObject(o, { a: 'isSafeInteger' }, { c: 'zz' });// const z3 = validateObject(o, { test: 'boolean', z: 'bug' });// const z4 = validateObject(o, { a: 'boolean', z: 'bug' });//# sourceMappingURL=utils.js.map
 |