예제 #1
0
    def peek_message(self, input_buffer):
        """
        Peeks message from input frame
        :param input_buffer: input buffer
        :return: tuple (flag if full message is received, message type)
        """

        if not isinstance(input_buffer, InputBuffer):
            raise ValueError("Expected type InputBuffer")

        if self._full_message_received:
            raise ValueError("Get full message before trying to peek another one")

        if not self._receiving_frame and input_buffer.length >= eth_common_constants.FRAME_HDR_TOTAL_LEN:
            enc_header_bytes = input_buffer.remove_bytes(eth_common_constants.FRAME_HDR_TOTAL_LEN)
            header_bytes = self._rlpx_cipher.decrypt_frame_header(enc_header_bytes)
            body_size, protocol_id, sequence_id, total_payload_len = frame_utils.parse_frame_header(header_bytes)

            self._current_frame_body_size = body_size
            self._current_frame_protocol_id = protocol_id
            self._current_frame_size = frame_utils.get_full_frame_size(body_size)
            self._current_frame_enc_body_size = self._current_frame_size - eth_common_constants.FRAME_HDR_TOTAL_LEN
            self._current_frame_sequence_id = sequence_id

            if sequence_id == 0 and total_payload_len is not None:
                self._chunked_frames_in_progress = True
                self._chunked_frames_total_body_size = total_payload_len

            self._receiving_frame = True

        if self._receiving_frame and input_buffer.length >= self._current_frame_enc_body_size:
            frame_enc_body_bytes = input_buffer.remove_bytes(self._current_frame_enc_body_size)

            body = self._rlpx_cipher.decrypt_frame_body(frame_enc_body_bytes, self._current_frame_body_size)

            msg_type_is_expected = not self._chunked_frames_in_progress or self._current_frame_sequence_id == 0
            payload, msg_type = frame_utils.parse_frame_body(body, msg_type_is_expected)

            if msg_type_is_expected:
                self._current_msg_type = msg_type

            self._payload_buffer.add_bytes(bytearray(rlp_utils.str_to_bytes(payload)))

            if not self._chunked_frames_in_progress:
                self._full_message_received = True
            else:
                self._chunked_frames_body_size_received += len(body)

                if self._chunked_frames_body_size_received > self._chunked_frames_total_body_size:
                    raise ParseError("Expected total body length for frame message is {0} but received {1}"
                                     .format(self._chunked_frames_total_body_size,
                                             self._chunked_frames_body_size_received))

                if self._chunked_frames_body_size_received == self._chunked_frames_total_body_size:
                    self._full_message_received = True

            self._receiving_frame = False

        return self._full_message_received, self._current_msg_type
예제 #2
0
파일: eccx.py 프로젝트: mxito3/bxgateway
    def get_raw_public_key(self):
        """
        Raw public ley user by instance of ECCx
        :return: public key
        """

        if self.pubkey_x and self.pubkey_y:
            return rlp_utils.str_to_bytes(self.pubkey_x + self.pubkey_y)
        return self.pubkey_x + self.pubkey_y
예제 #3
0
파일: eccx.py 프로젝트: mxito3/bxgateway
    def get_raw_private_key(self):
        """
        Raw private key used by instance of ECCx
        :return: private key
        """

        if self.privkey:
            return rlp_utils.str_to_bytes(self.privkey)
        return self.privkey
예제 #4
0
    def serialize(self):
        cmd_id = rlp_utils.str_to_bytes(chr(self.msg_type))
        encoded_payload = self._serialize_rlp_payload()
        signed_data = eth_common_utils.keccak_hash(cmd_id + encoded_payload)
        signature = crypto_utils.sign(signed_data, self._private_key)

        assert len(signature) == eth_common_constants.SIGNATURE_LEN
        mdc = eth_common_utils.keccak_hash(signature + cmd_id +
                                           encoded_payload)

        assert len(mdc) == eth_common_constants.MDC_LEN
        msg_bytes = bytearray(mdc + signature + cmd_id + encoded_payload)

        self._set_raw_bytes(msg_bytes)
예제 #5
0
파일: eccx.py 프로젝트: mxito3/bxgateway
    def encrypt(cls, data, raw_public_key, shared_mac_data=""):
        """
        ECIES Encrypt, where P = recipient public key is:
        1) generate r = random value
        2) generate shared-secret = kdf( ecdhAgree(r, P) )
        3) generate R = rG [same op as generating a public key]
        4) send 0x04 || R || AsymmetricEncrypt(shared-secret, plaintext) || tag


        currently used by go:
        ECIES_AES128_SHA256 = &ECIESParams{
            Hash: sha256.New,
            hashAlgo: crypto.SHA256,
            Cipher: aes.NewCipher,
            BlockSize: aes.BlockSize,
            KeyLen: 16,
            }

        :param data: data to encrypt
        :param raw_public_key: public key used of encryption
        :param shared_mac_data: shared mac
        :return: encrypted data
        """

        if not data:
            raise ValueError("Data is required")

        if len(raw_public_key) != eth_common_constants.PUBLIC_KEY_LEN:
            raise ValueError(
                "Public key of len {0} is expected but was {1}".format(
                    eth_common_constants.PUBLIC_KEY_LEN, len(raw_public_key)))

        # 1) generate r = random value
        ephem = ECCx()

        # 2) generate shared-secret = kdf( ecdhAgree(r, P) )
        pubkey_x = raw_public_key[:eth_common_constants.PUBLIC_KEY_X_Y_LEN]
        pubkey_y = raw_public_key[eth_common_constants.PUBLIC_KEY_X_Y_LEN:]
        key_material = ephem.raw_get_ecdh_key(pubkey_x=pubkey_x,
                                              pubkey_y=pubkey_y)

        key = crypto_utils.ecies_kdf(key_material,
                                     eth_common_constants.SHARED_KEY_LEN)
        assert len(key) == eth_common_constants.SHARED_KEY_LEN
        key_enc, key_mac = key[:eth_common_constants.ENC_KEY_LEN], key[
            eth_common_constants.ENC_KEY_LEN:]

        key_mac = hashlib.sha256(key_mac).digest()

        # 3) generate R = rG [same op as generating a public key]
        ephem_pubkey = ephem.get_raw_public_key()

        # encrypt
        iv = pyelliptic.Cipher.gen_IV(eth_common_constants.ECIES_CIPHER_NAME)
        assert len(iv) == eth_common_constants.IV_LEN

        ctx = pyelliptic.Cipher(key_enc, iv,
                                eth_common_constants.CIPHER_ENCRYPT_DO,
                                eth_common_constants.ECIES_CIPHER_NAME)
        cipher_text = ctx.ciphering(data)
        assert len(cipher_text) == len(data)

        # 4) send 0x04 || R || AsymmetricEncrypt(shared-secret, plaintext) || tag
        msg = rlp_utils.ascii_chr(eth_common_constants.ECIES_HEADER
                                  ) + ephem_pubkey + iv + cipher_text

        # the MAC of a message (called the tag) as per SEC 1, 3.5.
        tag = pyelliptic.hmac_sha256(
            key_mac, msg[eth_common_constants.ECIES_HEADER_LEN +
                         eth_common_constants.PUBLIC_KEY_LEN:] +
            rlp_utils.str_to_bytes(shared_mac_data))
        assert len(tag) == eth_common_constants.MAC_LEN
        msg += tag

        assert len(
            msg) - eth_common_constants.ECIES_ENCRYPT_OVERHEAD_LENGTH == len(
                data)
        return msg
예제 #6
0
 def mac_ingress(self, data=b""):
     data = rlp_utils.str_to_bytes(data)
     self._ingress_mac.update(data)
     return self._ingress_mac.digest()