def test_inverse_mod(self): prime = generator_secp256k1.curve().p() order = generator_secp256k1.order() for v in range(70): n = int(float("1e%d" % v)) i = inverse_mod(n, prime) assert n * i % prime == 1 i = inverse_mod(n, order) assert n * i % order == 1
def verify_dash_signature(generator, address, message, signature): compressed = False G = generator curve = G.curve() order = G.order() _a, _b, _p = curve.a(), curve.b(), curve.p() sig = base64.b64decode(signature) if len(sig) != 65: raise Exception("vmB", "Bad signature") hb = ord(sig[0]) r, s = map(str_to_long, [sig[1:33], sig[33:65]]) if hb < 27 or hb >= 35: raise Exception("vmB", "Bad first byte") if hb >= 31: compressed = True hb -= 4 recid = hb - 27 x = (r + (recid / 2) * order) % _p y2 = (pow(x, 3, _p) + _a * x + _b) % _p yomy = numbertheory.modular_sqrt(y2, _p) if (yomy - recid) % 2 == 0: y = yomy else: y = _p - yomy R = ellipticcurve.Point(curve, x, y, order) e = str_to_long(message) minus_e = -e % order inv_r = numbertheory.inverse_mod(r, order) Q = inv_r * (R * s + G * minus_e) key = Key(public_pair=(Q.x(), Q.y()), netcode='DASH') return key.address(use_uncompressed=not compressed) == address
def sign(self, message, compact=True): """Signs the supplied message with the private key""" if compact: fd = io.BytesIO() stream_bc_string(fd, bytearray('Bitcoin Signed Message:\n', 'ascii')) stream_bc_string(fd, bytearray(message, 'utf-8')) mhash = from_bytes_32(double_sha256(fd.getvalue())) G = generator_secp256k1 n = G.order() k = from_bytes_32(os.urandom(32)) p1 = k * G r = p1.x() if r == 0: raise RuntimeError("amazingly unlucky random number r") s = (numbertheory.inverse_mod(k, n) * (mhash + (self.keypair.secret_exponent() * r) % n)) % n if s == 0: raise RuntimeError("amazingly unlucky random number s") y_odd = p1.y() % 2 assert y_odd in (0, 1) first = 27 + y_odd + (4 if not self.keypair._use_uncompressed(False) else 0) sig = binascii.b2a_base64(bytearray([first]) + to_bytes_32(r) + to_bytes_32(s)).strip() if not isinstance(sig, str): # python3 b2a wrongness sig = str(sig, 'ascii') return sig else: return keys.sign_sha256(self.private_key, message)