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