UNPKG

@dedis/kyber

Version:

A typescript implementation of Kyber interfaces

70 lines (69 loc) 2.01 kB
"use strict"; 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;