def test_decrypt_odd_length_data():
    random_key = get_random_value_hex(32)
    random_encrypted_data_odd = get_random_value_hex(64)[:-1]
    random_encrypted_blob_odd = random_encrypted_data_odd

    with pytest.raises(InvalidParameter, match="Odd-length"):
        Cryptographer.decrypt(random_encrypted_blob_odd, random_key)
def test_decrypt_wrong_key_size():
    random_key = get_random_value_hex(31)
    random_encrypted_data_odd = get_random_value_hex(64)
    random_encrypted_blob_odd = random_encrypted_data_odd

    with pytest.raises(InvalidParameter, match="32-byte hex value"):
        Cryptographer.decrypt(random_encrypted_blob_odd, random_key)
def test_decrypt_invalid_tag():
    random_key = get_random_value_hex(32)
    random_encrypted_data = get_random_value_hex(64)
    random_encrypted_blob = random_encrypted_data

    # Trying to decrypt random data should result in an EncryptionError
    with pytest.raises(EncryptionError,
                       match="Cannot decrypt blob with the provided key"):
        Cryptographer.decrypt(random_encrypted_blob, random_key)
예제 #4
0
def test_decrypt_wrong_key_size():
    random_key = get_random_value_hex(31)
    random_encrypted_data_odd = get_random_value_hex(64)
    random_encrypted_blob_odd = EncryptedBlob(random_encrypted_data_odd)

    try:
        Cryptographer.decrypt(random_encrypted_blob_odd, random_key)
        assert False

    except ValueError:
        assert True
예제 #5
0
def test_decrypt_odd_length_data():
    random_key = get_random_value_hex(32)
    random_encrypted_data_odd = get_random_value_hex(64)[:-1]
    random_encrypted_blob_odd = EncryptedBlob(random_encrypted_data_odd)

    try:
        Cryptographer.decrypt(random_encrypted_blob_odd, random_key)
        assert False

    except ValueError:
        assert True
예제 #6
0
def test_decrypt_invalid_tag():
    random_key = get_random_value_hex(32)
    random_encrypted_data = get_random_value_hex(64)
    random_encrypted_blob = EncryptedBlob(random_encrypted_data)

    # Trying to decrypt random data should result in an InvalidTag exception. Our decrypt function
    # returns None
    hex_tx = Cryptographer.decrypt(random_encrypted_blob, random_key)
    assert hex_tx is None
예제 #7
0
    def filter_valid_breaches(self, breaches):
        """
        Filters what of the found breaches contain valid transaction data.

        The :obj:`Watcher` cannot if a given :obj:`EncryptedBlob <common.encrypted_blob.EncryptedBlob>` contains a valid
        transaction until a breach if seen. Blobs that contain arbitrary data are dropped and not sent to the
        :obj:`Responder <teos.responder.Responder>`.

        Args:
            breaches (:obj:`dict`): a dictionary containing channel breaches (``locator:txid``).

        Returns:
            :obj:`dict`: A dictionary containing all the breaches flagged either as valid or invalid.
            The structure is as follows:

            ``{locator, dispute_txid, penalty_txid, penalty_rawtx, valid_breach}``
        """

        valid_breaches = {}
        invalid_breaches = []

        # A cache of the already decrypted blobs so replicate decryption can be avoided
        decrypted_blobs = {}

        for locator, dispute_txid in breaches.items():
            for uuid in self.locator_uuid_map[locator]:
                appointment = Appointment.from_dict(self.db_manager.load_watcher_appointment(uuid))

                if appointment.encrypted_blob.data in decrypted_blobs:
                    penalty_tx, penalty_rawtx = decrypted_blobs[appointment.encrypted_blob.data]

                else:
                    try:
                        penalty_rawtx = Cryptographer.decrypt(appointment.encrypted_blob, dispute_txid)

                    except ValueError:
                        penalty_rawtx = None

                    penalty_tx = self.block_processor.decode_raw_transaction(penalty_rawtx)
                    decrypted_blobs[appointment.encrypted_blob.data] = (penalty_tx, penalty_rawtx)

                if penalty_tx is not None:
                    valid_breaches[uuid] = {
                        "locator": locator,
                        "dispute_txid": dispute_txid,
                        "penalty_txid": penalty_tx.get("txid"),
                        "penalty_rawtx": penalty_rawtx,
                    }

                    logger.info(
                        "Breach found for locator", locator=locator, uuid=uuid, penalty_txid=penalty_tx.get("txid")
                    )

                else:
                    invalid_breaches.append(uuid)

        return valid_breaches, invalid_breaches
예제 #8
0
    def check_breach(self, uuid, appointment, dispute_txid):
        """
        Checks if a breach is valid. Valid breaches should decrypt to a valid transaction.

        Args:
            uuid (:obj:`str`): the uuid of the appointment that was triggered by the breach.
            appointment (:obj:`ExtendedAppointment <teos.extended_appointment.ExtendedAppointment>`): the appointment
                data.
            dispute_txid (:obj:`str`): the id of the transaction that triggered the breach.

        Returns:
            :obj:`tuple`: A tuple containing the penalty txid and the raw penalty tx.

        Raises:
            :obj:`EncryptionError`: if the encrypted blob from the provided appointment cannot be decrypted with the
                key derived from the breach transaction id.
            :obj:`InvalidTransactionFormat`: if the decrypted data does not have a valid transaction format.
        """

        try:
            penalty_rawtx = Cryptographer.decrypt(appointment.encrypted_blob,
                                                  dispute_txid)
            penalty_tx = self.block_processor.decode_raw_transaction(
                penalty_rawtx)

        except EncryptionError as e:
            self.logger.info("Transaction cannot be decrypted", uuid=uuid)
            raise e

        except InvalidTransactionFormat as e:
            self.logger.info("The breach contained an invalid transaction",
                             uuid=uuid)
            raise e

        self.logger.info("Breach found for locator",
                         locator=appointment.locator,
                         uuid=uuid,
                         penalty_txid=penalty_tx.get("txid"))

        return penalty_tx.get("txid"), penalty_rawtx
def test_decrypt():
    # Valid data should run with no InvalidTag and verify
    assert Cryptographer.decrypt(encrypted_data, key) == data