class KeyPair(object): """ ECDSA key pair. Args: pkey (str): hexadecimal representation of the private key (secret exponent). secret (str): master password. Attributes: keypair (:py:class:`pycoin.key.Key.Key`): BIP0032-style hierarchical wallet. Raises: NotImplementedError when a randomness source is not found. """ def __init__(self, pkey=None, secret=None): if secret is not None: pkey = format( BIP32Node.from_master_secret( secret.encode('utf-8')).secret_exponent(), "064x") elif pkey is None: try: pkey = format( BIP32Node.from_master_secret( urandom(4096)).secret_exponent(), '064x') except NotImplementedError as e: raise ValueError('No randomness source found: %s' % e) self.keypair = Key(secret_exponent=int(pkey, 16)) @property def node_id(self): """(str): NodeID derived from the public key (RIPEMD160 hash of public key).""" return b2h(self.keypair.hash160()) @property def public_key(self): """(str): public key.""" return b2h(self.keypair.sec(use_uncompressed=False)) @property def private_key(self): """(str): private key.""" return format(self.keypair.secret_exponent(), '064x') @property def address(self): """(): base58 encoded bitcoin address version of the nodeID.""" return self.keypair.address(use_uncompressed=False) 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)
secret_exponent = parse_as_secret_exponent(secret) if secret_exponent: privkey = Key(secret_exponent=secret_exponent) if SEC_RE.match(secret): privkey = Key.from_sec(unhexlify(secret)) else: try: privkey = Key.from_text(secret) except encoding.EncodingError: pass # Define vars automatically from privkey (could be manually, if you had the values) privkey_uncompressed = '%x' % privkey.secret_exponent() pubkey_uncompressed = hexlify(privkey.sec(use_uncompressed=True)) ## # Prepare pubkey for encrypting ## pubkey_bin_tmp = arithmetic.changebase(pubkey_uncompressed[2:], 16, 256, minlen=64) pubkey_bin = '\x02\xca\x00 ' + pubkey_bin_tmp[:32] + '\x00 ' + pubkey_bin_tmp[ 32:] # Optionally you can use unhexlify, but need to add '\x20' after '\x00' #pubkey_bin_tmp = unhexlify(pubkey_uncompressed)
return v secret_exponent = parse_as_secret_exponent(secret) if secret_exponent: privkey = Key(secret_exponent=secret_exponent) if SEC_RE.match(secret): privkey = Key.from_sec(unhexlify(secret)) else: try: privkey = Key.from_text(secret) except encoding.EncodingError: pass # Define vars automatically from privkey (could be manually, if you had the values) privkey_uncompressed = '%x' % privkey.secret_exponent() pubkey_uncompressed = hexlify(privkey.sec(use_uncompressed=True)) ## # Prepare pubkey for encrypting ## pubkey_bin_tmp = arithmetic.changebase(pubkey_uncompressed[2:], 16, 256, minlen=64) pubkey_bin = '\x02\xca\x00 '+ pubkey_bin_tmp[:32] + '\x00 ' + pubkey_bin_tmp[32:] # Optionally you can use unhexlify, but need to add '\x20' after '\x00' #pubkey_bin_tmp = unhexlify(pubkey_uncompressed) #pubkey_bin = '\x02\xca\x00\x20' + pubkey_bin_tmp[1:-32] + '\x00\x20' + pubkey_bin_tmp[-32:] ## # Prepare private key for decrypting