@ -0,0 +1,39 @@ |
|||
const bigInt = require("big-integer"); |
|||
|
|||
const F1Field = require("./f1field"); |
|||
const F2Field = require("./f1field"); |
|||
|
|||
const C = { |
|||
|
|||
// Module of the field
|
|||
q : bigInt("21888242871839275222246405745257275088696311157297823662689037894645226208583"), |
|||
|
|||
// Order of the group
|
|||
r : bigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617"), |
|||
|
|||
g1 : [ bigInt(1), bigInt(2) ], |
|||
g2 : |
|||
[ |
|||
[ |
|||
bigInt("10857046999023057135944570762232829481370756359578518086990519993285655852781"), |
|||
bigInt("11559732032986387107991004021392285783925812861821192530917403151452391805634") |
|||
], |
|||
[ |
|||
bigInt("8495653923123431417604973247489272438418190587263600148770280649306958101930"), |
|||
bigInt("4082367875863433681332203403145435568316851327593401208105741076214120093531") |
|||
] |
|||
] |
|||
|
|||
}; |
|||
|
|||
const F1 = new F1Field(C.q); |
|||
const F2 = new F2Field(C.q); |
|||
|
|||
C.two_inv= F1.inverse(bigInt(2)); |
|||
|
|||
C.coef_b = bigInt(3); |
|||
C.twist = [bigInt(9) , bigInt(1)]; |
|||
// C.twist_coeff_b = F2.mulEscalar( F2.inverse(C.twist), C.coef_b );
|
|||
|
|||
|
|||
module.exports = C; |
@ -0,0 +1,55 @@ |
|||
|
|||
|
|||
|
|||
class F12Field { |
|||
constructor(p) { |
|||
this.p = n; |
|||
} |
|||
|
|||
add(a, b) { |
|||
const maxGrade = Math.max(a.length, b.length); |
|||
const res = new Array(maxGrade); |
|||
for (let i=0; i<maxGrade; i++) { |
|||
res[i] = this.F.add(a[i], b[i]); |
|||
} |
|||
return this._reduce(res); |
|||
} |
|||
|
|||
sub(a, b) { |
|||
// TODO
|
|||
throw new Error("Not Implementted"); |
|||
} |
|||
|
|||
neg(a) { |
|||
// TODO
|
|||
throw new Error("Not Implementted"); |
|||
} |
|||
|
|||
mul(a, b) { |
|||
// TODO
|
|||
throw new Error("Not Implementted"); |
|||
} |
|||
|
|||
inverse(a, b) { |
|||
// TODO
|
|||
throw new Error("Not Implementted"); |
|||
} |
|||
|
|||
div(a, b) { |
|||
// TODO
|
|||
throw new Error("Not Implementted"); |
|||
} |
|||
|
|||
isZero(a) { |
|||
// TODO
|
|||
throw new Error("Not Implementted"); |
|||
} |
|||
|
|||
mul_by_024(a, ell0, ellVW, ellVV) { |
|||
// TODO
|
|||
throw new Error("Not Implementted"); |
|||
} |
|||
|
|||
} |
|||
|
|||
module.exports = F2Field; |
@ -0,0 +1,78 @@ |
|||
const bigInt = require("big-integer"); |
|||
|
|||
class F1Field { |
|||
constructor(q) { |
|||
this.q = q; |
|||
this.nq = bigInt.zero.minus(q); |
|||
this.zero = bigInt.zero; |
|||
this.one = bigInt.one; |
|||
} |
|||
|
|||
e(a) { |
|||
return bigInt(a); |
|||
} |
|||
|
|||
copy(a) { |
|||
return bigInt(a); |
|||
} |
|||
|
|||
add(a, b) { |
|||
return a.add(b); |
|||
} |
|||
|
|||
sub(a, b) { |
|||
return a.minus(b); |
|||
} |
|||
|
|||
neg(a) { |
|||
return bigInt.zero.minus(a); |
|||
} |
|||
|
|||
mul(a, b) { |
|||
return a.times(b).mod(this.q); |
|||
} |
|||
|
|||
inverse(a) { |
|||
return this.affine(a).modInv(this.q); |
|||
} |
|||
|
|||
div(a, b) { |
|||
return this.mul(a, this.inverse(b)); |
|||
} |
|||
|
|||
square(a) { |
|||
return a.square().mod(this.q); |
|||
} |
|||
|
|||
isZero(a) { |
|||
return a.isZero(); |
|||
} |
|||
|
|||
equals(a, b) { |
|||
return this.affine(a).equals(this.affine(b)); |
|||
} |
|||
|
|||
affine(a) { |
|||
let aux = a; |
|||
if (aux.isNegative()) { |
|||
if (aux.lesserOrEquals(this.nq)) { |
|||
aux = a.mod(this.q); |
|||
} |
|||
if (aux.isNegative()) { |
|||
aux = aux.add(this.q); |
|||
} |
|||
} else { |
|||
if (aux.greaterOrEquals(this.q)) { |
|||
aux = aux.mod(this.q); |
|||
} |
|||
} |
|||
return aux; |
|||
} |
|||
|
|||
toString(a) { |
|||
const ca = this.affine(a); |
|||
return `"0x${ca.toString(16)}"`; |
|||
} |
|||
} |
|||
|
|||
module.exports = F1Field; |
@ -1,147 +0,0 @@ |
|||
const bigInt = require("big-integer"); |
|||
|
|||
const q = new bigInt("21888242871839275222246405745257275088696311157297823662689037894645226208583"); |
|||
|
|||
module.eports = class G1Curve { |
|||
|
|||
constructor() { |
|||
this.g = [ bigInt(1), bigInt(2), bigInt(1) ]; |
|||
this.zero = [ bigInt(0), bigInt(1), bigInt(0) ]; |
|||
} |
|||
|
|||
isZero(p) { |
|||
return p[2].isZero(); |
|||
} |
|||
add(p1, p2) { |
|||
|
|||
if (this.isZero(p1)) return p2; |
|||
if (this.isZero(p2)) return p1; |
|||
|
|||
const res = new Array(3); |
|||
|
|||
const Z1Z1 = p1[2].square().mod(q); |
|||
const Z2Z2 = p2[2].square().mod(q); |
|||
|
|||
const U1 = p1[0].times(Z2Z2).mod(q); |
|||
const U2 = p2[0].times(Z1Z1).mod(q); |
|||
|
|||
const Z1_cubed = p1[2].times(Z1Z1).mod(q); |
|||
const Z2_cubed = p2[2].times(Z2Z2).mod(q); |
|||
|
|||
const S1 = p1[1].times(Z2_cubed).mod(q); |
|||
const S2 = p2[1].times(Z1_cubed).mod(q); |
|||
|
|||
if (U1.equals(U2) && (S1.equals(S2))) { |
|||
return this.double(p1); |
|||
} |
|||
|
|||
let H = U2.minus(U1); |
|||
if (H.isNegative()) H = H.add(q); |
|||
|
|||
let S2_minus_S1 = S2.minus(S1); |
|||
if (S2_minus_S1.isNegative()) S2_minus_S1 = S2_minus_S1.add(q); |
|||
|
|||
const I = H.add(H).square().mod(q); |
|||
const J = H.times(I).mod(q); |
|||
|
|||
const r = S2_minus_S1.add(S2_minus_S1); |
|||
const V = U1.times(I).mod(q); |
|||
|
|||
res[0] = r.square().minus(J).minus(V).minus(V).mod(q); |
|||
if (res[0].isNegative()) res[0] = res[0].add(q); |
|||
|
|||
const S1_J = S1.times(J).mod(q); |
|||
|
|||
res[1] = r.times(V.minus(res[0])).minus(S1_J).minus(S1_J).mod(q); |
|||
if (res[1].isNegative()) res[1] = res[1].add(q); |
|||
|
|||
res[2] = p1[2].add(p2[2]).square().minus(Z1Z1).minus(Z2Z2).mod(q); |
|||
res[2] = res[2].times(H).mod(q); |
|||
if (res[2].isNegative()) res[2] = res[2].add(q); |
|||
|
|||
return res; |
|||
} |
|||
|
|||
double(p) { |
|||
const res = new Array(3); |
|||
|
|||
if (this.isZero(p)) return p; |
|||
|
|||
const A = p[0].square().mod(q); |
|||
const B = p[1].square().mod(q); |
|||
const C = B.square().mod(q); |
|||
|
|||
let D = p[0].add(B).square().minus(A).minus(C); |
|||
D = D.add(D); |
|||
|
|||
const E = A.times(3); |
|||
const F = E.square(); |
|||
|
|||
res[0] = F.minus(D).minus(D).mod(q); |
|||
if (res[0].isNegative()) res[0] = res[0].add(q); |
|||
|
|||
const eightC = C.times(8); |
|||
|
|||
res[1] = E.times(D.minus(res[0])).minus(eightC).mod(q); |
|||
if (res[1].isNegative()) res[1] = res[1].add(q); |
|||
|
|||
const Y1Z1 = p[1].times(p[2]); |
|||
res[2] = Y1Z1.add(Y1Z1).mod(q); |
|||
|
|||
return res; |
|||
} |
|||
|
|||
toAffineCoordinates(p) { |
|||
if (this.isZero(p)) { |
|||
return this.zero; |
|||
} else { |
|||
const Z_inv = p[2].modInv(q); |
|||
const Z2_inv = Z_inv.square().mod(q); |
|||
const Z3_inv = Z2_inv.times(Z_inv).mod(q); |
|||
|
|||
const res = new Array(3); |
|||
res[0] = p[0].times(Z2_inv).mod(q); |
|||
res[1] = p[1].times(Z3_inv).mod(q); |
|||
res[2] = bigInt(1); |
|||
|
|||
return res; |
|||
} |
|||
} |
|||
|
|||
mulEscalar(base, e) { |
|||
let res = this.zero; |
|||
let rem = e; |
|||
let exp = base; |
|||
|
|||
while (! rem.isZero()) { |
|||
if (rem.isOdd()) { |
|||
res = this.add(res, exp); |
|||
} |
|||
exp = this.double(exp); |
|||
rem = rem.shiftRight(1); |
|||
} |
|||
|
|||
return res; |
|||
} |
|||
|
|||
}; |
|||
|
|||
const G1 = new module.eports(); |
|||
|
|||
|
|||
const r = bigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617"); |
|||
// const np = G1.mulEscalar(G1.g, bigInt(2));
|
|||
|
|||
const np = G1.mulEscalar(G1.g, r.add(1)); |
|||
const p = G1.toAffineCoordinates(np); |
|||
|
|||
/* |
|||
const np2 = G1.add(G1.g, G1.g); |
|||
const np3 = G1.add(G1.g, np2); |
|||
|
|||
const p = G1.toAffineCoordinates(np3); |
|||
*/ |
|||
|
|||
console.log(p[0].toString() + ", " + p[1].toString() + ", " + p[2].toString()); |
|||
|
|||
|
@ -1,28 +0,0 @@ |
|||
const bigInt = require("big-integer"); |
|||
const ZnField = require("./znfield.js"); |
|||
|
|||
module.eports = class G2Curve { |
|||
|
|||
constructor() { |
|||
this.F = new ZnField(bigInt("21888242871839275222246405745257275088696311157297823662689037894645226208583")); |
|||
this.g = [ |
|||
|
|||
]; |
|||
} |
|||
|
|||
add(p1, p2) { |
|||
// TODO
|
|||
throw new Error("Not Implementted"); |
|||
} |
|||
|
|||
double(p1) { |
|||
// TODO
|
|||
throw new Error("Not Implementted"); |
|||
} |
|||
|
|||
mulEscalar(p1, e) { |
|||
// TODO
|
|||
throw new Error("Not Implementted"); |
|||
} |
|||
|
|||
}; |
@ -0,0 +1,167 @@ |
|||
|
|||
class GCurve { |
|||
|
|||
constructor(F, g) { |
|||
this.F = F; |
|||
this.g = F.copy(g); |
|||
if (this.g.length == 2) this.g[2] = this.F.one; |
|||
this.zero = [this.F.zero, this.F.one, this.F.zero]; |
|||
} |
|||
|
|||
isZero(p) { |
|||
return this.F.isZero(p[2]); |
|||
} |
|||
|
|||
add(p1, p2) { |
|||
|
|||
if (this.isZero(p1)) return p2; |
|||
if (this.isZero(p2)) return p1; |
|||
|
|||
const res = new Array(3); |
|||
|
|||
const Z1Z1 = this.F.square( p1[2] ); |
|||
const Z2Z2 = this.F.square( p2[2] ); |
|||
|
|||
const U1 = this.F.mul( p1[0] , Z2Z2 ); // U1 = X1 * Z2Z2
|
|||
const U2 = this.F.mul( p2[0] , Z1Z1 ); // U2 = X2 * Z1Z1
|
|||
|
|||
const Z1_cubed = this.F.mul( p1[2] , Z1Z1); |
|||
const Z2_cubed = this.F.mul( p2[2] , Z2Z2); |
|||
|
|||
const S1 = this.F.mul( p1[1] , Z2_cubed); // S1 = Y1 * Z2 * Z2Z2
|
|||
const S2 = this.F.mul( p2[1] , Z1_cubed); // S2 = Y2 * Z1 * Z1Z1
|
|||
|
|||
if (this.F.equals(U1,U2) && this.F.equals(S1,S2)) { |
|||
return this.double(p1); |
|||
} |
|||
|
|||
const H = this.F.sub( U2 , U1 ); // H = U2-U1
|
|||
|
|||
const S2_minus_S1 = this.F.sub( S2 , S1 ); |
|||
|
|||
const I = this.F.square( this.F.add(H,H) ); // I = (2 * H)^2
|
|||
const J = this.F.mul( H , I ); // J = H * I
|
|||
|
|||
const r = this.F.add( S2_minus_S1 , S2_minus_S1 ); // r = 2 * (S2-S1)
|
|||
const V = this.F.mul( U1 , I ); // V = U1 * I
|
|||
|
|||
res[0] = |
|||
this.F.sub( |
|||
this.F.sub( this.F.square(r) , J ), |
|||
this.F.add( V , V )); // X3 = r^2 - J - 2 * V
|
|||
|
|||
const S1_J = this.F.mul( S1 , J ); |
|||
|
|||
res[1] = |
|||
this.F.sub( |
|||
this.F.mul( r , this.F.sub(V,res[0])), |
|||
this.F.add( S1_J,S1_J )); // Y3 = r * (V-X3)-2 S1 J
|
|||
|
|||
res[2] = |
|||
this.F.mul( |
|||
H, |
|||
this.F.sub( |
|||
this.F.square( this.F.add(p1[2],p2[2]) ), |
|||
this.F.add( Z1Z1 , Z2Z2 ))); // Z3 = ((Z1+Z2)^2-Z1Z1-Z2Z2) * H
|
|||
|
|||
return res; |
|||
} |
|||
|
|||
double(p) { |
|||
const res = new Array(3); |
|||
|
|||
if (this.isZero(p)) return p; |
|||
|
|||
const A = this.F.square( p[0] ); // A = X1^2
|
|||
const B = this.F.square( p[1] ); // B = Y1^2
|
|||
const C = this.F.square( B ); // C = B^2
|
|||
|
|||
let D = |
|||
this.F.sub( |
|||
this.F.square( this.F.add(p[0] , B )), |
|||
this.F.add( A , C)); |
|||
D = this.F.add(D,D); // D = 2 * ((X1 + B)^2 - A - C)
|
|||
|
|||
const E = this.F.add( this.F.add(A,A), A); // E = 3 * A
|
|||
const F = this.F.square( E ); // F = E^2
|
|||
|
|||
res[0] = this.F.sub( F , this.F.add(D,D) ); // X3 = F - 2 D
|
|||
|
|||
let eightC = this.F.add( C , C ); |
|||
eightC = this.F.add( eightC , eightC ); |
|||
eightC = this.F.add( eightC , eightC ); |
|||
|
|||
res[1] = |
|||
this.F.sub( |
|||
this.F.mul( |
|||
E, |
|||
this.F.sub( D, res[0] )), |
|||
eightC); // Y3 = E * (D - X3) - 8 * C
|
|||
|
|||
const Y1Z1 = this.F.mul( p[1] , p[2] ); |
|||
res[2] = this.F.add( Y1Z1 , Y1Z1 ); // Z3 = 2 * Y1 * Z1
|
|||
|
|||
return res; |
|||
} |
|||
|
|||
mulEscalar(base, e) { |
|||
let res = this.zero; |
|||
let rem = e; |
|||
let exp = base; |
|||
|
|||
while (! rem.isZero()) { |
|||
if (rem.isOdd()) { |
|||
res = this.add(res, exp); |
|||
} |
|||
exp = this.double(exp); |
|||
rem = rem.shiftRight(1); |
|||
} |
|||
|
|||
return res; |
|||
} |
|||
|
|||
affine(p) { |
|||
if (this.isZero(p)) { |
|||
return this.zero; |
|||
} else { |
|||
const Z_inv = this.F.inverse(p[2]); |
|||
const Z2_inv = this.F.square(Z_inv); |
|||
const Z3_inv = this.F.mul(Z2_inv, Z_inv); |
|||
|
|||
const res = new Array(3); |
|||
res[0] = this.F.affine( this.F.mul(p[0],Z2_inv)); |
|||
res[1] = this.F.affine( this.F.mul(p[1],Z3_inv)); |
|||
res[2] = this.F.one; |
|||
|
|||
return res; |
|||
} |
|||
} |
|||
|
|||
equals(p1, p2) { |
|||
if (this.isZero(p1)) return this.isZero(p2); |
|||
if (this.isZero(p2)) return this.isZero(p1); |
|||
|
|||
const Z1Z1 = this.F.square( p1[2] ); |
|||
const Z2Z2 = this.F.square( p2[2] ); |
|||
|
|||
const U1 = this.F.mul( p1[0] , Z2Z2 ); |
|||
const U2 = this.F.mul( p2[0] , Z1Z1 ); |
|||
|
|||
const Z1_cubed = this.F.mul( p1[2] , Z1Z1); |
|||
const Z2_cubed = this.F.mul( p2[2] , Z2Z2); |
|||
|
|||
const S1 = this.F.mul( p1[1] , Z2_cubed); |
|||
const S2 = this.F.mul( p2[1] , Z1_cubed); |
|||
|
|||
return (this.F.equals(U1,U2) && this.F.equals(S1,S2)); |
|||
} |
|||
|
|||
toString(p) { |
|||
const cp = this.affine(p); |
|||
return `[ ${this.F.toString(cp[0])} , ${this.F.toString(cp[1])} ]`; |
|||
} |
|||
|
|||
} |
|||
|
|||
module.exports = GCurve; |
|||
|
@ -0,0 +1,35 @@ |
|||
const F1Field = require("../src/f1field.js"); |
|||
const GCurve = require("../src/gcurve.js"); |
|||
const constants = require("../src/constants.js"); |
|||
const chai = require('chai'); |
|||
|
|||
const assert = chai.assert; |
|||
|
|||
describe("Curve G1 Test", () => { |
|||
|
|||
it ("r*one == 0", () => { |
|||
const F1 = new F1Field(constants.q); |
|||
const G1 = new GCurve(F1, constants.g1); |
|||
|
|||
const res = G1.mulEscalar(G1.g, constants.r); |
|||
|
|||
assert(G1.equals(res, G1.zero), "G1 does not have range r"); |
|||
}); |
|||
|
|||
it("Should add match in various", () => { |
|||
const F1 = new F1Field(constants.q); |
|||
const G1 = new GCurve(F1, constants.g1); |
|||
|
|||
const r1 = F1.e(33); |
|||
const r2 = F1.e(44); |
|||
|
|||
const gr1 = G1.mulEscalar(G1.g, r1); |
|||
const gr2 = G1.mulEscalar(G1.g, r2); |
|||
|
|||
const grsum1 = G1.add(gr1, gr2); |
|||
|
|||
const grsum2 = G1.mulEscalar(G1.g, r1.add(r2)); |
|||
|
|||
assert(G1.equals(grsum1, grsum2)); |
|||
}); |
|||
}); |