@@ -10,6 +10,118 @@ function integerToBytes(i, len) {
1010 return bytes ;
1111} ;
1212
13+ /**
14+ * Find a quadratic residue (mod p) of this number. p must be an odd prime.
15+ *
16+ * For a given number a, this function solves the congruence of the form
17+ *
18+ * x^2 = a (mod p)
19+ *
20+ * And returns x. Note that p - x is also a root.
21+ *
22+ * 0 is returned if no square root exists for these a and p.
23+ *
24+ * The Tonelli-Shanks algorithm is used (except for some simple cases
25+ * in which the solution is known from an identity). This algorithm
26+ * runs in polynomial time (unless the generalized Riemann hypothesis
27+ * is false).
28+ *
29+ * Originally implemented in Python by Eli Bendersky:
30+ * http://eli.thegreenplace.net/2009/03/07/computing-modular-square-roots-in-python/
31+ *
32+ * Ported to JavaScript by Stefan Thomas.
33+ */
34+ BigInteger . prototype . modSqrt = function ( p ) {
35+ var ONE = BigInteger . ONE ,
36+ TWO = BigInteger . valueOf ( 2 ) ;
37+
38+ // Simple cases
39+ if ( this . legendre ( p ) != 1 ) {
40+ return BigInteger . ZERO ;
41+ } else if ( this . equals ( BigInteger . ZERO ) ) {
42+ return BigInteger . ZERO ;
43+ } else if ( p . equals ( TWO ) ) {
44+ return p ;
45+ } else if ( p . mod ( BigInteger . valueOf ( 4 ) ) . equals ( BigInteger . valueOf ( 3 ) ) ) {
46+ return this . modPow ( p . add ( ONE ) . divide ( BigInteger . valueOf ( 4 ) ) , p ) ;
47+ }
48+
49+ // Partition p-1 to s * 2^e for an odd s (i.e. reduce all the powers
50+ // of 2 from p-1)
51+ var s = p . subtract ( ONE ) ;
52+ var e = 0 ;
53+ while ( s . isEven ( ) ) {
54+ s = s . divide ( TWO ) ;
55+ ++ e ;
56+ }
57+
58+ // Find some 'n' with a legendre symbol n|p = -1.
59+ // Shouldn't take long.
60+ var n = TWO ;
61+ while ( n . legendre ( p ) != - 1 ) {
62+ n = n . add ( ONE ) ;
63+ }
64+
65+ // Here be dragons!
66+ // Read the paper "Square roots from 1; 24, 51, 10 to Dan Shanks" by
67+ // Ezra Brown for more information
68+
69+ // x is a guess of the square root that gets better with each
70+ // iteration.
71+ //
72+ // b is the "fudge factor" - by how much we're off with the guess.
73+ // The invariant x^2 = ab (mod p) is maintained throughout the loop.
74+ //
75+ // g is used for successive powers of n to update both a and b
76+ //
77+ // r is the exponent - decreases with each update
78+
79+ var x = this . modPow ( s . add ( ONE ) . divide ( TWO ) , p ) ;
80+ var b = this . modPow ( s , p ) ;
81+ var g = n . modPow ( s , p ) ;
82+ var r = e ;
83+
84+ for ( ; ; ) {
85+ var t = b ;
86+
87+ var m ;
88+ for ( m = 0 ; m < r ; m ++ ) {
89+ if ( t . equals ( ONE ) ) break ;
90+
91+ t = t . modPowInt ( 2 , p ) ;
92+ }
93+
94+ if ( m == 0 ) {
95+ return x ;
96+ }
97+
98+ var gs = g . modPow ( TWO . pow ( BigInteger . valueOf ( r - m - 1 ) ) , p ) ;
99+ g = gs . multiply ( gs ) . mod ( p ) ;
100+ x = x . multiply ( gs ) . mod ( p ) ;
101+ b = b . multiply ( g ) . mod ( p ) ;
102+ r = m ;
103+ }
104+ } ;
105+
106+ /**
107+ * Compute the Legendre symbol a|p using Euler's criterion.
108+ *
109+ * p is a prime, a is relatively prime to p
110+ * (if p divides a, then a | p = 0)
111+ *
112+ * Returns 1 if a has a square root modulo p, -1 otherwise.
113+ */
114+ BigInteger . prototype . legendre = function ( p ) {
115+ var ls = this . modPow ( p . subtract ( BigInteger . ONE ) . shiftRight ( 1 ) , p ) ;
116+ if ( ls . equals ( p . subtract ( BigInteger . ONE ) ) ) {
117+ return - 1 ;
118+ } else if ( ls . equals ( BigInteger . ZERO ) ) {
119+ return 0 ;
120+ } else {
121+ return 1 ;
122+ }
123+ } ;
124+
13125ECFieldElementFp . prototype . getByteLength = function ( ) {
14126 return Math . floor ( ( this . toBigInteger ( ) . bitLength ( ) + 7 ) / 8 ) ;
15127} ;
@@ -139,6 +251,11 @@ ECPointFp.prototype.isOnCurve = function () {
139251 return lhs . equals ( rhs ) ;
140252} ;
141253
254+ ECPointFp . prototype . toString = function ( ) {
255+ return '(' + this . getX ( ) . toBigInteger ( ) . toString ( ) + ',' +
256+ this . getY ( ) . toBigInteger ( ) . toString ( ) + ')' ;
257+ } ;
258+
142259/**
143260 * Validate an elliptic curve point.
144261 *
@@ -239,13 +356,35 @@ Bitcoin.ECDSA = (function () {
239356 } ,
240357
241358 verify : function ( hash , sig , pubkey ) {
242- var obj = ECDSA . parseSig ( sig ) ;
243- var r = obj . r ;
244- var s = obj . s ;
359+ var r , s ;
360+ if ( Bitcoin . Util . isArray ( sig ) ) {
361+ var obj = stringECDSA . parseSig ( sig ) ;
362+ r = obj . r ;
363+ s = obj . s ;
364+ } else if ( "object" === typeof sig && sig . r && sig . s ) {
365+ r = sig . r ;
366+ s = sig . s ;
367+ } else {
368+ throw "Invalid value for signature" ;
369+ }
245370
246- var n = ecparams . getN ( ) ;
371+ var Q ;
372+ if ( pubkey instanceof ECPointFp ) {
373+ Q = pubkey ;
374+ } else if ( Bitcoin . Util . isArray ( pubkey ) ) {
375+ Q = ECPointFp . decodeFrom ( ecparams . getCurve ( ) , pubkey ) ;
376+ } else {
377+ throw "Invalid format for pubkey value, must be byte array or ECPointFp" ;
378+ }
247379 var e = BigInteger . fromByteArrayUnsigned ( hash ) ;
248380
381+ return ECDSA . verifyRaw ( e , r , s , Q ) ;
382+ } ,
383+
384+ verifyRaw : function ( e , r , s , Q ) {
385+ var n = ecparams . getN ( ) ;
386+ var G = ecparams . getG ( ) ;
387+
249388 if ( r . compareTo ( BigInteger . ONE ) < 0 ||
250389 r . compareTo ( n ) >= 0 )
251390 return false ;
@@ -259,19 +398,20 @@ Bitcoin.ECDSA = (function () {
259398 var u1 = e . multiply ( c ) . mod ( n ) ;
260399 var u2 = r . multiply ( c ) . mod ( n ) ;
261400
262- var G = ecparams . getG ( ) ;
263- var Q = ECPointFp . decodeFrom ( ecparams . getCurve ( ) , pubkey ) ;
264-
265- var point = implShamirsTrick ( G , u1 , Q , u2 ) ;
401+ // TODO(!!!): For some reason Shamir's trick isn't working with
402+ // signed message verification!? Probably an implementation
403+ // error!
404+ //var point = implShamirsTrick(G, u1, Q, u2);
405+ var point = G . multiply ( u1 ) . add ( Q . multiply ( u2 ) ) ;
266406
267- var v = point . x . toBigInteger ( ) . mod ( n ) ;
407+ var v = point . getX ( ) . toBigInteger ( ) . mod ( n ) ;
268408
269409 return v . equals ( r ) ;
270410 } ,
271411
272412 /**
273413 * Serialize a signature into DER format.
274- *
414+ *
275415 * Takes two BigIntegers representing r and s and returns a byte array.
276416 */
277417 serializeSig : function ( r , s ) {
@@ -327,6 +467,111 @@ Bitcoin.ECDSA = (function () {
327467 var s = BigInteger . fromByteArrayUnsigned ( sBa ) ;
328468
329469 return { r : r , s : s } ;
470+ } ,
471+
472+ parseSigCompact : function ( sig ) {
473+ if ( sig . length !== 65 ) {
474+ throw "Signature has the wrong length" ;
475+ }
476+
477+ // Signature is prefixed with a type byte storing three bits of
478+ // information.
479+ var i = sig [ 0 ] - 27 ;
480+ if ( i < 0 || i > 7 ) {
481+ throw "Invalid signature type" ;
482+ }
483+
484+ var n = ecparams . getN ( ) ;
485+ var r = BigInteger . fromByteArrayUnsigned ( sig . slice ( 1 , 33 ) ) . mod ( n ) ;
486+ var s = BigInteger . fromByteArrayUnsigned ( sig . slice ( 33 , 65 ) ) . mod ( n ) ;
487+
488+ return { r : r , s : s , i : i } ;
489+ } ,
490+
491+ /**
492+ * Recover a public key from a signature.
493+ *
494+ * See SEC 1: Elliptic Curve Cryptography, section 4.1.6, "Public
495+ * Key Recovery Operation".
496+ *
497+ * http://www.secg.org/download/aid-780/sec1-v2.pdf
498+ */
499+ recoverPubKey : function ( r , s , hash , i ) {
500+ // The recovery parameter i has two bits.
501+ i = i & 3 ;
502+
503+ // The less significant bit specifies whether the y coordinate
504+ // of the compressed point is even or not.
505+ var isYEven = i & 1 ;
506+
507+ // The more significant bit specifies whether we should use the
508+ // first or second candidate key.
509+ var isSecondKey = i >> 1 ;
510+
511+ var n = ecparams . getN ( ) ;
512+ var G = ecparams . getG ( ) ;
513+ var curve = ecparams . getCurve ( ) ;
514+ var p = curve . getQ ( ) ;
515+ var a = curve . getA ( ) . toBigInteger ( ) ;
516+ var b = curve . getB ( ) . toBigInteger ( ) ;
517+
518+ // 1.1 Compute x
519+ var x = isSecondKey ? r . add ( n ) : r ;
520+
521+ // 1.3 Convert x to point
522+ var alpha = x . multiply ( x ) . multiply ( x ) . add ( a . multiply ( x ) ) . add ( b ) . mod ( p ) ;
523+ var beta = alpha . modSqrt ( p ) ;
524+
525+ var xorOdd = beta . isEven ( ) ? ( i % 2 ) : ( ( i + 1 ) % 2 ) ;
526+ // If beta is even, but y isn't or vice versa, then convert it,
527+ // otherwise we're done and y == beta.
528+ var y = ( beta . isEven ( ) ? ! isYEven : isYEven ) ? beta : p . subtract ( beta ) ;
529+
530+ // 1.4 Check that nR is at infinity
531+ var R = new ECPointFp ( curve ,
532+ curve . fromBigInteger ( x ) ,
533+ curve . fromBigInteger ( y ) ) ;
534+ R . validate ( ) ;
535+
536+ // 1.5 Compute e from M
537+ var e = BigInteger . fromByteArrayUnsigned ( hash ) ;
538+ var eNeg = BigInteger . ZERO . subtract ( e ) . mod ( n ) ;
539+
540+ // 1.6 Compute Q = r^-1 (sR - eG)
541+ var rInv = r . modInverse ( n ) ;
542+ var Q = implShamirsTrick ( R , s , G , eNeg ) . multiply ( rInv ) ;
543+
544+ Q . validate ( ) ;
545+ if ( ! ECDSA . verifyRaw ( e , r , s , Q ) ) {
546+ throw "Pubkey recovery unsuccessful" ;
547+ }
548+
549+ var pubKey = new Bitcoin . ECKey ( ) ;
550+ pubKey . pub = Q ;
551+ return pubKey ;
552+ } ,
553+
554+ /**
555+ * Calculate pubkey extraction parameter.
556+ *
557+ * When extracting a pubkey from a signature, we have to
558+ * distinguish four different cases. Rather than putting this
559+ * burden on the verifier, Bitcoin includes a 2-bit value with the
560+ * signature.
561+ *
562+ * This function simply tries all four cases and returns the value
563+ * that resulted in a successful pubkey recovery.
564+ */
565+ calcPubkeyRecoveryParam : function ( r , s , hash )
566+ {
567+ for ( var i = 0 ; i < 4 ; i ++ ) {
568+ try {
569+ if ( Bitcoin . ECDSA . recoverPubKey ( r , s , hash , i ) ) {
570+ return i ;
571+ }
572+ } catch ( e ) { }
573+ }
574+ throw "Unable to find valid recovery factor" ;
330575 }
331576 } ;
332577
0 commit comments