Esempio n. 1
0
    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())
Esempio n. 3
0
    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))