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