1 /* ecdsa-modified-1.1.1.js (c) Stephan Thomas, Kenji Urushima | github.com/bitcoinjs/bitcoinjs-lib/blob/master/LICENSE
  2  */
  3 /*
  4  * ecdsa-modified.js - modified Bitcoin.ECDSA class
  5  * 
  6  * Copyright (c) 2013-2017 Stefan Thomas (github.com/justmoon)
  7  *                         Kenji Urushima (kenji.urushima@gmail.com)
  8  * LICENSE
  9  *   https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/LICENSE
 10  */
 11 
 12 /**
 13  * @fileOverview
 14  * @name ecdsa-modified-1.0.js
 15  * @author Stefan Thomas (github.com/justmoon) and Kenji Urushima (kenji.urushima@gmail.com)
 16  * @version jsrsasign 7.2.0 ecdsa-modified 1.1.1 (2017-May-12)
 17  * @since jsrsasign 4.0
 18  * @license <a href="https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/LICENSE">MIT License</a>
 19  */
 20 
 21 if (typeof KJUR == "undefined" || !KJUR) KJUR = {};
 22 if (typeof KJUR.crypto == "undefined" || !KJUR.crypto) KJUR.crypto = {};
 23 
 24 /**
 25  * class for EC key generation,  ECDSA signing and verifcation
 26  * @name KJUR.crypto.ECDSA
 27  * @class class for EC key generation,  ECDSA signing and verifcation
 28  * @description
 29  * <p>
 30  * CAUTION: Most of the case, you don't need to use this class except
 31  * for generating an EC key pair. Please use {@link KJUR.crypto.Signature} class instead.
 32  * </p>
 33  * <p>
 34  * This class was originally developped by Stefan Thomas for Bitcoin JavaScript library.
 35  * (See {@link https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/src/ecdsa.js})
 36  * Currently this class supports following named curves and their aliases.
 37  * <ul>
 38  * <li>secp256r1, NIST P-256, P-256, prime256v1 (*)</li>
 39  * <li>secp256k1 (*)</li>
 40  * <li>secp384r1, NIST P-384, P-384 (*)</li>
 41  * </ul>
 42  * </p>
 43  */
 44 KJUR.crypto.ECDSA = function(params) {
 45     var curveName = "secp256r1";	// curve name default
 46     var ecparams = null;
 47     var prvKeyHex = null;
 48     var pubKeyHex = null;
 49 
 50     var rng = new SecureRandom();
 51 
 52     var P_OVER_FOUR = null;
 53 
 54     this.type = "EC";
 55     this.isPrivate = false;
 56     this.isPublic = false;
 57 
 58     function implShamirsTrick(P, k, Q, l) {
 59 	var m = Math.max(k.bitLength(), l.bitLength());
 60 	var Z = P.add2D(Q);
 61 	var R = P.curve.getInfinity();
 62 
 63 	for (var i = m - 1; i >= 0; --i) {
 64 	    R = R.twice2D();
 65 
 66 	    R.z = BigInteger.ONE;
 67 
 68 	    if (k.testBit(i)) {
 69 		if (l.testBit(i)) {
 70 		    R = R.add2D(Z);
 71 		} else {
 72 		    R = R.add2D(P);
 73 		}
 74 	    } else {
 75 		if (l.testBit(i)) {
 76 		    R = R.add2D(Q);
 77 		}
 78 	    }
 79 	}
 80 	
 81 	return R;
 82     };
 83 
 84     //===========================
 85     // PUBLIC METHODS
 86     //===========================
 87     this.getBigRandom = function (limit) {
 88 	return new BigInteger(limit.bitLength(), rng)
 89 	.mod(limit.subtract(BigInteger.ONE))
 90 	.add(BigInteger.ONE)
 91 	;
 92     };
 93 
 94     this.setNamedCurve = function(curveName) {
 95 	this.ecparams = KJUR.crypto.ECParameterDB.getByName(curveName);
 96 	this.prvKeyHex = null;
 97 	this.pubKeyHex = null;
 98 	this.curveName = curveName;
 99     };
100 
101     this.setPrivateKeyHex = function(prvKeyHex) {
102         this.isPrivate = true;
103 	this.prvKeyHex = prvKeyHex;
104     };
105 
106     this.setPublicKeyHex = function(pubKeyHex) {
107         this.isPublic = true;
108 	this.pubKeyHex = pubKeyHex;
109     };
110 
111     /**
112      * get X and Y hexadecimal string value of public key
113      * @name getPublicKeyXYHex
114      * @memberOf KJUR.crypto.ECDSA#
115      * @function
116      * @return {Array} associative array of x and y value of public key
117      * @since ecdsa-modified 1.0.5 jsrsasign 5.0.14
118      * @example
119      * ec = new KJUR.crypto.ECDSA({'curve': 'secp256r1', 'pub': pubHex});
120      * ec.getPublicKeyXYHex() → { x: '01bacf...', y: 'c3bc22...' }
121      */
122     this.getPublicKeyXYHex = function() {
123 	var h = this.pubKeyHex;
124 	if (h.substr(0, 2) !== "04")
125 	    throw "this method supports uncompressed format(04) only";
126 
127 	var charlen = this.ecparams.keylen / 4;
128 	if (h.length !== 2 + charlen * 2)
129 	    throw "malformed public key hex length";
130 
131 	var result = {};
132 	result.x = h.substr(2, charlen);
133 	result.y = h.substr(2 + charlen);
134 	return result;
135     };
136 
137     /**
138      * get NIST curve short name such as "P-256" or "P-384"
139      * @name getShortNISTPCurveName
140      * @memberOf KJUR.crypto.ECDSA#
141      * @function
142      * @return {String} short NIST P curve name such as "P-256" or "P-384" if it's NIST P curve otherwise null;
143      * @since ecdsa-modified 1.0.5 jsrsasign 5.0.14
144      * @example
145      * ec = new KJUR.crypto.ECDSA({'curve': 'secp256r1', 'pub': pubHex});
146      * ec.getShortPCurveName() → "P-256";
147      */
148     this.getShortNISTPCurveName = function() {
149 	var s = this.curveName;
150 	if (s === "secp256r1" || s === "NIST P-256" ||
151 	    s === "P-256" || s === "prime256v1")
152 	    return "P-256";
153 	if (s === "secp384r1" || s === "NIST P-384" || s === "P-384")
154 	    return "P-384";
155 	return null;
156     };
157 
158     /**
159      * generate a EC key pair
160      * @name generateKeyPairHex
161      * @memberOf KJUR.crypto.ECDSA#
162      * @function
163      * @return {Array} associative array of hexadecimal string of private and public key
164      * @since ecdsa-modified 1.0.1
165      * @example
166      * var ec = new KJUR.crypto.ECDSA({'curve': 'secp256r1'});
167      * var keypair = ec.generateKeyPairHex();
168      * var pubhex = keypair.ecpubhex; // hexadecimal string of EC public key
169      * var prvhex = keypair.ecprvhex; // hexadecimal string of EC private key (=d)
170      */
171     this.generateKeyPairHex = function() {
172 	var biN = this.ecparams['n'];
173 	var biPrv = this.getBigRandom(biN);
174 	var epPub = this.ecparams['G'].multiply(biPrv);
175 	var biX = epPub.getX().toBigInteger();
176 	var biY = epPub.getY().toBigInteger();
177 
178 	var charlen = this.ecparams['keylen'] / 4;
179 	var hPrv = ("0000000000" + biPrv.toString(16)).slice(- charlen);
180 	var hX   = ("0000000000" + biX.toString(16)).slice(- charlen);
181 	var hY   = ("0000000000" + biY.toString(16)).slice(- charlen);
182 	var hPub = "04" + hX + hY;
183 
184 	this.setPrivateKeyHex(hPrv);
185 	this.setPublicKeyHex(hPub);
186 	return {'ecprvhex': hPrv, 'ecpubhex': hPub};
187     };
188 
189     this.signWithMessageHash = function(hashHex) {
190 	return this.signHex(hashHex, this.prvKeyHex);
191     };
192 
193     /**
194      * signing to message hash
195      * @name signHex
196      * @memberOf KJUR.crypto.ECDSA#
197      * @function
198      * @param {String} hashHex hexadecimal string of hash value of signing message
199      * @param {String} privHex hexadecimal string of EC private key
200      * @return {String} hexadecimal string of ECDSA signature
201      * @since ecdsa-modified 1.0.1
202      * @example
203      * var ec = new KJUR.crypto.ECDSA({'curve': 'secp256r1'});
204      * var sigValue = ec.signHex(hash, prvKey);
205      */
206     this.signHex = function (hashHex, privHex) {
207 	var d = new BigInteger(privHex, 16);
208 	var n = this.ecparams['n'];
209 	var e = new BigInteger(hashHex, 16);
210 
211 	do {
212 	    var k = this.getBigRandom(n);
213 	    var G = this.ecparams['G'];
214 	    var Q = G.multiply(k);
215 	    var r = Q.getX().toBigInteger().mod(n);
216 	} while (r.compareTo(BigInteger.ZERO) <= 0);
217 
218 	var s = k.modInverse(n).multiply(e.add(d.multiply(r))).mod(n);
219 
220 	return KJUR.crypto.ECDSA.biRSSigToASN1Sig(r, s);
221     };
222 
223     this.sign = function (hash, priv) {
224 	var d = priv;
225 	var n = this.ecparams['n'];
226 	var e = BigInteger.fromByteArrayUnsigned(hash);
227 
228 	do {
229 	    var k = this.getBigRandom(n);
230 	    var G = this.ecparams['G'];
231 	    var Q = G.multiply(k);
232 	    var r = Q.getX().toBigInteger().mod(n);
233 	} while (r.compareTo(BigInteger.ZERO) <= 0);
234 
235 	var s = k.modInverse(n).multiply(e.add(d.multiply(r))).mod(n);
236 	return this.serializeSig(r, s);
237     };
238 
239     this.verifyWithMessageHash = function(hashHex, sigHex) {
240 	return this.verifyHex(hashHex, sigHex, this.pubKeyHex);
241     };
242 
243     /**
244      * verifying signature with message hash and public key
245      * @name verifyHex
246      * @memberOf KJUR.crypto.ECDSA#
247      * @function
248      * @param {String} hashHex hexadecimal string of hash value of signing message
249      * @param {String} sigHex hexadecimal string of signature value
250      * @param {String} pubkeyHex hexadecimal string of public key
251      * @return {Boolean} true if the signature is valid, otherwise false
252      * @since ecdsa-modified 1.0.1
253      * @example
254      * var ec = new KJUR.crypto.ECDSA({'curve': 'secp256r1'});
255      * var result = ec.verifyHex(msgHashHex, sigHex, pubkeyHex);
256      */
257     this.verifyHex = function(hashHex, sigHex, pubkeyHex) {
258 	var r,s;
259 
260 	var obj = KJUR.crypto.ECDSA.parseSigHex(sigHex);
261 	r = obj.r;
262 	s = obj.s;
263 
264 	var Q;
265 	Q = ECPointFp.decodeFromHex(this.ecparams['curve'], pubkeyHex);
266 	var e = new BigInteger(hashHex, 16);
267 
268 	return this.verifyRaw(e, r, s, Q);
269     };
270 
271     this.verify = function (hash, sig, pubkey) {
272 	var r,s;
273 	if (Bitcoin.Util.isArray(sig)) {
274 	    var obj = this.parseSig(sig);
275 	    r = obj.r;
276 	    s = obj.s;
277 	} else if ("object" === typeof sig && sig.r && sig.s) {
278 	    r = sig.r;
279 	    s = sig.s;
280 	} else {
281 	    throw "Invalid value for signature";
282 	}
283 
284 	var Q;
285 	if (pubkey instanceof ECPointFp) {
286 	    Q = pubkey;
287 	} else if (Bitcoin.Util.isArray(pubkey)) {
288 	    Q = ECPointFp.decodeFrom(this.ecparams['curve'], pubkey);
289 	} else {
290 	    throw "Invalid format for pubkey value, must be byte array or ECPointFp";
291 	}
292 	var e = BigInteger.fromByteArrayUnsigned(hash);
293 
294 	return this.verifyRaw(e, r, s, Q);
295     };
296 
297     this.verifyRaw = function (e, r, s, Q) {
298 	var n = this.ecparams['n'];
299 	var G = this.ecparams['G'];
300 
301 	if (r.compareTo(BigInteger.ONE) < 0 ||
302 	    r.compareTo(n) >= 0)
303 	    return false;
304 
305 	if (s.compareTo(BigInteger.ONE) < 0 ||
306 	    s.compareTo(n) >= 0)
307 	    return false;
308 
309 	var c = s.modInverse(n);
310 
311 	var u1 = e.multiply(c).mod(n);
312 	var u2 = r.multiply(c).mod(n);
313 
314 	// TODO(!!!): For some reason Shamir's trick isn't working with
315 	// signed message verification!? Probably an implementation
316 	// error!
317 	//var point = implShamirsTrick(G, u1, Q, u2);
318 	var point = G.multiply(u1).add(Q.multiply(u2));
319 
320 	var v = point.getX().toBigInteger().mod(n);
321 
322 	return v.equals(r);
323     };
324 
325     /**
326      * Serialize a signature into DER format.
327      *
328      * Takes two BigIntegers representing r and s and returns a byte array.
329      */
330     this.serializeSig = function (r, s) {
331 	var rBa = r.toByteArraySigned();
332 	var sBa = s.toByteArraySigned();
333 
334 	var sequence = [];
335 	sequence.push(0x02); // INTEGER
336 	sequence.push(rBa.length);
337 	sequence = sequence.concat(rBa);
338 
339 	sequence.push(0x02); // INTEGER
340 	sequence.push(sBa.length);
341 	sequence = sequence.concat(sBa);
342 
343 	sequence.unshift(sequence.length);
344 	sequence.unshift(0x30); // SEQUENCE
345 	return sequence;
346     };
347 
348     /**
349      * Parses a byte array containing a DER-encoded signature.
350      *
351      * This function will return an object of the form:
352      *
353      * {
354      *   r: BigInteger,
355      *   s: BigInteger
356      * }
357      */
358     this.parseSig = function (sig) {
359 	var cursor;
360 	if (sig[0] != 0x30)
361 	    throw new Error("Signature not a valid DERSequence");
362 
363 	cursor = 2;
364 	if (sig[cursor] != 0x02)
365 	    throw new Error("First element in signature must be a DERInteger");;
366 	var rBa = sig.slice(cursor+2, cursor+2+sig[cursor+1]);
367 
368 	cursor += 2+sig[cursor+1];
369 	if (sig[cursor] != 0x02)
370 	    throw new Error("Second element in signature must be a DERInteger");
371 	var sBa = sig.slice(cursor+2, cursor+2+sig[cursor+1]);
372 
373 	cursor += 2+sig[cursor+1];
374 
375 	//if (cursor != sig.length)
376 	//  throw new Error("Extra bytes in signature");
377 
378 	var r = BigInteger.fromByteArrayUnsigned(rBa);
379 	var s = BigInteger.fromByteArrayUnsigned(sBa);
380 
381 	return {r: r, s: s};
382     };
383 
384     this.parseSigCompact = function (sig) {
385 	if (sig.length !== 65) {
386 	    throw "Signature has the wrong length";
387 	}
388 
389 	// Signature is prefixed with a type byte storing three bits of
390 	// information.
391 	var i = sig[0] - 27;
392 	if (i < 0 || i > 7) {
393 	    throw "Invalid signature type";
394 	}
395 
396 	var n = this.ecparams['n'];
397 	var r = BigInteger.fromByteArrayUnsigned(sig.slice(1, 33)).mod(n);
398 	var s = BigInteger.fromByteArrayUnsigned(sig.slice(33, 65)).mod(n);
399 
400 	return {r: r, s: s, i: i};
401     };
402 
403     /**
404      * read an ASN.1 hexadecimal string of PKCS#1/5 plain ECC private key<br/>
405      * @name readPKCS5PrvKeyHex
406      * @memberOf KJUR.crypto.ECDSA#
407      * @function
408      * @param {String} h hexadecimal string of PKCS#1/5 ECC private key
409      * @since jsrsasign 7.1.0 ecdsa-modified 1.1.0
410      */
411     this.readPKCS5PrvKeyHex = function(h) {
412 	var _ASN1HEX = ASN1HEX;
413 	var _getName = KJUR.crypto.ECDSA.getName;
414 	var _getVbyList = _ASN1HEX.getVbyList;
415 
416 	if (_ASN1HEX.isASN1HEX(h) === false)
417 	    throw "not ASN.1 hex string";
418 
419 	var hCurve, hPrv, hPub;
420 	try {
421 	    hCurve = _getVbyList(h, 0, [2, 0], "06");
422 	    hPrv   = _getVbyList(h, 0, [1], "04");
423 	    try {
424 		hPub = _getVbyList(h, 0, [3, 0], "03").substr(2);
425 	    } catch(ex) {};
426 	} catch(ex) {
427 	    throw "malformed PKCS#1/5 plain ECC private key";
428 	}
429 
430 	this.curveName = _getName(hCurve);
431 	if (this.curveName === undefined) throw "unsupported curve name";
432 
433 	this.setNamedCurve(this.curveName);
434 	this.setPublicKeyHex(hPub);
435 	this.setPrivateKeyHex(hPrv);
436         this.isPublic = false;
437     };
438 
439     /**
440      * read an ASN.1 hexadecimal string of PKCS#8 plain ECC private key<br/>
441      * @name readPKCS8PrvKeyHex
442      * @memberOf KJUR.crypto.ECDSA#
443      * @function
444      * @param {String} h hexadecimal string of PKCS#8 ECC private key
445      * @since jsrsasign 7.1.0 ecdsa-modified 1.1.0
446      */
447     this.readPKCS8PrvKeyHex = function(h) {
448 	var _ASN1HEX = ASN1HEX;
449 	var _getName = KJUR.crypto.ECDSA.getName;
450 	var _getVbyList = _ASN1HEX.getVbyList;
451 
452 	if (_ASN1HEX.isASN1HEX(h) === false)
453 	    throw "not ASN.1 hex string";
454 
455 	var hECOID, hCurve, hPrv, hPub;
456 	try {
457 	    hECOID = _getVbyList(h, 0, [1, 0], "06");
458 	    hCurve = _getVbyList(h, 0, [1, 1], "06");
459 	    hPrv   = _getVbyList(h, 0, [2, 0, 1], "04");
460 	    try {
461 		hPub = _getVbyList(h, 0, [2, 0, 2, 0], "03").substr(2);
462 	    } catch(ex) {};
463 	} catch(ex) {
464 	    throw "malformed PKCS#8 plain ECC private key";
465 	}
466 
467 	this.curveName = _getName(hCurve);
468 	if (this.curveName === undefined) throw "unsupported curve name";
469 
470 	this.setNamedCurve(this.curveName);
471 	this.setPublicKeyHex(hPub);
472 	this.setPrivateKeyHex(hPrv);
473         this.isPublic = false;
474     };
475 
476     /**
477      * read an ASN.1 hexadecimal string of PKCS#8 ECC public key<br/>
478      * @name readPKCS8PubKeyHex
479      * @memberOf KJUR.crypto.ECDSA#
480      * @function
481      * @param {String} h hexadecimal string of PKCS#8 ECC public key
482      * @since jsrsasign 7.1.0 ecdsa-modified 1.1.0
483      */
484     this.readPKCS8PubKeyHex = function(h) {
485 	var _ASN1HEX = ASN1HEX;
486 	var _getName = KJUR.crypto.ECDSA.getName;
487 	var _getVbyList = _ASN1HEX.getVbyList;
488 
489 	if (_ASN1HEX.isASN1HEX(h) === false)
490 	    throw "not ASN.1 hex string";
491 
492 	var hECOID, hCurve, hPub;
493 	try {
494 	    hECOID = _getVbyList(h, 0, [0, 0], "06");
495 	    hCurve = _getVbyList(h, 0, [0, 1], "06");
496 	    hPub = _getVbyList(h, 0, [1], "03").substr(2);
497 	} catch(ex) {
498 	    throw "malformed PKCS#8 ECC public key";
499 	}
500 
501 	this.curveName = _getName(hCurve);
502 	if (this.curveName === null) throw "unsupported curve name";
503 
504 	this.setNamedCurve(this.curveName);
505 	this.setPublicKeyHex(hPub);
506     };
507 
508     /**
509      * read an ASN.1 hexadecimal string of X.509 ECC public key certificate<br/>
510      * @name readCertPubKeyHex
511      * @memberOf KJUR.crypto.ECDSA#
512      * @function
513      * @param {String} h hexadecimal string of X.509 ECC public key certificate
514      * @param {Integer} nthPKI nth index of publicKeyInfo. (DEFAULT: 6 for X509v3)
515      * @since jsrsasign 7.1.0 ecdsa-modified 1.1.0
516      */
517     this.readCertPubKeyHex = function(h, nthPKI) {
518 	if (nthPKI !== 5) nthPKI = 6;
519 	var _ASN1HEX = ASN1HEX;
520 	var _getName = KJUR.crypto.ECDSA.getName;
521 	var _getVbyList = _ASN1HEX.getVbyList;
522 
523 	if (_ASN1HEX.isASN1HEX(h) === false)
524 	    throw "not ASN.1 hex string";
525 
526 	var hCurve, hPub;
527 	try {
528 	    hCurve = _getVbyList(h, 0, [0, nthPKI, 0, 1], "06");
529 	    hPub = _getVbyList(h, 0, [0, nthPKI, 1], "03").substr(2);
530 	} catch(ex) {
531 	    throw "malformed X.509 certificate ECC public key";
532 	}
533 
534 	this.curveName = _getName(hCurve);
535 	if (this.curveName === null) throw "unsupported curve name";
536 
537 	this.setNamedCurve(this.curveName);
538 	this.setPublicKeyHex(hPub);
539     };
540 
541     /*
542      * Recover a public key from a signature.
543      *
544      * See SEC 1: Elliptic Curve Cryptography, section 4.1.6, "Public
545      * Key Recovery Operation".
546      *
547      * http://www.secg.org/download/aid-780/sec1-v2.pdf
548      */
549     /*
550     recoverPubKey: function (r, s, hash, i) {
551 	// The recovery parameter i has two bits.
552 	i = i & 3;
553 
554 	// The less significant bit specifies whether the y coordinate
555 	// of the compressed point is even or not.
556 	var isYEven = i & 1;
557 
558 	// The more significant bit specifies whether we should use the
559 	// first or second candidate key.
560 	var isSecondKey = i >> 1;
561 
562 	var n = this.ecparams['n'];
563 	var G = this.ecparams['G'];
564 	var curve = this.ecparams['curve'];
565 	var p = curve.getQ();
566 	var a = curve.getA().toBigInteger();
567 	var b = curve.getB().toBigInteger();
568 
569 	// We precalculate (p + 1) / 4 where p is if the field order
570 	if (!P_OVER_FOUR) {
571 	    P_OVER_FOUR = p.add(BigInteger.ONE).divide(BigInteger.valueOf(4));
572 	}
573 
574 	// 1.1 Compute x
575 	var x = isSecondKey ? r.add(n) : r;
576 
577 	// 1.3 Convert x to point
578 	var alpha = x.multiply(x).multiply(x).add(a.multiply(x)).add(b).mod(p);
579 	var beta = alpha.modPow(P_OVER_FOUR, p);
580 
581 	var xorOdd = beta.isEven() ? (i % 2) : ((i+1) % 2);
582 	// If beta is even, but y isn't or vice versa, then convert it,
583 	// otherwise we're done and y == beta.
584 	var y = (beta.isEven() ? !isYEven : isYEven) ? beta : p.subtract(beta);
585 
586 	// 1.4 Check that nR is at infinity
587 	var R = new ECPointFp(curve,
588 			      curve.fromBigInteger(x),
589 			      curve.fromBigInteger(y));
590 	R.validate();
591 
592 	// 1.5 Compute e from M
593 	var e = BigInteger.fromByteArrayUnsigned(hash);
594 	var eNeg = BigInteger.ZERO.subtract(e).mod(n);
595 
596 	// 1.6 Compute Q = r^-1 (sR - eG)
597 	var rInv = r.modInverse(n);
598 	var Q = implShamirsTrick(R, s, G, eNeg).multiply(rInv);
599 
600 	Q.validate();
601 	if (!this.verifyRaw(e, r, s, Q)) {
602 	    throw "Pubkey recovery unsuccessful";
603 	}
604 
605 	var pubKey = new Bitcoin.ECKey();
606 	pubKey.pub = Q;
607 	return pubKey;
608     },
609     */
610 
611     /*
612      * Calculate pubkey extraction parameter.
613      *
614      * When extracting a pubkey from a signature, we have to
615      * distinguish four different cases. Rather than putting this
616      * burden on the verifier, Bitcoin includes a 2-bit value with the
617      * signature.
618      *
619      * This function simply tries all four cases and returns the value
620      * that resulted in a successful pubkey recovery.
621      */
622     /*
623     calcPubkeyRecoveryParam: function (address, r, s, hash) {
624 	for (var i = 0; i < 4; i++) {
625 	    try {
626 		var pubkey = Bitcoin.ECDSA.recoverPubKey(r, s, hash, i);
627 		if (pubkey.getBitcoinAddress().toString() == address) {
628 		    return i;
629 		}
630 	    } catch (e) {}
631 	}
632 	throw "Unable to find valid recovery factor";
633     }
634     */
635 
636     if (params !== undefined) {
637 	if (params['curve'] !== undefined) {
638 	    this.curveName = params['curve'];
639 	}
640     }
641     if (this.curveName === undefined) this.curveName = curveName;
642     this.setNamedCurve(this.curveName);
643     if (params !== undefined) {
644 	if (params.prv !== undefined) this.setPrivateKeyHex(params.prv);
645 	if (params.pub !== undefined) this.setPublicKeyHex(params.pub);
646     }
647 };
648 
649 /**
650  * parse ASN.1 DER encoded ECDSA signature
651  * @name parseSigHex
652  * @memberOf KJUR.crypto.ECDSA
653  * @function
654  * @static
655  * @param {String} sigHex hexadecimal string of ECDSA signature value
656  * @return {Array} associative array of signature field r and s of BigInteger
657  * @since ecdsa-modified 1.0.1
658  * @example
659  * var ec = new KJUR.crypto.ECDSA({'curve': 'secp256r1'});
660  * var sig = ec.parseSigHex('30...');
661  * var biR = sig.r; // BigInteger object for 'r' field of signature.
662  * var biS = sig.s; // BigInteger object for 's' field of signature.
663  */
664 KJUR.crypto.ECDSA.parseSigHex = function(sigHex) {
665     var p = KJUR.crypto.ECDSA.parseSigHexInHexRS(sigHex);
666     var biR = new BigInteger(p.r, 16);
667     var biS = new BigInteger(p.s, 16);
668     
669     return {'r': biR, 's': biS};
670 };
671 
672 /**
673  * parse ASN.1 DER encoded ECDSA signature
674  * @name parseSigHexInHexRS
675  * @memberOf KJUR.crypto.ECDSA
676  * @function
677  * @static
678  * @param {String} sigHex hexadecimal string of ECDSA signature value
679  * @return {Array} associative array of signature field r and s in hexadecimal
680  * @since ecdsa-modified 1.0.3
681  * @example
682  * var ec = new KJUR.crypto.ECDSA({'curve': 'secp256r1'});
683  * var sig = ec.parseSigHexInHexRS('30...');
684  * var hR = sig.r; // hexadecimal string for 'r' field of signature.
685  * var hS = sig.s; // hexadecimal string for 's' field of signature.
686  */
687 KJUR.crypto.ECDSA.parseSigHexInHexRS = function(sigHex) {
688     var _ASN1HEX = ASN1HEX;
689     var _getChildIdx = _ASN1HEX.getChildIdx;
690     var _getV = _ASN1HEX.getV;
691 
692     // 1. ASN.1 Sequence Check
693     if (sigHex.substr(0, 2) != "30")
694 	throw "signature is not a ASN.1 sequence";
695 
696     // 2. Items of ASN.1 Sequence Check
697     var a = _getChildIdx(sigHex, 0);
698     if (a.length != 2)
699 	throw "number of signature ASN.1 sequence elements seem wrong";
700     
701     // 3. Integer check
702     var iTLV1 = a[0];
703     var iTLV2 = a[1];
704     if (sigHex.substr(iTLV1, 2) != "02")
705 	throw "1st item of sequene of signature is not ASN.1 integer";
706     if (sigHex.substr(iTLV2, 2) != "02")
707 	throw "2nd item of sequene of signature is not ASN.1 integer";
708 
709     // 4. getting value
710     var hR = _getV(sigHex, iTLV1);
711     var hS = _getV(sigHex, iTLV2);
712     
713     return {'r': hR, 's': hS};
714 };
715 
716 /**
717  * convert hexadecimal ASN.1 encoded signature to concatinated signature
718  * @name asn1SigToConcatSig
719  * @memberOf KJUR.crypto.ECDSA
720  * @function
721  * @static
722  * @param {String} asn1Hex hexadecimal string of ASN.1 encoded ECDSA signature value
723  * @return {String} r-s concatinated format of ECDSA signature value
724  * @since ecdsa-modified 1.0.3
725  */
726 KJUR.crypto.ECDSA.asn1SigToConcatSig = function(asn1Sig) {
727     var pSig = KJUR.crypto.ECDSA.parseSigHexInHexRS(asn1Sig);
728     var hR = pSig.r;
729     var hS = pSig.s;
730 
731     if (hR.substr(0, 2) == "00" && (((hR.length / 2) * 8) % (16 * 8)) == 8) 
732 	hR = hR.substr(2);
733 
734     if (hS.substr(0, 2) == "00" && (((hS.length / 2) * 8) % (16 * 8)) == 8) 
735 	hS = hS.substr(2);
736 
737     if ((((hR.length / 2) * 8) % (16 * 8)) != 0)
738 	throw "unknown ECDSA sig r length error";
739 
740     if ((((hS.length / 2) * 8) % (16 * 8)) != 0)
741 	throw "unknown ECDSA sig s length error";
742 
743     return hR + hS;
744 };
745 
746 /**
747  * convert hexadecimal concatinated signature to ASN.1 encoded signature
748  * @name concatSigToASN1Sig
749  * @memberOf KJUR.crypto.ECDSA
750  * @function
751  * @static
752  * @param {String} concatSig r-s concatinated format of ECDSA signature value
753  * @return {String} hexadecimal string of ASN.1 encoded ECDSA signature value
754  * @since ecdsa-modified 1.0.3
755  */
756 KJUR.crypto.ECDSA.concatSigToASN1Sig = function(concatSig) {
757     if ((((concatSig.length / 2) * 8) % (16 * 8)) != 0)
758 	throw "unknown ECDSA concatinated r-s sig  length error";
759 
760     var hR = concatSig.substr(0, concatSig.length / 2);
761     var hS = concatSig.substr(concatSig.length / 2);
762     return KJUR.crypto.ECDSA.hexRSSigToASN1Sig(hR, hS);
763 };
764 
765 /**
766  * convert hexadecimal R and S value of signature to ASN.1 encoded signature
767  * @name hexRSSigToASN1Sig
768  * @memberOf KJUR.crypto.ECDSA
769  * @function
770  * @static
771  * @param {String} hR hexadecimal string of R field of ECDSA signature value
772  * @param {String} hS hexadecimal string of S field of ECDSA signature value
773  * @return {String} hexadecimal string of ASN.1 encoded ECDSA signature value
774  * @since ecdsa-modified 1.0.3
775  */
776 KJUR.crypto.ECDSA.hexRSSigToASN1Sig = function(hR, hS) {
777     var biR = new BigInteger(hR, 16);
778     var biS = new BigInteger(hS, 16);
779     return KJUR.crypto.ECDSA.biRSSigToASN1Sig(biR, biS);
780 };
781 
782 /**
783  * convert R and S BigInteger object of signature to ASN.1 encoded signature
784  * @name biRSSigToASN1Sig
785  * @memberOf KJUR.crypto.ECDSA
786  * @function
787  * @static
788  * @param {BigInteger} biR BigInteger object of R field of ECDSA signature value
789  * @param {BigInteger} biS BIgInteger object of S field of ECDSA signature value
790  * @return {String} hexadecimal string of ASN.1 encoded ECDSA signature value
791  * @since ecdsa-modified 1.0.3
792  */
793 KJUR.crypto.ECDSA.biRSSigToASN1Sig = function(biR, biS) {
794     var _KJUR_asn1 = KJUR.asn1;
795     var derR = new _KJUR_asn1.DERInteger({'bigint': biR});
796     var derS = new _KJUR_asn1.DERInteger({'bigint': biS});
797     var derSeq = new _KJUR_asn1.DERSequence({'array': [derR, derS]});
798     return derSeq.getEncodedHex();
799 };
800 
801 /**
802  * static method to get normalized EC curve name from curve name or hexadecimal OID value
803  * @name getName
804  * @memberOf KJUR.crypto.ECDSA
805  * @function
806  * @static
807  * @param {String} s curve name (ex. P-256) or hexadecimal OID value (ex. 2a86...)
808  * @return {String} normalized EC curve name (ex. secp256r1) 
809  * @since jsrsasign 7.1.0 ecdsa-modified 1.1.0 
810  * @description
811  * This static method returns normalized EC curve name 
812  * which is supported in jsrsasign
813  * from curve name or hexadecimal OID value.
814  * When curve is not supported in jsrsasign, this method returns null.
815  * Normalized name will be "secp*" in jsrsasign.
816  * @example
817  * KJUR.crypto.ECDSA.getName("2b8104000a") → "secp256k1"
818  * KJUR.crypto.ECDSA.getName("NIST P-256") → "secp256r1"
819  * KJUR.crypto.ECDSA.getName("P-521") → undefined // not supported
820  */
821 KJUR.crypto.ECDSA.getName = function(s) {
822     if (s === "2a8648ce3d030107") return "secp256r1"; // 1.2.840.10045.3.1.7
823     if (s === "2b8104000a") return "secp256k1"; // 1.3.132.0.10
824     if (s === "2b81040022") return "secp384r1"; // 1.3.132.0.34
825     if ("|secp256r1|NIST P-256|P-256|prime256v1|".indexOf(s) !== -1) return "secp256r1";
826     if ("|secp256k1|".indexOf(s) !== -1) return "secp256k1";
827     if ("|secp384r1|NIST P-384|P-384|".indexOf(s) !== -1) return "secp384r1";
828     return null;
829 };
830 
831