@dedis/kyber
Version:
A typescript implementation of Kyber interfaces
179 lines (178 loc) • 6.44 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const constants_1 = require("./constants");
const gfp_1 = __importDefault(require("./gfp"));
const gfp12_1 = __importDefault(require("./gfp12"));
const gfp2_1 = __importStar(require("./gfp2"));
const gfp6_1 = __importDefault(require("./gfp6"));
const twist_point_1 = __importDefault(require("./twist-point"));
const sixuPlus2NAF = [0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, -1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, -1,
0, 1, 0, 0, 0, 1, 0, -1, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, -1, 0, 0, 0, 0, 1, 0, 0, 0, 1];
/**
* See the mixed addition algorithm from "Faster Computation of the
* Tate Pairing", http://arxiv.org/pdf/0904.0854v3.pdf
*/
function lineFunctionAdd(r, p, q, r2) {
const B = p.getX().mul(r.getT());
const D = p.getY().add(r.getZ()).square().sub(r2).sub(r.getT()).mul(r.getT());
const H = B.sub(r.getX());
const I = H.square();
let E = I.add(I);
E = E.add(E);
const J = H.mul(E);
const L1 = D.sub(r.getY()).sub(r.getY());
const V = r.getX().mul(E);
const rx = L1.square().sub(J).sub(V).sub(V);
const rz = r.getZ().add(H).square().sub(r.getT()).sub(I);
let t = V.sub(rx).mul(L1);
let t2 = r.getY().mul(J);
t2 = t2.add(t2);
const ry = t.sub(t2);
const rt = rz.square();
t = p.getY().add(rz).square().sub(r2).sub(rt);
t2 = L1.mul(p.getX());
t2 = t2.add(t2);
const a = t2.sub(t);
let c = rz.mulScalar(q.getY());
c = c.add(c);
let b = gfp2_1.default.zero().sub(L1).mulScalar(q.getX());
b = b.add(b);
return {
a,
b,
c,
rOut: new twist_point_1.default(rx, ry, rz, rt),
};
}
/**
* See the doubling algorithm for a=0 from "Faster Computation of the
* Tate Pairing", http://arxiv.org/pdf/0904.0854v3.pdf
*/
function lineFunctionDouble(r, q) {
const A = r.getX().square();
const B = r.getY().square();
const C = B.square();
let D = r.getX().add(B).square().sub(A).sub(C);
D = D.add(D);
const E = A.add(A).add(A);
const G = E.square();
const rx = G.sub(D).sub(D);
const rz = r.getY().add(r.getZ()).square().sub(B).sub(r.getT());
let ry = D.sub(rx).mul(E);
let t = C.add(C);
t = t.add(t);
t = t.add(t);
ry = ry.sub(t);
const rt = rz.square();
t = E.mul(r.getT());
t = t.add(t);
const b = gfp2_1.default.zero().sub(t).mulScalar(q.getX());
t = B.add(B);
t = t.add(t);
const a = r.getX().add(E).square().sub(A).sub(G).sub(t);
let c = rz.mul(r.getT());
c = c.add(c).mulScalar(q.getY());
return {
a,
b,
c,
rOut: new twist_point_1.default(rx, ry, rz, rt),
};
}
function mulLine(ret, res) {
const a2 = new gfp6_1.default(gfp2_1.default.zero(), res.a, res.b).mul(ret.getX());
const t3 = ret.getY().mulScalar(res.c);
const t = res.b.add(res.c);
const t2 = new gfp6_1.default(gfp2_1.default.zero(), res.a, t);
const tx = ret.getX().add(ret.getY()).mul(t2).sub(a2).sub(t3);
const ty = t3.add(a2.mulTau());
return new gfp12_1.default(tx, ty);
}
/**
* miller implements the Miller loop for calculating the Optimal Ate pairing.
* See algorithm 1 from http://cryptojedi.org/papers/dclxvi-20100714.pdf
*/
function miller(q, p) {
let ret = gfp12_1.default.one();
const aAffine = q.clone();
aAffine.makeAffine();
const bAffine = p.clone();
bAffine.makeAffine();
const minusA = new twist_point_1.default();
minusA.neg(aAffine);
let r = aAffine.clone();
let r2 = aAffine.getY().square();
for (let i = sixuPlus2NAF.length - 1; i > 0; i--) {
let lfd = lineFunctionDouble(r, bAffine);
if (i !== sixuPlus2NAF.length - 1) {
ret = ret.square();
}
ret = mulLine(ret, lfd);
r = lfd.rOut;
if (sixuPlus2NAF[i - 1] === 1) {
lfd = lineFunctionAdd(r, aAffine, bAffine, r2);
}
else if (sixuPlus2NAF[i - 1] === -1) {
lfd = lineFunctionAdd(r, minusA, bAffine, r2);
}
else {
continue;
}
ret = mulLine(ret, lfd);
r = lfd.rOut;
}
const q1 = new twist_point_1.default(aAffine.getX().conjugate().mul(gfp2_1.xiToPMinus1Over3), aAffine.getY().conjugate().mul(gfp2_1.xiToPMinus1Over2), gfp2_1.default.one(), gfp2_1.default.one());
const minusQ2 = new twist_point_1.default(aAffine.getX().mulScalar(new gfp_1.default(gfp2_1.xiToPSquaredMinus1Over3)), aAffine.getY(), gfp2_1.default.one(), gfp2_1.default.one());
r2 = q1.getY().square();
const res = lineFunctionAdd(r, q1, bAffine, r2);
ret = mulLine(ret, res);
r = res.rOut;
r2 = minusQ2.getY().square();
const res2 = lineFunctionAdd(r, minusQ2, bAffine, r2);
return mulLine(ret, res2);
}
exports.miller = miller;
/**
* finalExponentiation computes the (p¹²-1)/Order-th power of an element of
* GF(p¹²) to obtain an element of GT (steps 13-15 of algorithm 1 from
* http://cryptojedi.org/papers/dclxvi-20100714.pdf)
*/
function finalExponentiation(a) {
let t1 = a.conjugate();
t1 = t1.mul(a.invert());
const t2 = t1.frobeniusP2();
t1 = t1.mul(t2);
const fp = t1.frobenius();
const fp2 = t1.frobeniusP2();
const fp3 = fp2.frobenius();
const fu = t1.exp(constants_1.u);
const fu2 = fu.exp(constants_1.u);
const fu3 = fu2.exp(constants_1.u);
const fu2p = fu2.frobenius();
const fu3p = fu3.frobenius();
const y0 = fp.mul(fp2).mul(fp3);
const y1 = t1.conjugate();
const y2 = fu2.frobeniusP2();
const y3 = fu.frobenius().conjugate();
const y4 = fu.mul(fu2p).conjugate();
const y5 = fu2.conjugate();
const y6 = fu3.mul(fu3p).conjugate();
let t0 = y6.square().mul(y4).mul(y5);
t1 = y3.mul(y5).mul(t0).square();
t0 = t0.mul(y2);
t1 = t1.mul(t0).square();
t0 = t1.mul(y1);
t1 = t1.mul(y0);
return t0.square().mul(t1);
}
exports.finalExponentiation = finalExponentiation;