def get_key(self, compressed=None): """Get the hex-encoded key. :param compressed: False if you want a standard 65 Byte key (the most standard option). True if you want the compressed 33 Byte form. Defaults to None, which in turn uses the self.compressed attribute. :type compressed: bool PublicKeys consist of an ID byte, the x, and the y coordinates on the elliptic curve. In the case of uncompressed keys, the ID byte is 04. Compressed keys use the SEC1 format: If Y is odd: id_byte = 03 else: id_byte = 02 Note that I pieced this algorithm together from the pycoin source. This is documented in http://www.secg.org/collateral/sec1_final.pdf but, honestly, it's pretty confusing. I guess this is a pretty big warning that I'm not *positive* this will do the right thing in all cases. The tests pass, and this does exactly what pycoin does, but I'm not positive pycoin works either! """ if compressed is None: compressed = self.compressed if compressed: parity = 2 + (self.y & 1) # 0x02 even, 0x03 odd return ensure_bytes( long_to_hex(parity, 2) + long_to_hex(self.x, 64)) else: return ensure_bytes(b'04' + long_to_hex(self.x, 64) + long_to_hex(self.y, 64))
def from_hex_key(cls, key, network=BitcoinMainNet): """Load the PublicKey from a compressed or uncompressed hex key. This format is defined in PublicKey.get_key() """ if len(key) == 130 or len(key) == 66: # It might be a hexlified byte array try: key = unhexlify(ensure_bytes(key)) except (TypeError, binascii.Error): pass key = ensure_bytes(key) compressed = False id_byte = key[0] if not isinstance(id_byte, six.integer_types): id_byte = ord(id_byte) if id_byte == 4: # Uncompressed public point # 1B ID + 32B x coord + 32B y coord = 65 B if len(key) != 65: raise KeyParseError("Invalid key length") public_pair = PublicPair(long_or_int(hexlify(key[1:33]), 16), long_or_int(hexlify(key[33:]), 16)) elif id_byte in [2, 3]: # Compressed public point! compressed = True if len(key) != 33: raise KeyParseError("Invalid key length") y_odd = bool(id_byte & 0x01) # 0 even, 1 odd x = long_or_int(hexlify(key[1:]), 16) # The following x-to-pair algorithm was lifted from pycoin # I still need to sit down an understand it. It is also described # in http://www.secg.org/collateral/sec1_final.pdf curve = SECP256k1.curve p = curve.p() # For SECP256k1, curve.a() is 0 and curve.b() is 7, so this is # effectively (x ** 3 + 7) % p, but the full equation is kept # for just-in-case-the-curve-is-broken future-proofing alpha = (pow(x, 3, p) + curve.a() * x + curve.b()) % p beta = square_root_mod_prime(alpha, p) y_even = not y_odd if y_even == bool(beta & 1): public_pair = PublicPair(x, p - beta) else: public_pair = PublicPair(x, beta) else: raise KeyParseError("The given key is not in a known format.") return cls.from_public_pair(public_pair, network=network, compressed=compressed)
def get_extended_key(self): """Get the extended key. Extended keys contain the network bytes and the public or private key. """ network_hex_chars = hexlify(chr_py2(self.network.SECRET_KEY)) return ensure_bytes(network_hex_chars + self.get_key())
def from_hex_key(cls, key, network=BitcoinMainNet): if len(key) == 32: # Oh! we have bytes instead of a hex string key = hexlify(key) key = ensure_bytes(key) if not is_hex_string(key) or len(key) != 64: raise ValueError("Invalid hex key") return cls(long_or_int(key, 16), network)
def from_master_password(cls, password, network=BitcoinMainNet): """Generate a new key from a master password. This password is hashed via a single round of sha256 and is highly breakable, but it's the standard brainwallet approach. See `PrivateKey.from_master_password_slow` for a slightly more secure generation method (which will still be subject to a rainbow table attack :\) """ password = ensure_bytes(password) key = sha256(password).hexdigest() return cls.from_hex_key(key, network)
def to_address(self, compressed=None): """Create a public address from this key. :param compressed: False if you want a normal uncompressed address (the most standard option). True if you want the compressed form. Note that most clients will not accept compressed addresses. Defaults to None, which in turn uses the self.compressed attribute. :type compressed: bool https://en.bitcoin.it/wiki/Technical_background_of_Bitcoin_addresses """ key = unhexlify(ensure_bytes(self.get_key(compressed))) # First get the hash160 of the key hash160_bytes = hash160(key) # Prepend the network address byte network_hash160_bytes = \ chr_py2(self.network.PUBKEY_ADDRESS) + hash160_bytes # Return a base58 encoded address with a checksum return ensure_str(base58.b58encode_check(network_hash160_bytes))
def export_to_wif(self, compressed=None): """Export a key to WIF. :param compressed: False if you want a standard WIF export (the most standard option). True if you want the compressed form (Note that not all clients will accept this form). Defaults to None, which in turn uses the self.compressed attribute. :type compressed: bool See https://en.bitcoin.it/wiki/Wallet_import_format for a full description. """ # Add the network byte, creating the "extended key" extended_key_hex = self.get_extended_key() extended_key_bytes = unhexlify(ensure_bytes(extended_key_hex)) if compressed is None: compressed = self.compressed if compressed: extended_key_bytes += b'\01' # And return the base58-encoded result with a checksum return ensure_str(base58.b58encode_check(extended_key_bytes))
import socket from time import ctime import utils HOST = '' PORT = 21567 BUFSIZE = 1024 ADDR = (HOST, PORT) sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.bind(ADDR) sock.listen(5) while True: print("waiting for connection...") client_sock, addr = sock.accept() print("connection from: ", addr) while True: data = client_sock.recv(BUFSIZE) if not data: break msg = '[%s] %s' % (ctime(), utils.ensure_unicode(data)) print('Received: ', msg) client_sock.send(utils.ensure_bytes(msg)) client_sock.close() sock.close()
import socket import utils HOST = 'localhost' service = 'daytime' port = socket.getservbyname(service) sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.connect((HOST, port)) sock.send(utils.ensure_bytes(service)) data = sock.recvfrom(1024) print(utils.ensure_unicode(data)) sock.close()
def get_key(self): """Get the key - a hex formatted private exponent for the curve.""" return ensure_bytes(hexlify(self._private_key.to_string()))
def handle(self): print("...connection from: ", self.client_address) msg = '[%s] %s' % (ctime(), utils.ensure_unicode(self.rfile.readline()).strip()) print(msg) self.wfile.write(utils.ensure_bytes(msg))