Advertisement
Guest User

Ed25519 in SJCL

a guest
Jan 15th, 2016
222
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /**
  2.  * base class for all ecc operations.
  3.  */
  4. sjcl.ecc = {};
  5.  
  6. /**
  7.  * Represents a point on a curve in affine coordinates.
  8.  * @constructor
  9.  * @param {sjcl.ecc.curve} curve The curve that this point lies on.
  10.  * @param {bigInt} x The x coordinate.
  11.  * @param {bigInt} y The y coordinate.
  12.  */
  13. sjcl.ecc.point = function(curve,x,y) {
  14.   if (x === undefined) {
  15.     this.isIdentity = true;
  16.   } else {
  17.     if (x instanceof sjcl.bn) {
  18.       x = new curve.field(x);
  19.     }
  20.     if (y instanceof sjcl.bn) {
  21.       y = new curve.field(y);
  22.     }
  23.  
  24.     this.x = x;
  25.     this.y = y;
  26.  
  27.     this.isIdentity = false;
  28.   }
  29.   this.curve = curve;
  30. };
  31.  
  32. sjcl.ecc.point.prototype = {
  33.   toJac: function() {
  34.     return new sjcl.ecc.pointJac(this.curve, this.x, this.y, new this.curve.field(1));
  35.   },
  36.  
  37.   mult: function(k) {
  38.     return this.toJac().mult(k, this).toAffine();
  39.   },
  40.  
  41.   /**
  42.    * Multiply this point by k, added to affine2*k2, and return the answer in Jacobian coordinates.
  43.    * @param {bigInt} k The coefficient to multiply this by.
  44.    * @param {bigInt} k2 The coefficient to multiply affine2 this by.
  45.    * @param {sjcl.ecc.point} affine The other point in affine coordinates.
  46.    * @return {sjcl.ecc.pointJac} The result of the multiplication and addition, in Jacobian coordinates.
  47.    */
  48.   mult2: function(k, k2, affine2) {
  49.     return this.toJac().mult2(k, this, k2, affine2).toAffine();
  50.   },
  51.  
  52.   multiples: function() {
  53.     var m, i, j;
  54.     if (this._multiples === undefined) {
  55.       j = this.toJac().doubl();
  56.       m = this._multiples = [new sjcl.ecc.point(this.curve), this, j.toAffine()];
  57.       for (i=3; i<16; i++) {
  58.         j = j.add(this);
  59.         m.push(j.toAffine());
  60.       }
  61.     }
  62.     return this._multiples;
  63.   },
  64.  
  65.   negate: function() {
  66.     var newY = new this.curve.field(0).sub(this.y).normalize().reduce();
  67.     return new sjcl.ecc.point(this.curve, this.x, newY);
  68.   },
  69.  
  70.   isValid: function() {
  71.     return this.y.square().equals(this.curve.b.add(this.x.mul(this.curve.a.add(this.x.square()))));
  72.   },
  73.  
  74.   toBits: function(compress, littleEndian) {
  75.     var out, x, y;
  76.  
  77.     if (!compress) {
  78.       x = this.x.toBits();
  79.       y = this.y.toBits();
  80.       if (!!littleEndian) {
  81.         x = sjcl.bitArray.swapEndian(x);
  82.         y = sjcl.bitArray.swapEndian(y);
  83.       }
  84.       out = sjcl.bitArray.concat(x, y);
  85.     } else {
  86.       out = new sjcl.bn(this.x.fullReduce());
  87.       if (this.y.fullReduce().mod(2).equals(1)) {
  88.         out.addM(new sjcl.bn(Math.pow(2, this.x.exponent)));
  89.       }
  90.       out = out.toBits(this.x.exponent + 1);
  91.       if (!!littleEndian) {
  92.         out = sjcl.bitArray.swapEndian(out);
  93.       }
  94.     }
  95.     return out;
  96.   }
  97. };
  98.  
  99. /**
  100.  * Represents a point on a curve in Jacobian coordinates. Coordinates can be specified as bigInts or strings (which
  101.  * will be converted to bigInts).
  102.  *
  103.  * @constructor
  104.  * @param {bigInt/string} x The x coordinate.
  105.  * @param {bigInt/string} y The y coordinate.
  106.  * @param {bigInt/string} z The z coordinate.
  107.  * @param {sjcl.ecc.curve} curve The curve that this point lies on.
  108.  */
  109. sjcl.ecc.pointJac = function(curve, x, y, z) {
  110.   if (x === undefined) {
  111.     this.isIdentity = true;
  112.   } else {
  113.     this.x = x;
  114.     this.y = y;
  115.     this.z = z;
  116.     this.isIdentity = false;
  117.   }
  118.   this.curve = curve;
  119. };
  120.  
  121. sjcl.ecc.pointJac.prototype = {
  122.   /**
  123.    * Adds S and T and returns the result in Jacobian coordinates. Note that S must be in Jacobian coordinates and T must be in affine coordinates.
  124.    * @param {sjcl.ecc.pointJac} S One of the points to add, in Jacobian coordinates.
  125.    * @param {sjcl.ecc.point} T The other point to add, in affine coordinates.
  126.    * @return {sjcl.ecc.pointJac} The sum of the two points, in Jacobian coordinates.
  127.    */
  128.   add: function(T) {
  129.     var S = this, sz2, c, d, c2, x1, x2, x, y1, y2, y, z;
  130.     if (S.curve !== T.curve) {
  131.       throw("sjcl.ecc.add(): Points must be on the same curve to add them!");
  132.     }
  133.  
  134.     if (S.isIdentity) {
  135.       return T.toJac();
  136.     } else if (T.isIdentity) {
  137.       return S;
  138.     }
  139.  
  140.     sz2 = S.z.square();
  141.     c = T.x.mul(sz2).subM(S.x);
  142.  
  143.     if (c.equals(0)) {
  144.       if (S.y.equals(T.y.mul(sz2.mul(S.z)))) {
  145.         // same point
  146.         return S.doubl();
  147.       } else {
  148.         // inverses
  149.         return new sjcl.ecc.pointJac(S.curve);
  150.       }
  151.     }
  152.  
  153.     d = T.y.mul(sz2.mul(S.z)).subM(S.y);
  154.     c2 = c.square();
  155.  
  156.     x1 = d.square();
  157.     x2 = c.square().mul(c).addM( S.x.add(S.x).mul(c2) );
  158.     x  = x1.subM(x2);
  159.  
  160.     y1 = S.x.mul(c2).subM(x).mul(d);
  161.     y2 = S.y.mul(c.square().mul(c));
  162.     y  = y1.subM(y2);
  163.  
  164.     z  = S.z.mul(c);
  165.  
  166.     return new sjcl.ecc.pointJac(this.curve,x,y,z);
  167.   },
  168.  
  169.   /**
  170.    * doubles this point.
  171.    * @return {sjcl.ecc.pointJac} The doubled point.
  172.    */
  173.   doubl: function() {
  174.     if (this.isIdentity) { return this; }
  175.  
  176.     var
  177.       y2 = this.y.square(),
  178.       a  = y2.mul(this.x.mul(4)),
  179.       b  = y2.square().mul(8),
  180.       z2 = this.z.square(),
  181.       c  = this.curve.a.toString() == (new sjcl.bn(-3)).toString() ?
  182.                 this.x.sub(z2).mul(3).mul(this.x.add(z2)) :
  183.                 this.x.square().mul(3).add(z2.square().mul(this.curve.a)),
  184.       x  = c.square().subM(a).subM(a),
  185.       y  = a.sub(x).mul(c).subM(b),
  186.       z  = this.y.add(this.y).mul(this.z);
  187.     return new sjcl.ecc.pointJac(this.curve, x, y, z);
  188.   },
  189.  
  190.   /**
  191.    * Returns a copy of this point converted to affine coordinates.
  192.    * @return {sjcl.ecc.point} The converted point.
  193.    */
  194.   toAffine: function() {
  195.     if (this.isIdentity || this.z.equals(0)) {
  196.       return new sjcl.ecc.point(this.curve);
  197.     }
  198.     var zi = this.z.inverse(), zi2 = zi.square();
  199.     return new sjcl.ecc.point(this.curve, this.x.mul(zi2).fullReduce(), this.y.mul(zi2.mul(zi)).fullReduce());
  200.   },
  201.  
  202.   /**
  203.    * Multiply this point by k and return the answer in Jacobian coordinates.
  204.    * @param {bigInt} k The coefficient to multiply by.
  205.    * @param {sjcl.ecc.point} affine This point in affine coordinates.
  206.    * @return {sjcl.ecc.pointJac} The result of the multiplication, in Jacobian coordinates.
  207.    */
  208.   mult: function(k, affine) {
  209.     if (typeof(k) === "number") {
  210.       k = [k];
  211.     } else if (k.limbs !== undefined) {
  212.       k = k.normalize().limbs;
  213.     }
  214.  
  215.     var i, j, out = new sjcl.ecc.point(this.curve).toJac(), multiples = affine.multiples();
  216.  
  217.     for (i=k.length-1; i>=0; i--) {
  218.       for (j=sjcl.bn.prototype.radix-4; j>=0; j-=4) {
  219.         out = out.doubl().doubl().doubl().doubl().add(multiples[k[i]>>j & 0xF]);
  220.       }
  221.     }
  222.  
  223.     return out;
  224.   },
  225.  
  226.   /**
  227.    * Multiply this point by k, added to affine2*k2, and return the answer in Jacobian coordinates.
  228.    * @param {bigInt} k The coefficient to multiply this by.
  229.    * @param {sjcl.ecc.point} affine This point in affine coordinates.
  230.    * @param {bigInt} k2 The coefficient to multiply affine2 this by.
  231.    * @param {sjcl.ecc.point} affine The other point in affine coordinates.
  232.    * @return {sjcl.ecc.pointJac} The result of the multiplication and addition, in Jacobian coordinates.
  233.    */
  234.   mult2: function(k1, affine, k2, affine2) {
  235.     if (typeof(k1) === "number") {
  236.       k1 = [k1];
  237.     } else if (k1.limbs !== undefined) {
  238.       k1 = k1.normalize().limbs;
  239.     }
  240.  
  241.     if (typeof(k2) === "number") {
  242.       k2 = [k2];
  243.     } else if (k2.limbs !== undefined) {
  244.       k2 = k2.normalize().limbs;
  245.     }
  246.  
  247.     var i, j, out = new sjcl.ecc.point(this.curve).toJac(), m1 = affine.multiples(),
  248.         m2 = affine2.multiples(), l1, l2;
  249.  
  250.     for (i=Math.max(k1.length,k2.length)-1; i>=0; i--) {
  251.       l1 = k1[i] | 0;
  252.       l2 = k2[i] | 0;
  253.       for (j=sjcl.bn.prototype.radix-4; j>=0; j-=4) {
  254.         out = out.doubl().doubl().doubl().doubl().add(m1[l1>>j & 0xF]).add(m2[l2>>j & 0xF]);
  255.       }
  256.     }
  257.  
  258.     return out;
  259.   },
  260.  
  261.   negate: function() {
  262.     return this.toAffine().negate().toJac();
  263.   },
  264.  
  265.   isValid: function() {
  266.     var z2 = this.z.square(), z4 = z2.square(), z6 = z4.mul(z2);
  267.     return this.y.square().equals(
  268.              this.curve.b.mul(z6).add(this.x.mul(
  269.                this.curve.a.mul(z4).add(this.x.square()))));
  270.   }
  271. };
  272.  
  273. /**
  274.  * Construct an elliptic curve. Most users will not use this and instead start with one of the NIST curves defined below.
  275.  *
  276.  * @constructor
  277.  * @param {bigInt} p The prime modulus.
  278.  * @param {bigInt} r The prime order of the curve.
  279.  * @param {bigInt} a The constant a in the equation of the curve y^2 = x^3 + ax + b (for NIST curves, a is always -3).
  280.  * @param {bigInt} b The constant b in the equation of the curve y^2 = x^3 + ax + b.
  281.  * @param {bigInt} x The x coordinate of a base point of the curve.
  282.  * @param {bigInt} y The y coordinate of a base point of the curve.
  283.  * @param {bigInt} mx The x coordinate of the M point of the curve for SPAKE2/PAKE2+.
  284.  * @param {bigInt} my The y coordinate of the M point of the curve for SPAKE2/PAKE2+.
  285.  * @param {bigInt} nx The x coordinate of the N point of the curve for SPAKE2/PAKE2+.
  286.  * @param {bigInt} ny The y coordinate of the N point of the curve for SPAKE2/PAKE2+.
  287.  */
  288. sjcl.ecc.curve = function(Field, r, a, b, x, y, mx, my, nx, ny) {
  289.   this.field = Field;
  290.   this.r = new sjcl.bn(r);
  291.   this.a = new Field(a);
  292.   this.b = new Field(b);
  293.   this.G = new sjcl.ecc.point(this, new Field(x), new Field(y));
  294.   if (mx && my && nx && ny) {
  295.     this.M = new sjcl.ecc.point(this, new Field(mx), new Field(my));
  296.     this.N = new sjcl.ecc.point(this, new Field(nx), new Field(ny));
  297.   }
  298. };
  299.  
  300. sjcl.ecc.curve.prototype = {
  301.   fromBits: function(bits, littleEndian) {
  302.     var w = sjcl.bitArray, n = this.field.prototype.exponent, l = n + 7 & -8, p, x, y;
  303.     if (w.bitLength(bits) == 2*l) {
  304.       x = w.bitSlice(bits, 0, l);
  305.       y = w.bitSlice(bits, l, 2*l);
  306.       if (littleEndian) {
  307.         x = sjcl.bitArray.swapEndian(x);
  308.         y = sjcl.bitArray.swapEndian(y);
  309.       }
  310.       p = new sjcl.ecc.point(this, this.field.fromBits(x), this.field.fromBits(y));
  311.     } else if (w.bitLength(bits) == (n + 8 & -8)) {
  312.       if (littleEndian) {
  313.         bits = sjcl.bitArray.swapEndian(bits);
  314.       }
  315.       var bit = new sjcl.bn(Math.pow(2, this.field.prototype.exponent)),
  316.           x = sjcl.bn.fromBits(bits);
  317.       if (x.greaterEquals(bit)) {
  318.         x.subM(bit);
  319.         bit = 1;
  320.       } else {
  321.         bit = 0;
  322.       }
  323.       p = this.recoverPt(x);
  324.       if (!p.y.fullReduce().mod(2).equals(bit)) {
  325.         p = p.negate();
  326.       }
  327.     } else {
  328.       throw new sjcl.exception.corrupt("not on the curve!");
  329.     }
  330.     if (!p.isValid()) {
  331.       throw new sjcl.exception.corrupt("not on the curve!");
  332.     }
  333.     return p;
  334.   },
  335.  
  336.   /**
  337.    * Recovers the y value from x.
  338.    *
  339.    * @param {bigInt} x The x value.
  340.    * @return {sjcl.ecc.point}
  341.    */
  342.   recoverPt: function(x) {
  343.     // y = sqrt(x^3 + ax + b)
  344.     x = new this.field(x);
  345.     return new sjcl.ecc.point(this, x, x.mul(x.square()).add(x.mul(this.a)).add(this.b).sqrtMod().fullReduce());
  346.   },
  347.  
  348.   /**
  349.    * Creates a deterministic random point in constant time.
  350.    * Uses the simplified Shallue-Woestijne-Ulas algorithm (https://eprint.iacr.org/2009/340.pdf, page 16)
  351.    *
  352.    * Yes: c192, c256, c384, c521, k192, k256
  353.    * No:  c224, k224
  354.    *
  355.    * @param {bigInt} num A number 0 <= x < sjcl.ecc.curve.field.modulus.
  356.    * @return {sjcl.ecc.point} A deterministic random point.
  357.    */
  358.   deterministicRandomPoint: function (num) {
  359.     var u, c, x2, x3, h2, h3, p, y2, y3, pow, zero = new this.field(0), one = new this.field(1);
  360.  
  361.     if (!this.canDeterministicRandomPoint()) {
  362.       throw("sjcl.ecc.curve.deterministicRandomPoint(): Curve can't create a deterministic random point in constant time");
  363.     }
  364.  
  365.     u = new this.field(num);
  366.     // c = -u^2
  367.     c = zero.sub(u.square());
  368.     // X2 = -b / a * (1 + 1 / (c^2 + c))
  369.     x2 = zero.sub(this.b.mul(this.a.inverse())).mul(one.add(c.square().add(c).inverse()));
  370.     // X3 = c * X2
  371.     x3 = c.mul(x2);
  372.     // h2 = X2^3 + a * X2 + b
  373.     h2 = x2.square().mul(x2).add(this.a.mul(x2)).add(this.b);
  374.     // h3 = X3^3 + a * X3 + b
  375.     h3 = x3.square().mul(x3).add(this.a.mul(x3)).add(this.b);
  376.     // if (h2 is square)
  377.     pow = this.field.modulus.add(one).normalize().halveM().halveM();
  378.     y2 =          h2.power(pow);
  379.     y3 = zero.sub(h3.power(pow));
  380.     if (h2.equals(y2.square())) {
  381.       // (X2, h2 ^ ((q + 1) / 4))
  382.       p = new sjcl.ecc.point(this, x2, y2);
  383.     } else {
  384.       // (X3, -h3 ^ ((q + 1) / 4))
  385.       p = new sjcl.ecc.point(this, x3, y3);
  386.     }
  387.     return p;
  388.   },
  389.  
  390.   /**
  391.    * Determines if the curve can create a deterministic random point in constant time.
  392.    * Yes: c192, c256, c384, c521, k192, k256
  393.    * No:  c224, k224
  394.    *
  395.    * @return {Bool} True if this curve can.
  396.    */
  397.   canDeterministicRandomPoint: function () {
  398.     return this.field.modulus.mod(4).equals(3);
  399.   }
  400. };
  401.  
  402. /**
  403.  * Represents a point on a twisted Edwards curve in affine coordinates.
  404.  * @constructor
  405.  * @param {sjcl.ecc.tEdCurve} curve The curve that this point lies on.
  406.  * @param {bigInt} x The x coordinate.
  407.  * @param {bigInt} y The y coordinate.
  408.  */
  409. sjcl.ecc.tEdPoint = function(curve,x,y) {
  410.   this.isIdentity = true;
  411.   if (x !== undefined) {
  412.     if (x instanceof sjcl.bn) {
  413.       x = new curve.field(x);
  414.     }
  415.     if (y instanceof sjcl.bn) {
  416.       y = new curve.field(y);
  417.     }
  418.  
  419.     if (!x.equals(0) || !y.equals(1)) {
  420.       this.x = x;
  421.       this.y = y;
  422.  
  423.       this.isIdentity = false;
  424.     }
  425.   }
  426.   this.curve = curve;
  427. };
  428.  
  429. sjcl.ecc.tEdPoint.prototype = {
  430.   toJac: function() {
  431.     if (this.isIdentity) {
  432.       return new sjcl.ecc.tEdPointJac(this.curve);
  433.     }
  434.     return new sjcl.ecc.tEdPointJac(this.curve, this.x, this.y, new this.curve.field(1), this.x.mul(this.y));
  435.   },
  436.  
  437.   mult: function(k) {
  438.     return this.toJac().mult(k, this).toAffine();
  439.   },
  440.  
  441.   /**
  442.    * Multiply this point by k, added to affine2*k2, and return the answer in Jacobian coordinates.
  443.    * @param {bigInt} k The coefficient to multiply this by.
  444.    * @param {bigInt} k2 The coefficient to multiply affine2 this by.
  445.    * @param {sjcl.ecc.tEdPoint} affine The other point in affine coordinates.
  446.    * @return {sjcl.ecc.tEdPointJac} The result of the multiplication and addition, in Jacobian coordinates.
  447.    */
  448.   mult2: function(k, k2, affine2) {
  449.     return this.toJac().mult2(k, this, k2, affine2).toAffine();
  450.   },
  451.  
  452.   multiples: function() {
  453.     var m, i, j;
  454.     if (this._multiples === undefined) {
  455.       j = this.toJac().doubl();
  456.       m = this._multiples = [new sjcl.ecc.tEdPoint(this.curve), this, j.toAffine()];
  457.       for (i=3; i<16; i++) {
  458.         j = j.add(this);
  459.         m.push(j.toAffine());
  460.       }
  461.     }
  462.     return this._multiples;
  463.   },
  464.  
  465.   negate: function() {
  466.     var newX = new this.curve.field(0).sub(this.x).normalize().reduce();
  467.     return new sjcl.ecc.tEdPoint(this.curve, newX, this.y);
  468.   },
  469.  
  470.   isValid: function() {
  471.     // a = -1
  472.     // a * x^2 + y^2 = 1 + d * x^2 * y^2
  473.     var xx, yy;
  474.  
  475.     xx = this.x.square();
  476.     yy = this.y.square();
  477.     return yy.sub(xx).equals(this.curve.d.mul(xx).mul(yy).add(1));
  478.   },
  479.  
  480.   toBits: function(compress, littleEndian) {
  481.     var out, x, y;
  482.  
  483.     if (!compress) {
  484.       x = this.x.toBits();
  485.       y = this.y.toBits();
  486.       if (!!littleEndian) {
  487.         x = sjcl.bitArray.swapEndian(x);
  488.         y = sjcl.bitArray.swapEndian(y);
  489.       }
  490.       out = sjcl.bitArray.concat(x, y);
  491.     } else {
  492.       out = new sjcl.bn(this.y.fullReduce());
  493.       if (this.x.fullReduce().mod(2).equals(1)) {
  494.         out.addM(new sjcl.bn(Math.pow(2, this.x.exponent)));
  495.       }
  496.       out = out.toBits(this.x.exponent + 1);
  497.       if (!!littleEndian) {
  498.         out = sjcl.bitArray.swapEndian(out);
  499.       }
  500.     }
  501.     return out;
  502.   }
  503. };
  504.  
  505. /**
  506.  * Represents a point on a twisted Edwards curve in Jacobian coordinates. Coordinates can be specified as bigInts or strings (which
  507.  * will be converted to bigInts).
  508.  *
  509.  * @constructor
  510.  * @param {bigInt/string} x The x coordinate.
  511.  * @param {bigInt/string} y The y coordinate.
  512.  * @param {bigInt/string} z The z coordinate.
  513.  * @param {bigInt/string} t The t coordinate.
  514.  * @param {sjcl.ecc.curve} curve The curve that this point lies on.
  515.  */
  516. sjcl.ecc.tEdPointJac = function(curve, x, y, z, t) {
  517.   if (x === undefined) {
  518.     this.isIdentity = true;
  519.   } else {
  520.     this.x = x;
  521.     this.y = y;
  522.     this.z = z;
  523.     this.t = t;
  524.     this.isIdentity = false;
  525.   }
  526.   this.curve = curve;
  527. };
  528.  
  529. sjcl.ecc.tEdPointJac.prototype = {
  530.   /**
  531.    * Adds S and T and returns the result in Jacobian coordinates. Note that S must be in Jacobian coordinates and T must be in affine coordinates.
  532.    * @param {sjcl.ecc.tEdPointJac} S One of the points to add, in Jacobian coordinates.
  533.    * @param {sjcl.ecc.tEdPoint} T The other point to add, in affine coordinates.
  534.    * @return {sjcl.ecc.tEdPointJac} The sum of the two points, in Jacobian coordinates.
  535.    */
  536.   add: function(T) {
  537.     var S = this, a, b, c, d, e, f, g, h, x, y, z, t;
  538.     if (S.curve !== T.curve) {
  539.       throw("sjcl.ecc.add(): Points must be on the same curve to add them!");
  540.     }
  541.  
  542.     if (S.isIdentity) {
  543.       return T.toJac();
  544.     } else if (T.isIdentity) {
  545.       return S;
  546.     }
  547.  
  548.     // A = (Y1-X1)*(Y2-X2)
  549.     a = S.y.sub(S.x).mul(T.y.sub(T.x));
  550.     // B = (Y1+X1)*(Y2+X2)
  551.     b = S.y.add(S.x).mul(T.y.add(T.x));
  552.     // C = T1*k*T2
  553.     c = S.t.mul(S.curve.k).mul(T.x.mul(T.y));
  554.     d = S.z.add(S.z); // D = 2*Z1
  555.     e = b.sub(a);     // E = B-A
  556.     f = d.sub(c);     // F = D-C
  557.     g = d.add(c);     // G = D+C
  558.     h = b.add(a);     // H = B+A
  559.     x = e.mul(f);     // X3 = E*F
  560.     y = g.mul(h);     // Y3 = G*H
  561.     t = e.mul(h);     // T3 = E*H
  562.     z = f.mul(g);     // Z3 = F*G
  563.  
  564.     return new sjcl.ecc.tEdPointJac(this.curve,x,y,z,t);
  565.   },
  566.  
  567.   /**
  568.    * doubles this point.
  569.    * @return {sjcl.ecc.tEdPointJac} The doubled point.
  570.    */
  571.   doubl: function() {
  572.     var a, b, c, d, e, f, g, h, x, y, z, t;
  573.     if (this.isIdentity) { return this; }
  574.  
  575.     a = this.x.square(); // A = X1^2
  576.     b = this.y.square(); // B = Y1^2
  577.     c = this.z.square(); // C = 2*Z1^2
  578.     c = c.add(c);
  579.     // D = -A
  580.     d = new this.curve.field(0).sub(a);
  581.     // E = (X1+Y1)^2-A-B
  582.     e = this.x.add(this.y).square().sub(a).sub(b);
  583.     g = d.add(b); // G = D+B
  584.     f = g.sub(c); // F = G-C
  585.     h = d.sub(b); // H = D-B
  586.     x = e.mul(f); // X3 = E*F
  587.     y = g.mul(h); // Y3 = G*H
  588.     t = e.mul(h); // T3 = E*H
  589.     z = f.mul(g); // Z3 = F*G
  590.     return new sjcl.ecc.tEdPointJac(this.curve, x, y, z, t);
  591.   },
  592.  
  593.   /**
  594.    * Returns a copy of this point converted to affine coordinates.
  595.    * @return {sjcl.ecc.tEdPoint} The converted point.
  596.    */
  597.   toAffine: function() {
  598.     if (this.isIdentity || this.z.equals(0)) {
  599.       return new sjcl.ecc.tEdPoint(this.curve);
  600.     }
  601.     var zi = this.z.inverse();
  602.     return new sjcl.ecc.tEdPoint(this.curve, this.x.mul(zi).fullReduce(), this.y.mul(zi).fullReduce());
  603.   },
  604.  
  605.   /**
  606.    * Multiply this point by k and return the answer in Jacobian coordinates.
  607.    * @param {bigInt} k The coefficient to multiply by.
  608.    * @param {sjcl.ecc.tEdPoint} affine This point in affine coordinates.
  609.    * @return {sjcl.ecc.tEdPointJac} The result of the multiplication, in Jacobian coordinates.
  610.    */
  611.   mult: function(k, affine) {
  612.     if (typeof(k) === "number") {
  613.       k = [k];
  614.     } else if (k.limbs !== undefined) {
  615.       k = k.normalize().limbs;
  616.     }
  617.  
  618.     var i, j, out = new sjcl.ecc.tEdPoint(this.curve).toJac(), multiples = affine.multiples();
  619.  
  620.     for (i=k.length-1; i>=0; i--) {
  621.       for (j=sjcl.bn.prototype.radix-4; j>=0; j-=4) {
  622.         out = out.doubl().doubl().doubl().doubl().add(multiples[k[i]>>j & 0xF]);
  623.       }
  624.     }
  625.  
  626.     return out;
  627.   },
  628.  
  629.   /**
  630.    * Multiply this point by k, added to affine2*k2, and return the answer in Jacobian coordinates.
  631.    * @param {bigInt} k The coefficient to multiply this by.
  632.    * @param {sjcl.ecc.tEdPoint} affine This point in affine coordinates.
  633.    * @param {bigInt} k2 The coefficient to multiply affine2 this by.
  634.    * @param {sjcl.ecc.tEdPoint} affine The other point in affine coordinates.
  635.    * @return {sjcl.ecc.tEdPointJac} The result of the multiplication and addition, in Jacobian coordinates.
  636.    */
  637.   mult2: function(k1, affine, k2, affine2) {
  638.     if (typeof(k1) === "number") {
  639.       k1 = [k1];
  640.     } else if (k1.limbs !== undefined) {
  641.       k1 = k1.normalize().limbs;
  642.     }
  643.  
  644.     if (typeof(k2) === "number") {
  645.       k2 = [k2];
  646.     } else if (k2.limbs !== undefined) {
  647.       k2 = k2.normalize().limbs;
  648.     }
  649.  
  650.     var i, j, out = new sjcl.ecc.tEdPoint(this.curve).toJac(), m1 = affine.multiples(),
  651.         m2 = affine2.multiples(), l1, l2;
  652.  
  653.     for (i=Math.max(k1.length,k2.length)-1; i>=0; i--) {
  654.       l1 = k1[i] | 0;
  655.       l2 = k2[i] | 0;
  656.       for (j=sjcl.bn.prototype.radix-4; j>=0; j-=4) {
  657.         out = out.doubl().doubl().doubl().doubl().add(m1[l1>>j & 0xF]).add(m2[l2>>j & 0xF]);
  658.       }
  659.     }
  660.  
  661.     return out;
  662.   },
  663.  
  664.   negate: function() {
  665.     return this.toAffine().negate().toJac();
  666.   },
  667.  
  668.   isValid: function() {
  669.     // a = -1
  670.     // a * x^2 + y^2 = 1 + d * x^2 * y^2
  671.     // a * X^2 / Z^2 + Y^2 / Z^2 = Z^2 / Z^2 + d * X^2 * Y^2 / Z^2
  672.     // (a * X^2 + Y^2) / Z^2 = (Z^2 + d * X^2 * Y^2) / Z^2
  673.     // a * X^2 + Y^2 = Z^2 + d * X^2 * Y^2
  674.  
  675.     // T/Z = x*y
  676.     // T/Z = X/Z*Y/Z
  677.     // T*Z = X*Y
  678.     var xx, yy;
  679.  
  680.     xx = this.x.square();
  681.     yy = this.y.square();
  682.     return
  683.       yy.sub(xx).equals(this.z.square().add(this.curve.d.mul(xx).mul(yy))) &&
  684.       this.t.mul(this.z).equals(this.x.mul(this.y));
  685.   }
  686. };
  687.  
  688. /**
  689.  * Construct a twisted Edwards elliptic curve. Most users will not use this and instead start with Ed25519 defined below.
  690.  *
  691.  * @constructor
  692.  * @param {bigInt} p The prime modulus.
  693.  * @param {bigInt} r The prime order of the curve.
  694.  * @param {bigInt} d The constant d in the equation of the curve a * x^2 + y^2 = 1 + d * x^2 * y^2 (a = -1).
  695.  * @param {bigInt} x The x coordinate of a base point of the curve.
  696.  * @param {bigInt} y The y coordinate of a base point of the curve.
  697.  * @param {bigInt} mx The x coordinate of the M point of the curve for SPAKE2/PAKE2+.
  698.  * @param {bigInt} my The y coordinate of the M point of the curve for SPAKE2/PAKE2+.
  699.  * @param {bigInt} nx The x coordinate of the N point of the curve for SPAKE2/PAKE2+.
  700.  * @param {bigInt} ny The y coordinate of the N point of the curve for SPAKE2/PAKE2+.
  701.  * @param {bigInt} ex The x coordinate of a point of order 2.
  702.  * @param {bigInt} ey The y coordinate of a point of order 2.
  703.  */
  704. sjcl.ecc.tEdCurve = function(Field, r, d, x, y, mx, my, nx, ny, ex, ey) {
  705.   this.field = Field;
  706.   this.r = new sjcl.bn(r);
  707.   this.d = new Field(d);
  708.   this.k = this.d.add(this.d);
  709.   this.G = new sjcl.ecc.tEdPoint(this, new Field(x), new Field(y));
  710.   if (mx && my && nx && ny) {
  711.     this.M = new sjcl.ecc.tEdPoint(this, new Field(mx), new Field(my));
  712.     this.N = new sjcl.ecc.tEdPoint(this, new Field(nx), new Field(ny));
  713.   }
  714.   if (ex && ey) {
  715.     this.order2P = new sjcl.ecc.tEdPoint(this, new Field(ex), new Field(ey));
  716.   }
  717. };
  718.  
  719. sjcl.ecc.tEdCurve.prototype = {
  720.   fromBits: function(bits, littleEndian) {
  721.     var w = sjcl.bitArray, n = this.field.prototype.exponent, l = n + 7 & -8, p, x, y;
  722.     if (w.bitLength(bits) == 2*l) {
  723.       x = w.bitSlice(bits, 0, l);
  724.       y = w.bitSlice(bits, l, 2*l);
  725.       if (littleEndian) {
  726.         x = sjcl.bitArray.swapEndian(x);
  727.         y = sjcl.bitArray.swapEndian(y);
  728.       }
  729.       p = new sjcl.ecc.tEdPoint(this, this.field.fromBits(x), this.field.fromBits(y));
  730.     } else if (w.bitLength(bits) == (n + 8 & -8)) {
  731.       if (littleEndian) {
  732.         bits = sjcl.bitArray.swapEndian(bits);
  733.       }
  734.       var bit = new sjcl.bn(Math.pow(2, this.field.prototype.exponent)),
  735.           y = sjcl.bn.fromBits(bits);
  736.       if (y.greaterEquals(bit)) {
  737.         y.subM(bit);
  738.         bit = 1;
  739.       } else {
  740.         bit = 0;
  741.       }
  742.       p = this.recoverPt(y);
  743.       if (!p.x.fullReduce().mod(2).equals(bit)) {
  744.         p = p.negate();
  745.       }
  746.     } else {
  747.       throw new sjcl.exception.corrupt("not on the curve!");
  748.     }
  749.     if (!p.isValid()) {
  750.       throw new sjcl.exception.corrupt("not on the curve!");
  751.     }
  752.     return p;
  753.   },
  754.  
  755.   /**
  756.    * Recovers the x value from y.
  757.    *
  758.    * @param {bigInt} y The y value.
  759.    * @return {sjcl.ecc.point}
  760.    */
  761.   recoverPt: function(y) {
  762.     // a = -1
  763.     // x = sqrt((y^2 - 1) * inv(d * y^2 - a))
  764.     y = new this.field(y);
  765.     yy = y.square();
  766.     return new sjcl.ecc.tEdPoint(this, yy.sub(1).mul(this.d.mul(yy).add(1).inverse()).sqrtMod().fullReduce(), y);
  767.   },
  768.  
  769.   /**
  770.    * Creates a deterministic random point in constant time.
  771.    * Uses elligator
  772.    *
  773.    * @param {bigInt} num A number 0 <= x < sjcl.ecc.tEdCurve.field.modulus.
  774.    * @return {sjcl.ecc.tEdPoint} A deterministic random point.
  775.    */
  776.   deterministicRandomPoint: function (data) {
  777.     var p;
  778.  
  779.     if (!this.canDeterministicRandomPoint()) {
  780.       throw("sjcl.ecc.tEdCurve.deterministicRandomPoint(): Curve can't create a deterministic random point in constant time");
  781.     }
  782.  
  783.     return p;
  784.   },
  785.  
  786.   /**
  787.    * Determines if the curve can use elligator.
  788.    *
  789.    * @return {Bool} True if curve can use elligator.
  790.    */
  791.   canDeterministicRandomPoint: function () {
  792.     return false;
  793.     // return this.order2P !== undefined;
  794.   }
  795. };
  796.  
  797. sjcl.ecc.curves = {
  798.   c192: new sjcl.ecc.curve(
  799.     sjcl.bn.prime.p192,
  800.     "0xffffffffffffffffffffffff99def836146bc9b1b4d22831",
  801.     -3,
  802.     "0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1",
  803.     "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012",
  804.     "0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811",
  805.     "0x2","0x2df5fa08ab474e8f8f2ad5caca8264347d1fb30043214687",
  806.     "0x3","0x64fc66b7c0f932d5564fa514b3ba7858c8ee083f8c728022"),
  807.  
  808.   c224: new sjcl.ecc.curve(
  809.     sjcl.bn.prime.p224,
  810.     "0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d",
  811.     -3,
  812.     "0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4",
  813.     "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21",
  814.     "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34",
  815.     "0x3","0x7cac269c67bd55ea14efff4eadefe5e74978514af14c88fab46ec046",
  816.     "0x5","0x725c51c9ec2d0e1eb2dbc219f8d67054e02eda5b8431629fe0c0ec8b"),
  817.  
  818.   c256: new sjcl.ecc.curve(
  819.     sjcl.bn.prime.p256,
  820.     "0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551",
  821.     -3,
  822.     "0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b",
  823.     "0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296",
  824.     "0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5",
  825.     "0x5","0x459243b9aa581806fe913bce99817ade11ca503c64d9a3c533415c083248fbcc",
  826.     "0x6","0x36b24c2c54250ac2466985e533720047dcd102b80fe7c0e9220d5128828223cb"),
  827.  
  828.   c384: new sjcl.ecc.curve(
  829.     sjcl.bn.prime.p384,
  830.     "0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973",
  831.     -3,
  832.     "0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef",
  833.     "0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7",
  834.     "0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f",
  835.     "0x2","0x732152442fb6ee5c3e6ce1d920c059bc623563814d79042b903ce60f1d4487fccd450a86da03f3e6ed525d02017bfdb3",
  836.     "0x3","0x6660041b1c7984620e8d7fd7ccdb50cc3ba816da14d41a4d8affaba8488867f0ca5a24f8d42dd7e44b530a27dc5b58da"),
  837.  
  838.   c521: new sjcl.ecc.curve(
  839.     sjcl.bn.prime.p521,
  840.     "0x1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409",
  841.     -3,
  842.     "0x051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00",
  843.     "0xC6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66",
  844.     "0x11839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650",
  845.     "0x2","0xd9254fdf800496acb33790b103c5ee9fac12832fe546c632225b0f7fce3da4574b1a879b623d722fa8fc34d5fc2a8731aad691a9a8bb8b554c95a051d6aa505acf",
  846.     "0x4","0x3eae97c9f1965bfeb023757973f48b400405b8b2741c47a8839cb83cfdee4aea8b729ca7a63034b4055e124dfb8bb8058b74b4aee5d42e5741ec130466549d7e27"),
  847.  
  848.   k192: new sjcl.ecc.curve(
  849.     sjcl.bn.prime.p192k,
  850.     "0xfffffffffffffffffffffffe26f2fc170f69466a74defd8d",
  851.     0,
  852.     3,
  853.     "0xdb4ff10ec057e9ae26b07d0280b7f4341da5d1b1eae06c7d",
  854.     "0x9b2f2f6d9c5628a7844163d015be86344082aa88d95e2f9d",
  855.     "0x3","0xc13d09285ad3c2891f1318edf676acb26d65aaecc45fdbf",
  856.     "0x5","0x231585f0375e78018e41d7a0a1c1ab087a0851ebd58dc1f0"),
  857.  
  858.   k224: new sjcl.ecc.curve(
  859.     sjcl.bn.prime.p224k,
  860.     "0x010000000000000000000000000001dce8d2ec6184caf0a971769fb1f7",
  861.     0,
  862.     5,
  863.     "0xa1455b334df099df30fc28a169a467e9e47075a90f7e650eb6b7a45c",
  864.     "0x7e089fed7fba344282cafbd6f7e319f7c0b0bd59e2ca4bdb556d61a5",
  865.     "0x2","0x16c4805dc7abc9a9c59dd8fb4d9d379d3bd4f4a2e9beb766d4d999ab",
  866.     "0x4","0x7f7a7ae1abee58fb26ffec3765dd846b9fec0bd24fdeb8383ff49c9"),
  867.  
  868.   k256: new sjcl.ecc.curve(
  869.     sjcl.bn.prime.p256k,
  870.     "0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141",
  871.     0,
  872.     7,
  873.     "0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798",
  874.     "0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8",
  875.     "0x2","0x66fbe727b2ba09e09f5a98d70a5efce8424c5fa425bbda1c511f860657b8535e",
  876.     "0x3","0x2f233395c8b07a3834a0e59bda43944b5df378852e560ebc0f22877e9f49bb4b"),
  877.  
  878.   ed25519: new sjcl.ecc.tEdCurve(
  879.     sjcl.bn.prime.p25519,
  880.     "0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed",
  881.     "0x52036cee2b6ffe738cc740797779e89800700a4d4141d8ab75eb4dca135978a3",
  882.     "0x216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51a",
  883.     "0x6666666666666666666666666666666666666666666666666666666666666658",
  884.     "0x6fe31a937f53b0714daaa6d39e2975afa4564f8c5508aa235bf5acbd527f9b28","0x1a",
  885.     "0x6b1b681577e2349d5ea02296162c66ef40b529560c69a20cd52c69e793baba86","0x25",
  886.     0,"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec")
  887. };
  888.  
  889. sjcl.ecc.curveName = function (curve) {
  890.   var curcurve;
  891.   for (curcurve in sjcl.ecc.curves) {
  892.     if (sjcl.ecc.curves.hasOwnProperty(curcurve)) {
  893.       if (sjcl.ecc.curves[curcurve] === curve) {
  894.         return curcurve;
  895.       }
  896.     }
  897.   }
  898.  
  899.   throw new sjcl.exception.invalid("no such curve");
  900. };
  901.  
  902. sjcl.ecc.deserialize = function (key) {
  903.   var types = ["elGamal", "ecdsa"];
  904.  
  905.   if (!key || !key.curve || !sjcl.ecc.curves[key.curve]) { throw new sjcl.exception.invalid("invalid serialization"); }
  906.   if (types.indexOf(key.type) === -1) { throw new sjcl.exception.invalid("invalid type"); }
  907.  
  908.   var curve = sjcl.ecc.curves[key.curve];
  909.  
  910.   if (key.secretKey) {
  911.     if (!key.exponent) { throw new sjcl.exception.invalid("invalid exponent"); }
  912.     var exponent = new sjcl.bn(key.exponent);
  913.     return new sjcl.ecc[key.type].secretKey(curve, exponent);
  914.   } else {
  915.     if (!key.point) { throw new sjcl.exception.invalid("invalid point"); }
  916.    
  917.     var point = curve.fromBits(sjcl.codec.hex.toBits(key.point));
  918.     return new sjcl.ecc[key.type].publicKey(curve, point);
  919.   }
  920. };
  921.  
  922. /** our basicKey classes
  923. */
  924. sjcl.ecc.basicKey = {
  925.   /** ecc publicKey.
  926.   * @constructor
  927.   * @param {curve} curve the elliptic curve
  928.   * @param {point} point the point on the curve
  929.   */
  930.   publicKey: function(curve, point) {
  931.     this._curve = curve;
  932.     this._curveBitLength = curve.r.bitLength();
  933.     if (point instanceof Array) {
  934.       this._point = curve.fromBits(point);
  935.     } else {
  936.       this._point = point;
  937.     }
  938.  
  939.     this.serialize = function () {
  940.       var curveName = sjcl.ecc.curveName(curve);
  941.       return {
  942.         type: this.getType(),
  943.         secretKey: false,
  944.         point: sjcl.codec.hex.fromBits(this._point.toBits()),
  945.         curve: curveName
  946.       };
  947.     };
  948.  
  949.     /** get this keys point data
  950.     * @return x and y as bitArrays
  951.     */
  952.     this.get = function() {
  953.       var pointbits = this._point.toBits();
  954.       var len = sjcl.bitArray.bitLength(pointbits);
  955.       var x = sjcl.bitArray.bitSlice(pointbits, 0, len/2);
  956.       var y = sjcl.bitArray.bitSlice(pointbits, len/2);
  957.       return { x: x, y: y };
  958.     };
  959.   },
  960.  
  961.   /** ecc secretKey
  962.   * @constructor
  963.   * @param {curve} curve the elliptic curve
  964.   * @param exponent
  965.   */
  966.   secretKey: function(curve, exponent) {
  967.     this._curve = curve;
  968.     this._curveBitLength = curve.r.bitLength();
  969.     this._exponent = exponent;
  970.  
  971.     this.serialize = function () {
  972.       var exponent = this.get();
  973.       var curveName = sjcl.ecc.curveName(curve);
  974.       return {
  975.         type: this.getType(),
  976.         secretKey: true,
  977.         exponent: sjcl.codec.hex.fromBits(exponent),
  978.         curve: curveName
  979.       };
  980.     };
  981.  
  982.     /** get this keys exponent data
  983.     * @return {bitArray} exponent
  984.     */
  985.     this.get = function () {
  986.       return this._exponent.toBits();
  987.     };
  988.   }
  989. };
  990.  
  991. /** @private */
  992. sjcl.ecc.basicKey.generateKeys = function(cn) {
  993.   return function generateKeys(curve, paranoia, sec) {
  994.     curve = curve || 256;
  995.  
  996.     if (typeof curve === "number") {
  997.       curve = sjcl.ecc.curves['c'+curve];
  998.       if (curve === undefined) {
  999.         throw new sjcl.exception.invalid("no such curve");
  1000.       }
  1001.     }
  1002.     sec = sec || sjcl.bn.random(curve.r, paranoia);
  1003.  
  1004.     var pub = curve.G.mult(sec);
  1005.     return { pub: new sjcl.ecc[cn].publicKey(curve, pub),
  1006.              sec: new sjcl.ecc[cn].secretKey(curve, sec) };
  1007.   };
  1008. };
  1009.  
  1010. /** elGamal keys */
  1011. sjcl.ecc.elGamal = {
  1012.   /** generate keys
  1013.   * @function
  1014.   * @param curve
  1015.   * @param {int} paranoia Paranoia for generation (default 6)
  1016.   * @param {secretKey} sec secret Key to use. used to get the publicKey for ones secretKey
  1017.   */
  1018.   generateKeys: sjcl.ecc.basicKey.generateKeys("elGamal"),
  1019.   /** elGamal publicKey.
  1020.   * @constructor
  1021.   * @augments sjcl.ecc.basicKey.publicKey
  1022.   */
  1023.   publicKey: function (curve, point) {
  1024.     sjcl.ecc.basicKey.publicKey.apply(this, arguments);
  1025.   },
  1026.   /** elGamal secretKey
  1027.   * @constructor
  1028.   * @augments sjcl.ecc.basicKey.secretKey
  1029.   */
  1030.   secretKey: function (curve, exponent) {
  1031.     sjcl.ecc.basicKey.secretKey.apply(this, arguments);
  1032.   }
  1033. };
  1034.  
  1035. sjcl.ecc.elGamal.publicKey.prototype = {
  1036.   /** Kem function of elGamal Public Key
  1037.   * @param paranoia paranoia to use for randomization.
  1038.   * @return {object} key and tag. unkem(tag) with the corresponding secret key results in the key returned.
  1039.   */
  1040.   kem: function(paranoia) {
  1041.     var sec = sjcl.bn.random(this._curve.r, paranoia),
  1042.         tag = this._curve.G.mult(sec).toBits(),
  1043.         key = sjcl.hash.sha256.hash(this._point.mult(sec).toBits());
  1044.     return { key: key, tag: tag };
  1045.   },
  1046.  
  1047.   getType: function() {
  1048.     return "elGamal";
  1049.   }
  1050. };
  1051.  
  1052. sjcl.ecc.elGamal.secretKey.prototype = {
  1053.   /** UnKem function of elGamal Secret Key
  1054.   * @param {bitArray} tag The Tag to decrypt.
  1055.   * @return {bitArray} decrypted key.
  1056.   */
  1057.   unkem: function(tag) {
  1058.     return sjcl.hash.sha256.hash(this._curve.fromBits(tag).mult(this._exponent).toBits());
  1059.   },
  1060.  
  1061.   /** Diffie-Hellmann function
  1062.   * @param {elGamal.publicKey} pk The Public Key to do Diffie-Hellmann with
  1063.   * @return {bitArray} diffie-hellmann result for this key combination.
  1064.   */
  1065.   dh: function(pk) {
  1066.     return sjcl.hash.sha256.hash(pk._point.mult(this._exponent).toBits());
  1067.   },
  1068.  
  1069.   /** Diffie-Hellmann function, compatible with Java generateSecret
  1070.   * @param {elGamal.publicKey} pk The Public Key to do Diffie-Hellmann with
  1071.   * @return {bitArray} undigested X value, diffie-hellmann result for this key combination,
  1072.   * compatible with Java generateSecret().
  1073.   */
  1074.   dhJavaEc: function(pk) {
  1075.     return pk._point.mult(this._exponent).x.toBits();
  1076.   },
  1077.  
  1078.   getType: function() {
  1079.     return "elGamal";
  1080.   }
  1081. };
  1082.  
  1083. /** ecdsa keys */
  1084. sjcl.ecc.ecdsa = {
  1085.   /** generate keys
  1086.   * @function
  1087.   * @param curve
  1088.   * @param {int} paranoia Paranoia for generation (default 6)
  1089.   * @param {secretKey} sec secret Key to use. used to get the publicKey for ones secretKey
  1090.   */
  1091.   generateKeys: sjcl.ecc.basicKey.generateKeys("ecdsa")
  1092. };
  1093.  
  1094. /** ecdsa publicKey.
  1095. * @constructor
  1096. * @augments sjcl.ecc.basicKey.publicKey
  1097. */
  1098. sjcl.ecc.ecdsa.publicKey = function (curve, point) {
  1099.   sjcl.ecc.basicKey.publicKey.apply(this, arguments);
  1100. };
  1101.  
  1102. /** specific functions for ecdsa publicKey. */
  1103. sjcl.ecc.ecdsa.publicKey.prototype = {
  1104.   /** Diffie-Hellmann function
  1105.   * @param {bitArray} hash hash to verify.
  1106.   * @param {bitArray} rs signature bitArray.
  1107.   * @param {boolean}  fakeLegacyVersion use old legacy version
  1108.   */
  1109.   verify: function(hash, rs, fakeLegacyVersion) {
  1110.     if (sjcl.bitArray.bitLength(hash) > this._curveBitLength) {
  1111.       hash = sjcl.bitArray.clamp(hash, this._curveBitLength);
  1112.     }
  1113.     var w = sjcl.bitArray,
  1114.         R = this._curve.r,
  1115.         l = this._curveBitLength,
  1116.         r = sjcl.bn.fromBits(w.bitSlice(rs,0,l)),
  1117.         ss = sjcl.bn.fromBits(w.bitSlice(rs,l,2*l)),
  1118.         s = fakeLegacyVersion ? ss : ss.inverseMod(R),
  1119.         hG = sjcl.bn.fromBits(hash).mul(s).mod(R),
  1120.         hA = r.mul(s).mod(R),
  1121.         r2 = this._curve.G.mult2(hG, hA, this._point).x;
  1122.     if (r.equals(0) || ss.equals(0) || r.greaterEquals(R) || ss.greaterEquals(R) || !r2.equals(r)) {
  1123.       if (fakeLegacyVersion === undefined) {
  1124.         return this.verify(hash, rs, true);
  1125.       } else {
  1126.         throw (new sjcl.exception.corrupt("signature didn't check out"));
  1127.       }
  1128.     }
  1129.     return true;
  1130.   },
  1131.  
  1132.   getType: function() {
  1133.     return "ecdsa";
  1134.   }
  1135. };
  1136.  
  1137. /** ecdsa secretKey
  1138. * @constructor
  1139. * @augments sjcl.ecc.basicKey.publicKey
  1140. */
  1141. sjcl.ecc.ecdsa.secretKey = function (curve, exponent) {
  1142.   sjcl.ecc.basicKey.secretKey.apply(this, arguments);
  1143. };
  1144.  
  1145. /** specific functions for ecdsa secretKey. */
  1146. sjcl.ecc.ecdsa.secretKey.prototype = {
  1147.   /** Diffie-Hellmann function
  1148.   * @param {bitArray} hash hash to sign.
  1149.   * @param {int} paranoia paranoia for random number generation
  1150.   * @param {boolean} fakeLegacyVersion use old legacy version
  1151.   */
  1152.   sign: function(hash, paranoia, fakeLegacyVersion, fixedKForTesting) {
  1153.     if (sjcl.bitArray.bitLength(hash) > this._curveBitLength) {
  1154.       hash = sjcl.bitArray.clamp(hash, this._curveBitLength);
  1155.     }
  1156.     var R  = this._curve.r,
  1157.         l  = R.bitLength(),
  1158.         k  = fixedKForTesting || sjcl.bn.random(R.sub(1), paranoia).add(1),
  1159.         r  = this._curve.G.mult(k).x.mod(R),
  1160.         ss = sjcl.bn.fromBits(hash).add(r.mul(this._exponent)),
  1161.         s  = fakeLegacyVersion ? ss.inverseMod(R).mul(k).mod(R)
  1162.              : ss.mul(k.inverseMod(R)).mod(R);
  1163.     return sjcl.bitArray.concat(r.toBits(l), s.toBits(l));
  1164.   },
  1165.  
  1166.   getType: function() {
  1167.     return "ecdsa";
  1168.   }
  1169. };
  1170.  
  1171. // fully compatible with https://github.com/warner/python-spake2
  1172. sjcl.ecc.curves.ed25519.M = sjcl.ecc.curves.ed25519.fromBits(sjcl.codec.hex.toBits("d6305877e6a4e08cbaff4e57326d5a9575c20a4e304b58b7cd30526edf2f0ea4"));
  1173. sjcl.ecc.curves.ed25519.N = sjcl.ecc.curves.ed25519.fromBits(sjcl.codec.hex.toBits("5b4393b59342dc791867774ceeb92152ac7240044410c0c97334f22302025402"));
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement