@dedis/kyber
Version:
A typescript implementation of Kyber interfaces
241 lines (240 loc) • 6.71 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const gfp2_1 = __importDefault(require("./gfp2"));
const twistB = new gfp2_1.default("6500054969564660373279643874235990574282535810762300357187714502686418407178", "45500384786952622612957507119651934019977750675336102500314001518804928850249");
/**
* Point class used by G2
*/
class TwistPoint {
constructor(x, y, z, t) {
this.x = x || gfp2_1.default.zero();
this.y = y || gfp2_1.default.zero();
this.z = z || gfp2_1.default.zero();
this.t = t || gfp2_1.default.zero();
}
/**
* 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;
}
/**
* Get the z element of the point
* @returns the z element
*/
getZ() {
return this.z;
}
/**
* Get the t element of the point
* @returns the t element
*/
getT() {
return this.t;
}
/**
* Check if the point is on the curve, meaning it's a valid point
* @returns true for a valid point, false otherwise
*/
isOnCurve() {
const cpy = this.clone();
cpy.makeAffine();
if (cpy.isInfinity()) {
return true;
}
const yy = cpy.y.square();
const xxx = cpy.x.square().mul(cpy.x).add(twistB);
return yy.equals(xxx);
}
/**
* Set the point to the infinity value
*/
setInfinity() {
this.x = gfp2_1.default.zero();
this.y = gfp2_1.default.one();
this.z = gfp2_1.default.zero();
this.t = gfp2_1.default.zero();
}
/**
* Check if the point is the infinity
* @returns true when the infinity, false otherwise
*/
isInfinity() {
return this.z.isZero();
}
/**
* Add a to b and set the value to the point
* @param a first point
* @param b second point
*/
add(a, b) {
if (a.isInfinity()) {
this.copy(b);
return;
}
if (b.isInfinity()) {
this.copy(a);
return;
}
const z12 = a.z.square();
const z22 = b.z.square();
const u1 = a.x.mul(z22);
const u2 = b.x.mul(z12);
let t = b.z.mul(z22);
const s1 = a.y.mul(t);
t = a.z.mul(z12);
const s2 = b.y.mul(t);
const h = u2.sub(u1);
t = h.add(h);
const i = t.square();
const j = h.mul(i);
t = s2.sub(s1);
if (h.isZero() && t.isZero()) {
this.double(a);
return;
}
const r = t.add(t);
const v = u1.mul(i);
let t4 = r.square();
t = v.add(v);
let t6 = t4.sub(j);
this.x = t6.sub(t);
t = v.sub(this.x);
t4 = s1.mul(j);
t6 = t4.add(t4);
t4 = r.mul(t);
this.y = t4.sub(t6);
t = a.z.add(b.z);
t4 = t.square();
t = t4.sub(z12);
t4 = t.sub(z22);
this.z = t4.mul(h);
}
/**
* Compute the double of the given point and set the value
* @param a the point
*/
double(a) {
const A = a.x.square();
const B = a.y.square();
const C = B.square();
let t = a.x.add(B);
let t2 = t.square();
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.square();
t = d.add(d);
this.x = f.sub(t);
t = C.add(C);
t2 = t.add(t);
t = t2.add(t2);
this.y = d.sub(this.x);
t2 = e.mul(this.y);
this.y = t2.sub(t);
t = a.y.mul(a.z);
this.z = t.add(t);
}
/**
* Multiply a point by a scalar and set the value to the point
* @param a the point
* @param k the scalar
*/
mul(a, k) {
const sum = new TwistPoint();
const t = new TwistPoint();
for (let i = k.bitLength(); i >= 0; i--) {
t.double(sum);
if (k.testn(i)) {
sum.add(t, a);
}
else {
sum.copy(t);
}
}
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.invert();
const t = this.y.mul(zInv);
const zInv2 = zInv.square();
this.y = t.mul(zInv2);
this.x = this.x.mul(zInv2);
this.z = gfp2_1.default.one();
this.t = gfp2_1.default.one();
}
/**
* Compute the negative of a and set the value to the point
* @param a the point
*/
neg(a) {
this.x = a.x;
this.y = a.y.negative();
this.z = a.z;
}
/**
* Fill the point with the values of a
* @param a the point
*/
copy(a) {
this.x = a.x;
this.y = a.y;
this.z = a.z;
this.t = a.t;
}
/**
* Get the a clone of the current point
* @returns a copy of the point
*/
clone() {
return new TwistPoint(this.x, this.y, this.z, this.t);
}
/**
* Check the equality between two points
* @returns true when both are equal, false otherwise
*/
equals(o) {
if (!(o instanceof TwistPoint)) {
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 cpy = this.clone();
cpy.makeAffine();
return `(${cpy.x.toString()},${cpy.y.toString()},${cpy.z.toString()})`;
}
}
TwistPoint.generator = new TwistPoint(new gfp2_1.default("21167961636542580255011770066570541300993051739349375019639421053990175267184", "64746500191241794695844075326670126197795977525365406531717464316923369116492"), new gfp2_1.default("20666913350058776956210519119118544732556678129809273996262322366050359951122", "17778617556404439934652658462602675281523610326338642107814333856843981424549"), new gfp2_1.default("0", "1"), new gfp2_1.default("0", "1"));
exports.default = TwistPoint;