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