예제 #1
0
 async def read_msg(self) -> Tuple[protocol.Command, protocol.PayloadType]:
     header_data = await self.read(HEADER_LEN + MAC_LEN)
     header = self.decrypt_header(header_data)
     frame_size = self.get_frame_size(header)
     # The frame_size specified in the header does not include the padding to 16-byte boundary,
     # so need to do this here to ensure we read all the frame's data.
     read_size = roundup_16(frame_size)
     frame_data = await self.read(read_size + MAC_LEN)
     msg = self.decrypt_body(frame_data, frame_size)
     cmd = self.get_protocol_command_for(msg)
     # NOTE: This used to be a bottleneck but it doesn't seem to be so anymore. If we notice
     # too much time is being spent on this again, we need to consider running this in a
     # ProcessPoolExecutor(). Need to make sure we don't use all CPUs in the machine for that,
     # though, otherwise asyncio's event loop can't run and we can't keep up with other peers.
     try:
         decoded_msg = cast(Dict[str, Any], cmd.decode(msg))
     except MalformedMessage as err:
         self.logger.debug(
             "Malformed message from peer %s: CMD:%s Error: %r",
             self,
             type(cmd).__name__,
             err,
         )
         raise
     else:
         self.logger.trace("Successfully decoded %s msg: %s", cmd,
                           decoded_msg)
         self.received_msgs[cmd] += 1
         return cmd, decoded_msg
예제 #2
0
    def decrypt_body(self, data: bytes, body_size: int) -> bytes:
        read_size = roundup_16(body_size)
        if len(data) < read_size + MAC_LEN:
            raise ValueError(
                f"Insufficient body length; Got {len(data)}, wanted {read_size} + {MAC_LEN}"
            )

        frame_ciphertext = data[:read_size]
        frame_mac = data[read_size:read_size + MAC_LEN]

        self.ingress_mac.update(frame_ciphertext)
        fmac_seed = self.ingress_mac.digest()[:MAC_LEN]
        self.ingress_mac.update(sxor(self.mac_enc(fmac_seed), fmac_seed))
        expected_frame_mac = self.ingress_mac.digest()[:MAC_LEN]
        if not bytes_eq(expected_frame_mac, frame_mac):
            raise DecryptionError(
                f"Invalid frame mac: expected {expected_frame_mac}, got {frame_mac}"
            )
        return self.aes_dec.update(frame_ciphertext)[:body_size]