7b3985100499908c8b00379f89b9f0541ac0b7e9f0084e4e283d0880499b8128.json raw

   1  {"ast":null,"code":"\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n  value: true\n});\nexports._DST_scalar = void 0;\nexports.expand_message_xmd = expand_message_xmd;\nexports.expand_message_xof = expand_message_xof;\nexports.hash_to_field = hash_to_field;\nexports.isogenyMap = isogenyMap;\nexports.createHasher = createHasher;\nconst utils_ts_1 = require(\"../utils.js\");\nconst modular_ts_1 = require(\"./modular.js\");\n// Octet Stream to Integer. \"spec\" implementation of os2ip is 2.5x slower vs bytesToNumberBE.\nconst os2ip = utils_ts_1.bytesToNumberBE;\n// Integer to Octet Stream (numberToBytesBE)\nfunction i2osp(value, length) {\n  anum(value);\n  anum(length);\n  if (value < 0 || value >= 1 << 8 * length) throw new Error('invalid I2OSP input: ' + value);\n  const res = Array.from({\n    length\n  }).fill(0);\n  for (let i = length - 1; i >= 0; i--) {\n    res[i] = value & 0xff;\n    value >>>= 8;\n  }\n  return new Uint8Array(res);\n}\nfunction strxor(a, b) {\n  const arr = new Uint8Array(a.length);\n  for (let i = 0; i < a.length; i++) {\n    arr[i] = a[i] ^ b[i];\n  }\n  return arr;\n}\nfunction anum(item) {\n  if (!Number.isSafeInteger(item)) throw new Error('number expected');\n}\nfunction normDST(DST) {\n  if (!(0, utils_ts_1.isBytes)(DST) && typeof DST !== 'string') throw new Error('DST must be Uint8Array or string');\n  return typeof DST === 'string' ? (0, utils_ts_1.utf8ToBytes)(DST) : DST;\n}\n/**\n * Produces a uniformly random byte string using a cryptographic hash function H that outputs b bits.\n * [RFC 9380 5.3.1](https://www.rfc-editor.org/rfc/rfc9380#section-5.3.1).\n */\nfunction expand_message_xmd(msg, DST, lenInBytes, H) {\n  (0, utils_ts_1.abytes)(msg);\n  anum(lenInBytes);\n  DST = normDST(DST);\n  // https://www.rfc-editor.org/rfc/rfc9380#section-5.3.3\n  if (DST.length > 255) DST = H((0, utils_ts_1.concatBytes)((0, utils_ts_1.utf8ToBytes)('H2C-OVERSIZE-DST-'), DST));\n  const {\n    outputLen: b_in_bytes,\n    blockLen: r_in_bytes\n  } = H;\n  const ell = Math.ceil(lenInBytes / b_in_bytes);\n  if (lenInBytes > 65535 || ell > 255) throw new Error('expand_message_xmd: invalid lenInBytes');\n  const DST_prime = (0, utils_ts_1.concatBytes)(DST, i2osp(DST.length, 1));\n  const Z_pad = i2osp(0, r_in_bytes);\n  const l_i_b_str = i2osp(lenInBytes, 2); // len_in_bytes_str\n  const b = new Array(ell);\n  const b_0 = H((0, utils_ts_1.concatBytes)(Z_pad, msg, l_i_b_str, i2osp(0, 1), DST_prime));\n  b[0] = H((0, utils_ts_1.concatBytes)(b_0, i2osp(1, 1), DST_prime));\n  for (let i = 1; i <= ell; i++) {\n    const args = [strxor(b_0, b[i - 1]), i2osp(i + 1, 1), DST_prime];\n    b[i] = H((0, utils_ts_1.concatBytes)(...args));\n  }\n  const pseudo_random_bytes = (0, utils_ts_1.concatBytes)(...b);\n  return pseudo_random_bytes.slice(0, lenInBytes);\n}\n/**\n * Produces a uniformly random byte string using an extendable-output function (XOF) H.\n * 1. The collision resistance of H MUST be at least k bits.\n * 2. H MUST be an XOF that has been proved indifferentiable from\n *    a random oracle under a reasonable cryptographic assumption.\n * [RFC 9380 5.3.2](https://www.rfc-editor.org/rfc/rfc9380#section-5.3.2).\n */\nfunction expand_message_xof(msg, DST, lenInBytes, k, H) {\n  (0, utils_ts_1.abytes)(msg);\n  anum(lenInBytes);\n  DST = normDST(DST);\n  // https://www.rfc-editor.org/rfc/rfc9380#section-5.3.3\n  // DST = H('H2C-OVERSIZE-DST-' || a_very_long_DST, Math.ceil((lenInBytes * k) / 8));\n  if (DST.length > 255) {\n    const dkLen = Math.ceil(2 * k / 8);\n    DST = H.create({\n      dkLen\n    }).update((0, utils_ts_1.utf8ToBytes)('H2C-OVERSIZE-DST-')).update(DST).digest();\n  }\n  if (lenInBytes > 65535 || DST.length > 255) throw new Error('expand_message_xof: invalid lenInBytes');\n  return H.create({\n    dkLen: lenInBytes\n  }).update(msg).update(i2osp(lenInBytes, 2))\n  // 2. DST_prime = DST || I2OSP(len(DST), 1)\n  .update(DST).update(i2osp(DST.length, 1)).digest();\n}\n/**\n * Hashes arbitrary-length byte strings to a list of one or more elements of a finite field F.\n * [RFC 9380 5.2](https://www.rfc-editor.org/rfc/rfc9380#section-5.2).\n * @param msg a byte string containing the message to hash\n * @param count the number of elements of F to output\n * @param options `{DST: string, p: bigint, m: number, k: number, expand: 'xmd' | 'xof', hash: H}`, see above\n * @returns [u_0, ..., u_(count - 1)], a list of field elements.\n */\nfunction hash_to_field(msg, count, options) {\n  (0, utils_ts_1._validateObject)(options, {\n    p: 'bigint',\n    m: 'number',\n    k: 'number',\n    hash: 'function'\n  });\n  const {\n    p,\n    k,\n    m,\n    hash,\n    expand,\n    DST\n  } = options;\n  if (!(0, utils_ts_1.isHash)(options.hash)) throw new Error('expected valid hash');\n  (0, utils_ts_1.abytes)(msg);\n  anum(count);\n  const log2p = p.toString(2).length;\n  const L = Math.ceil((log2p + k) / 8); // section 5.1 of ietf draft link above\n  const len_in_bytes = count * m * L;\n  let prb; // pseudo_random_bytes\n  if (expand === 'xmd') {\n    prb = expand_message_xmd(msg, DST, len_in_bytes, hash);\n  } else if (expand === 'xof') {\n    prb = expand_message_xof(msg, DST, len_in_bytes, k, hash);\n  } else if (expand === '_internal_pass') {\n    // for internal tests only\n    prb = msg;\n  } else {\n    throw new Error('expand must be \"xmd\" or \"xof\"');\n  }\n  const u = new Array(count);\n  for (let i = 0; i < count; i++) {\n    const e = new Array(m);\n    for (let j = 0; j < m; j++) {\n      const elm_offset = L * (j + i * m);\n      const tv = prb.subarray(elm_offset, elm_offset + L);\n      e[j] = (0, modular_ts_1.mod)(os2ip(tv), p);\n    }\n    u[i] = e;\n  }\n  return u;\n}\nfunction isogenyMap(field, map) {\n  // Make same order as in spec\n  const coeff = map.map(i => Array.from(i).reverse());\n  return (x, y) => {\n    const [xn, xd, yn, yd] = coeff.map(val => val.reduce((acc, i) => field.add(field.mul(acc, x), i)));\n    // 6.6.3\n    // Exceptional cases of iso_map are inputs that cause the denominator of\n    // either rational function to evaluate to zero; such cases MUST return\n    // the identity point on E.\n    const [xd_inv, yd_inv] = (0, modular_ts_1.FpInvertBatch)(field, [xd, yd], true);\n    x = field.mul(xn, xd_inv); // xNum / xDen\n    y = field.mul(y, field.mul(yn, yd_inv)); // y * (yNum / yDev)\n    return {\n      x,\n      y\n    };\n  };\n}\nexports._DST_scalar = (0, utils_ts_1.utf8ToBytes)('HashToScalar-');\n/** Creates hash-to-curve methods from EC Point and mapToCurve function. See {@link H2CHasher}. */\nfunction createHasher(Point, mapToCurve, defaults) {\n  if (typeof mapToCurve !== 'function') throw new Error('mapToCurve() must be defined');\n  function map(num) {\n    return Point.fromAffine(mapToCurve(num));\n  }\n  function clear(initial) {\n    const P = initial.clearCofactor();\n    if (P.equals(Point.ZERO)) return Point.ZERO; // zero will throw in assert\n    P.assertValidity();\n    return P;\n  }\n  return {\n    defaults,\n    hashToCurve(msg, options) {\n      const opts = Object.assign({}, defaults, options);\n      const u = hash_to_field(msg, 2, opts);\n      const u0 = map(u[0]);\n      const u1 = map(u[1]);\n      return clear(u0.add(u1));\n    },\n    encodeToCurve(msg, options) {\n      const optsDst = defaults.encodeDST ? {\n        DST: defaults.encodeDST\n      } : {};\n      const opts = Object.assign({}, defaults, optsDst, options);\n      const u = hash_to_field(msg, 1, opts);\n      const u0 = map(u[0]);\n      return clear(u0);\n    },\n    /** See {@link H2CHasher} */\n    mapToCurve(scalars) {\n      if (!Array.isArray(scalars)) throw new Error('expected array of bigints');\n      for (const i of scalars) if (typeof i !== 'bigint') throw new Error('expected array of bigints');\n      return clear(map(scalars));\n    },\n    // hash_to_scalar can produce 0: https://www.rfc-editor.org/errata/eid8393\n    // RFC 9380, draft-irtf-cfrg-bbs-signatures-08\n    hashToScalar(msg, options) {\n      // @ts-ignore\n      const N = Point.Fn.ORDER;\n      const opts = Object.assign({}, defaults, {\n        p: N,\n        m: 1,\n        DST: exports._DST_scalar\n      }, options);\n      return hash_to_field(msg, 1, opts)[0][0];\n    }\n  };\n}\n//# sourceMappingURL=hash-to-curve.js.map","map":null,"metadata":{},"sourceType":"script","externalDependencies":[]}