def from_signature(cls, 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 cls.from_public_point(Q, curve)
def _decode_pub_compressed(bytes): if bytes[0] not in ['\x02', '\x03']: raise Error('first byte not x02 or \x03') x = decode_bigint(bytes[1:]) alpha = (x * x * x + curve_secp256k1.a() * x + curve_secp256k1.b()) % curve_secp256k1.p() beta = msqr.modular_sqrt(alpha, curve_secp256k1.p()) y = beta if (beta - ord(bytes[0])) % 2 == 0 else curve_secp256k1.p() - beta return ecdsa.ellipticcurve.Point( curve_secp256k1, x, y, secp256k1.order)
def verify_message(self, address, signature, message): """See http://www.secg.org/download/aid-780/sec1-v2.pdf for the math""" 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 BaseException("Wrong encoding") r, s = ecdsa.util.sigdecode_string(sig[1:], order) nV = ord(sig[0]) if nV < 27 or nV >= 35: raise BaseException("Bad encoding") if nV >= 31: compressed = True nV -= 4 else: 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 = ecdsa.ellipticcurve.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 = ecdsa.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.verify_digest(sig[1:], h, sigdecode=ecdsa.util.sigdecode_string) # check that we get the original signing address addr = public_key_to_bc_address(encode_point(public_key, compressed)) if address != addr: raise BaseException("Bad signature")
def verify_message(self, address, signature, message): """See http://www.secg.org/download/aid-780/sec1-v2.pdf for the math""" 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 BaseException("Wrong encoding") r, s = ecdsa.util.sigdecode_string(sig[1:], order) nV = ord(sig[0]) if nV < 27 or nV >= 35: raise BaseException("Bad encoding") if nV >= 31: compressed = True nV -= 4 else: 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 = ecdsa.ellipticcurve.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 = ecdsa.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.verify_digest( sig[1:], h, sigdecode=ecdsa.util.sigdecode_string ) # check that we get the original signing address addr = public_key_to_bc_address(encode_point(public_key, compressed)) if address != addr: raise BaseException("Bad signature")
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)