forked from tornado-packages/noble-curves
modular: Tonneli-Shanks refactoring
This commit is contained in:
parent
069452dbe7
commit
bfe929aac3
@ -69,7 +69,8 @@ export function invert(number: bigint, modulo: bigint): bigint {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Tonelli-Shanks algorithm
|
// Tonelli-Shanks algorithm
|
||||||
// https://eprint.iacr.org/2012/685.pdf (page 12)
|
// Paper 1: https://eprint.iacr.org/2012/685.pdf (page 12)
|
||||||
|
// Paper 2: Square Roots from 1; 24, 51, 10 to Dan Shanks
|
||||||
export function tonelliShanks(P: bigint) {
|
export function tonelliShanks(P: bigint) {
|
||||||
// Legendre constant: used to calculate Legendre symbol (a | p),
|
// Legendre constant: used to calculate Legendre symbol (a | p),
|
||||||
// which denotes the value of a^((p-1)/2) (mod p).
|
// which denotes the value of a^((p-1)/2) (mod p).
|
||||||
@ -101,29 +102,26 @@ export function tonelliShanks(P: bigint) {
|
|||||||
return function tonelliSlow<T>(Fp: Field<T>, n: T): T {
|
return function tonelliSlow<T>(Fp: Field<T>, n: T): T {
|
||||||
// Step 0: Check that n is indeed a square: (n | p) must be ≡ 1
|
// Step 0: Check that n is indeed a square: (n | p) must be ≡ 1
|
||||||
if (Fp.pow(n, legendreC) !== Fp.ONE) throw new Error('Cannot find square root');
|
if (Fp.pow(n, legendreC) !== Fp.ONE) throw new Error('Cannot find square root');
|
||||||
let s = S;
|
let r = S;
|
||||||
|
let g = Fp.pow(Fp.create(Z as any as T), Q); // will update both x and b
|
||||||
|
let x = Fp.pow(n, Q1div2); // first guess at the square root
|
||||||
|
let b = Fp.pow(n, Q); // first guess at the fudge factor
|
||||||
|
|
||||||
let c = pow(Z, Q, P);
|
let t2: typeof Fp.ZERO;
|
||||||
let r = Fp.pow(n, Q1div2);
|
while (!Fp.equals(Fp.sub(b, Fp.ONE), Fp.ZERO)) {
|
||||||
let t = Fp.pow(n, Q);
|
t2 = Fp.square(b);
|
||||||
|
let m;
|
||||||
let t2 = Fp.ZERO;
|
for (m = 1; m < r; m++) {
|
||||||
while (!Fp.equals(Fp.sub(t, Fp.ONE), Fp.ZERO)) {
|
if (Fp.equals(t2, Fp.ONE)) break;
|
||||||
t2 = Fp.square(t);
|
t2 = Fp.square(t2); // t2 *= t2
|
||||||
let i;
|
|
||||||
for (i = 1; i < s; i++) {
|
|
||||||
// stop if t2-1 == 0
|
|
||||||
if (Fp.equals(Fp.sub(t2, Fp.ONE), Fp.ZERO)) break;
|
|
||||||
// t2 *= t2
|
|
||||||
t2 = Fp.square(t2);
|
|
||||||
}
|
}
|
||||||
let b = pow(c, BigInt(1 << (s - i - 1)), P);
|
let ge = Fp.pow(g, BigInt(1 << (r - m - 1))); // ge = 2^(r-m-1)
|
||||||
r = Fp.mul(r, b);
|
g = Fp.square(ge); // g = ge * ge
|
||||||
c = mod(b * b, P);
|
x = Fp.mul(x, ge); // x *= ge
|
||||||
t = Fp.mul(t, c);
|
b = Fp.mul(b, g); // b *= g
|
||||||
s = i;
|
r = m;
|
||||||
}
|
}
|
||||||
return r;
|
return x;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user