forked from tornado-packages/noble-curves
weierstrass, edwards: get rid of bigint literals. Closes gh-22
This commit is contained in:
parent
3936449e7b
commit
618508d32c
@ -5,11 +5,9 @@ import * as ut from './utils.js';
|
|||||||
import { ensureBytes, FHash, Hex } from './utils.js';
|
import { ensureBytes, FHash, Hex } from './utils.js';
|
||||||
import { Group, GroupConstructor, wNAF, BasicCurve, validateBasic, AffinePoint } from './curve.js';
|
import { Group, GroupConstructor, wNAF, BasicCurve, validateBasic, AffinePoint } from './curve.js';
|
||||||
|
|
||||||
// Be friendly to bad ECMAScript parsers by not using bigint literals like 123n
|
// Be friendly to bad ECMAScript parsers by not using bigint literals
|
||||||
const _0n = BigInt(0);
|
// prettier-ignore
|
||||||
const _1n = BigInt(1);
|
const _0n = BigInt(0), _1n = BigInt(1), _2n = BigInt(2), _8n = BigInt(8);
|
||||||
const _2n = BigInt(2);
|
|
||||||
const _8n = BigInt(8);
|
|
||||||
|
|
||||||
// Edwards curves must declare params a & d.
|
// Edwards curves must declare params a & d.
|
||||||
export type CurveType = BasicCurve<bigint> & {
|
export type CurveType = BasicCurve<bigint> & {
|
||||||
@ -111,7 +109,7 @@ export function twistedEdwards(curveDef: CurveType): CurveFn {
|
|||||||
if (ctx.length || phflag) throw new Error('Contexts/pre-hash are not supported');
|
if (ctx.length || phflag) throw new Error('Contexts/pre-hash are not supported');
|
||||||
return data;
|
return data;
|
||||||
}); // NOOP
|
}); // 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 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]
|
const in0MaskRange = (n: bigint) => n === _0n || inRange(n, MASK); // n in [0..MASK-1]
|
||||||
function assertInRange(n: bigint, max: bigint) {
|
function assertInRange(n: bigint, max: bigint) {
|
||||||
|
@ -275,7 +275,7 @@ export function FpPow<T>(f: IField<T>, num: T, power: bigint): T {
|
|||||||
while (power > _0n) {
|
while (power > _0n) {
|
||||||
if (power & _1n) p = f.mul(p, d);
|
if (power & _1n) p = f.mul(p, d);
|
||||||
d = f.sqr(d);
|
d = f.sqr(d);
|
||||||
power >>= 1n;
|
power >>= _1n;
|
||||||
}
|
}
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
@ -176,9 +176,9 @@ const DER = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// Be friendly to bad ECMAScript parsers by not using bigint literals like 123n
|
// Be friendly to bad ECMAScript parsers by not using bigint literals
|
||||||
const _0n = BigInt(0);
|
// prettier-ignore
|
||||||
const _1n = BigInt(1);
|
const _0n = BigInt(0), _1n = BigInt(1), _2n = BigInt(2), _3n = BigInt(3), _4n = BigInt(4);
|
||||||
|
|
||||||
export function weierstrassPoints<T>(opts: CurvePointsType<T>) {
|
export function weierstrassPoints<T>(opts: CurvePointsType<T>) {
|
||||||
const CURVE = validatePointOpts(opts);
|
const CURVE = validatePointOpts(opts);
|
||||||
@ -365,7 +365,7 @@ export function weierstrassPoints<T>(opts: CurvePointsType<T>) {
|
|||||||
// Cost: 8M + 3S + 3*a + 2*b3 + 15add.
|
// Cost: 8M + 3S + 3*a + 2*b3 + 15add.
|
||||||
double() {
|
double() {
|
||||||
const { a, b } = CURVE;
|
const { a, b } = CURVE;
|
||||||
const b3 = Fp.mul(b, 3n);
|
const b3 = Fp.mul(b, _3n);
|
||||||
const { px: X1, py: Y1, pz: Z1 } = this;
|
const { px: X1, py: Y1, pz: Z1 } = this;
|
||||||
let X3 = Fp.ZERO, Y3 = Fp.ZERO, Z3 = Fp.ZERO; // prettier-ignore
|
let X3 = Fp.ZERO, Y3 = Fp.ZERO, Z3 = Fp.ZERO; // prettier-ignore
|
||||||
let t0 = Fp.mul(X1, X1); // step 1
|
let t0 = Fp.mul(X1, X1); // step 1
|
||||||
@ -412,7 +412,7 @@ export function weierstrassPoints<T>(opts: CurvePointsType<T>) {
|
|||||||
const { px: X2, py: Y2, pz: Z2 } = other;
|
const { px: X2, py: Y2, pz: Z2 } = other;
|
||||||
let X3 = Fp.ZERO, Y3 = Fp.ZERO, Z3 = Fp.ZERO; // prettier-ignore
|
let X3 = Fp.ZERO, Y3 = Fp.ZERO, Z3 = Fp.ZERO; // prettier-ignore
|
||||||
const a = CURVE.a;
|
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 t0 = Fp.mul(X1, X2); // step 1
|
||||||
let t1 = Fp.mul(Y1, Y2);
|
let t1 = Fp.mul(Y1, Y2);
|
||||||
let t2 = Fp.mul(Z1, Z2);
|
let t2 = Fp.mul(Z1, Z2);
|
||||||
@ -1078,15 +1078,15 @@ export function weierstrass(curveDef: CurveType): CurveFn {
|
|||||||
export function SWUFpSqrtRatio<T>(Fp: mod.IField<T>, Z: T) {
|
export function SWUFpSqrtRatio<T>(Fp: mod.IField<T>, Z: T) {
|
||||||
// Generic implementation
|
// Generic implementation
|
||||||
const q = Fp.ORDER;
|
const q = Fp.ORDER;
|
||||||
let l = 0n;
|
let l = _0n;
|
||||||
for (let o = q - 1n; o % 2n === 0n; o /= 2n) l += 1n;
|
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 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 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 c3 = (c2 - _1n) / _2n; // 3. c3 = (c2 - 1) / 2 # Integer arithmetic
|
||||||
const c4 = 2n ** c1 - 1n; // 4. c4 = 2^c1 - 1 # 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 c5 = _2n ** (c1 - _1n); // 5. c5 = 2^(c1 - 1) # Integer arithmetic
|
||||||
const c6 = Fp.pow(Z, c2); // 6. c6 = Z^c2
|
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 sqrtRatio = (u: T, v: T): { isValid: boolean; value: T } => {
|
||||||
let tv1 = c6; // 1. tv1 = c6
|
let tv1 = c6; // 1. tv1 = c6
|
||||||
let tv2 = Fp.pow(v, c4); // 2. tv2 = v^c4
|
let tv2 = Fp.pow(v, c4); // 2. tv2 = v^c4
|
||||||
@ -1106,7 +1106,7 @@ export function SWUFpSqrtRatio<T>(Fp: mod.IField<T>, Z: T) {
|
|||||||
tv4 = Fp.cmov(tv5, tv4, isQR); // 16. tv4 = CMOV(tv5, tv4, isQR)
|
tv4 = Fp.cmov(tv5, tv4, isQR); // 16. tv4 = CMOV(tv5, tv4, isQR)
|
||||||
// 17. for i in (c1, c1 - 1, ..., 2):
|
// 17. for i in (c1, c1 - 1, ..., 2):
|
||||||
for (let i = c1; i > 1; i--) {
|
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
|
let tvv5 = Fp.pow(tv4, tv5); // 20. tv5 = tv4^tv5
|
||||||
const e1 = Fp.eql(tvv5, Fp.ONE); // 21. e1 = tv5 == 1
|
const e1 = Fp.eql(tvv5, Fp.ONE); // 21. e1 = tv5 == 1
|
||||||
tv2 = Fp.mul(tv3, tv1); // 22. tv2 = tv3 * tv1
|
tv2 = Fp.mul(tv3, tv1); // 22. tv2 = tv3 * tv1
|
||||||
@ -1117,9 +1117,9 @@ export function SWUFpSqrtRatio<T>(Fp: mod.IField<T>, Z: T) {
|
|||||||
}
|
}
|
||||||
return { isValid: isQR, value: tv3 };
|
return { isValid: isQR, value: tv3 };
|
||||||
};
|
};
|
||||||
if (Fp.ORDER % 4n === 3n) {
|
if (Fp.ORDER % _4n === _3n) {
|
||||||
// sqrt_ratio_3mod4(u, v)
|
// 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)
|
const c2 = Fp.sqrt(Fp.neg(Z)); // 2. c2 = sqrt(-Z)
|
||||||
sqrtRatio = (u: T, v: T) => {
|
sqrtRatio = (u: T, v: T) => {
|
||||||
let tv1 = Fp.sqr(v); // 1. tv1 = v^2
|
let tv1 = Fp.sqr(v); // 1. tv1 = v^2
|
||||||
@ -1135,7 +1135,7 @@ export function SWUFpSqrtRatio<T>(Fp: mod.IField<T>, Z: T) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
// No curves uses that
|
// No curves uses that
|
||||||
// if (Fp.ORDER % 8n === 5n) // sqrt_ratio_5mod8
|
// if (Fp.ORDER % _8n === _5n) // sqrt_ratio_5mod8
|
||||||
return sqrtRatio;
|
return sqrtRatio;
|
||||||
}
|
}
|
||||||
// From draft-irtf-cfrg-hash-to-curve-16
|
// From draft-irtf-cfrg-hash-to-curve-16
|
||||||
|
@ -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 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
|
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)
|
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
|
const ELL2_C1_EDWARDS = FpSqrtEven(Fp, Fp.neg(BigInt(486664))); // sgn0(c1) MUST equal 0
|
||||||
|
@ -54,6 +54,7 @@ function adjustScalarBytes(bytes: Uint8Array): Uint8Array {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const Fp = Field(ed448P, 456, true);
|
const Fp = Field(ed448P, 456, true);
|
||||||
|
const _4n = BigInt(4);
|
||||||
|
|
||||||
const ED448_DEF = {
|
const ED448_DEF = {
|
||||||
// Param: a
|
// 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, xd2); // 9. xEn = xEn * xd2
|
||||||
xEn = Fp.mul(xEn, yd); // 10. xEn = xEn * yd
|
xEn = Fp.mul(xEn, yd); // 10. xEn = xEn * yd
|
||||||
xEn = Fp.mul(xEn, yn); // 11. xEn = xEn * yn
|
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, xn2); // 13. tv2 = tv2 * xn2
|
||||||
tv2 = Fp.mul(tv2, yd2); // 14. tv2 = tv2 * yd2
|
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
|
let tv1 = Fp.add(tv3, yd2); // 16. tv1 = tv3 + yd2
|
||||||
tv1 = Fp.mul(tv1, xd4); // 17. tv1 = tv1 * xd4
|
tv1 = Fp.mul(tv1, xd4); // 17. tv1 = tv1 * xd4
|
||||||
let xEd = Fp.add(tv1, tv2); // 18. xEd = tv1 + tv2
|
let xEd = Fp.add(tv1, tv2); // 18. xEd = tv1 + tv2
|
||||||
|
@ -131,7 +131,7 @@ function lift_x(x: bigint): PointType<bigint> {
|
|||||||
const xx = modP(x * x);
|
const xx = modP(x * x);
|
||||||
const c = modP(xx * x + BigInt(7)); // Let c = x³ + 7 mod p.
|
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.
|
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.
|
const p = new Point(x, y, _1n); // y(P) = y if y mod 2 = 0 or y(P) = p-y otherwise.
|
||||||
p.assertValidity();
|
p.assertValidity();
|
||||||
return p;
|
return p;
|
||||||
|
Loading…
Reference in New Issue
Block a user