def verifyMessage(self, address, message, signature, message_magic=None) -> bool: if message_magic is None: message_magic = chainparams[self.coin_type()]['message_magic'] message_bytes = SerialiseNumCompact(len(message_magic)) + bytes( message_magic, 'utf-8') + SerialiseNumCompact( len(message)) + bytes(message, 'utf-8') message_hash = hashlib.sha256( hashlib.sha256(message_bytes).digest()).digest() signature_bytes = base64.b64decode(signature) rec_id = (signature_bytes[0] - 27) & 3 signature_bytes = signature_bytes[1:] + bytes((rec_id, )) try: pubkey = PublicKey.from_signature_and_message(signature_bytes, message_hash, hasher=None) except Exception as e: self._log.info('verifyMessage failed: ' + str(e)) return False address_hash = self.decodeAddress(address) pubkey_hash = hash160(pubkey.format()) return True if address_hash == pubkey_hash else False
def test_from_signature_and_message(self): assert (PublicKey.from_secret(PRIVATE_KEY_BYTES).format() == PublicKey.from_signature_and_message(RECOVERABLE_SIGNATURE, MESSAGE).format())
def process_handshake(self, peer, msg_mv): self._sc.log.debug('process_handshake %s', peer._address) # TODO: Drain peer._recv_messages if not peer._recv_messages.empty(): self._sc.log.warning( 'process_handshake %s - Receive queue dumped.', peer._address) while not peer._recv_messages.empty(): peer._recv_messages.get(False) msg = MsgHandshake() msg.decode(msg_mv) try: now = int(time.time()) if now - peer._last_handshake_at < 30: raise ValueError('Too many handshakes from peer %s', peer._address) if abs(msg._timestamp - now) > TIMESTAMP_LEEWAY: raise ValueError('Bad handshake timestamp from peer %s', peer._address) self.check_handshake_ephem_key(peer, msg._timestamp, msg._ephem_pk, direction=2) nk = PrivateKey(self._network_key) ss = nk.ecdh(msg._ephem_pk) hashed = hashlib.sha512( ss + struct.pack('>Q', msg._timestamp)).digest() peer._ke = hashed[:32] peer._km = hashed[32:] nonce = peer._km[24:] aad = msg.encode_aad() aad += nonce cipher = ChaCha20_Poly1305.new(key=peer._ke, nonce=nonce) cipher.update(aad) plaintext = cipher.decrypt_and_verify( msg._ct, msg._mac) # Will raise error if mac doesn't match peer._version = plaintext[:6] sig = plaintext[6:] pk_peer = PublicKey.from_signature_and_message(sig, peer._km) # TODO: Should pk_peer be linked to public data? peer._pubkey = pk_peer.format() peer._recv_nonce = hashlib.sha256(nonce + msg._mac).digest() peer._sent_nonce = hashlib.sha256(peer._km).digest() # Init nonce peer._last_handshake_at = msg._timestamp peer._ready = True # Schedule a ping to complete the handshake, TODO: Send here? peer._last_ping_at = 0 except Exception as e: # TODO: misbehaving self._sc.log.debug('[rm] process_handshake %s', str(e))