UNPKG

@iacobus/hd

Version:

Hierarchical Deterministic Symmetric Keys.

95 lines (94 loc) 3.5 kB
"use strict"; /** * @fileoverview Exports utility functions. * @author Jacob V. B. Haap <iacobus.xyz> * @license MIT */ Object.defineProperty(exports, "__esModule", { value: true }); exports.calcSalt = calcSalt; exports.encodeInt = encodeInt; exports.strToIndex = strToIndex; exports.getIndex = getIndex; exports.fingerprint = fingerprint; const hmac_1 = require("@noble/hashes/hmac"); /** calcSalt creates a 16 byte salt from a given hash, message, and optional context info. */ function calcSalt(h, msg, info) { if (info) { const hash = h.create().update(info); // Hash to expand the info info = hash.digest().slice(0, 16); // Expanded info from hash digest } else { info = new Uint8Array(16); // 16 byte array } const mac = hmac_1.hmac.create(h, info); // Create HMAC using info mac.update(msg); const domain = Uint8Array.from([83, 65, 76, 84]); // Bytes SALT for domain separation mac.update(domain); return mac.digest().slice(0, 16); // Return a salt from the MAC digest } /** encodeInt encodes a given integer as a 4 byte Uint8Array. */ function encodeInt(int) { const buf = new Uint8Array(4); buf[0] = (int >>> 24) & 0xff; buf[1] = (int >>> 16) & 0xff; buf[2] = (int >>> 8) & 0xff; buf[3] = int & 0xff; return buf; } /** strToIndex obtains a 32 bit integer from a given hash and string. */ function strToIndex(h, str) { const sum = h.create().update(str).digest().slice(0, 4); // Create a hash of the string const buf = new DataView(new Uint8Array(sum).buffer); // Dataview of the hash digest return buf.getUint32(0, false); // Return 32 bit integer from the buffer } /** getIndex obtains a 32 bit integer index from a given hash, index string, and type. */ function getIndex(h, index, type) { if (!["num", "str", "any"].includes(type)) { throw new TypeError(`type "${type}" invalid for index`); } let i; if (type === "num") { try { const n = parseInt(index, 10); // Parse string to integer if (!Number.isInteger(n) || n < 0 || n > 0xFFFFFFFF) { throw new RangeError(`parsed index outside of uint32 range`); } i = n; } catch (error) { throw new TypeError(`invalid numeric index "${index}", ${error}`); } } else if (type === "str") { try { i = strToIndex(h, index); // Convert string to an integer } catch (error) { throw new TypeError(`invalid alphabetic index "${index}", ${error}`); } } else { try { const n = parseInt(index, 10); // Try parsing integer first if (!Number.isInteger(n) || n < 0 || n > 0xFFFFFFFF) { throw new RangeError(`parsed index outside of uint32 range`); } i = n; } catch { try { i = strToIndex(h, index); // Try string conversion next } catch (error) { throw new SyntaxError(`invalid index "${index}", ${error}`); } } } return i; } /** fingerprint calculates a fingerprint from a given hash, parent key, and child key. */ function fingerprint(h, parent, child) { const mac = hmac_1.hmac.create(h, parent); // Create an HMAC using the parent mac.update(child); // Write the child to the MAC return mac.digest().slice(0, 16); // Return the MAC as the fingerprint }