| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180 | 
							- "use strict";
 
- Object.defineProperty(exports, "__esModule", { value: true });
 
- exports.expand_message_xmd = expand_message_xmd;
 
- exports.expand_message_xof = expand_message_xof;
 
- exports.hash_to_field = hash_to_field;
 
- exports.isogenyMap = isogenyMap;
 
- exports.createHasher = createHasher;
 
- const modular_js_1 = require("./modular.js");
 
- const utils_js_1 = require("./utils.js");
 
- // Octet Stream to Integer. "spec" implementation of os2ip is 2.5x slower vs bytesToNumberBE.
 
- const os2ip = utils_js_1.bytesToNumberBE;
 
- // Integer to Octet Stream (numberToBytesBE)
 
- function i2osp(value, length) {
 
-     if (value < 0 || value >= 1 << (8 * length)) {
 
-         throw new Error(`bad I2OSP call: value=${value} length=${length}`);
 
-     }
 
-     const res = Array.from({ length }).fill(0);
 
-     for (let i = length - 1; i >= 0; i--) {
 
-         res[i] = value & 0xff;
 
-         value >>>= 8;
 
-     }
 
-     return new Uint8Array(res);
 
- }
 
- function strxor(a, b) {
 
-     const arr = new Uint8Array(a.length);
 
-     for (let i = 0; i < a.length; i++) {
 
-         arr[i] = a[i] ^ b[i];
 
-     }
 
-     return arr;
 
- }
 
- function anum(item) {
 
-     if (!Number.isSafeInteger(item))
 
-         throw new Error('number expected');
 
- }
 
- // Produces a uniformly random byte string using a cryptographic hash function H that outputs b bits
 
- // https://www.rfc-editor.org/rfc/rfc9380#section-5.3.1
 
- function expand_message_xmd(msg, DST, lenInBytes, H) {
 
-     (0, utils_js_1.abytes)(msg);
 
-     (0, utils_js_1.abytes)(DST);
 
-     anum(lenInBytes);
 
-     // https://www.rfc-editor.org/rfc/rfc9380#section-5.3.3
 
-     if (DST.length > 255)
 
-         DST = H((0, utils_js_1.concatBytes)((0, utils_js_1.utf8ToBytes)('H2C-OVERSIZE-DST-'), DST));
 
-     const { outputLen: b_in_bytes, blockLen: r_in_bytes } = H;
 
-     const ell = Math.ceil(lenInBytes / b_in_bytes);
 
-     if (ell > 255)
 
-         throw new Error('Invalid xmd length');
 
-     const DST_prime = (0, utils_js_1.concatBytes)(DST, i2osp(DST.length, 1));
 
-     const Z_pad = i2osp(0, r_in_bytes);
 
-     const l_i_b_str = i2osp(lenInBytes, 2); // len_in_bytes_str
 
-     const b = new Array(ell);
 
-     const b_0 = H((0, utils_js_1.concatBytes)(Z_pad, msg, l_i_b_str, i2osp(0, 1), DST_prime));
 
-     b[0] = H((0, utils_js_1.concatBytes)(b_0, i2osp(1, 1), DST_prime));
 
-     for (let i = 1; i <= ell; i++) {
 
-         const args = [strxor(b_0, b[i - 1]), i2osp(i + 1, 1), DST_prime];
 
-         b[i] = H((0, utils_js_1.concatBytes)(...args));
 
-     }
 
-     const pseudo_random_bytes = (0, utils_js_1.concatBytes)(...b);
 
-     return pseudo_random_bytes.slice(0, lenInBytes);
 
- }
 
- // Produces a uniformly random byte string using an extendable-output function (XOF) H.
 
- // 1. The collision resistance of H MUST be at least k bits.
 
- // 2. H MUST be an XOF that has been proved indifferentiable from
 
- //    a random oracle under a reasonable cryptographic assumption.
 
- // https://www.rfc-editor.org/rfc/rfc9380#section-5.3.2
 
- function expand_message_xof(msg, DST, lenInBytes, k, H) {
 
-     (0, utils_js_1.abytes)(msg);
 
-     (0, utils_js_1.abytes)(DST);
 
-     anum(lenInBytes);
 
-     // https://www.rfc-editor.org/rfc/rfc9380#section-5.3.3
 
-     // DST = H('H2C-OVERSIZE-DST-' || a_very_long_DST, Math.ceil((lenInBytes * k) / 8));
 
-     if (DST.length > 255) {
 
-         const dkLen = Math.ceil((2 * k) / 8);
 
-         DST = H.create({ dkLen }).update((0, utils_js_1.utf8ToBytes)('H2C-OVERSIZE-DST-')).update(DST).digest();
 
-     }
 
-     if (lenInBytes > 65535 || DST.length > 255)
 
-         throw new Error('expand_message_xof: invalid lenInBytes');
 
-     return (H.create({ dkLen: lenInBytes })
 
-         .update(msg)
 
-         .update(i2osp(lenInBytes, 2))
 
-         // 2. DST_prime = DST || I2OSP(len(DST), 1)
 
-         .update(DST)
 
-         .update(i2osp(DST.length, 1))
 
-         .digest());
 
- }
 
- /**
 
-  * Hashes arbitrary-length byte strings to a list of one or more elements of a finite field F
 
-  * https://www.rfc-editor.org/rfc/rfc9380#section-5.2
 
-  * @param msg a byte string containing the message to hash
 
-  * @param count the number of elements of F to output
 
-  * @param options `{DST: string, p: bigint, m: number, k: number, expand: 'xmd' | 'xof', hash: H}`, see above
 
-  * @returns [u_0, ..., u_(count - 1)], a list of field elements.
 
-  */
 
- function hash_to_field(msg, count, options) {
 
-     (0, utils_js_1.validateObject)(options, {
 
-         DST: 'stringOrUint8Array',
 
-         p: 'bigint',
 
-         m: 'isSafeInteger',
 
-         k: 'isSafeInteger',
 
-         hash: 'hash',
 
-     });
 
-     const { p, k, m, hash, expand, DST: _DST } = options;
 
-     (0, utils_js_1.abytes)(msg);
 
-     anum(count);
 
-     const DST = typeof _DST === 'string' ? (0, utils_js_1.utf8ToBytes)(_DST) : _DST;
 
-     const log2p = p.toString(2).length;
 
-     const L = Math.ceil((log2p + k) / 8); // section 5.1 of ietf draft link above
 
-     const len_in_bytes = count * m * L;
 
-     let prb; // pseudo_random_bytes
 
-     if (expand === 'xmd') {
 
-         prb = expand_message_xmd(msg, DST, len_in_bytes, hash);
 
-     }
 
-     else if (expand === 'xof') {
 
-         prb = expand_message_xof(msg, DST, len_in_bytes, k, hash);
 
-     }
 
-     else if (expand === '_internal_pass') {
 
-         // for internal tests only
 
-         prb = msg;
 
-     }
 
-     else {
 
-         throw new Error('expand must be "xmd" or "xof"');
 
-     }
 
-     const u = new Array(count);
 
-     for (let i = 0; i < count; i++) {
 
-         const e = new Array(m);
 
-         for (let j = 0; j < m; j++) {
 
-             const elm_offset = L * (j + i * m);
 
-             const tv = prb.subarray(elm_offset, elm_offset + L);
 
-             e[j] = (0, modular_js_1.mod)(os2ip(tv), p);
 
-         }
 
-         u[i] = e;
 
-     }
 
-     return u;
 
- }
 
- function isogenyMap(field, map) {
 
-     // Make same order as in spec
 
-     const COEFF = map.map((i) => Array.from(i).reverse());
 
-     return (x, y) => {
 
-         const [xNum, xDen, yNum, yDen] = COEFF.map((val) => val.reduce((acc, i) => field.add(field.mul(acc, x), i)));
 
-         x = field.div(xNum, xDen); // xNum / xDen
 
-         y = field.mul(y, field.div(yNum, yDen)); // y * (yNum / yDev)
 
-         return { x, y };
 
-     };
 
- }
 
- function createHasher(Point, mapToCurve, def) {
 
-     if (typeof mapToCurve !== 'function')
 
-         throw new Error('mapToCurve() must be defined');
 
-     return {
 
-         // Encodes byte string to elliptic curve.
 
-         // hash_to_curve from https://www.rfc-editor.org/rfc/rfc9380#section-3
 
-         hashToCurve(msg, options) {
 
-             const u = hash_to_field(msg, 2, { ...def, DST: def.DST, ...options });
 
-             const u0 = Point.fromAffine(mapToCurve(u[0]));
 
-             const u1 = Point.fromAffine(mapToCurve(u[1]));
 
-             const P = u0.add(u1).clearCofactor();
 
-             P.assertValidity();
 
-             return P;
 
-         },
 
-         // Encodes byte string to elliptic curve.
 
-         // encode_to_curve from https://www.rfc-editor.org/rfc/rfc9380#section-3
 
-         encodeToCurve(msg, options) {
 
-             const u = hash_to_field(msg, 1, { ...def, DST: def.encodeDST, ...options });
 
-             const P = Point.fromAffine(mapToCurve(u[0])).clearCofactor();
 
-             P.assertValidity();
 
-             return P;
 
-         },
 
-         // Same as encodeToCurve, but without hash
 
-         mapToCurve(scalars) {
 
-             if (!Array.isArray(scalars))
 
-                 throw new Error('mapToCurve: expected array of bigints');
 
-             for (const i of scalars)
 
-                 if (typeof i !== 'bigint')
 
-                     throw new Error(`mapToCurve: expected array of bigints, got ${i} in array`);
 
-             const P = Point.fromAffine(mapToCurve(scalars)).clearCofactor();
 
-             P.assertValidity();
 
-             return P;
 
-         },
 
-     };
 
- }
 
- //# sourceMappingURL=hash-to-curve.js.map
 
 
  |