def setUp(self):
     # Set up KMSMasterKeyProvider patch
     self.mock_kms_client = MagicMock()
     self.mock_kms_client.__class__ = botocore.client.BaseClient
     self.mock_kms_client.generate_data_key.return_value = {
         'Plaintext': six.b(''.join(VALUES['data_key_256'])),
         'CiphertextBlob': VALUES['encrypted_data_key'],
         'KeyId': VALUES['arn']
     }
     self.mock_kms_client.encrypt.return_value = {
         'CiphertextBlob': VALUES['encrypted_data_key'],
         'KeyId': VALUES['arn']
     }
     self.mock_kms_client.decrypt.return_value = {
         'Plaintext': six.b(''.join(VALUES['data_key_256'])),
         'KeyId': VALUES['arn']
     }
     self.mock_kms_key_provider = KMSMasterKeyProvider()
     self.mock_kms_key_provider._regional_clients[
         'us-east-1'] = self.mock_kms_client
     self.mock_kms_key_provider.add_master_key(VALUES['arn'])
     self.fake_raw_key_provider_aes_gcm = FakeRawMasterKeyProvider(
         wrapping_algorithm=WrappingAlgorithm.
         AES_256_GCM_IV12_TAG16_NO_PADDING,
         encryption_key_type=EncryptionKeyType.SYMMETRIC)
     self.fake_raw_key_provider_aes_gcm.add_master_key('sym1')
     self.fake_raw_key_provider_rsa_pkcs1_private_key = FakeRawMasterKeyProvider(
         wrapping_algorithm=WrappingAlgorithm.RSA_PKCS1,
         encryption_key_type=EncryptionKeyType.PRIVATE)
     self.fake_raw_key_provider_rsa_pkcs1_private_key.add_master_key(
         'asym1')
     self.fake_raw_key_provider_rsa_pkcs1_public_key = FakeRawMasterKeyProvider(
         wrapping_algorithm=WrappingAlgorithm.RSA_PKCS1,
         encryption_key_type=EncryptionKeyType.PUBLIC)
     self.fake_raw_key_provider_rsa_pkcs1_public_key.add_master_key('asym1')
     self.fake_raw_key_provider_rsa_oaep_sha1_private_key = FakeRawMasterKeyProvider(
         wrapping_algorithm=WrappingAlgorithm.RSA_OAEP_SHA1_MGF1,
         encryption_key_type=EncryptionKeyType.PRIVATE)
     self.fake_raw_key_provider_rsa_oaep_sha1_private_key.add_master_key(
         'asym1')
     self.fake_raw_key_provider_rsa_oaep_sha1_public_key = FakeRawMasterKeyProvider(
         wrapping_algorithm=WrappingAlgorithm.RSA_OAEP_SHA1_MGF1,
         encryption_key_type=EncryptionKeyType.PUBLIC)
     self.fake_raw_key_provider_rsa_oaep_sha1_public_key.add_master_key(
         'asym1')
     self.fake_raw_key_provider_rsa_oaep_sha256_private_key = FakeRawMasterKeyProvider(
         wrapping_algorithm=WrappingAlgorithm.RSA_OAEP_SHA256_MGF1,
         encryption_key_type=EncryptionKeyType.PRIVATE)
     self.fake_raw_key_provider_rsa_oaep_sha256_private_key.add_master_key(
         'asym1')
     self.fake_raw_key_provider_rsa_oaep_sha256_public_key = FakeRawMasterKeyProvider(
         wrapping_algorithm=WrappingAlgorithm.RSA_OAEP_SHA256_MGF1,
         encryption_key_type=EncryptionKeyType.PUBLIC)
     self.fake_raw_key_provider_rsa_oaep_sha256_public_key.add_master_key(
         'asym1')
def encrypt_decrypt(key_arn, source_plaintext, botocore_session=None):
    """Encrypts and then decrypts a string under one KMS customer master key (CMK) with an unsigned algorithm.

    :param str key_arn: Amazon Resource Name (ARN) of the KMS CMK
    :param bytes source_plaintext: Data to encrypt
    :param botocore_session: existing botocore session instance
    :type botocore_session: botocore.session.Session
    """
    kwargs = dict(key_ids=[key_arn])

    if botocore_session is not None:
        kwargs["botocore_session"] = botocore_session

    # Create master key provider using the ARN of the key and the session (botocore_session)
    kms_key_provider = KMSMasterKeyProvider(**kwargs)

    # Encrypt the plaintext using the AWS Encryption SDK. It returns the encrypted message and the header
    ciphertext, encrypted_message_header = encrypt(
        algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA256,
        source=source_plaintext,
        key_provider=kms_key_provider)

    # Decrypt the encrypted message using the AWS Encryption SDK. It returns the decrypted message and the header
    plaintext, decrypted_message_header = decrypt(
        source=ciphertext, key_provider=kms_key_provider)

    # Check if the original message and the decrypted message are the same
    assert source_plaintext == plaintext

    # Check if the headers of the encrypted message and decrypted message match
    assert all(pair in encrypted_message_header.encryption_context.items()
               for pair in decrypted_message_header.encryption_context.items())
Exemplo n.º 3
0
def aws_kms_master_key_provider(**kwargs):
    # type: (**List[Union[Text, str]]) -> KMSMasterKeyProvider
    """Apply post-processing to transform ``KMSMasterKeyProvider``-specific values from CLI
    arguments to valid ``KMSMasterKeyProvider`` parameters, then call ``KMSMasterKeyprovider``
    with those parameters.

    :param dict kwargs: Named parameters collected from CLI arguments as prepared
        in aws_encryption_sdk_cli.internal.master_key_parsing._parse_master_key_providers_from_args
    :rtype: aws_encryption_sdk.key_providers.kms.KMSMasterKeyProvider
    """
    kwargs = copy.deepcopy(kwargs)
    try:
        profile_names = kwargs.pop("profile")
        if len(profile_names) != 1:
            raise BadUserArgumentError(
                "Only one profile may be specified per master key provider configuration. {} provided."
                .format(len(profile_names)))
        profile_name = profile_names[0]
    except KeyError:
        profile_name = None

    botocore_session = botocore.session.Session(profile=profile_name)
    botocore_session.user_agent_extra = USER_AGENT_SUFFIX
    kwargs["botocore_session"] = botocore_session

    try:
        region_name = kwargs.pop("region")
        if len(region_name) != 1:
            raise BadUserArgumentError(
                "Only one region may be specified per master key provider configuration. {} provided."
                .format(len(region_name)))
        kwargs["region_names"] = region_name
    except KeyError:
        pass
    return KMSMasterKeyProvider(**kwargs)
Exemplo n.º 4
0
    def encrypt(self):
        kms_key_provider = KMSMasterKeyProvider(
            key_ids=[self.kms_key],
            botocore_session=Session(profile=self.aws_profile))

        with open(self.path, 'rb') as plain_file, open(self.out_path,
                                                       'wb') as cipher_file:
            with aws_encryption_sdk.stream(
                    mode='e',
                    source=plain_file,
                    key_provider=kms_key_provider,
                    encryption_context=self.encryption_context,
                    frame_length=1048576) as encryptor:
                for chunk in encryptor:
                    cipher_file.write(chunk)
Exemplo n.º 5
0
    def decrypt(self):
        kms_key_provider = KMSMasterKeyProvider(
            key_ids=[self.kms_key],
            botocore_session=Session(profile=self.aws_profile))

        with open(self.path, 'rb') as cipher_file, open(self.out_path,
                                                        'wb') as plain_file:
            with aws_encryption_sdk.stream(
                    mode='d', source=cipher_file,
                    key_provider=kms_key_provider) as decryptor:
                encrypted_context = decryptor.header.encryption_context
                if self._dictionary_is_subset(
                        encrypted_context, self.encryption_context) is False:
                    decryptor.footer = None  # Set the footer so that when decryptor is closed when leaving the with
                    # context due to the raised exception, it doesn't throw its own unneeded exception
                    raise EncryptionContextMismatch()
                for chunk in decryptor:
                    plain_file.write(chunk)
def fake_kms_key_provider(keysize=32):
    mock_kms_key_provider = KMSMasterKeyProvider()
    mock_kms_key_provider._regional_clients["us-east-1"] = fake_kms_client(
        keysize)
    mock_kms_key_provider.add_master_key(VALUES["arn"])
    return mock_kms_key_provider
class TestAwsEncryptionSdkFunctional(unittest.TestCase):
    def setUp(self):
        # Set up KMSMasterKeyProvider patch
        self.mock_kms_client = MagicMock()
        self.mock_kms_client.__class__ = botocore.client.BaseClient
        self.mock_kms_client.generate_data_key.return_value = {
            'Plaintext': six.b(''.join(VALUES['data_key_256'])),
            'CiphertextBlob': VALUES['encrypted_data_key'],
            'KeyId': VALUES['arn']
        }
        self.mock_kms_client.encrypt.return_value = {
            'CiphertextBlob': VALUES['encrypted_data_key'],
            'KeyId': VALUES['arn']
        }
        self.mock_kms_client.decrypt.return_value = {
            'Plaintext': six.b(''.join(VALUES['data_key_256'])),
            'KeyId': VALUES['arn']
        }
        self.mock_kms_key_provider = KMSMasterKeyProvider()
        self.mock_kms_key_provider._regional_clients[
            'us-east-1'] = self.mock_kms_client
        self.mock_kms_key_provider.add_master_key(VALUES['arn'])
        self.fake_raw_key_provider_aes_gcm = FakeRawMasterKeyProvider(
            wrapping_algorithm=WrappingAlgorithm.
            AES_256_GCM_IV12_TAG16_NO_PADDING,
            encryption_key_type=EncryptionKeyType.SYMMETRIC)
        self.fake_raw_key_provider_aes_gcm.add_master_key('sym1')
        self.fake_raw_key_provider_rsa_pkcs1_private_key = FakeRawMasterKeyProvider(
            wrapping_algorithm=WrappingAlgorithm.RSA_PKCS1,
            encryption_key_type=EncryptionKeyType.PRIVATE)
        self.fake_raw_key_provider_rsa_pkcs1_private_key.add_master_key(
            'asym1')
        self.fake_raw_key_provider_rsa_pkcs1_public_key = FakeRawMasterKeyProvider(
            wrapping_algorithm=WrappingAlgorithm.RSA_PKCS1,
            encryption_key_type=EncryptionKeyType.PUBLIC)
        self.fake_raw_key_provider_rsa_pkcs1_public_key.add_master_key('asym1')
        self.fake_raw_key_provider_rsa_oaep_sha1_private_key = FakeRawMasterKeyProvider(
            wrapping_algorithm=WrappingAlgorithm.RSA_OAEP_SHA1_MGF1,
            encryption_key_type=EncryptionKeyType.PRIVATE)
        self.fake_raw_key_provider_rsa_oaep_sha1_private_key.add_master_key(
            'asym1')
        self.fake_raw_key_provider_rsa_oaep_sha1_public_key = FakeRawMasterKeyProvider(
            wrapping_algorithm=WrappingAlgorithm.RSA_OAEP_SHA1_MGF1,
            encryption_key_type=EncryptionKeyType.PUBLIC)
        self.fake_raw_key_provider_rsa_oaep_sha1_public_key.add_master_key(
            'asym1')
        self.fake_raw_key_provider_rsa_oaep_sha256_private_key = FakeRawMasterKeyProvider(
            wrapping_algorithm=WrappingAlgorithm.RSA_OAEP_SHA256_MGF1,
            encryption_key_type=EncryptionKeyType.PRIVATE)
        self.fake_raw_key_provider_rsa_oaep_sha256_private_key.add_master_key(
            'asym1')
        self.fake_raw_key_provider_rsa_oaep_sha256_public_key = FakeRawMasterKeyProvider(
            wrapping_algorithm=WrappingAlgorithm.RSA_OAEP_SHA256_MGF1,
            encryption_key_type=EncryptionKeyType.PUBLIC)
        self.fake_raw_key_provider_rsa_oaep_sha256_public_key.add_master_key(
            'asym1')

    def test_no_infinite_encryption_cycle_on_empty_source(self):
        """This catches a race condition where when calling encrypt with
            an empty byte string, encrypt would enter an infinite loop.
            If this test does not hang, the race condition is not present.
        """
        aws_encryption_sdk.encrypt(source=b'',
                                   key_provider=self.mock_kms_key_provider)

    def test_encrypt_load_header(self):
        """Test that StreamEncryptor can extract header without reading plaintext."""
        # Using a non-signed algorithm to simplify header size calculation
        algorithm = aws_encryption_sdk.Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA256
        header_length = len(
            serialize_encryption_context(VALUES['encryption_context']))
        header_length += 34
        header_length += algorithm.iv_len
        header_length += algorithm.auth_len
        header_length += 6 + 7 + len(VALUES['arn']) + len(
            VALUES['encrypted_data_key'])
        with aws_encryption_sdk.stream(
                mode='e',
                source=VALUES['plaintext_128'],
                key_provider=self.mock_kms_key_provider,
                encryption_context=VALUES['encryption_context'],
                algorithm=algorithm,
                frame_length=1024) as encryptor:
            encryptor_header = encryptor.header
        # Ensure that only the header has been written into the output buffer
        assert len(encryptor.output_buffer) == header_length
        assert encryptor_header.encryption_context == VALUES[
            'encryption_context']

    def test_encrypt_decrypt_header_only(self):
        """Test that StreamDecryptor can extract header without reading ciphertext."""
        ciphertext, encryptor_header = aws_encryption_sdk.encrypt(
            source=VALUES['plaintext_128'],
            key_provider=self.mock_kms_key_provider,
            encryption_context=VALUES['encryption_context'])
        with aws_encryption_sdk.stream(
                mode='d',
                source=ciphertext,
                key_provider=self.mock_kms_key_provider) as decryptor:
            decryptor_header = decryptor.header
        assert decryptor.output_buffer == b''
        assert all(pair in decryptor_header.encryption_context.items()
                   for pair in encryptor_header.encryption_context.items())

    def test_encryption_cycle_default_algorithm_non_framed(self):
        """Test that the enrypt/decrypt cycle completes
            successfully for a non-framed message
            using the default algorithm.
        """
        ciphertext, _ = aws_encryption_sdk.encrypt(
            source=VALUES['plaintext_128'],
            key_provider=self.mock_kms_key_provider,
            encryption_context=VALUES['encryption_context'],
            frame_length=0)
        plaintext, _ = aws_encryption_sdk.decrypt(
            source=ciphertext, key_provider=self.mock_kms_key_provider)
        assert plaintext == VALUES['plaintext_128']

    def test_encryption_cycle_default_algorithm_non_framed_fake_aes(self):
        """Test that the enrypt/decrypt cycle completes
            successfully for a non-framed message
            using the default algorithm and the fake AES-GCM
            key provider.
        """
        key_provider = self.fake_raw_key_provider_aes_gcm
        ciphertext, _ = aws_encryption_sdk.encrypt(
            source=VALUES['plaintext_128'],
            key_provider=key_provider,
            encryption_context=VALUES['encryption_context'],
            frame_length=0)
        plaintext, _ = aws_encryption_sdk.decrypt(source=ciphertext,
                                                  key_provider=key_provider)
        assert plaintext == VALUES['plaintext_128']

    def test_encryption_cycle_default_algorithm_non_framed_fake_rsa_pkcs(self):
        """Test that the enrypt/decrypt cycle completes
            successfully for a non-framed message
            using the default algorithm and the fake RSA-PKCS
            key provider.
        """
        key_provider = self.fake_raw_key_provider_rsa_pkcs1_private_key
        ciphertext, _ = aws_encryption_sdk.encrypt(
            source=VALUES['plaintext_128'],
            key_provider=key_provider,
            encryption_context=VALUES['encryption_context'],
            frame_length=0)
        plaintext, _ = aws_encryption_sdk.decrypt(source=ciphertext,
                                                  key_provider=key_provider)
        assert plaintext == VALUES['plaintext_128']

    def test_encryption_cycle_default_algorithm_non_framed_fake_rsa_pkcs_asymmetric(
            self):
        """Test that the enrypt/decrypt cycle completes
            successfully for a non-framed message
            using the default algorithm and the fake RSA-PKCS
            key provider.
        """
        ciphertext, _ = aws_encryption_sdk.encrypt(
            source=VALUES['plaintext_128'],
            key_provider=self.fake_raw_key_provider_rsa_pkcs1_public_key,
            encryption_context=VALUES['encryption_context'],
            frame_length=0)
        plaintext, _ = aws_encryption_sdk.decrypt(
            source=ciphertext,
            key_provider=self.fake_raw_key_provider_rsa_pkcs1_private_key)
        assert plaintext == VALUES['plaintext_128']

    def test_encryption_cycle_default_algorithm_non_framed_fake_rsa_oaep_sha1(
            self):
        """Test that the enrypt/decrypt cycle completes
            successfully for a non-framed message
            using the default algorithm and the fake RSA-OAEP-SHA1
            key provider.
        """
        key_provider = self.fake_raw_key_provider_rsa_oaep_sha1_private_key
        ciphertext, _ = aws_encryption_sdk.encrypt(
            source=VALUES['plaintext_128'],
            key_provider=key_provider,
            encryption_context=VALUES['encryption_context'],
            frame_length=0)
        plaintext, _ = aws_encryption_sdk.decrypt(source=ciphertext,
                                                  key_provider=key_provider)
        assert plaintext == VALUES['plaintext_128']

    def test_encryption_cycle_default_algorithm_non_framed_fake_rsa_oaep_sha1_asymmetric(
            self):
        """Test that the enrypt/decrypt cycle completes
            successfully for a non-framed message
            using the default algorithm and the fake RSA-OAEP-SHA1
            key provider.
        """
        ciphertext, _ = aws_encryption_sdk.encrypt(
            source=VALUES['plaintext_128'],
            key_provider=self.fake_raw_key_provider_rsa_oaep_sha1_public_key,
            encryption_context=VALUES['encryption_context'],
            frame_length=0)
        plaintext, _ = aws_encryption_sdk.decrypt(
            source=ciphertext,
            key_provider=self.fake_raw_key_provider_rsa_oaep_sha1_private_key)
        assert plaintext == VALUES['plaintext_128']

    @unittest.skipUnless(_mgf1_sha256_supported(),
                         'MGF1-SHA256 not supported by this backend')
    def test_encryption_cycle_default_algorithm_non_framed_fake_rsa_oaep_sha256(
            self):
        """Test that the enrypt/decrypt cycle completes
            successfully for a non-framed message
            using the default algorithm and the fake RSA-OAEP-SHA256
            key provider.
        """
        key_provider = self.fake_raw_key_provider_rsa_oaep_sha256_private_key
        ciphertext, _ = aws_encryption_sdk.encrypt(
            source=VALUES['plaintext_128'],
            key_provider=key_provider,
            encryption_context=VALUES['encryption_context'],
            frame_length=0)
        plaintext, _ = aws_encryption_sdk.decrypt(source=ciphertext,
                                                  key_provider=key_provider)
        assert plaintext == VALUES['plaintext_128']

    @unittest.skipUnless(_mgf1_sha256_supported(),
                         'MGF1-SHA256 not supported by this backend')
    def test_encryption_cycle_default_algorithm_non_framed_fake_rsa_oaep_sha256_asymmetric(
            self):
        """Test that the enrypt/decrypt cycle completes
            successfully for a non-framed message
            using the default algorithm and the fake RSA-OAEP-SHA256
            key provider.
        """
        ciphertext, _ = aws_encryption_sdk.encrypt(
            source=VALUES['plaintext_128'],
            key_provider=self.fake_raw_key_provider_rsa_oaep_sha256_public_key,
            encryption_context=VALUES['encryption_context'],
            frame_length=0)
        plaintext, _ = aws_encryption_sdk.decrypt(
            source=ciphertext,
            key_provider=self.fake_raw_key_provider_rsa_oaep_sha256_private_key
        )
        assert plaintext == VALUES['plaintext_128']

    def test_encryption_cycle_default_algorithm_non_framed_no_encryption_context(
            self):
        """Test that the enrypt/decrypt cycle completes
            successfully for a non-framed message
            using the default algorithm.
        """
        ciphertext, _ = aws_encryption_sdk.encrypt(
            source=VALUES['plaintext_128'],
            key_provider=self.mock_kms_key_provider,
            frame_length=0)
        plaintext, _ = aws_encryption_sdk.decrypt(
            source=ciphertext, key_provider=self.mock_kms_key_provider)
        assert plaintext == VALUES['plaintext_128']

    def test_encryption_cycle_default_algorithm_single_frame(self):
        """Test that the enrypt/decrypt cycle completes
            successfully for a single frame message
            using the default algorithm.
        """
        ciphertext, _ = aws_encryption_sdk.encrypt(
            source=VALUES['plaintext_128'],
            key_provider=self.mock_kms_key_provider,
            encryption_context=VALUES['encryption_context'],
            frame_length=1024)
        plaintext, _ = aws_encryption_sdk.decrypt(
            source=ciphertext, key_provider=self.mock_kms_key_provider)
        assert plaintext == VALUES['plaintext_128']

    def test_encryption_cycle_default_algorithm_multiple_frames(self):
        """Test that the enrypt/decrypt cycle completes
            successfully for a framed message with multiple
            frames using the default algorithm.
        """
        ciphertext, _ = aws_encryption_sdk.encrypt(
            source=VALUES['plaintext_128'] * 100,
            key_provider=self.mock_kms_key_provider,
            encryption_context=VALUES['encryption_context'],
            frame_length=1024)
        plaintext, _ = aws_encryption_sdk.decrypt(
            source=ciphertext, key_provider=self.mock_kms_key_provider)
        assert plaintext == VALUES['plaintext_128'] * 100

    def test_encryption_cycle_default_algorithm_framed_stream(self):
        """Test that the enrypt/decrypt cycle completes successfully
            for a framed message using the default algorithm.
        """
        encryptor = aws_encryption_sdk.stream(
            source=io.BytesIO(VALUES['plaintext_128']),
            key_provider=self.mock_kms_key_provider,
            mode='e',
            encryption_context=VALUES['encryption_context'])
        ciphertext = encryptor.read()
        encryptor.close()
        header_1 = encryptor.header
        decryptor = aws_encryption_sdk.stream(
            source=io.BytesIO(ciphertext),
            key_provider=self.mock_kms_key_provider,
            mode='d')
        plaintext = decryptor.read()
        decryptor.close()
        header_2 = decryptor.header
        assert plaintext == VALUES['plaintext_128']
        assert header_1.encryption_context == header_2.encryption_context

    def test_encryption_cycle_default_algorithm_framed_stream_many_lines_readlines(
            self):
        """Test that the streaming enrypt/decrypt cycle completes
            successfully for a framed message with multiple
            frames using the default algorithm.
        """
        ciphertext = b''
        encryptor = aws_encryption_sdk.stream(
            source=io.BytesIO(VALUES['plaintext_128'] * 100),
            key_provider=self.mock_kms_key_provider,
            mode='e',
            encryption_context=VALUES['encryption_context'],
            frame_length=128)
        for chunk in encryptor.readlines():
            ciphertext += chunk
        encryptor.close()
        header_1 = encryptor.header
        plaintext = b''
        decryptor = aws_encryption_sdk.stream(
            source=io.BytesIO(ciphertext),
            key_provider=self.mock_kms_key_provider,
            mode='d')
        for chunk in decryptor.readlines():
            plaintext += chunk
        decryptor.close()
        header_2 = decryptor.header
        assert plaintext == VALUES['plaintext_128'] * 100
        assert header_1.encryption_context == header_2.encryption_context

    def test_encryption_cycle_default_algorithm_framed_stream_many_lines_iterator(
            self):
        """Test that the streaming enrypt/decrypt cycle completes
            successfully for a framed message with multiple
            frames using the default algorithm.
        """
        ciphertext = b''
        encryptor = aws_encryption_sdk.stream(
            source=io.BytesIO(VALUES['plaintext_128'] * 100),
            key_provider=self.mock_kms_key_provider,
            mode='e',
            encryption_context=VALUES['encryption_context'],
            frame_length=128)
        for chunk in encryptor:
            ciphertext += chunk
        encryptor.close()
        header_1 = encryptor.header
        plaintext = b''
        decryptor = aws_encryption_sdk.stream(
            source=io.BytesIO(ciphertext),
            key_provider=self.mock_kms_key_provider,
            mode='d')
        for chunk in decryptor:
            plaintext += chunk
        decryptor.close()
        header_2 = decryptor.header
        assert plaintext == VALUES['plaintext_128'] * 100
        assert header_1.encryption_context == header_2.encryption_context

    def test_encryption_cycle_default_algorithm_framed_stream_many_lines_with_statement(
            self):
        """Test that the streaming enrypt/decrypt cycle completes
            successfully using the iterator behavior.
        """
        ciphertext = b''
        with aws_encryption_sdk.stream(
                source=io.BytesIO(VALUES['plaintext_128'] * 100),
                key_provider=self.mock_kms_key_provider,
                mode='e',
                encryption_context=VALUES['encryption_context'],
                frame_length=128) as encryptor:
            for chunk in encryptor:
                ciphertext += chunk
        header_1 = encryptor.header
        plaintext = b''
        with aws_encryption_sdk.stream(source=io.BytesIO(ciphertext),
                                       key_provider=self.mock_kms_key_provider,
                                       mode='d') as decryptor:
            for chunk in decryptor:
                plaintext += chunk
        header_2 = decryptor.header
        assert plaintext == VALUES['plaintext_128'] * 100
        assert header_1.encryption_context == header_2.encryption_context

    def test_decrypt_legacy_provided_message(self):
        """Tests backwards compatiblity against some legacy provided ciphertext."""
        region = 'us-west-2'
        key_info = 'arn:aws:kms:us-west-2:249645522726:key/d1720f4e-953b-44bb-b9dd-fc8b9d0baa5f'
        self.mock_kms_client.decrypt.return_value = {
            'Plaintext': six.b(''.join(VALUES['provided']['key']))
        }
        self.mock_kms_key_provider._regional_clients[
            region] = self.mock_kms_client
        self.mock_kms_key_provider.add_master_key(key_info)
        plaintext, _ = aws_encryption_sdk.decrypt(
            source=VALUES['provided']['ciphertext'],
            key_provider=self.mock_kms_key_provider)
        self.assertEqual(plaintext, VALUES['provided']['plaintext'])