UNPKG

@dedis/kyber

Version:

A typescript implementation of Kyber interfaces

255 lines (254 loc) 7.78 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 crypto_browserify_1 = require("crypto-browserify"); const constants_1 = require("../constants"); const tonelli_shanks_1 = require("../utils/tonelli-shanks"); const constants_2 = require("./constants"); const gfp_1 = __importDefault(require("./gfp")); const curveB = new gfp_1.default(3); /** * Point class used by G1 */ class CurvePoint { constructor(x, y, z, t) { // the coefficient are modulo p to insure we have same // values when it comes to comparison // Other arithmetic operations are already modulo. this.x = new gfp_1.default(x || 0).mod(constants_2.p); this.y = new gfp_1.default(y || 1).mod(constants_2.p); this.z = new gfp_1.default(z || 0).mod(constants_2.p); this.t = new gfp_1.default(t || 0).mod(constants_2.p); } /** * Hash the message to a point * @param msg The message to hash * @returns a valid point */ static hashToPoint(msg) { const h = crypto_browserify_1.createHash("sha256"); h.update(msg); let x = new bn_js_1.default(h.digest(), null, "be").mod(constants_2.p); for (;;) { const xxx = x.mul(x).mul(x).mod(constants_2.p); const t = xxx.add(curveB.getValue()); const y = tonelli_shanks_1.modSqrt(t, constants_2.p); if (y != null) { return new CurvePoint(x, y, 1, 1); } x = x.add(constants_1.oneBN); } } /** * Get the x element of the point * @returns the x element */ getX() { return this.x; } /** * Get the y element of the point * @returns the y element */ getY() { return this.y; } /** * Check if the point is valid by checking if it is on the curve * @returns true when the point is valid, false otherwise */ isOnCurve() { let yy = this.y.sqr(); const xxx = this.x.pow(new bn_js_1.default(3)); yy = yy.sub(xxx); yy = yy.sub(curveB); if (yy.signum() < 0 || yy.compareTo(new gfp_1.default(constants_2.p)) >= 0) { yy = yy.mod(constants_2.p); } return yy.signum() === 0; } /** * Set the point to the infinity */ setInfinity() { this.x = new gfp_1.default(0); this.y = new gfp_1.default(1); this.z = new gfp_1.default(0); this.t = new gfp_1.default(0); } /** * Check if the point is the infinity * @returns true when infinity, false otherwise */ isInfinity() { return this.z.isZero(); } /** * Add a to b and set the value to the point * @param a the first point * @param b the second point */ add(a, b) { if (a.isInfinity()) { this.copy(b); return; } if (b.isInfinity()) { this.copy(a); return; } const z1z1 = a.z.sqr().mod(constants_2.p); const z2z2 = b.z.sqr().mod(constants_2.p); const u1 = a.x.mul(z2z2).mod(constants_2.p); const u2 = b.x.mul(z1z1).mod(constants_2.p); let t = b.z.mul(z2z2).mod(constants_2.p); const s1 = a.y.mul(t).mod(constants_2.p); t = a.z.mul(z1z1).mod(constants_2.p); const s2 = b.y.mul(t).mod(constants_2.p); const h = u2.sub(u1); t = h.add(h); const i = t.sqr().mod(constants_2.p); const j = h.mul(i).mod(constants_2.p); t = s2.sub(s1); if (h.signum() === 0 && t.signum() === 0) { this.dbl(a); return; } const r = t.add(t); const v = u1.mul(i).mod(constants_2.p); let t4 = r.sqr().mod(constants_2.p); t = v.add(v); let t6 = t4.sub(j); this.x = t6.sub(t).mod(constants_2.p); t = v.sub(this.x); t4 = s1.mul(j).mod(constants_2.p); t6 = t4.add(t4); t4 = r.mul(t).mod(constants_2.p); this.y = t4.sub(t6).mod(constants_2.p); t = a.z.add(b.z); t4 = t.sqr().mod(constants_2.p); t = t4.sub(z1z1); t4 = t.sub(z2z2); this.z = t4.mul(h).mod(constants_2.p); } /** * Compute the double of a and set the value to the point * @param a the point to double */ dbl(a) { const A = a.x.sqr().mod(constants_2.p); const B = a.y.sqr().mod(constants_2.p); const C = B.sqr().mod(constants_2.p); let t = a.y.mul(a.z).mod(constants_2.p); this.z = t.add(t).mod(constants_2.p); t = a.x.add(B); let t2 = t.sqr().mod(constants_2.p); t = t2.sub(A); t2 = t.sub(C); const d = t2.add(t2); t = A.add(A); const e = t.add(A); const f = e.sqr().mod(constants_2.p); t = d.add(d); this.x = f.sub(t).mod(constants_2.p); t = C.add(C); t2 = t.add(t); t = t2.add(t2); this.y = d.sub(this.x); t2 = e.mul(this.y).mod(constants_2.p); this.y = t2.sub(t).mod(constants_2.p); } /** * Multiply a by a scalar * @param a the point to multiply * @param scalar the scalar */ mul(a, scalar) { const sum = new CurvePoint(); for (let i = scalar.bitLength() - 1; i >= 0; i--) { sum.dbl(sum); if (scalar.testn(i)) { sum.add(sum, a); } } this.copy(sum); } /** * Normalize the point coordinates */ makeAffine() { if (this.z.isOne()) { return; } else if (this.z.isZero()) { this.setInfinity(); return; } const zInv = this.z.invmod(constants_2.p); let t = this.y.mul(zInv).mod(constants_2.p); const zInv2 = zInv.sqr().mod(constants_2.p); this.y = t.mul(zInv2).mod(constants_2.p); t = this.x.mul(zInv2).mod(constants_2.p); this.x = t; this.z = new gfp_1.default(1); this.t = new gfp_1.default(1); } /** * Compute the negative of a and set the value to the point * @param a the point to negate */ negative(a) { this.x = a.x; this.y = a.y.negate().mod(constants_2.p); this.z = a.z; } /** * Fill the point with the values of a * @param cp the point to copy */ copy(cp) { // immutable objects so we can copy them this.x = cp.x; this.y = cp.y; this.z = cp.z; this.t = cp.t; } /** * Get a clone of the current point * @returns a clone of the point */ clone() { const cp = new CurvePoint(); cp.copy(this); return cp; } /** * Check the equality between the point and the object * @param o the object * @returns true when both are equal, false otherwise */ equals(o) { if (!(o instanceof CurvePoint)) { return false; } const a = this.clone(); a.makeAffine(); const b = o.clone(); b.makeAffine(); return a.x.equals(b.x) && a.y.equals(b.y) && a.z.equals(b.z) && a.t.equals(b.t); } /** * Get the string representation of the point * @returns the string representation */ toString() { const cp = this.clone(); cp.makeAffine(); return `(${cp.getX().toString()},${cp.getY().toString()})`; } } CurvePoint.generator = new CurvePoint(1, -2, 1, 1); exports.default = CurvePoint;