Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ultraviolet
GitHub Repository: ultraviolet/bitaddress.org
Path: blob/master/src/ellipticcurve.js
248 views
1
//https://raw.github.com/bitcoinjs/bitcoinjs-lib/faa10f0f6a1fff0b9a99fffb9bc30cee33b17212/src/ecdsa.js
2
/*!
3
* Basic Javascript Elliptic Curve implementation
4
* Ported loosely from BouncyCastle's Java EC code
5
* Only Fp curves implemented for now
6
*
7
* Copyright Tom Wu, bitaddress.org BSD License.
8
* http://www-cs-students.stanford.edu/~tjw/jsbn/LICENSE
9
*/
10
(function () {
11
12
// Constructor function of Global EllipticCurve object
13
var ec = window.EllipticCurve = function () { };
14
15
16
// ----------------
17
// ECFieldElementFp constructor
18
// q instanceof BigInteger
19
// x instanceof BigInteger
20
ec.FieldElementFp = function (q, x) {
21
this.x = x;
22
// TODO if(x.compareTo(q) >= 0) error
23
this.q = q;
24
};
25
26
ec.FieldElementFp.prototype.equals = function (other) {
27
if (other == this) return true;
28
return (this.q.equals(other.q) && this.x.equals(other.x));
29
};
30
31
ec.FieldElementFp.prototype.toBigInteger = function () {
32
return this.x;
33
};
34
35
ec.FieldElementFp.prototype.negate = function () {
36
return new ec.FieldElementFp(this.q, this.x.negate().mod(this.q));
37
};
38
39
ec.FieldElementFp.prototype.add = function (b) {
40
return new ec.FieldElementFp(this.q, this.x.add(b.toBigInteger()).mod(this.q));
41
};
42
43
ec.FieldElementFp.prototype.subtract = function (b) {
44
return new ec.FieldElementFp(this.q, this.x.subtract(b.toBigInteger()).mod(this.q));
45
};
46
47
ec.FieldElementFp.prototype.multiply = function (b) {
48
return new ec.FieldElementFp(this.q, this.x.multiply(b.toBigInteger()).mod(this.q));
49
};
50
51
ec.FieldElementFp.prototype.square = function () {
52
return new ec.FieldElementFp(this.q, this.x.square().mod(this.q));
53
};
54
55
ec.FieldElementFp.prototype.divide = function (b) {
56
return new ec.FieldElementFp(this.q, this.x.multiply(b.toBigInteger().modInverse(this.q)).mod(this.q));
57
};
58
59
ec.FieldElementFp.prototype.getByteLength = function () {
60
return Math.floor((this.toBigInteger().bitLength() + 7) / 8);
61
};
62
63
// D.1.4 91
64
/**
65
* return a sqrt root - the routine verifies that the calculation
66
* returns the right value - if none exists it returns null.
67
*
68
* Copyright (c) 2000 - 2011 The Legion Of The Bouncy Castle (http://www.bouncycastle.org)
69
* Ported to JavaScript by bitaddress.org
70
*/
71
ec.FieldElementFp.prototype.sqrt = function () {
72
if (!this.q.testBit(0)) throw new Error("even value of q");
73
74
// p mod 4 == 3
75
if (this.q.testBit(1)) {
76
// z = g^(u+1) + p, p = 4u + 3
77
var z = new ec.FieldElementFp(this.q, this.x.modPow(this.q.shiftRight(2).add(BigInteger.ONE), this.q));
78
return z.square().equals(this) ? z : null;
79
}
80
81
// p mod 4 == 1
82
var qMinusOne = this.q.subtract(BigInteger.ONE);
83
var legendreExponent = qMinusOne.shiftRight(1);
84
if (!(this.x.modPow(legendreExponent, this.q).equals(BigInteger.ONE))) return null;
85
var u = qMinusOne.shiftRight(2);
86
var k = u.shiftLeft(1).add(BigInteger.ONE);
87
var Q = this.x;
88
var fourQ = Q.shiftLeft(2).mod(this.q);
89
var U, V;
90
91
do {
92
var rand = new SecureRandom();
93
var P;
94
do {
95
P = new BigInteger(this.q.bitLength(), rand);
96
}
97
while (P.compareTo(this.q) >= 0 || !(P.multiply(P).subtract(fourQ).modPow(legendreExponent, this.q).equals(qMinusOne)));
98
99
var result = ec.FieldElementFp.fastLucasSequence(this.q, P, Q, k);
100
101
U = result[0];
102
V = result[1];
103
if (V.multiply(V).mod(this.q).equals(fourQ)) {
104
// Integer division by 2, mod q
105
if (V.testBit(0)) {
106
V = V.add(this.q);
107
}
108
V = V.shiftRight(1);
109
return new ec.FieldElementFp(this.q, V);
110
}
111
}
112
while (U.equals(BigInteger.ONE) || U.equals(qMinusOne));
113
114
return null;
115
};
116
117
/*
118
* Copyright (c) 2000 - 2011 The Legion Of The Bouncy Castle (http://www.bouncycastle.org)
119
* Ported to JavaScript by bitaddress.org
120
*/
121
ec.FieldElementFp.fastLucasSequence = function (p, P, Q, k) {
122
// TODO Research and apply "common-multiplicand multiplication here"
123
124
var n = k.bitLength();
125
var s = k.getLowestSetBit();
126
var Uh = BigInteger.ONE;
127
var Vl = BigInteger.TWO;
128
var Vh = P;
129
var Ql = BigInteger.ONE;
130
var Qh = BigInteger.ONE;
131
132
for (var j = n - 1; j >= s + 1; --j) {
133
Ql = Ql.multiply(Qh).mod(p);
134
if (k.testBit(j)) {
135
Qh = Ql.multiply(Q).mod(p);
136
Uh = Uh.multiply(Vh).mod(p);
137
Vl = Vh.multiply(Vl).subtract(P.multiply(Ql)).mod(p);
138
Vh = Vh.multiply(Vh).subtract(Qh.shiftLeft(1)).mod(p);
139
}
140
else {
141
Qh = Ql;
142
Uh = Uh.multiply(Vl).subtract(Ql).mod(p);
143
Vh = Vh.multiply(Vl).subtract(P.multiply(Ql)).mod(p);
144
Vl = Vl.multiply(Vl).subtract(Ql.shiftLeft(1)).mod(p);
145
}
146
}
147
148
Ql = Ql.multiply(Qh).mod(p);
149
Qh = Ql.multiply(Q).mod(p);
150
Uh = Uh.multiply(Vl).subtract(Ql).mod(p);
151
Vl = Vh.multiply(Vl).subtract(P.multiply(Ql)).mod(p);
152
Ql = Ql.multiply(Qh).mod(p);
153
154
for (var j = 1; j <= s; ++j) {
155
Uh = Uh.multiply(Vl).mod(p);
156
Vl = Vl.multiply(Vl).subtract(Ql.shiftLeft(1)).mod(p);
157
Ql = Ql.multiply(Ql).mod(p);
158
}
159
160
return [Uh, Vl];
161
};
162
163
// ----------------
164
// ECPointFp constructor
165
ec.PointFp = function (curve, x, y, z, compressed) {
166
this.curve = curve;
167
this.x = x;
168
this.y = y;
169
// Projective coordinates: either zinv == null or z * zinv == 1
170
// z and zinv are just BigIntegers, not fieldElements
171
if (z == null) {
172
this.z = BigInteger.ONE;
173
}
174
else {
175
this.z = z;
176
}
177
this.zinv = null;
178
// compression flag
179
this.compressed = !!compressed;
180
};
181
182
ec.PointFp.prototype.getX = function () {
183
if (this.zinv == null) {
184
this.zinv = this.z.modInverse(this.curve.q);
185
}
186
var r = this.x.toBigInteger().multiply(this.zinv);
187
this.curve.reduce(r);
188
return this.curve.fromBigInteger(r);
189
};
190
191
ec.PointFp.prototype.getY = function () {
192
if (this.zinv == null) {
193
this.zinv = this.z.modInverse(this.curve.q);
194
}
195
var r = this.y.toBigInteger().multiply(this.zinv);
196
this.curve.reduce(r);
197
return this.curve.fromBigInteger(r);
198
};
199
200
ec.PointFp.prototype.equals = function (other) {
201
if (other == this) return true;
202
if (this.isInfinity()) return other.isInfinity();
203
if (other.isInfinity()) return this.isInfinity();
204
var u, v;
205
// u = Y2 * Z1 - Y1 * Z2
206
u = other.y.toBigInteger().multiply(this.z).subtract(this.y.toBigInteger().multiply(other.z)).mod(this.curve.q);
207
if (!u.equals(BigInteger.ZERO)) return false;
208
// v = X2 * Z1 - X1 * Z2
209
v = other.x.toBigInteger().multiply(this.z).subtract(this.x.toBigInteger().multiply(other.z)).mod(this.curve.q);
210
return v.equals(BigInteger.ZERO);
211
};
212
213
ec.PointFp.prototype.isInfinity = function () {
214
if ((this.x == null) && (this.y == null)) return true;
215
return this.z.equals(BigInteger.ZERO) && !this.y.toBigInteger().equals(BigInteger.ZERO);
216
};
217
218
ec.PointFp.prototype.negate = function () {
219
return new ec.PointFp(this.curve, this.x, this.y.negate(), this.z);
220
};
221
222
ec.PointFp.prototype.add = function (b) {
223
if (this.isInfinity()) return b;
224
if (b.isInfinity()) return this;
225
226
// u = Y2 * Z1 - Y1 * Z2
227
var u = b.y.toBigInteger().multiply(this.z).subtract(this.y.toBigInteger().multiply(b.z)).mod(this.curve.q);
228
// v = X2 * Z1 - X1 * Z2
229
var v = b.x.toBigInteger().multiply(this.z).subtract(this.x.toBigInteger().multiply(b.z)).mod(this.curve.q);
230
231
232
if (BigInteger.ZERO.equals(v)) {
233
if (BigInteger.ZERO.equals(u)) {
234
return this.twice(); // this == b, so double
235
}
236
return this.curve.getInfinity(); // this = -b, so infinity
237
}
238
239
var THREE = new BigInteger("3");
240
var x1 = this.x.toBigInteger();
241
var y1 = this.y.toBigInteger();
242
var x2 = b.x.toBigInteger();
243
var y2 = b.y.toBigInteger();
244
245
var v2 = v.square();
246
var v3 = v2.multiply(v);
247
var x1v2 = x1.multiply(v2);
248
var zu2 = u.square().multiply(this.z);
249
250
// x3 = v * (z2 * (z1 * u^2 - 2 * x1 * v^2) - v^3)
251
var x3 = zu2.subtract(x1v2.shiftLeft(1)).multiply(b.z).subtract(v3).multiply(v).mod(this.curve.q);
252
// y3 = z2 * (3 * x1 * u * v^2 - y1 * v^3 - z1 * u^3) + u * v^3
253
var y3 = x1v2.multiply(THREE).multiply(u).subtract(y1.multiply(v3)).subtract(zu2.multiply(u)).multiply(b.z).add(u.multiply(v3)).mod(this.curve.q);
254
// z3 = v^3 * z1 * z2
255
var z3 = v3.multiply(this.z).multiply(b.z).mod(this.curve.q);
256
257
return new ec.PointFp(this.curve, this.curve.fromBigInteger(x3), this.curve.fromBigInteger(y3), z3);
258
};
259
260
ec.PointFp.prototype.twice = function () {
261
if (this.isInfinity()) return this;
262
if (this.y.toBigInteger().signum() == 0) return this.curve.getInfinity();
263
264
// TODO: optimized handling of constants
265
var THREE = new BigInteger("3");
266
var x1 = this.x.toBigInteger();
267
var y1 = this.y.toBigInteger();
268
269
var y1z1 = y1.multiply(this.z);
270
var y1sqz1 = y1z1.multiply(y1).mod(this.curve.q);
271
var a = this.curve.a.toBigInteger();
272
273
// w = 3 * x1^2 + a * z1^2
274
var w = x1.square().multiply(THREE);
275
if (!BigInteger.ZERO.equals(a)) {
276
w = w.add(this.z.square().multiply(a));
277
}
278
w = w.mod(this.curve.q);
279
//this.curve.reduce(w);
280
// x3 = 2 * y1 * z1 * (w^2 - 8 * x1 * y1^2 * z1)
281
var x3 = w.square().subtract(x1.shiftLeft(3).multiply(y1sqz1)).shiftLeft(1).multiply(y1z1).mod(this.curve.q);
282
// y3 = 4 * y1^2 * z1 * (3 * w * x1 - 2 * y1^2 * z1) - w^3
283
var y3 = w.multiply(THREE).multiply(x1).subtract(y1sqz1.shiftLeft(1)).shiftLeft(2).multiply(y1sqz1).subtract(w.square().multiply(w)).mod(this.curve.q);
284
// z3 = 8 * (y1 * z1)^3
285
var z3 = y1z1.square().multiply(y1z1).shiftLeft(3).mod(this.curve.q);
286
287
return new ec.PointFp(this.curve, this.curve.fromBigInteger(x3), this.curve.fromBigInteger(y3), z3);
288
};
289
290
// Simple NAF (Non-Adjacent Form) multiplication algorithm
291
// TODO: modularize the multiplication algorithm
292
ec.PointFp.prototype.multiply = function (k) {
293
if (this.isInfinity()) return this;
294
if (k.signum() == 0) return this.curve.getInfinity();
295
296
var e = k;
297
var h = e.multiply(new BigInteger("3"));
298
299
var neg = this.negate();
300
var R = this;
301
302
var i;
303
for (i = h.bitLength() - 2; i > 0; --i) {
304
R = R.twice();
305
306
var hBit = h.testBit(i);
307
var eBit = e.testBit(i);
308
309
if (hBit != eBit) {
310
R = R.add(hBit ? this : neg);
311
}
312
}
313
314
return R;
315
};
316
317
// Compute this*j + x*k (simultaneous multiplication)
318
ec.PointFp.prototype.multiplyTwo = function (j, x, k) {
319
var i;
320
if (j.bitLength() > k.bitLength())
321
i = j.bitLength() - 1;
322
else
323
i = k.bitLength() - 1;
324
325
var R = this.curve.getInfinity();
326
var both = this.add(x);
327
while (i >= 0) {
328
R = R.twice();
329
if (j.testBit(i)) {
330
if (k.testBit(i)) {
331
R = R.add(both);
332
}
333
else {
334
R = R.add(this);
335
}
336
}
337
else {
338
if (k.testBit(i)) {
339
R = R.add(x);
340
}
341
}
342
--i;
343
}
344
345
return R;
346
};
347
348
// patched by bitaddress.org and Casascius for use with Bitcoin.ECKey
349
// patched by coretechs to support compressed public keys
350
ec.PointFp.prototype.getEncoded = function (compressed) {
351
var x = this.getX().toBigInteger();
352
var y = this.getY().toBigInteger();
353
var len = 32; // integerToBytes will zero pad if integer is less than 32 bytes. 32 bytes length is required by the Bitcoin protocol.
354
var enc = ec.integerToBytes(x, len);
355
356
// when compressed prepend byte depending if y point is even or odd
357
if (compressed) {
358
if (y.isEven()) {
359
enc.unshift(0x02);
360
}
361
else {
362
enc.unshift(0x03);
363
}
364
}
365
else {
366
enc.unshift(0x04);
367
enc = enc.concat(ec.integerToBytes(y, len)); // uncompressed public key appends the bytes of the y point
368
}
369
return enc;
370
};
371
372
ec.PointFp.decodeFrom = function (curve, enc) {
373
var type = enc[0];
374
var dataLen = enc.length - 1;
375
376
// Extract x and y as byte arrays
377
var xBa = enc.slice(1, 1 + dataLen / 2);
378
var yBa = enc.slice(1 + dataLen / 2, 1 + dataLen);
379
380
// Prepend zero byte to prevent interpretation as negative integer
381
xBa.unshift(0);
382
yBa.unshift(0);
383
384
// Convert to BigIntegers
385
var x = new BigInteger(xBa);
386
var y = new BigInteger(yBa);
387
388
// Return point
389
return new ec.PointFp(curve, curve.fromBigInteger(x), curve.fromBigInteger(y));
390
};
391
392
ec.PointFp.prototype.add2D = function (b) {
393
if (this.isInfinity()) return b;
394
if (b.isInfinity()) return this;
395
396
if (this.x.equals(b.x)) {
397
if (this.y.equals(b.y)) {
398
// this = b, i.e. this must be doubled
399
return this.twice();
400
}
401
// this = -b, i.e. the result is the point at infinity
402
return this.curve.getInfinity();
403
}
404
405
var x_x = b.x.subtract(this.x);
406
var y_y = b.y.subtract(this.y);
407
var gamma = y_y.divide(x_x);
408
409
var x3 = gamma.square().subtract(this.x).subtract(b.x);
410
var y3 = gamma.multiply(this.x.subtract(x3)).subtract(this.y);
411
412
return new ec.PointFp(this.curve, x3, y3);
413
};
414
415
ec.PointFp.prototype.twice2D = function () {
416
if (this.isInfinity()) return this;
417
if (this.y.toBigInteger().signum() == 0) {
418
// if y1 == 0, then (x1, y1) == (x1, -y1)
419
// and hence this = -this and thus 2(x1, y1) == infinity
420
return this.curve.getInfinity();
421
}
422
423
var TWO = this.curve.fromBigInteger(BigInteger.valueOf(2));
424
var THREE = this.curve.fromBigInteger(BigInteger.valueOf(3));
425
var gamma = this.x.square().multiply(THREE).add(this.curve.a).divide(this.y.multiply(TWO));
426
427
var x3 = gamma.square().subtract(this.x.multiply(TWO));
428
var y3 = gamma.multiply(this.x.subtract(x3)).subtract(this.y);
429
430
return new ec.PointFp(this.curve, x3, y3);
431
};
432
433
ec.PointFp.prototype.multiply2D = function (k) {
434
if (this.isInfinity()) return this;
435
if (k.signum() == 0) return this.curve.getInfinity();
436
437
var e = k;
438
var h = e.multiply(new BigInteger("3"));
439
440
var neg = this.negate();
441
var R = this;
442
443
var i;
444
for (i = h.bitLength() - 2; i > 0; --i) {
445
R = R.twice();
446
447
var hBit = h.testBit(i);
448
var eBit = e.testBit(i);
449
450
if (hBit != eBit) {
451
R = R.add2D(hBit ? this : neg);
452
}
453
}
454
455
return R;
456
};
457
458
ec.PointFp.prototype.isOnCurve = function () {
459
var x = this.getX().toBigInteger();
460
var y = this.getY().toBigInteger();
461
var a = this.curve.getA().toBigInteger();
462
var b = this.curve.getB().toBigInteger();
463
var n = this.curve.getQ();
464
var lhs = y.multiply(y).mod(n);
465
var rhs = x.multiply(x).multiply(x).add(a.multiply(x)).add(b).mod(n);
466
return lhs.equals(rhs);
467
};
468
469
ec.PointFp.prototype.toString = function () {
470
return '(' + this.getX().toBigInteger().toString() + ',' + this.getY().toBigInteger().toString() + ')';
471
};
472
473
/**
474
* Validate an elliptic curve point.
475
*
476
* See SEC 1, section 3.2.2.1: Elliptic Curve Public Key Validation Primitive
477
*/
478
ec.PointFp.prototype.validate = function () {
479
var n = this.curve.getQ();
480
481
// Check Q != O
482
if (this.isInfinity()) {
483
throw new Error("Point is at infinity.");
484
}
485
486
// Check coordinate bounds
487
var x = this.getX().toBigInteger();
488
var y = this.getY().toBigInteger();
489
if (x.compareTo(BigInteger.ONE) < 0 || x.compareTo(n.subtract(BigInteger.ONE)) > 0) {
490
throw new Error('x coordinate out of bounds');
491
}
492
if (y.compareTo(BigInteger.ONE) < 0 || y.compareTo(n.subtract(BigInteger.ONE)) > 0) {
493
throw new Error('y coordinate out of bounds');
494
}
495
496
// Check y^2 = x^3 + ax + b (mod n)
497
if (!this.isOnCurve()) {
498
throw new Error("Point is not on the curve.");
499
}
500
501
// Check nQ = 0 (Q is a scalar multiple of G)
502
if (this.multiply(n).isInfinity()) {
503
// TODO: This check doesn't work - fix.
504
throw new Error("Point is not a scalar multiple of G.");
505
}
506
507
return true;
508
};
509
510
511
512
513
// ----------------
514
// ECCurveFp constructor
515
ec.CurveFp = function (q, a, b) {
516
this.q = q;
517
this.a = this.fromBigInteger(a);
518
this.b = this.fromBigInteger(b);
519
this.infinity = new ec.PointFp(this, null, null);
520
this.reducer = new Barrett(this.q);
521
}
522
523
ec.CurveFp.prototype.getQ = function () {
524
return this.q;
525
};
526
527
ec.CurveFp.prototype.getA = function () {
528
return this.a;
529
};
530
531
ec.CurveFp.prototype.getB = function () {
532
return this.b;
533
};
534
535
ec.CurveFp.prototype.equals = function (other) {
536
if (other == this) return true;
537
return (this.q.equals(other.q) && this.a.equals(other.a) && this.b.equals(other.b));
538
};
539
540
ec.CurveFp.prototype.getInfinity = function () {
541
return this.infinity;
542
};
543
544
ec.CurveFp.prototype.fromBigInteger = function (x) {
545
return new ec.FieldElementFp(this.q, x);
546
};
547
548
ec.CurveFp.prototype.reduce = function (x) {
549
this.reducer.reduce(x);
550
};
551
552
// for now, work with hex strings because they're easier in JS
553
// compressed support added by bitaddress.org
554
ec.CurveFp.prototype.decodePointHex = function (s) {
555
var firstByte = parseInt(s.substr(0, 2), 16);
556
switch (firstByte) { // first byte
557
case 0:
558
return this.infinity;
559
case 2: // compressed
560
case 3: // compressed
561
var yTilde = firstByte & 1;
562
var xHex = s.substr(2, s.length - 2);
563
var X1 = new BigInteger(xHex, 16);
564
return this.decompressPoint(yTilde, X1);
565
case 4: // uncompressed
566
case 6: // hybrid
567
case 7: // hybrid
568
var len = (s.length - 2) / 2;
569
var xHex = s.substr(2, len);
570
var yHex = s.substr(len + 2, len);
571
572
return new ec.PointFp(this,
573
this.fromBigInteger(new BigInteger(xHex, 16)),
574
this.fromBigInteger(new BigInteger(yHex, 16)));
575
576
default: // unsupported
577
return null;
578
}
579
};
580
581
ec.CurveFp.prototype.encodePointHex = function (p) {
582
if (p.isInfinity()) return "00";
583
var xHex = p.getX().toBigInteger().toString(16);
584
var yHex = p.getY().toBigInteger().toString(16);
585
var oLen = this.getQ().toString(16).length;
586
if ((oLen % 2) != 0) oLen++;
587
while (xHex.length < oLen) {
588
xHex = "0" + xHex;
589
}
590
while (yHex.length < oLen) {
591
yHex = "0" + yHex;
592
}
593
return "04" + xHex + yHex;
594
};
595
596
/*
597
* Copyright (c) 2000 - 2011 The Legion Of The Bouncy Castle (http://www.bouncycastle.org)
598
* Ported to JavaScript by bitaddress.org
599
*
600
* Number yTilde
601
* BigInteger X1
602
*/
603
ec.CurveFp.prototype.decompressPoint = function (yTilde, X1) {
604
var x = this.fromBigInteger(X1);
605
var alpha = x.multiply(x.square().add(this.getA())).add(this.getB());
606
var beta = alpha.sqrt();
607
// if we can't find a sqrt we haven't got a point on the curve - run!
608
if (beta == null) throw new Error("Invalid point compression");
609
var betaValue = beta.toBigInteger();
610
var bit0 = betaValue.testBit(0) ? 1 : 0;
611
if (bit0 != yTilde) {
612
// Use the other root
613
beta = this.fromBigInteger(this.getQ().subtract(betaValue));
614
}
615
return new ec.PointFp(this, x, beta, null, true);
616
};
617
618
619
ec.fromHex = function (s) { return new BigInteger(s, 16); };
620
621
ec.integerToBytes = function (i, len) {
622
var bytes = i.toByteArrayUnsigned();
623
if (len < bytes.length) {
624
bytes = bytes.slice(bytes.length - len);
625
} else while (len > bytes.length) {
626
bytes.unshift(0);
627
}
628
return bytes;
629
};
630
631
632
// Named EC curves
633
// ----------------
634
// X9ECParameters constructor
635
ec.X9Parameters = function (curve, g, n, h) {
636
this.curve = curve;
637
this.g = g;
638
this.n = n;
639
this.h = h;
640
}
641
ec.X9Parameters.prototype.getCurve = function () { return this.curve; };
642
ec.X9Parameters.prototype.getG = function () { return this.g; };
643
ec.X9Parameters.prototype.getN = function () { return this.n; };
644
ec.X9Parameters.prototype.getH = function () { return this.h; };
645
646
// secp256k1 is the Curve used by Bitcoin
647
ec.secNamedCurves = {
648
// used by Bitcoin
649
"secp256k1": function () {
650
// p = 2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1
651
var p = ec.fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F");
652
var a = BigInteger.ZERO;
653
var b = ec.fromHex("7");
654
var n = ec.fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141");
655
var h = BigInteger.ONE;
656
var curve = new ec.CurveFp(p, a, b);
657
var G = curve.decodePointHex("04"
658
+ "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798"
659
+ "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8");
660
return new ec.X9Parameters(curve, G, n, h);
661
}
662
};
663
664
// secp256k1 called by Bitcoin's ECKEY
665
ec.getSECCurveByName = function (name) {
666
if (ec.secNamedCurves[name] == undefined) return null;
667
return ec.secNamedCurves[name]();
668
}
669
})();
670