@dedis/kyber
Version:
A typescript implementation of Kyber interfaces
70 lines (69 loc) • 2.01 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const bn_js_1 = __importDefault(require("bn.js"));
const constants_1 = require("../constants");
const ZERO = constants_1.zeroBN;
const ONE = constants_1.oneBN;
const TWO = new bn_js_1.default(2);
const FOUR = new bn_js_1.default(4);
function powMod(a, e, p) {
return a.toRed(bn_js_1.default.red(p)).redPow(e).fromRed();
}
function ls(a, p) {
return powMod(a, p.sub(ONE).div(TWO), p);
}
/**
* Computes the square root of n mod p if it exists, otherwise null is returned.
* In other words, find x such that x^2 = n mod p, where p must be an odd prime.
* The implementation is adapted from https://rosettacode.org/wiki/Tonelli-Shanks_algorithm#Java
* to reflect the Java library.
*/
function modSqrt(n, p) {
n = new bn_js_1.default(n);
p = new bn_js_1.default(p);
if (!ls(n, p).eq(ONE)) {
return null;
}
let q = p.sub(ONE);
let ss = ZERO;
while (q.and(ONE).eq(ZERO)) {
ss = ss.add(ONE);
q = q.shrn(1);
}
if (ss.eq(ONE)) {
return powMod(n, p.add(ONE).div(FOUR), p);
}
let z = TWO;
while (!ls(z, p).eq(p.sub(ONE))) {
z = z.add(ONE);
}
let c = powMod(z, q, p);
let r = powMod(n, q.add(ONE).div(TWO), p);
let t = powMod(n, q, p);
let m = ss;
for (;;) {
if (t.eq(ONE)) {
return r;
}
let i = ZERO;
let zz = t;
while (!zz.eq(ONE) && i.cmp(m.sub(ONE)) < 0) {
zz = zz.mul(zz).mod(p);
i = i.add(ONE);
}
let b = c;
let e = m.sub(i).sub(ONE);
while (e.cmp(ZERO) > 0) {
b = b.mul(b).mod(p);
e = e.sub(ONE);
}
r = r.mul(b).mod(p);
c = b.mul(b).mod(p);
t = t.mul(c).mod(p);
m = i;
}
}
exports.modSqrt = modSqrt;