ed448.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.hash_to_decaf448 = exports.hashToDecaf448 = exports.DecafPoint = exports.encodeToCurve = exports.hashToCurve = exports.edwardsToMontgomery = exports.x448 = exports.ed448ph = exports.ed448 = void 0;
  4. exports.edwardsToMontgomeryPub = edwardsToMontgomeryPub;
  5. /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
  6. const sha3_1 = require("@noble/hashes/sha3");
  7. const utils_1 = require("@noble/hashes/utils");
  8. const edwards_js_1 = require("./abstract/edwards.js");
  9. const hash_to_curve_js_1 = require("./abstract/hash-to-curve.js");
  10. const modular_js_1 = require("./abstract/modular.js");
  11. const montgomery_js_1 = require("./abstract/montgomery.js");
  12. const utils_js_1 = require("./abstract/utils.js");
  13. /**
  14. * Edwards448 (not Ed448-Goldilocks) curve with following addons:
  15. * - X448 ECDH
  16. * - Decaf cofactor elimination
  17. * - Elligator hash-to-group / point indistinguishability
  18. * Conforms to RFC 8032 https://www.rfc-editor.org/rfc/rfc8032.html#section-5.2
  19. */
  20. const shake256_114 = (0, utils_1.wrapConstructor)(() => sha3_1.shake256.create({ dkLen: 114 }));
  21. const shake256_64 = (0, utils_1.wrapConstructor)(() => sha3_1.shake256.create({ dkLen: 64 }));
  22. const ed448P = BigInt('726838724295606890549323807888004534353641360687318060281490199180612328166730772686396383698676545930088884461843637361053498018365439');
  23. // prettier-ignore
  24. const _1n = BigInt(1), _2n = BigInt(2), _3n = BigInt(3), _4n = BigInt(4), _11n = BigInt(11);
  25. // prettier-ignore
  26. const _22n = BigInt(22), _44n = BigInt(44), _88n = BigInt(88), _223n = BigInt(223);
  27. // powPminus3div4 calculates z = x^k mod p, where k = (p-3)/4.
  28. // Used for efficient square root calculation.
  29. // ((P-3)/4).toString(2) would produce bits [223x 1, 0, 222x 1]
  30. function ed448_pow_Pminus3div4(x) {
  31. const P = ed448P;
  32. const b2 = (x * x * x) % P;
  33. const b3 = (b2 * b2 * x) % P;
  34. const b6 = ((0, modular_js_1.pow2)(b3, _3n, P) * b3) % P;
  35. const b9 = ((0, modular_js_1.pow2)(b6, _3n, P) * b3) % P;
  36. const b11 = ((0, modular_js_1.pow2)(b9, _2n, P) * b2) % P;
  37. const b22 = ((0, modular_js_1.pow2)(b11, _11n, P) * b11) % P;
  38. const b44 = ((0, modular_js_1.pow2)(b22, _22n, P) * b22) % P;
  39. const b88 = ((0, modular_js_1.pow2)(b44, _44n, P) * b44) % P;
  40. const b176 = ((0, modular_js_1.pow2)(b88, _88n, P) * b88) % P;
  41. const b220 = ((0, modular_js_1.pow2)(b176, _44n, P) * b44) % P;
  42. const b222 = ((0, modular_js_1.pow2)(b220, _2n, P) * b2) % P;
  43. const b223 = ((0, modular_js_1.pow2)(b222, _1n, P) * x) % P;
  44. return ((0, modular_js_1.pow2)(b223, _223n, P) * b222) % P;
  45. }
  46. function adjustScalarBytes(bytes) {
  47. // Section 5: Likewise, for X448, set the two least significant bits of the first byte to 0, and the most
  48. // significant bit of the last byte to 1.
  49. bytes[0] &= 252; // 0b11111100
  50. // and the most significant bit of the last byte to 1.
  51. bytes[55] |= 128; // 0b10000000
  52. // NOTE: is is NOOP for 56 bytes scalars (X25519/X448)
  53. bytes[56] = 0; // Byte outside of group (456 buts vs 448 bits)
  54. return bytes;
  55. }
  56. // Constant-time ratio of u to v. Allows to combine inversion and square root u/√v.
  57. // Uses algo from RFC8032 5.1.3.
  58. function uvRatio(u, v) {
  59. const P = ed448P;
  60. // https://www.rfc-editor.org/rfc/rfc8032#section-5.2.3
  61. // To compute the square root of (u/v), the first step is to compute the
  62. // candidate root x = (u/v)^((p+1)/4). This can be done using the
  63. // following trick, to use a single modular powering for both the
  64. // inversion of v and the square root:
  65. // x = (u/v)^((p+1)/4) = u³v(u⁵v³)^((p-3)/4) (mod p)
  66. const u2v = (0, modular_js_1.mod)(u * u * v, P); // u²v
  67. const u3v = (0, modular_js_1.mod)(u2v * u, P); // u³v
  68. const u5v3 = (0, modular_js_1.mod)(u3v * u2v * v, P); // u⁵v³
  69. const root = ed448_pow_Pminus3div4(u5v3);
  70. const x = (0, modular_js_1.mod)(u3v * root, P);
  71. // Verify that root is exists
  72. const x2 = (0, modular_js_1.mod)(x * x, P); // x²
  73. // If vx² = u, the recovered x-coordinate is x. Otherwise, no
  74. // square root exists, and the decoding fails.
  75. return { isValid: (0, modular_js_1.mod)(x2 * v, P) === u, value: x };
  76. }
  77. const Fp = (0, modular_js_1.Field)(ed448P, 456, true);
  78. const ED448_DEF = {
  79. // Param: a
  80. a: BigInt(1),
  81. // -39081. Negative number is P - number
  82. d: BigInt('726838724295606890549323807888004534353641360687318060281490199180612328166730772686396383698676545930088884461843637361053498018326358'),
  83. // Finite field 𝔽p over which we'll do calculations; 2n**448n - 2n**224n - 1n
  84. Fp,
  85. // Subgroup order: how many points curve has;
  86. // 2n**446n - 13818066809895115352007386748515426880336692474882178609894547503885n
  87. n: BigInt('181709681073901722637330951972001133588410340171829515070372549795146003961539585716195755291692375963310293709091662304773755859649779'),
  88. // RFC 7748 has 56-byte keys, RFC 8032 has 57-byte keys
  89. nBitLength: 456,
  90. // Cofactor
  91. h: BigInt(4),
  92. // Base point (x, y) aka generator point
  93. Gx: BigInt('224580040295924300187604334099896036246789641632564134246125461686950415467406032909029192869357953282578032075146446173674602635247710'),
  94. Gy: BigInt('298819210078481492676017930443930673437544040154080242095928241372331506189835876003536878655418784733982303233503462500531545062832660'),
  95. // SHAKE256(dom4(phflag,context)||x, 114)
  96. hash: shake256_114,
  97. randomBytes: utils_1.randomBytes,
  98. adjustScalarBytes,
  99. // dom4
  100. domain: (data, ctx, phflag) => {
  101. if (ctx.length > 255)
  102. throw new Error(`Context is too big: ${ctx.length}`);
  103. return (0, utils_1.concatBytes)((0, utils_1.utf8ToBytes)('SigEd448'), new Uint8Array([phflag ? 1 : 0, ctx.length]), ctx, data);
  104. },
  105. uvRatio,
  106. };
  107. exports.ed448 = (0, edwards_js_1.twistedEdwards)(ED448_DEF);
  108. // NOTE: there is no ed448ctx, since ed448 supports ctx by default
  109. exports.ed448ph = (0, edwards_js_1.twistedEdwards)({ ...ED448_DEF, prehash: shake256_64 });
  110. exports.x448 = (() => (0, montgomery_js_1.montgomery)({
  111. a: BigInt(156326),
  112. // RFC 7748 has 56-byte keys, RFC 8032 has 57-byte keys
  113. montgomeryBits: 448,
  114. nByteLength: 56,
  115. P: ed448P,
  116. Gu: BigInt(5),
  117. powPminus2: (x) => {
  118. const P = ed448P;
  119. const Pminus3div4 = ed448_pow_Pminus3div4(x);
  120. const Pminus3 = (0, modular_js_1.pow2)(Pminus3div4, BigInt(2), P);
  121. return (0, modular_js_1.mod)(Pminus3 * x, P); // Pminus3 * x = Pminus2
  122. },
  123. adjustScalarBytes,
  124. randomBytes: utils_1.randomBytes,
  125. }))();
  126. /**
  127. * Converts edwards448 public key to x448 public key. Uses formula:
  128. * * `(u, v) = ((y-1)/(y+1), sqrt(156324)*u/x)`
  129. * * `(x, y) = (sqrt(156324)*u/v, (1+u)/(1-u))`
  130. * @example
  131. * const aPub = ed448.getPublicKey(utils.randomPrivateKey());
  132. * x448.getSharedSecret(edwardsToMontgomery(aPub), edwardsToMontgomery(someonesPub))
  133. */
  134. function edwardsToMontgomeryPub(edwardsPub) {
  135. const { y } = exports.ed448.ExtendedPoint.fromHex(edwardsPub);
  136. const _1n = BigInt(1);
  137. return Fp.toBytes(Fp.create((y - _1n) * Fp.inv(y + _1n)));
  138. }
  139. exports.edwardsToMontgomery = edwardsToMontgomeryPub; // deprecated
  140. // TODO: add edwardsToMontgomeryPriv, similar to ed25519 version
  141. // Hash To Curve Elligator2 Map
  142. const ELL2_C1 = (Fp.ORDER - BigInt(3)) / BigInt(4); // 1. c1 = (q - 3) / 4 # Integer arithmetic
  143. const ELL2_J = BigInt(156326);
  144. function map_to_curve_elligator2_curve448(u) {
  145. let tv1 = Fp.sqr(u); // 1. tv1 = u^2
  146. let e1 = Fp.eql(tv1, Fp.ONE); // 2. e1 = tv1 == 1
  147. tv1 = Fp.cmov(tv1, Fp.ZERO, e1); // 3. tv1 = CMOV(tv1, 0, e1) # If Z * u^2 == -1, set tv1 = 0
  148. let xd = Fp.sub(Fp.ONE, tv1); // 4. xd = 1 - tv1
  149. let x1n = Fp.neg(ELL2_J); // 5. x1n = -J
  150. let tv2 = Fp.sqr(xd); // 6. tv2 = xd^2
  151. let gxd = Fp.mul(tv2, xd); // 7. gxd = tv2 * xd # gxd = xd^3
  152. let gx1 = Fp.mul(tv1, Fp.neg(ELL2_J)); // 8. gx1 = -J * tv1 # x1n + J * xd
  153. gx1 = Fp.mul(gx1, x1n); // 9. gx1 = gx1 * x1n # x1n^2 + J * x1n * xd
  154. gx1 = Fp.add(gx1, tv2); // 10. gx1 = gx1 + tv2 # x1n^2 + J * x1n * xd + xd^2
  155. gx1 = Fp.mul(gx1, x1n); // 11. gx1 = gx1 * x1n # x1n^3 + J * x1n^2 * xd + x1n * xd^2
  156. let tv3 = Fp.sqr(gxd); // 12. tv3 = gxd^2
  157. tv2 = Fp.mul(gx1, gxd); // 13. tv2 = gx1 * gxd # gx1 * gxd
  158. tv3 = Fp.mul(tv3, tv2); // 14. tv3 = tv3 * tv2 # gx1 * gxd^3
  159. let y1 = Fp.pow(tv3, ELL2_C1); // 15. y1 = tv3^c1 # (gx1 * gxd^3)^((p - 3) / 4)
  160. y1 = Fp.mul(y1, tv2); // 16. y1 = y1 * tv2 # gx1 * gxd * (gx1 * gxd^3)^((p - 3) / 4)
  161. let x2n = Fp.mul(x1n, Fp.neg(tv1)); // 17. x2n = -tv1 * x1n # x2 = x2n / xd = -1 * u^2 * x1n / xd
  162. let y2 = Fp.mul(y1, u); // 18. y2 = y1 * u
  163. y2 = Fp.cmov(y2, Fp.ZERO, e1); // 19. y2 = CMOV(y2, 0, e1)
  164. tv2 = Fp.sqr(y1); // 20. tv2 = y1^2
  165. tv2 = Fp.mul(tv2, gxd); // 21. tv2 = tv2 * gxd
  166. let e2 = Fp.eql(tv2, gx1); // 22. e2 = tv2 == gx1
  167. let xn = Fp.cmov(x2n, x1n, e2); // 23. xn = CMOV(x2n, x1n, e2) # If e2, x = x1, else x = x2
  168. let y = Fp.cmov(y2, y1, e2); // 24. y = CMOV(y2, y1, e2) # If e2, y = y1, else y = y2
  169. let e3 = Fp.isOdd(y); // 25. e3 = sgn0(y) == 1 # Fix sign of y
  170. y = Fp.cmov(y, Fp.neg(y), e2 !== e3); // 26. y = CMOV(y, -y, e2 XOR e3)
  171. return { xn, xd, yn: y, yd: Fp.ONE }; // 27. return (xn, xd, y, 1)
  172. }
  173. function map_to_curve_elligator2_edwards448(u) {
  174. let { xn, xd, yn, yd } = map_to_curve_elligator2_curve448(u); // 1. (xn, xd, yn, yd) = map_to_curve_elligator2_curve448(u)
  175. let xn2 = Fp.sqr(xn); // 2. xn2 = xn^2
  176. let xd2 = Fp.sqr(xd); // 3. xd2 = xd^2
  177. let xd4 = Fp.sqr(xd2); // 4. xd4 = xd2^2
  178. let yn2 = Fp.sqr(yn); // 5. yn2 = yn^2
  179. let yd2 = Fp.sqr(yd); // 6. yd2 = yd^2
  180. let xEn = Fp.sub(xn2, xd2); // 7. xEn = xn2 - xd2
  181. let tv2 = Fp.sub(xEn, xd2); // 8. tv2 = xEn - xd2
  182. xEn = Fp.mul(xEn, xd2); // 9. xEn = xEn * xd2
  183. xEn = Fp.mul(xEn, yd); // 10. xEn = xEn * yd
  184. xEn = Fp.mul(xEn, yn); // 11. xEn = xEn * yn
  185. xEn = Fp.mul(xEn, _4n); // 12. xEn = xEn * 4
  186. tv2 = Fp.mul(tv2, xn2); // 13. tv2 = tv2 * xn2
  187. tv2 = Fp.mul(tv2, yd2); // 14. tv2 = tv2 * yd2
  188. let tv3 = Fp.mul(yn2, _4n); // 15. tv3 = 4 * yn2
  189. let tv1 = Fp.add(tv3, yd2); // 16. tv1 = tv3 + yd2
  190. tv1 = Fp.mul(tv1, xd4); // 17. tv1 = tv1 * xd4
  191. let xEd = Fp.add(tv1, tv2); // 18. xEd = tv1 + tv2
  192. tv2 = Fp.mul(tv2, xn); // 19. tv2 = tv2 * xn
  193. let tv4 = Fp.mul(xn, xd4); // 20. tv4 = xn * xd4
  194. let yEn = Fp.sub(tv3, yd2); // 21. yEn = tv3 - yd2
  195. yEn = Fp.mul(yEn, tv4); // 22. yEn = yEn * tv4
  196. yEn = Fp.sub(yEn, tv2); // 23. yEn = yEn - tv2
  197. tv1 = Fp.add(xn2, xd2); // 24. tv1 = xn2 + xd2
  198. tv1 = Fp.mul(tv1, xd2); // 25. tv1 = tv1 * xd2
  199. tv1 = Fp.mul(tv1, xd); // 26. tv1 = tv1 * xd
  200. tv1 = Fp.mul(tv1, yn2); // 27. tv1 = tv1 * yn2
  201. tv1 = Fp.mul(tv1, BigInt(-2)); // 28. tv1 = -2 * tv1
  202. let yEd = Fp.add(tv2, tv1); // 29. yEd = tv2 + tv1
  203. tv4 = Fp.mul(tv4, yd2); // 30. tv4 = tv4 * yd2
  204. yEd = Fp.add(yEd, tv4); // 31. yEd = yEd + tv4
  205. tv1 = Fp.mul(xEd, yEd); // 32. tv1 = xEd * yEd
  206. let e = Fp.eql(tv1, Fp.ZERO); // 33. e = tv1 == 0
  207. xEn = Fp.cmov(xEn, Fp.ZERO, e); // 34. xEn = CMOV(xEn, 0, e)
  208. xEd = Fp.cmov(xEd, Fp.ONE, e); // 35. xEd = CMOV(xEd, 1, e)
  209. yEn = Fp.cmov(yEn, Fp.ONE, e); // 36. yEn = CMOV(yEn, 1, e)
  210. yEd = Fp.cmov(yEd, Fp.ONE, e); // 37. yEd = CMOV(yEd, 1, e)
  211. const inv = Fp.invertBatch([xEd, yEd]); // batch division
  212. return { x: Fp.mul(xEn, inv[0]), y: Fp.mul(yEn, inv[1]) }; // 38. return (xEn, xEd, yEn, yEd)
  213. }
  214. const htf = /* @__PURE__ */ (() => (0, hash_to_curve_js_1.createHasher)(exports.ed448.ExtendedPoint, (scalars) => map_to_curve_elligator2_edwards448(scalars[0]), {
  215. DST: 'edwards448_XOF:SHAKE256_ELL2_RO_',
  216. encodeDST: 'edwards448_XOF:SHAKE256_ELL2_NU_',
  217. p: Fp.ORDER,
  218. m: 1,
  219. k: 224,
  220. expand: 'xof',
  221. hash: sha3_1.shake256,
  222. }))();
  223. exports.hashToCurve = (() => htf.hashToCurve)();
  224. exports.encodeToCurve = (() => htf.encodeToCurve)();
  225. function assertDcfPoint(other) {
  226. if (!(other instanceof DcfPoint))
  227. throw new Error('DecafPoint expected');
  228. }
  229. // 1-d
  230. const ONE_MINUS_D = BigInt('39082');
  231. // 1-2d
  232. const ONE_MINUS_TWO_D = BigInt('78163');
  233. // √(-d)
  234. const SQRT_MINUS_D = BigInt('98944233647732219769177004876929019128417576295529901074099889598043702116001257856802131563896515373927712232092845883226922417596214');
  235. // 1 / √(-d)
  236. const INVSQRT_MINUS_D = BigInt('315019913931389607337177038330951043522456072897266928557328499619017160722351061360252776265186336876723201881398623946864393857820716');
  237. // Calculates 1/√(number)
  238. const invertSqrt = (number) => uvRatio(_1n, number);
  239. const MAX_448B = BigInt('0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff');
  240. const bytes448ToNumberLE = (bytes) => exports.ed448.CURVE.Fp.create((0, utils_js_1.bytesToNumberLE)(bytes) & MAX_448B);
  241. // Computes Elligator map for Decaf
  242. // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-element-derivation-2
  243. function calcElligatorDecafMap(r0) {
  244. const { d } = exports.ed448.CURVE;
  245. const P = exports.ed448.CURVE.Fp.ORDER;
  246. const mod = exports.ed448.CURVE.Fp.create;
  247. const r = mod(-(r0 * r0)); // 1
  248. const u0 = mod(d * (r - _1n)); // 2
  249. const u1 = mod((u0 + _1n) * (u0 - r)); // 3
  250. const { isValid: was_square, value: v } = uvRatio(ONE_MINUS_TWO_D, mod((r + _1n) * u1)); // 4
  251. let v_prime = v; // 5
  252. if (!was_square)
  253. v_prime = mod(r0 * v);
  254. let sgn = _1n; // 6
  255. if (!was_square)
  256. sgn = mod(-_1n);
  257. const s = mod(v_prime * (r + _1n)); // 7
  258. let s_abs = s;
  259. if ((0, modular_js_1.isNegativeLE)(s, P))
  260. s_abs = mod(-s);
  261. const s2 = s * s;
  262. const W0 = mod(s_abs * _2n); // 8
  263. const W1 = mod(s2 + _1n); // 9
  264. const W2 = mod(s2 - _1n); // 10
  265. const W3 = mod(v_prime * s * (r - _1n) * ONE_MINUS_TWO_D + sgn); // 11
  266. return new exports.ed448.ExtendedPoint(mod(W0 * W3), mod(W2 * W1), mod(W1 * W3), mod(W0 * W2));
  267. }
  268. /**
  269. * Each ed448/ExtendedPoint has 4 different equivalent points. This can be
  270. * a source of bugs for protocols like ring signatures. Decaf was created to solve this.
  271. * Decaf point operates in X:Y:Z:T extended coordinates like ExtendedPoint,
  272. * but it should work in its own namespace: do not combine those two.
  273. * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448
  274. */
  275. class DcfPoint {
  276. // Private property to discourage combining ExtendedPoint + DecafPoint
  277. // Always use Decaf encoding/decoding instead.
  278. constructor(ep) {
  279. this.ep = ep;
  280. }
  281. static fromAffine(ap) {
  282. return new DcfPoint(exports.ed448.ExtendedPoint.fromAffine(ap));
  283. }
  284. /**
  285. * Takes uniform output of 112-byte hash function like shake256 and converts it to `DecafPoint`.
  286. * The hash-to-group operation applies Elligator twice and adds the results.
  287. * **Note:** this is one-way map, there is no conversion from point to hash.
  288. * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-element-derivation-2
  289. * @param hex 112-byte output of a hash function
  290. */
  291. static hashToCurve(hex) {
  292. hex = (0, utils_js_1.ensureBytes)('decafHash', hex, 112);
  293. const r1 = bytes448ToNumberLE(hex.slice(0, 56));
  294. const R1 = calcElligatorDecafMap(r1);
  295. const r2 = bytes448ToNumberLE(hex.slice(56, 112));
  296. const R2 = calcElligatorDecafMap(r2);
  297. return new DcfPoint(R1.add(R2));
  298. }
  299. /**
  300. * Converts decaf-encoded string to decaf point.
  301. * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-decode-2
  302. * @param hex Decaf-encoded 56 bytes. Not every 56-byte string is valid decaf encoding
  303. */
  304. static fromHex(hex) {
  305. hex = (0, utils_js_1.ensureBytes)('decafHex', hex, 56);
  306. const { d } = exports.ed448.CURVE;
  307. const P = exports.ed448.CURVE.Fp.ORDER;
  308. const mod = exports.ed448.CURVE.Fp.create;
  309. const emsg = 'DecafPoint.fromHex: the hex is not valid encoding of DecafPoint';
  310. const s = bytes448ToNumberLE(hex);
  311. // 1. Check that s_bytes is the canonical encoding of a field element, or else abort.
  312. // 2. Check that s is non-negative, or else abort
  313. if (!(0, utils_js_1.equalBytes)((0, utils_js_1.numberToBytesLE)(s, 56), hex) || (0, modular_js_1.isNegativeLE)(s, P))
  314. throw new Error(emsg);
  315. const s2 = mod(s * s); // 1
  316. const u1 = mod(_1n + s2); // 2
  317. const u1sq = mod(u1 * u1);
  318. const u2 = mod(u1sq - _4n * d * s2); // 3
  319. const { isValid, value: invsqrt } = invertSqrt(mod(u2 * u1sq)); // 4
  320. let u3 = mod((s + s) * invsqrt * u1 * SQRT_MINUS_D); // 5
  321. if ((0, modular_js_1.isNegativeLE)(u3, P))
  322. u3 = mod(-u3);
  323. const x = mod(u3 * invsqrt * u2 * INVSQRT_MINUS_D); // 6
  324. const y = mod((_1n - s2) * invsqrt * u1); // 7
  325. const t = mod(x * y); // 8
  326. if (!isValid)
  327. throw new Error(emsg);
  328. return new DcfPoint(new exports.ed448.ExtendedPoint(x, y, _1n, t));
  329. }
  330. /**
  331. * Encodes decaf point to Uint8Array.
  332. * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-encode-2
  333. */
  334. toRawBytes() {
  335. let { ex: x, ey: _y, ez: z, et: t } = this.ep;
  336. const P = exports.ed448.CURVE.Fp.ORDER;
  337. const mod = exports.ed448.CURVE.Fp.create;
  338. const u1 = mod(mod(x + t) * mod(x - t)); // 1
  339. const x2 = mod(x * x);
  340. const { value: invsqrt } = invertSqrt(mod(u1 * ONE_MINUS_D * x2)); // 2
  341. let ratio = mod(invsqrt * u1 * SQRT_MINUS_D); // 3
  342. if ((0, modular_js_1.isNegativeLE)(ratio, P))
  343. ratio = mod(-ratio);
  344. const u2 = mod(INVSQRT_MINUS_D * ratio * z - t); // 4
  345. let s = mod(ONE_MINUS_D * invsqrt * x * u2); // 5
  346. if ((0, modular_js_1.isNegativeLE)(s, P))
  347. s = mod(-s);
  348. return (0, utils_js_1.numberToBytesLE)(s, 56);
  349. }
  350. toHex() {
  351. return (0, utils_js_1.bytesToHex)(this.toRawBytes());
  352. }
  353. toString() {
  354. return this.toHex();
  355. }
  356. // Compare one point to another.
  357. // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-equals-2
  358. equals(other) {
  359. assertDcfPoint(other);
  360. const { ex: X1, ey: Y1 } = this.ep;
  361. const { ex: X2, ey: Y2 } = other.ep;
  362. const mod = exports.ed448.CURVE.Fp.create;
  363. // (x1 * y2 == y1 * x2)
  364. return mod(X1 * Y2) === mod(Y1 * X2);
  365. }
  366. add(other) {
  367. assertDcfPoint(other);
  368. return new DcfPoint(this.ep.add(other.ep));
  369. }
  370. subtract(other) {
  371. assertDcfPoint(other);
  372. return new DcfPoint(this.ep.subtract(other.ep));
  373. }
  374. multiply(scalar) {
  375. return new DcfPoint(this.ep.multiply(scalar));
  376. }
  377. multiplyUnsafe(scalar) {
  378. return new DcfPoint(this.ep.multiplyUnsafe(scalar));
  379. }
  380. double() {
  381. return new DcfPoint(this.ep.double());
  382. }
  383. negate() {
  384. return new DcfPoint(this.ep.negate());
  385. }
  386. }
  387. exports.DecafPoint = (() => {
  388. // decaf448 base point is ed448 base x 2
  389. // https://github.com/dalek-cryptography/curve25519-dalek/blob/59837c6ecff02b77b9d5ff84dbc239d0cf33ef90/vendor/ristretto.sage#L699
  390. if (!DcfPoint.BASE)
  391. DcfPoint.BASE = new DcfPoint(exports.ed448.ExtendedPoint.BASE).multiply(_2n);
  392. if (!DcfPoint.ZERO)
  393. DcfPoint.ZERO = new DcfPoint(exports.ed448.ExtendedPoint.ZERO);
  394. return DcfPoint;
  395. })();
  396. // Hashing to decaf448. https://www.rfc-editor.org/rfc/rfc9380#appendix-C
  397. const hashToDecaf448 = (msg, options) => {
  398. const d = options.DST;
  399. const DST = typeof d === 'string' ? (0, utils_1.utf8ToBytes)(d) : d;
  400. const uniform_bytes = (0, hash_to_curve_js_1.expand_message_xof)(msg, DST, 112, 224, sha3_1.shake256);
  401. const P = DcfPoint.hashToCurve(uniform_bytes);
  402. return P;
  403. };
  404. exports.hashToDecaf448 = hashToDecaf448;
  405. exports.hash_to_decaf448 = exports.hashToDecaf448; // legacy
  406. //# sourceMappingURL=ed448.js.map