UNPKG

@okxweb3/crypto-lib

Version:

A base package for @okxweb3/coin-*

206 lines 7.33 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.validateObject = exports.createHmacDrbg = exports.bitMask = exports.bitSet = exports.bitGet = exports.bitLen = exports.utf8ToBytes = exports.equalBytes = exports.concatBytes = exports.ensureBytes = exports.numberToVarBytesBE = exports.numberToBytesLE = exports.numberToBytesBE = exports.bytesToNumberLE = exports.bytesToNumberBE = exports.hexToBytes = exports.hexToNumber = exports.numberToHexUnpadded = exports.bytesToHex = void 0; const _0n = BigInt(0); const _1n = BigInt(1); const _2n = BigInt(2); const u8a = (a) => a instanceof Uint8Array; const hexes = Array.from({ length: 256 }, (v, i) => i.toString(16).padStart(2, '0')); function bytesToHex(bytes) { if (!u8a(bytes)) throw new Error('Uint8Array expected'); let hex = ''; for (let i = 0; i < bytes.length; i++) { hex += hexes[bytes[i]]; } return hex; } exports.bytesToHex = bytesToHex; function numberToHexUnpadded(num) { const hex = num.toString(16); return hex.length & 1 ? `0${hex}` : hex; } exports.numberToHexUnpadded = numberToHexUnpadded; function hexToNumber(hex) { if (typeof hex !== 'string') throw new Error('hex string expected, got ' + typeof hex); return BigInt(hex === '' ? '0' : `0x${hex}`); } exports.hexToNumber = hexToNumber; function hexToBytes(hex) { if (typeof hex !== 'string') throw new Error('hex string expected, got ' + typeof hex); if (hex.length % 2) throw new Error('hex string is invalid: unpadded ' + hex.length); const array = new Uint8Array(hex.length / 2); for (let i = 0; i < array.length; i++) { const j = i * 2; const hexByte = hex.slice(j, j + 2); const byte = Number.parseInt(hexByte, 16); if (Number.isNaN(byte) || byte < 0) throw new Error('invalid byte sequence'); array[i] = byte; } return array; } exports.hexToBytes = hexToBytes; function bytesToNumberBE(bytes) { return hexToNumber(bytesToHex(bytes)); } exports.bytesToNumberBE = bytesToNumberBE; function bytesToNumberLE(bytes) { if (!u8a(bytes)) throw new Error('Uint8Array expected'); return hexToNumber(bytesToHex(Uint8Array.from(bytes).reverse())); } exports.bytesToNumberLE = bytesToNumberLE; const numberToBytesBE = (n, len) => hexToBytes(n.toString(16).padStart(len * 2, '0')); exports.numberToBytesBE = numberToBytesBE; const numberToBytesLE = (n, len) => (0, exports.numberToBytesBE)(n, len).reverse(); exports.numberToBytesLE = numberToBytesLE; const numberToVarBytesBE = (n) => hexToBytes(numberToHexUnpadded(n)); exports.numberToVarBytesBE = numberToVarBytesBE; 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 (u8a(hex)) { 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; } exports.ensureBytes = ensureBytes; function concatBytes(...arrs) { const r = new Uint8Array(arrs.reduce((sum, a) => sum + a.length, 0)); let pad = 0; arrs.forEach((a) => { if (!u8a(a)) throw new Error('Uint8Array expected'); r.set(a, pad); pad += a.length; }); return r; } exports.concatBytes = concatBytes; function equalBytes(b1, b2) { if (b1.length !== b2.length) return false; for (let i = 0; i < b1.length; i++) if (b1[i] !== b2[i]) return false; return true; } exports.equalBytes = equalBytes; function utf8ToBytes(str) { if (typeof str !== 'string') { throw new Error(`utf8ToBytes expected string, got ${typeof str}`); } return new TextEncoder().encode(str); } exports.utf8ToBytes = utf8ToBytes; function bitLen(n) { let len; for (len = 0; n > _0n; n >>= _1n, len += 1) ; return len; } exports.bitLen = bitLen; const bitGet = (n, pos) => (n >> BigInt(pos)) & _1n; exports.bitGet = bitGet; const bitSet = (n, pos, value) => n | ((value ? _1n : _0n) << BigInt(pos)); exports.bitSet = bitSet; const bitMask = (n) => (_2n << BigInt(n - 1)) - _1n; exports.bitMask = bitMask; const u8n = (data) => new Uint8Array(data); const u8fr = (arr) => Uint8Array.from(arr); 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'); let v = u8n(hashLen); let k = u8n(hashLen); let i = 0; const reset = () => { v.fill(1); k.fill(0); i = 0; }; const h = (...b) => hmacFn(k, v, ...b); const reseed = (seed = u8n()) => { k = h(u8fr([0x00]), seed); v = h(); if (seed.length === 0) return; k = h(u8fr([0x01]), seed); v = h(); }; const gen = () => { 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); let res = undefined; while (!(res = pred(gen()))) reseed(); reset(); return res; }; return genUntil; } exports.createHmacDrbg = createHmacDrbg; const validatorFns = { bigint: (val) => typeof val === 'bigint', function: (val) => typeof val === 'function', boolean: (val) => typeof val === 'boolean', string: (val) => typeof val === 'string', 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), }; 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; } exports.validateObject = validateObject; //# sourceMappingURL=utils.js.map