From 618508d32c01166bf2fb29c470bef6761e6f3227 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Tue, 28 Mar 2023 17:01:00 +0000 Subject: [PATCH] weierstrass, edwards: get rid of bigint literals. Closes gh-22 --- src/abstract/edwards.ts | 10 ++++------ src/abstract/modular.ts | 2 +- src/abstract/weierstrass.ts | 32 ++++++++++++++++---------------- src/ed25519.ts | 2 +- src/ed448.ts | 5 +++-- src/secp256k1.ts | 2 +- 6 files changed, 26 insertions(+), 27 deletions(-) diff --git a/src/abstract/edwards.ts b/src/abstract/edwards.ts index d290dab..2f374c7 100644 --- a/src/abstract/edwards.ts +++ b/src/abstract/edwards.ts @@ -5,11 +5,9 @@ import * as ut from './utils.js'; import { ensureBytes, FHash, Hex } from './utils.js'; import { Group, GroupConstructor, wNAF, BasicCurve, validateBasic, AffinePoint } from './curve.js'; -// Be friendly to bad ECMAScript parsers by not using bigint literals like 123n -const _0n = BigInt(0); -const _1n = BigInt(1); -const _2n = BigInt(2); -const _8n = BigInt(8); +// Be friendly to bad ECMAScript parsers by not using bigint literals +// prettier-ignore +const _0n = BigInt(0), _1n = BigInt(1), _2n = BigInt(2), _8n = BigInt(8); // Edwards curves must declare params a & d. export type CurveType = BasicCurve & { @@ -111,7 +109,7 @@ export function twistedEdwards(curveDef: CurveType): CurveFn { if (ctx.length || phflag) throw new Error('Contexts/pre-hash are not supported'); return data; }); // NOOP - const inBig = (n: bigint) => typeof n === 'bigint' && 0n < n; // n in [1..] + const inBig = (n: bigint) => typeof n === 'bigint' && _0n < n; // n in [1..] const inRange = (n: bigint, max: bigint) => inBig(n) && inBig(max) && n < max; // n in [1..max-1] const in0MaskRange = (n: bigint) => n === _0n || inRange(n, MASK); // n in [0..MASK-1] function assertInRange(n: bigint, max: bigint) { diff --git a/src/abstract/modular.ts b/src/abstract/modular.ts index 58825e8..db2e9cb 100644 --- a/src/abstract/modular.ts +++ b/src/abstract/modular.ts @@ -275,7 +275,7 @@ export function FpPow(f: IField, num: T, power: bigint): T { while (power > _0n) { if (power & _1n) p = f.mul(p, d); d = f.sqr(d); - power >>= 1n; + power >>= _1n; } return p; } diff --git a/src/abstract/weierstrass.ts b/src/abstract/weierstrass.ts index f3d48a4..c83b048 100644 --- a/src/abstract/weierstrass.ts +++ b/src/abstract/weierstrass.ts @@ -176,9 +176,9 @@ const DER = { }, }; -// Be friendly to bad ECMAScript parsers by not using bigint literals like 123n -const _0n = BigInt(0); -const _1n = BigInt(1); +// Be friendly to bad ECMAScript parsers by not using bigint literals +// prettier-ignore +const _0n = BigInt(0), _1n = BigInt(1), _2n = BigInt(2), _3n = BigInt(3), _4n = BigInt(4); export function weierstrassPoints(opts: CurvePointsType) { const CURVE = validatePointOpts(opts); @@ -365,7 +365,7 @@ export function weierstrassPoints(opts: CurvePointsType) { // Cost: 8M + 3S + 3*a + 2*b3 + 15add. double() { const { a, b } = CURVE; - const b3 = Fp.mul(b, 3n); + const b3 = Fp.mul(b, _3n); const { px: X1, py: Y1, pz: Z1 } = this; let X3 = Fp.ZERO, Y3 = Fp.ZERO, Z3 = Fp.ZERO; // prettier-ignore let t0 = Fp.mul(X1, X1); // step 1 @@ -412,7 +412,7 @@ export function weierstrassPoints(opts: CurvePointsType) { const { px: X2, py: Y2, pz: Z2 } = other; let X3 = Fp.ZERO, Y3 = Fp.ZERO, Z3 = Fp.ZERO; // prettier-ignore const a = CURVE.a; - const b3 = Fp.mul(CURVE.b, 3n); + const b3 = Fp.mul(CURVE.b, _3n); let t0 = Fp.mul(X1, X2); // step 1 let t1 = Fp.mul(Y1, Y2); let t2 = Fp.mul(Z1, Z2); @@ -1078,15 +1078,15 @@ export function weierstrass(curveDef: CurveType): CurveFn { export function SWUFpSqrtRatio(Fp: mod.IField, Z: T) { // Generic implementation const q = Fp.ORDER; - let l = 0n; - for (let o = q - 1n; o % 2n === 0n; o /= 2n) l += 1n; + let l = _0n; + for (let o = q - _1n; o % _2n === _0n; o /= _2n) l += _1n; const c1 = l; // 1. c1, the largest integer such that 2^c1 divides q - 1. - const c2 = (q - 1n) / 2n ** c1; // 2. c2 = (q - 1) / (2^c1) # Integer arithmetic - const c3 = (c2 - 1n) / 2n; // 3. c3 = (c2 - 1) / 2 # Integer arithmetic - const c4 = 2n ** c1 - 1n; // 4. c4 = 2^c1 - 1 # Integer arithmetic - const c5 = 2n ** (c1 - 1n); // 5. c5 = 2^(c1 - 1) # Integer arithmetic + const c2 = (q - _1n) / _2n ** c1; // 2. c2 = (q - 1) / (2^c1) # Integer arithmetic + const c3 = (c2 - _1n) / _2n; // 3. c3 = (c2 - 1) / 2 # Integer arithmetic + const c4 = _2n ** c1 - _1n; // 4. c4 = 2^c1 - 1 # Integer arithmetic + const c5 = _2n ** (c1 - _1n); // 5. c5 = 2^(c1 - 1) # Integer arithmetic const c6 = Fp.pow(Z, c2); // 6. c6 = Z^c2 - const c7 = Fp.pow(Z, (c2 + 1n) / 2n); // 7. c7 = Z^((c2 + 1) / 2) + const c7 = Fp.pow(Z, (c2 + _1n) / _2n); // 7. c7 = Z^((c2 + 1) / 2) let sqrtRatio = (u: T, v: T): { isValid: boolean; value: T } => { let tv1 = c6; // 1. tv1 = c6 let tv2 = Fp.pow(v, c4); // 2. tv2 = v^c4 @@ -1106,7 +1106,7 @@ export function SWUFpSqrtRatio(Fp: mod.IField, Z: T) { tv4 = Fp.cmov(tv5, tv4, isQR); // 16. tv4 = CMOV(tv5, tv4, isQR) // 17. for i in (c1, c1 - 1, ..., 2): for (let i = c1; i > 1; i--) { - let tv5 = 2n ** (i - 2n); // 18. tv5 = i - 2; 19. tv5 = 2^tv5 + let tv5 = _2n ** (i - _2n); // 18. tv5 = i - 2; 19. tv5 = 2^tv5 let tvv5 = Fp.pow(tv4, tv5); // 20. tv5 = tv4^tv5 const e1 = Fp.eql(tvv5, Fp.ONE); // 21. e1 = tv5 == 1 tv2 = Fp.mul(tv3, tv1); // 22. tv2 = tv3 * tv1 @@ -1117,9 +1117,9 @@ export function SWUFpSqrtRatio(Fp: mod.IField, Z: T) { } return { isValid: isQR, value: tv3 }; }; - if (Fp.ORDER % 4n === 3n) { + if (Fp.ORDER % _4n === _3n) { // sqrt_ratio_3mod4(u, v) - const c1 = (Fp.ORDER - 3n) / 4n; // 1. c1 = (q - 3) / 4 # Integer arithmetic + const c1 = (Fp.ORDER - _3n) / _4n; // 1. c1 = (q - 3) / 4 # Integer arithmetic const c2 = Fp.sqrt(Fp.neg(Z)); // 2. c2 = sqrt(-Z) sqrtRatio = (u: T, v: T) => { let tv1 = Fp.sqr(v); // 1. tv1 = v^2 @@ -1135,7 +1135,7 @@ export function SWUFpSqrtRatio(Fp: mod.IField, Z: T) { }; } // No curves uses that - // if (Fp.ORDER % 8n === 5n) // sqrt_ratio_5mod8 + // if (Fp.ORDER % _8n === _5n) // sqrt_ratio_5mod8 return sqrtRatio; } // From draft-irtf-cfrg-hash-to-curve-16 diff --git a/src/ed25519.ts b/src/ed25519.ts index 9aaef0b..599dc6c 100644 --- a/src/ed25519.ts +++ b/src/ed25519.ts @@ -204,7 +204,7 @@ function map_to_curve_elligator2_curve25519(u: bigint) { let y = Fp.cmov(y2, y1, e3); // 36. y = CMOV(y2, y1, e3) # If e3, y = y1, else y = y2 let e4 = Fp.isOdd(y); // 37. e4 = sgn0(y) == 1 # Fix sign of y y = Fp.cmov(y, Fp.neg(y), e3 !== e4); // 38. y = CMOV(y, -y, e3 XOR e4) - return { xMn: xn, xMd: xd, yMn: y, yMd: 1n }; // 39. return (xn, xd, y, 1) + return { xMn: xn, xMd: xd, yMn: y, yMd: _1n }; // 39. return (xn, xd, y, 1) } const ELL2_C1_EDWARDS = FpSqrtEven(Fp, Fp.neg(BigInt(486664))); // sgn0(c1) MUST equal 0 diff --git a/src/ed448.ts b/src/ed448.ts index a842ae3..96aeeaa 100644 --- a/src/ed448.ts +++ b/src/ed448.ts @@ -54,6 +54,7 @@ function adjustScalarBytes(bytes: Uint8Array): Uint8Array { } const Fp = Field(ed448P, 456, true); +const _4n = BigInt(4); const ED448_DEF = { // Param: a @@ -195,10 +196,10 @@ function map_to_curve_elligator2_edwards448(u: bigint) { xEn = Fp.mul(xEn, xd2); // 9. xEn = xEn * xd2 xEn = Fp.mul(xEn, yd); // 10. xEn = xEn * yd xEn = Fp.mul(xEn, yn); // 11. xEn = xEn * yn - xEn = Fp.mul(xEn, 4n); // 12. xEn = xEn * 4 + xEn = Fp.mul(xEn, _4n); // 12. xEn = xEn * 4 tv2 = Fp.mul(tv2, xn2); // 13. tv2 = tv2 * xn2 tv2 = Fp.mul(tv2, yd2); // 14. tv2 = tv2 * yd2 - let tv3 = Fp.mul(yn2, 4n); // 15. tv3 = 4 * yn2 + let tv3 = Fp.mul(yn2, _4n); // 15. tv3 = 4 * yn2 let tv1 = Fp.add(tv3, yd2); // 16. tv1 = tv3 + yd2 tv1 = Fp.mul(tv1, xd4); // 17. tv1 = tv1 * xd4 let xEd = Fp.add(tv1, tv2); // 18. xEd = tv1 + tv2 diff --git a/src/secp256k1.ts b/src/secp256k1.ts index 545ce89..c2256b5 100644 --- a/src/secp256k1.ts +++ b/src/secp256k1.ts @@ -131,7 +131,7 @@ function lift_x(x: bigint): PointType { const xx = modP(x * x); const c = modP(xx * x + BigInt(7)); // Let c = x³ + 7 mod p. let y = sqrtMod(c); // Let y = c^(p+1)/4 mod p. - if (y % 2n !== 0n) y = modP(-y); // Return the unique point P such that x(P) = x and + if (y % _2n !== _0n) y = modP(-y); // Return the unique point P such that x(P) = x and const p = new Point(x, y, _1n); // y(P) = y if y mod 2 = 0 or y(P) = p-y otherwise. p.assertValidity(); return p;