Source: ecc.js

  1. /**
  2. * base class for all ecc operations.
  3. * @namespace
  4. */
  5. sjcl.ecc = {};
  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. this.x = x;
  24. this.y = y;
  25. this.isIdentity = false;
  26. }
  27. this.curve = curve;
  28. };
  29. sjcl.ecc.point.prototype = {
  30. toJac: function() {
  31. return new sjcl.ecc.pointJac(this.curve, this.x, this.y, new this.curve.field(1));
  32. },
  33. mult: function(k) {
  34. return this.toJac().mult(k, this).toAffine();
  35. },
  36. /**
  37. * Multiply this point by k, added to affine2*k2, and return the answer in Jacobian coordinates.
  38. * @param {bigInt} k The coefficient to multiply this by.
  39. * @param {bigInt} k2 The coefficient to multiply affine2 this by.
  40. * @param {sjcl.ecc.point} affine The other point in affine coordinates.
  41. * @return {sjcl.ecc.pointJac} The result of the multiplication and addition, in Jacobian coordinates.
  42. */
  43. mult2: function(k, k2, affine2) {
  44. return this.toJac().mult2(k, this, k2, affine2).toAffine();
  45. },
  46. multiples: function() {
  47. var m, i, j;
  48. if (this._multiples === undefined) {
  49. j = this.toJac().doubl();
  50. m = this._multiples = [new sjcl.ecc.point(this.curve), this, j.toAffine()];
  51. for (i=3; i<16; i++) {
  52. j = j.add(this);
  53. m.push(j.toAffine());
  54. }
  55. }
  56. return this._multiples;
  57. },
  58. negate: function() {
  59. var newY = new this.curve.field(0).sub(this.y).normalize().reduce();
  60. return new sjcl.ecc.point(this.curve, this.x, newY);
  61. },
  62. isValid: function() {
  63. return this.y.square().equals(this.curve.b.add(this.x.mul(this.curve.a.add(this.x.square()))));
  64. },
  65. toBits: function() {
  66. return sjcl.bitArray.concat(this.x.toBits(), this.y.toBits());
  67. }
  68. };
  69. /**
  70. * Represents a point on a curve in Jacobian coordinates. Coordinates can be specified as bigInts or strings (which
  71. * will be converted to bigInts).
  72. *
  73. * @constructor
  74. * @param {bigInt/string} x The x coordinate.
  75. * @param {bigInt/string} y The y coordinate.
  76. * @param {bigInt/string} z The z coordinate.
  77. * @param {sjcl.ecc.curve} curve The curve that this point lies on.
  78. */
  79. sjcl.ecc.pointJac = function(curve, x, y, z) {
  80. if (x === undefined) {
  81. this.isIdentity = true;
  82. } else {
  83. this.x = x;
  84. this.y = y;
  85. this.z = z;
  86. this.isIdentity = false;
  87. }
  88. this.curve = curve;
  89. };
  90. sjcl.ecc.pointJac.prototype = {
  91. /**
  92. * 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.
  93. * @param {sjcl.ecc.pointJac} S One of the points to add, in Jacobian coordinates.
  94. * @param {sjcl.ecc.point} T The other point to add, in affine coordinates.
  95. * @return {sjcl.ecc.pointJac} The sum of the two points, in Jacobian coordinates.
  96. */
  97. add: function(T) {
  98. var S = this, sz2, c, d, c2, x1, x2, x, y1, y2, y, z;
  99. if (S.curve !== T.curve) {
  100. throw new sjcl.exception.invalid("sjcl.ecc.add(): Points must be on the same curve to add them!");
  101. }
  102. if (S.isIdentity) {
  103. return T.toJac();
  104. } else if (T.isIdentity) {
  105. return S;
  106. }
  107. sz2 = S.z.square();
  108. c = T.x.mul(sz2).subM(S.x);
  109. if (c.equals(0)) {
  110. if (S.y.equals(T.y.mul(sz2.mul(S.z)))) {
  111. // same point
  112. return S.doubl();
  113. } else {
  114. // inverses
  115. return new sjcl.ecc.pointJac(S.curve);
  116. }
  117. }
  118. d = T.y.mul(sz2.mul(S.z)).subM(S.y);
  119. c2 = c.square();
  120. x1 = d.square();
  121. x2 = c.square().mul(c).addM( S.x.add(S.x).mul(c2) );
  122. x = x1.subM(x2);
  123. y1 = S.x.mul(c2).subM(x).mul(d);
  124. y2 = S.y.mul(c.square().mul(c));
  125. y = y1.subM(y2);
  126. z = S.z.mul(c);
  127. return new sjcl.ecc.pointJac(this.curve,x,y,z);
  128. },
  129. /**
  130. * doubles this point.
  131. * @return {sjcl.ecc.pointJac} The doubled point.
  132. */
  133. doubl: function() {
  134. if (this.isIdentity) { return this; }
  135. var
  136. y2 = this.y.square(),
  137. a = y2.mul(this.x.mul(4)),
  138. b = y2.square().mul(8),
  139. z2 = this.z.square(),
  140. c = this.curve.a.toString() == (new sjcl.bn(-3)).toString() ?
  141. this.x.sub(z2).mul(3).mul(this.x.add(z2)) :
  142. this.x.square().mul(3).add(z2.square().mul(this.curve.a)),
  143. x = c.square().subM(a).subM(a),
  144. y = a.sub(x).mul(c).subM(b),
  145. z = this.y.add(this.y).mul(this.z);
  146. return new sjcl.ecc.pointJac(this.curve, x, y, z);
  147. },
  148. /**
  149. * Returns a copy of this point converted to affine coordinates.
  150. * @return {sjcl.ecc.point} The converted point.
  151. */
  152. toAffine: function() {
  153. if (this.isIdentity || this.z.equals(0)) {
  154. return new sjcl.ecc.point(this.curve);
  155. }
  156. var zi = this.z.inverse(), zi2 = zi.square();
  157. return new sjcl.ecc.point(this.curve, this.x.mul(zi2).fullReduce(), this.y.mul(zi2.mul(zi)).fullReduce());
  158. },
  159. /**
  160. * Multiply this point by k and return the answer in Jacobian coordinates.
  161. * @param {bigInt} k The coefficient to multiply by.
  162. * @param {sjcl.ecc.point} affine This point in affine coordinates.
  163. * @return {sjcl.ecc.pointJac} The result of the multiplication, in Jacobian coordinates.
  164. */
  165. mult: function(k, affine) {
  166. if (typeof(k) === "number") {
  167. k = [k];
  168. } else if (k.limbs !== undefined) {
  169. k = k.normalize().limbs;
  170. }
  171. var i, j, out = new sjcl.ecc.point(this.curve).toJac(), multiples = affine.multiples();
  172. for (i=k.length-1; i>=0; i--) {
  173. for (j=sjcl.bn.prototype.radix-4; j>=0; j-=4) {
  174. out = out.doubl().doubl().doubl().doubl().add(multiples[k[i]>>j & 0xF]);
  175. }
  176. }
  177. return out;
  178. },
  179. /**
  180. * Multiply this point by k, added to affine2*k2, and return the answer in Jacobian coordinates.
  181. * @param {bigInt} k The coefficient to multiply this by.
  182. * @param {sjcl.ecc.point} affine This point in affine coordinates.
  183. * @param {bigInt} k2 The coefficient to multiply affine2 this by.
  184. * @param {sjcl.ecc.point} affine The other point in affine coordinates.
  185. * @return {sjcl.ecc.pointJac} The result of the multiplication and addition, in Jacobian coordinates.
  186. */
  187. mult2: function(k1, affine, k2, affine2) {
  188. if (typeof(k1) === "number") {
  189. k1 = [k1];
  190. } else if (k1.limbs !== undefined) {
  191. k1 = k1.normalize().limbs;
  192. }
  193. if (typeof(k2) === "number") {
  194. k2 = [k2];
  195. } else if (k2.limbs !== undefined) {
  196. k2 = k2.normalize().limbs;
  197. }
  198. var i, j, out = new sjcl.ecc.point(this.curve).toJac(), m1 = affine.multiples(),
  199. m2 = affine2.multiples(), l1, l2;
  200. for (i=Math.max(k1.length,k2.length)-1; i>=0; i--) {
  201. l1 = k1[i] | 0;
  202. l2 = k2[i] | 0;
  203. for (j=sjcl.bn.prototype.radix-4; j>=0; j-=4) {
  204. out = out.doubl().doubl().doubl().doubl().add(m1[l1>>j & 0xF]).add(m2[l2>>j & 0xF]);
  205. }
  206. }
  207. return out;
  208. },
  209. negate: function() {
  210. return this.toAffine().negate().toJac();
  211. },
  212. isValid: function() {
  213. var z2 = this.z.square(), z4 = z2.square(), z6 = z4.mul(z2);
  214. return this.y.square().equals(
  215. this.curve.b.mul(z6).add(this.x.mul(
  216. this.curve.a.mul(z4).add(this.x.square()))));
  217. }
  218. };
  219. /**
  220. * Construct an elliptic curve. Most users will not use this and instead start with one of the NIST curves defined below.
  221. *
  222. * @constructor
  223. * @param {bigInt} p The prime modulus.
  224. * @param {bigInt} r The prime order of the curve.
  225. * @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).
  226. * @param {bigInt} x The x coordinate of a base point of the curve.
  227. * @param {bigInt} y The y coordinate of a base point of the curve.
  228. */
  229. sjcl.ecc.curve = function(Field, r, a, b, x, y) {
  230. this.field = Field;
  231. this.r = new sjcl.bn(r);
  232. this.a = new Field(a);
  233. this.b = new Field(b);
  234. this.G = new sjcl.ecc.point(this, new Field(x), new Field(y));
  235. };
  236. sjcl.ecc.curve.prototype.fromBits = function (bits) {
  237. var w = sjcl.bitArray, l = this.field.prototype.exponent + 7 & -8,
  238. p = new sjcl.ecc.point(this, this.field.fromBits(w.bitSlice(bits, 0, l)),
  239. this.field.fromBits(w.bitSlice(bits, l, 2*l)));
  240. if (!p.isValid()) {
  241. throw new sjcl.exception.corrupt("not on the curve!");
  242. }
  243. return p;
  244. };
  245. sjcl.ecc.curves = {
  246. c192: new sjcl.ecc.curve(
  247. sjcl.bn.prime.p192,
  248. "0xffffffffffffffffffffffff99def836146bc9b1b4d22831",
  249. -3,
  250. "0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1",
  251. "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012",
  252. "0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"),
  253. c224: new sjcl.ecc.curve(
  254. sjcl.bn.prime.p224,
  255. "0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d",
  256. -3,
  257. "0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4",
  258. "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21",
  259. "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34"),
  260. c256: new sjcl.ecc.curve(
  261. sjcl.bn.prime.p256,
  262. "0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551",
  263. -3,
  264. "0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b",
  265. "0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296",
  266. "0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5"),
  267. c384: new sjcl.ecc.curve(
  268. sjcl.bn.prime.p384,
  269. "0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973",
  270. -3,
  271. "0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef",
  272. "0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7",
  273. "0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f"),
  274. c521: new sjcl.ecc.curve(
  275. sjcl.bn.prime.p521,
  276. "0x1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409",
  277. -3,
  278. "0x051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00",
  279. "0xC6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66",
  280. "0x11839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650"),
  281. k192: new sjcl.ecc.curve(
  282. sjcl.bn.prime.p192k,
  283. "0xfffffffffffffffffffffffe26f2fc170f69466a74defd8d",
  284. 0,
  285. 3,
  286. "0xdb4ff10ec057e9ae26b07d0280b7f4341da5d1b1eae06c7d",
  287. "0x9b2f2f6d9c5628a7844163d015be86344082aa88d95e2f9d"),
  288. k224: new sjcl.ecc.curve(
  289. sjcl.bn.prime.p224k,
  290. "0x010000000000000000000000000001dce8d2ec6184caf0a971769fb1f7",
  291. 0,
  292. 5,
  293. "0xa1455b334df099df30fc28a169a467e9e47075a90f7e650eb6b7a45c",
  294. "0x7e089fed7fba344282cafbd6f7e319f7c0b0bd59e2ca4bdb556d61a5"),
  295. k256: new sjcl.ecc.curve(
  296. sjcl.bn.prime.p256k,
  297. "0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141",
  298. 0,
  299. 7,
  300. "0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798",
  301. "0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8")
  302. };
  303. sjcl.ecc.curveName = function (curve) {
  304. var curcurve;
  305. for (curcurve in sjcl.ecc.curves) {
  306. if (sjcl.ecc.curves.hasOwnProperty(curcurve)) {
  307. if (sjcl.ecc.curves[curcurve] === curve) {
  308. return curcurve;
  309. }
  310. }
  311. }
  312. throw new sjcl.exception.invalid("no such curve");
  313. };
  314. sjcl.ecc.deserialize = function (key) {
  315. var types = ["elGamal", "ecdsa"];
  316. if (!key || !key.curve || !sjcl.ecc.curves[key.curve]) { throw new sjcl.exception.invalid("invalid serialization"); }
  317. if (types.indexOf(key.type) === -1) { throw new sjcl.exception.invalid("invalid type"); }
  318. var curve = sjcl.ecc.curves[key.curve];
  319. if (key.secretKey) {
  320. if (!key.exponent) { throw new sjcl.exception.invalid("invalid exponent"); }
  321. var exponent = new sjcl.bn(key.exponent);
  322. return new sjcl.ecc[key.type].secretKey(curve, exponent);
  323. } else {
  324. if (!key.point) { throw new sjcl.exception.invalid("invalid point"); }
  325. var point = curve.fromBits(sjcl.codec.hex.toBits(key.point));
  326. return new sjcl.ecc[key.type].publicKey(curve, point);
  327. }
  328. };
  329. /** our basicKey classes
  330. */
  331. sjcl.ecc.basicKey = {
  332. /** ecc publicKey.
  333. * @constructor
  334. * @param {curve} curve the elliptic curve
  335. * @param {point} point the point on the curve
  336. */
  337. publicKey: function(curve, point) {
  338. this._curve = curve;
  339. this._curveBitLength = curve.r.bitLength();
  340. if (point instanceof Array) {
  341. this._point = curve.fromBits(point);
  342. } else {
  343. this._point = point;
  344. }
  345. this.serialize = function () {
  346. var curveName = sjcl.ecc.curveName(curve);
  347. return {
  348. type: this.getType(),
  349. secretKey: false,
  350. point: sjcl.codec.hex.fromBits(this._point.toBits()),
  351. curve: curveName
  352. };
  353. };
  354. /** get this keys point data
  355. * @return x and y as bitArrays
  356. */
  357. this.get = function() {
  358. var pointbits = this._point.toBits();
  359. var len = sjcl.bitArray.bitLength(pointbits);
  360. var x = sjcl.bitArray.bitSlice(pointbits, 0, len/2);
  361. var y = sjcl.bitArray.bitSlice(pointbits, len/2);
  362. return { x: x, y: y };
  363. };
  364. },
  365. /** ecc secretKey
  366. * @constructor
  367. * @param {curve} curve the elliptic curve
  368. * @param exponent
  369. */
  370. secretKey: function(curve, exponent) {
  371. this._curve = curve;
  372. this._curveBitLength = curve.r.bitLength();
  373. this._exponent = exponent;
  374. this.serialize = function () {
  375. var exponent = this.get();
  376. var curveName = sjcl.ecc.curveName(curve);
  377. return {
  378. type: this.getType(),
  379. secretKey: true,
  380. exponent: sjcl.codec.hex.fromBits(exponent),
  381. curve: curveName
  382. };
  383. };
  384. /** get this keys exponent data
  385. * @return {bitArray} exponent
  386. */
  387. this.get = function () {
  388. return this._exponent.toBits();
  389. };
  390. }
  391. };
  392. /** @private */
  393. sjcl.ecc.basicKey.generateKeys = function(cn) {
  394. return function generateKeys(curve, paranoia, sec) {
  395. curve = curve || 256;
  396. if (typeof curve === "number") {
  397. curve = sjcl.ecc.curves['c'+curve];
  398. if (curve === undefined) {
  399. throw new sjcl.exception.invalid("no such curve");
  400. }
  401. }
  402. sec = sec || sjcl.bn.random(curve.r, paranoia);
  403. var pub = curve.G.mult(sec);
  404. return { pub: new sjcl.ecc[cn].publicKey(curve, pub),
  405. sec: new sjcl.ecc[cn].secretKey(curve, sec) };
  406. };
  407. };
  408. /** elGamal keys */
  409. sjcl.ecc.elGamal = {
  410. /** generate keys
  411. * @function
  412. * @param curve
  413. * @param {int} paranoia Paranoia for generation (default 6)
  414. * @param {secretKey} sec secret Key to use. used to get the publicKey for ones secretKey
  415. */
  416. generateKeys: sjcl.ecc.basicKey.generateKeys("elGamal"),
  417. /** elGamal publicKey.
  418. * @constructor
  419. * @augments sjcl.ecc.basicKey.publicKey
  420. */
  421. publicKey: function (curve, point) {
  422. sjcl.ecc.basicKey.publicKey.apply(this, arguments);
  423. },
  424. /** elGamal secretKey
  425. * @constructor
  426. * @augments sjcl.ecc.basicKey.secretKey
  427. */
  428. secretKey: function (curve, exponent) {
  429. sjcl.ecc.basicKey.secretKey.apply(this, arguments);
  430. }
  431. };
  432. sjcl.ecc.elGamal.publicKey.prototype = {
  433. /** Kem function of elGamal Public Key
  434. * @param paranoia paranoia to use for randomization.
  435. * @return {object} key and tag. unkem(tag) with the corresponding secret key results in the key returned.
  436. */
  437. kem: function(paranoia) {
  438. var sec = sjcl.bn.random(this._curve.r, paranoia),
  439. tag = this._curve.G.mult(sec).toBits(),
  440. key = sjcl.hash.sha256.hash(this._point.mult(sec).toBits());
  441. return { key: key, tag: tag };
  442. },
  443. getType: function() {
  444. return "elGamal";
  445. }
  446. };
  447. sjcl.ecc.elGamal.secretKey.prototype = {
  448. /** UnKem function of elGamal Secret Key
  449. * @param {bitArray} tag The Tag to decrypt.
  450. * @return {bitArray} decrypted key.
  451. */
  452. unkem: function(tag) {
  453. return sjcl.hash.sha256.hash(this._curve.fromBits(tag).mult(this._exponent).toBits());
  454. },
  455. /** Diffie-Hellmann function
  456. * @param {elGamal.publicKey} pk The Public Key to do Diffie-Hellmann with
  457. * @return {bitArray} diffie-hellmann result for this key combination.
  458. */
  459. dh: function(pk) {
  460. return sjcl.hash.sha256.hash(pk._point.mult(this._exponent).toBits());
  461. },
  462. /** Diffie-Hellmann function, compatible with Java generateSecret
  463. * @param {elGamal.publicKey} pk The Public Key to do Diffie-Hellmann with
  464. * @return {bitArray} undigested X value, diffie-hellmann result for this key combination,
  465. * compatible with Java generateSecret().
  466. */
  467. dhJavaEc: function(pk) {
  468. return pk._point.mult(this._exponent).x.toBits();
  469. },
  470. getType: function() {
  471. return "elGamal";
  472. }
  473. };
  474. /** ecdsa keys */
  475. sjcl.ecc.ecdsa = {
  476. /** generate keys
  477. * @function
  478. * @param curve
  479. * @param {int} paranoia Paranoia for generation (default 6)
  480. * @param {secretKey} sec secret Key to use. used to get the publicKey for ones secretKey
  481. */
  482. generateKeys: sjcl.ecc.basicKey.generateKeys("ecdsa")
  483. };
  484. /** ecdsa publicKey.
  485. * @constructor
  486. * @augments sjcl.ecc.basicKey.publicKey
  487. */
  488. sjcl.ecc.ecdsa.publicKey = function (curve, point) {
  489. sjcl.ecc.basicKey.publicKey.apply(this, arguments);
  490. };
  491. /** specific functions for ecdsa publicKey. */
  492. sjcl.ecc.ecdsa.publicKey.prototype = {
  493. /** Diffie-Hellmann function
  494. * @param {bitArray} hash hash to verify.
  495. * @param {bitArray} rs signature bitArray.
  496. * @param {boolean} fakeLegacyVersion use old legacy version
  497. */
  498. verify: function(hash, rs, fakeLegacyVersion) {
  499. if (sjcl.bitArray.bitLength(hash) > this._curveBitLength) {
  500. hash = sjcl.bitArray.clamp(hash, this._curveBitLength);
  501. }
  502. var w = sjcl.bitArray,
  503. R = this._curve.r,
  504. l = this._curveBitLength,
  505. r = sjcl.bn.fromBits(w.bitSlice(rs,0,l)),
  506. ss = sjcl.bn.fromBits(w.bitSlice(rs,l,2*l)),
  507. s = fakeLegacyVersion ? ss : ss.inverseMod(R),
  508. hG = sjcl.bn.fromBits(hash).mul(s).mod(R),
  509. hA = r.mul(s).mod(R),
  510. r2 = this._curve.G.mult2(hG, hA, this._point).x;
  511. if (r.equals(0) || ss.equals(0) || r.greaterEquals(R) || ss.greaterEquals(R) || !r2.equals(r)) {
  512. if (fakeLegacyVersion === undefined) {
  513. return this.verify(hash, rs, true);
  514. } else {
  515. throw (new sjcl.exception.corrupt("signature didn't check out"));
  516. }
  517. }
  518. return true;
  519. },
  520. getType: function() {
  521. return "ecdsa";
  522. }
  523. };
  524. /** ecdsa secretKey
  525. * @constructor
  526. * @augments sjcl.ecc.basicKey.publicKey
  527. */
  528. sjcl.ecc.ecdsa.secretKey = function (curve, exponent) {
  529. sjcl.ecc.basicKey.secretKey.apply(this, arguments);
  530. };
  531. /** specific functions for ecdsa secretKey. */
  532. sjcl.ecc.ecdsa.secretKey.prototype = {
  533. /** Diffie-Hellmann function
  534. * @param {bitArray} hash hash to sign.
  535. * @param {int} paranoia paranoia for random number generation
  536. * @param {boolean} fakeLegacyVersion use old legacy version
  537. */
  538. sign: function(hash, paranoia, fakeLegacyVersion, fixedKForTesting) {
  539. if (sjcl.bitArray.bitLength(hash) > this._curveBitLength) {
  540. hash = sjcl.bitArray.clamp(hash, this._curveBitLength);
  541. }
  542. var R = this._curve.r,
  543. l = R.bitLength(),
  544. k = fixedKForTesting || sjcl.bn.random(R.sub(1), paranoia).add(1),
  545. r = this._curve.G.mult(k).x.mod(R),
  546. ss = sjcl.bn.fromBits(hash).add(r.mul(this._exponent)),
  547. s = fakeLegacyVersion ? ss.inverseMod(R).mul(k).mod(R)
  548. : ss.mul(k.inverseMod(R)).mod(R);
  549. return sjcl.bitArray.concat(r.toBits(l), s.toBits(l));
  550. },
  551. getType: function() {
  552. return "ecdsa";
  553. }
  554. };