commit 650ef92c5f41a881788c7f490b77ad7979118cae
parent 16929a40b15c3ca6f5d673adb2ffb5025e218ee9
Author: ThomasV <thomasv@gitorious>
Date: Fri, 30 May 2014 21:24:23 +0200
class MyVerifyingKey, with constructor to submit to python-ecdsa
Diffstat:
M | lib/bitcoin.py | | | 57 | +++++++++++++++++++++++++++++++++------------------------ |
1 file changed, 33 insertions(+), 24 deletions(-)
diff --git a/lib/bitcoin.py b/lib/bitcoin.py
@@ -406,6 +406,34 @@ def ser_to_point(Aser):
+class MyVerifyingKey(ecdsa.VerifyingKey):
+ @classmethod
+ def from_signature(klass, sig, recid, h, curve):
+ """ See http://www.secg.org/download/aid-780/sec1-v2.pdf, chapter 4.1.6 """
+ from ecdsa import util, numbertheory
+ import msqr
+ curveFp = curve.curve
+ G = curve.generator
+ order = G.order()
+ # extract r,s from signature
+ r, s = util.sigdecode_string(sig, order)
+ # 1.1
+ x = r + (recid/2) * order
+ # 1.3
+ alpha = ( x * x * x + curveFp.a() * x + curveFp.b() ) % curveFp.p()
+ beta = msqr.modular_sqrt(alpha, curveFp.p())
+ y = beta if (beta - recid) % 2 == 0 else curveFp.p() - beta
+ # 1.4 the constructor checks that nR is at infinity
+ R = Point(curveFp, x, y, order)
+ # 1.5 compute e from message:
+ e = string_to_number(h)
+ minus_e = -e % order
+ # 1.6 compute Q = r^-1 (sR - eG)
+ inv_r = numbertheory.inverse_mod(r,order)
+ Q = inv_r * ( s * R + minus_e * G )
+ return klass.from_public_point( Q, curve )
+
+
class EC_KEY(object):
def __init__( self, k ):
secret = string_to_number(k)
@@ -434,16 +462,9 @@ class EC_KEY(object):
@classmethod
def verify_message(self, address, signature, message):
- """ See http://www.secg.org/download/aid-780/sec1-v2.pdf for the math """
- from ecdsa import numbertheory, util
- import msqr
- curve = curve_secp256k1
- G = generator_secp256k1
- order = G.order()
- # extract r,s from signature
sig = base64.b64decode(signature)
if len(sig) != 65: raise Exception("Wrong encoding")
- r,s = util.sigdecode_string(sig[1:], order)
+
nV = ord(sig[0])
if nV < 27 or nV >= 35:
raise Exception("Bad encoding")
@@ -454,24 +475,12 @@ class EC_KEY(object):
compressed = False
recid = nV - 27
- # 1.1
- x = r + (recid/2) * order
- # 1.3
- alpha = ( x * x * x + curve.a() * x + curve.b() ) % curve.p()
- beta = msqr.modular_sqrt(alpha, curve.p())
- y = beta if (beta - recid) % 2 == 0 else curve.p() - beta
- # 1.4 the constructor checks that nR is at infinity
- R = Point(curve, x, y, order)
- # 1.5 compute e from message:
h = Hash( msg_magic(message) )
- e = string_to_number(h)
- minus_e = -e % order
- # 1.6 compute Q = r^-1 (sR - eG)
- inv_r = numbertheory.inverse_mod(r,order)
- Q = inv_r * ( s * R + minus_e * G )
- public_key = ecdsa.VerifyingKey.from_public_point( Q, curve = SECP256k1 )
- # check that Q is the public key
+ public_key = MyVerifyingKey.from_signature( sig[1:], recid, h, curve = SECP256k1 )
+
+ # check public key
public_key.verify_digest( sig[1:], h, sigdecode = ecdsa.util.sigdecode_string)
+
# check that we get the original signing address
addr = public_key_to_bc_address( point_to_ser(public_key.pubkey.point, compressed) )
if address != addr: