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(self):
     """Test that the enrypt/decrypt cycle completes successfully
         for a framed message with many frames using the default algorithm.
     """
     ciphertext = b""
     with aws_encryption_sdk.stream(
             source=io.BytesIO(VALUES["plaintext_128"] * 10),
             key_provider=self.kms_master_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.kms_master_key_provider,
             mode="d") as decryptor:
         for chunk in decryptor:
             plaintext += chunk
     header_2 = decryptor.header
     assert plaintext == VALUES["plaintext_128"] * 10
     assert header_1.encryption_context == header_2.encryption_context
示例#3
0
 def test_stream_unknown(self):
     with pytest.raises(ValueError) as excinfo:
         aws_encryption_sdk.stream(mode="ERROR",
                                   a=sentinel.a,
                                   b=sentinel.b,
                                   c=sentinel.b)
     excinfo.match("Unsupported mode: *")
def test_encryption_cycle_stream_kms(frame_length, algorithm,
                                     encryption_context):
    key_provider = fake_kms_key_provider(algorithm.kdf_input_len)

    ciphertext = bytearray()
    with aws_encryption_sdk.stream(
            mode="e",
            source=VALUES["plaintext_128"] * 10,
            key_provider=key_provider,
            frame_length=frame_length,
            algorithm=algorithm,
            encryption_context=encryption_context,
    ) as encryptor:
        for chunk in encryptor:
            ciphertext.extend(chunk)
    ciphertext = bytes(ciphertext)

    plaintext = bytearray()
    with aws_encryption_sdk.stream(mode="d",
                                   source=io.BytesIO(ciphertext),
                                   key_provider=key_provider) as decryptor:
        for chunk in decryptor:
            plaintext.extend(chunk)
    plaintext = bytes(plaintext)

    assert ciphertext != plaintext
    assert plaintext == VALUES["plaintext_128"] * 10
    assert encryptor.header.encryption_context == decryptor.header.encryption_context
示例#5
0
 def test_stream_unknown(self):
     with six.assertRaisesRegex(self, ValueError, 'Unsupported mode: *'):
         aws_encryption_sdk.stream(
             mode='ERROR',
             a=sentinel.a,
             b=sentinel.b,
             c=sentinel.b
         )
def encrypt_decrypt_stream(key_arn,
                           source_plaintext_filename,
                           botocore_session=None):
    """Encrypts and then decrypts streaming data under one KMS customer master key (CMK).

    :param str key_arn: Amazon Resource Name (ARN) of the KMS CMK
    :param str source_plaintext_filename: Filename of file to encrypt
    :param botocore_session: existing botocore session instance
    :type botocore_session: botocore.session.Session
    """
    kwargs = dict()

    kwargs["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 = aws_encryption_sdk.KMSMasterKeyProvider(**kwargs)

    ciphertext_filename = source_plaintext_filename + ".encrypted"
    decrypted_text_filename = source_plaintext_filename + ".decrypted"

    # Encrypt the plaintext using the AWS Encryption SDK.
    with open(source_plaintext_filename,
              "rb") as plaintext, open(ciphertext_filename,
                                       "wb") as ciphertext:
        with aws_encryption_sdk.stream(
                source=plaintext, mode="e",
                key_provider=kms_key_provider) as encryptor:
            for chunk in encryptor:
                ciphertext.write(chunk)

    # Decrypt the encrypted message using the AWS Encryption SDK.
    with open(ciphertext_filename,
              "rb") as ciphertext, open(decrypted_text_filename,
                                        "wb") as plaintext:
        with aws_encryption_sdk.stream(
                source=ciphertext, mode="d",
                key_provider=kms_key_provider) as decryptor:
            for chunk in decryptor:
                plaintext.write(chunk)

    # Check if the original message and the decrypted message are the same
    assert filecmp.cmp(source_plaintext_filename, decrypted_text_filename)

    # Check if the headers of the encrypted message and decrypted message match
    assert all(pair in encryptor.header.encryption_context.items()
               for pair in decryptor.header.encryption_context.items())
    return ciphertext_filename, decrypted_text_filename
def encrypt_file(source_plaintext_filename, path_to_pem_file):
    """Encrypts a file.....

    :param str xxxxxxx: xxxxxxx
    :param str xxxxx: yyyyyyyy
    """
    print("Plaintext file in: %s [%s bytes]" % (source_plaintext_filename, len(source_plaintext_filename)))
    print("Public key file in: %s" % path_to_pem_file)

    ciphertext_filename = source_plaintext_filename + '.encrypted'

    # Load the key
    local_key_id = os.urandom(8)
    local_master_key_provider = LocalRSAMasterKeyProvider()
    local_master_key_provider.set_public_key_path(path_to_pem_file)
    local_master_key_provider.add_master_key(local_key_id)

    # Encrypt plaintext with local master keys
    with open(source_plaintext_filename, 'rb') as plaintext, open(ciphertext_filename, 'wb') as ciphertext:
        with aws_encryption_sdk.stream(
            source=plaintext,
            mode='e',
            key_provider=local_master_key_provider
        ) as encryptor:
            for chunk in encryptor:
                ciphertext.write(chunk)
    print("Encrypted file in: %s [%s bytes]" % (ciphertext_filename, len(ciphertext_filename)))

    return ciphertext_filename
 def decrypt_file_to_env(self, key_alias, input_filename):
     key_provider = self.build_kms_master_key_provider(key_alias)
     used_keys = []
     output = cStringIO.StringIO()
     p = subprocess.Popen(['/bin/bash'],
                          env={},
                          stdin=subprocess.PIPE,
                          stdout=subprocess.PIPE)
     with open(input_filename, 'rb') as infile, \
             aws_encryption_sdk.stream(
                 mode='d',
                 source=infile,
                 key_provider=key_provider
             ) as decryptor:
         for chunk in decryptor:
             output.write(chunk)
     output.seek(0)
     for output_line in output:
         (key, _, _) = output_line.partition("=")
         used_keys.append(key)
         p.stdin.write(output_line)
     p.stdin.write('\nset\nexit\n')
     for line in p.stdout:
         (key, _, value) = line.partition("=")
         if key in used_keys:
             print(line.strip())
def test_decryptor_deprecated_attributes(caplog, attribute, no_later_than):
    caplog.set_level(logging.WARNING)
    plaintext = exact_length_plaintext(100)
    key_provider = fake_kms_key_provider()
    ciphertext, _header = aws_encryption_sdk.encrypt(source=plaintext,
                                                     key_provider=key_provider,
                                                     frame_length=0)
    with aws_encryption_sdk.stream(mode="decrypt",
                                   source=ciphertext,
                                   key_provider=key_provider) as decryptor:
        decrypted = decryptor.read()

    assert decrypted == plaintext
    if aws_encryption_sdk.__version__ < no_later_than:
        _assert_deprecated_but_not_yet_removed(
            logcap=caplog,
            instance=decryptor,
            attribute_name=attribute,
            error_message=
            "StreamDecryptor.{name} is deprecated and will be removed in {version}"
            .format(name=attribute, version=no_later_than),
            no_later_than=no_later_than,
        )
    else:
        _assert_decrypted_and_removed(instance=decryptor,
                                      attribute_name=attribute,
                                      removed_in=no_later_than)
示例#10
0
    def encrypt_file(self, source_file_name, target_file_name):
        """
        Encrypt a file using aws_encryption SDK and a KMS key

        :param source_file_name: File name (path) to encrypt
        :type source_file_name: str
        :param target_file_name: File name (path) to be used as target encrypted file. Use to be a NamedTemporaryFile
        :type target_file_name: str
        """

        logging.info('Open a AWS session for KMS actions using ')

        kms_key_provider = aws_encryption_sdk.KMSMasterKeyProvider(
            config=self.get_conn(), key_ids=[self.aws_kms_key_arn])

        with open(source_file_name,
                  'rb') as pt_file, open(target_file_name, 'wb') as ct_file:
            with aws_encryption_sdk.stream(mode='e',
                                           source=pt_file,
                                           key_provider=kms_key_provider,
                                           frame_length=1024) as encryptor:
                for chunk in encryptor:
                    ct_file.write(chunk)

        logging.info('Comparing source and target files:')
        logging.info('Source file size: {}kb'.format(
            os.stat(source_file_name).st_size >> 10))
        logging.info('Source file type: [{}]'.format(
            magic.from_file(source_file_name)))
        logging.info('Taget file size: {}kb'.format(
            os.stat(target_file_name).st_size >> 10))
        logging.info('Target file type: [{}]'.format(
            magic.from_file(target_file_name)))

        return target_file_name
示例#11
0
    def _stream(self, source, destination, mode):
        with aws_encryption_sdk.stream(
                mode=mode, source=source,
                key_provider=self._kms_key_provider) as encryptor:
            for chunk in encryptor:
                destination.write(chunk)

        destination.seek(0)
示例#12
0
 def test_stream_decryptor_decrypt(self):
     test = aws_encryption_sdk.stream(
         mode='DECRYPT',
         a=sentinel.a,
         b=sentinel.b,
         c=sentinel.b
     )
     assert test is self.mock_stream_decryptor_instance
示例#13
0
def run(source_plaintext_filename):
    """Encrypts and then decrypts a file under a custom static master key provider.

    :param str source_plaintext_filename: Filename of file to encrypt
    """
    # Create a static random master key provider
    key_id = os.urandom(8)
    master_key_provider = StaticRandomMasterKeyProvider()
    master_key_provider.add_master_key(key_id)

    ciphertext_filename = source_plaintext_filename + ".encrypted"
    cycled_plaintext_filename = source_plaintext_filename + ".decrypted"

    # Encrypt the plaintext source data
    with open(source_plaintext_filename,
              "rb") as plaintext, open(ciphertext_filename,
                                       "wb") as ciphertext:
        with aws_encryption_sdk.stream(
                mode="e", source=plaintext,
                key_provider=master_key_provider) as encryptor:
            for chunk in encryptor:
                ciphertext.write(chunk)

    # Decrypt the ciphertext
    with open(ciphertext_filename,
              "rb") as ciphertext, open(cycled_plaintext_filename,
                                        "wb") as plaintext:
        with aws_encryption_sdk.stream(
                mode="d", source=ciphertext,
                key_provider=master_key_provider) as decryptor:
            for chunk in decryptor:
                plaintext.write(chunk)

    # Verify that the "cycled" (encrypted, then decrypted) plaintext is identical to the source
    # plaintext
    assert filecmp.cmp(source_plaintext_filename, cycled_plaintext_filename)

    # Verify that the encryption context used in the decrypt operation includes all key pairs from
    # the encrypt operation
    #
    # In production, always use a meaningful encryption context. In this sample, we omit the
    # encryption context (no key pairs).
    assert all(pair in decryptor.header.encryption_context.items()
               for pair in encryptor.header.encryption_context.items())
    return ciphertext_filename, cycled_plaintext_filename
示例#14
0
 def test_stream_decryptor_d(self):
     test = aws_encryption_sdk.stream(mode="d",
                                      a=sentinel.a,
                                      b=sentinel.b,
                                      c=sentinel.b)
     assert test is self.mock_stream_decryptor_instance
     self.mock_stream_decryptor.assert_called_once_with(a=sentinel.a,
                                                        b=sentinel.b,
                                                        c=sentinel.b)
 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.
     """
     with aws_encryption_sdk.stream(
             source=io.BytesIO(VALUES['plaintext_128']),
             key_provider=self.kms_master_key_provider,
             mode='e',
             encryption_context=VALUES['encryption_context']) as encryptor:
         ciphertext = encryptor.read()
     header_1 = encryptor.header
     with aws_encryption_sdk.stream(
             source=io.BytesIO(ciphertext),
             key_provider=self.kms_master_key_provider,
             mode='d') as decryptor:
         plaintext = decryptor.read()
     header_2 = decryptor.header
     assert plaintext == VALUES['plaintext_128']
     assert header_1.encryption_context == header_2.encryption_context
def test_incomplete_read_stream_cycle(frame_length):
    chunk_size = 21  # Will never be an exact match for the frame size
    key_provider = fake_kms_key_provider()

    plaintext = exact_length_plaintext(384)
    ciphertext = b""
    cycle_count = 0
    with aws_encryption_sdk.stream(
            mode="encrypt",
            source=SometimesIncompleteReaderIO(plaintext),
            key_provider=key_provider,
            frame_length=frame_length,
    ) as encryptor:
        while True:
            cycle_count += 1
            chunk = encryptor.read(chunk_size)
            if not chunk:
                break
            ciphertext += chunk
            if cycle_count > len(VALUES["plaintext_128"]):
                raise aws_encryption_sdk.exceptions.AWSEncryptionSDKClientError(
                    "Unexpected error encrypting message: infinite loop detected."
                )

    decrypted = b""
    cycle_count = 0
    with aws_encryption_sdk.stream(
            mode="decrypt",
            source=SometimesIncompleteReaderIO(ciphertext),
            key_provider=key_provider) as decryptor:
        while True:
            cycle_count += 1
            chunk = decryptor.read(chunk_size)
            if not chunk:
                break
            decrypted += chunk
            if cycle_count > len(VALUES["plaintext_128"]):
                raise aws_encryption_sdk.exceptions.AWSEncryptionSDKClientError(
                    "Unexpected error encrypting message: infinite loop detected."
                )

    assert ciphertext != decrypted == plaintext
示例#17
0
def encrypt_file(file):
    ct_filename = str(file) + '.ct'
    with open(file, 'rb') as pt_file, open(ct_filename, 'wb') as ct_file:
        with aws_encryption_sdk.stream(
                mode='e',
                source=pt_file,
                key_provider=kms_key_provider
        ) as encryptor:
            for chunk in encryptor:
                ct_file.write(chunk)
    return ct_filename
示例#18
0
 def decrypt_file(self, key_alias, input_filename, output_filename):
     key_provider = self.build_kms_master_key_provider(key_alias)
     with open(input_filename, 'rb') as infile, \
             open(output_filename, 'wb') as outfile, \
             aws_encryption_sdk.stream(
                 mode='d',
                 source=infile,
                 key_provider=key_provider
             ) as decryptor:
         for chunk in decryptor:
             outfile.write(chunk)
示例#19
0
    def _single_io_write(self, stream_args, source, destination_writer):
        # type: (STREAM_KWARGS, IO, IO) -> OperationResult
        """Performs the actual write operations for a single operation.

        :param dict stream_args: kwargs to pass to `aws_encryption_sdk.stream`
        :param source: source to write
        :type source: file-like object
        :param destination_writer: destination object to which to write
        :type destination_writer: file-like object
        :returns: OperationResult stating whether the file was written
        :rtype: aws_encryption_sdk_cli.internal.identifiers.OperationResult
        """
        with _encoder(source, self.decode_input) as _source, _encoder(
            destination_writer, self.encode_output
        ) as _destination:  # noqa pylint: disable=line-too-long
            with aws_encryption_sdk.stream(source=_source, **stream_args) as handler, self.metadata_writer as metadata:
                metadata_kwargs = dict(
                    mode=stream_args["mode"],
                    input=source.name,
                    output=destination_writer.name,
                    header=json_ready_header(handler.header),
                )
                try:
                    header_auth = handler.header_auth
                except AttributeError:
                    # EncryptStream doesn't expose the header auth at this time
                    pass
                else:
                    metadata_kwargs["header_auth"] = json_ready_header_auth(header_auth)

                if stream_args["mode"] == "decrypt":
                    discovered_ec = handler.header.encryption_context
                    missing_keys = set(self.required_encryption_context_keys).difference(set(discovered_ec.keys()))
                    missing_pairs = set(self.required_encryption_context.items()).difference(set(discovered_ec.items()))
                    if missing_keys or missing_pairs:
                        _LOGGER.warning(
                            "Skipping decrypt because discovered encryption context did not match required elements."
                        )
                        metadata_kwargs.update(
                            dict(
                                skipped=True,
                                reason="Missing encryption context key or value",
                                missing_encryption_context_keys=list(missing_keys),
                                missing_encryption_context_pairs=list(missing_pairs),
                            )
                        )
                        metadata.write_metadata(**metadata_kwargs)
                        return OperationResult.FAILED_VALIDATION

                metadata.write_metadata(**metadata_kwargs)
                for chunk in handler:
                    _destination.write(chunk)
                    _destination.flush()
        return OperationResult.SUCCESS
示例#20
0
def decrypt_file(file):
    pt_filename = splitext(file)[0]
    with open(file, 'rb') as ct_file, open(pt_filename, 'wb') as pt_file:
        with aws_encryption_sdk.stream(
                mode='d',
                source=ct_file,
                key_provider=kms_key_provider
        ) as decryptor:
            for chunk in decryptor:
                pt_file.write(chunk)
    return pt_filename
示例#21
0
def cycle_file(source_plaintext_filename):
    """Encrypts and then decrypts a file under a custom static Master Key Provider.

    :param str source_plaintext_filename: Filename of file to encrypt
    """

    # Create the Static Random Master Key Provider
    key_id = os.urandom(8)
    master_key_provider = StaticRandomMasterKeyProvider()
    master_key_provider.add_master_key(key_id)

    ciphertext_filename = source_plaintext_filename + '.encrypted'
    cycled_plaintext_filename = source_plaintext_filename + '.decrypted'

    # Encrypt the source plaintext
    with open(source_plaintext_filename,
              'rb') as plaintext, open(ciphertext_filename,
                                       'wb') as ciphertext:
        with aws_encryption_sdk.stream(
                mode='e', source=plaintext,
                key_provider=master_key_provider) as encryptor:
            for chunk in encryptor:
                ciphertext.write(chunk)

    # Decrypt the ciphertext
    with open(ciphertext_filename,
              'rb') as ciphertext, open(cycled_plaintext_filename,
                                        'wb') as plaintext:
        with aws_encryption_sdk.stream(
                mode='d', source=ciphertext,
                key_provider=master_key_provider) as decryptor:
            for chunk in decryptor:
                plaintext.write(chunk)

    # Validate that the cycled plaintext is identical to the source plaintext
    assert filecmp.cmp(source_plaintext_filename, cycled_plaintext_filename)

    # Validate that the encryption context used by the decryptor has all the key-pairs from the encryptor
    assert all(pair in decryptor.header.encryption_context.items()
               for pair in encryptor.header.encryption_context.items())
    return ciphertext_filename, cycled_plaintext_filename
示例#22
0
def test_plaintext_logs_stream(caplog, capsys, plaintext_length, frame_size):
    plaintext, key_provider = _prep_plaintext_and_logs(caplog, plaintext_length)

    ciphertext = b""
    with aws_encryption_sdk.stream(
        mode="encrypt", source=plaintext, key_provider=key_provider, frame_length=frame_size
    ) as encryptor:
        for line in encryptor:
            ciphertext += line

    _look_in_logs(caplog, plaintext)
    _error_check(capsys)
示例#23
0
def test_encrypt_decrypt_header_only():
    """Test that StreamDecryptor can extract header without reading ciphertext."""
    ciphertext, encryptor_header = aws_encryption_sdk.encrypt(
        source=VALUES["plaintext_128"],
        key_provider=fake_kms_key_provider(),
        encryption_context=VALUES["encryption_context"],
    )
    with aws_encryption_sdk.stream(mode="d", source=ciphertext, key_provider=fake_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()
    )
示例#24
0
def test_encrypt_ciphertext_message(frame_length, algorithm, encryption_context):
    with aws_encryption_sdk.stream(
        mode="e",
        source=VALUES["plaintext_128"] * 10,
        key_provider=fake_kms_key_provider(algorithm.kdf_input_len),
        encryption_context=encryption_context,
        algorithm=algorithm,
        frame_length=frame_length,
    ) as encryptor:
        results_length = encryptor.ciphertext_length()
        ciphertext = encryptor.read()

    assert len(ciphertext) == results_length
 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_encrypt_decrypt_cycle_aws_kms_streaming(plaintext):
    keyring = build_aws_kms_keyring()
    ciphertext = b""
    with aws_encryption_sdk.stream(
            source=io.BytesIO(plaintext),
            keyring=keyring,
            mode="e",
            encryption_context=VALUES["encryption_context"],
    ) as encryptor:
        for chunk in encryptor:
            ciphertext += chunk
    header_1 = encryptor.header

    decrypted = b""
    with aws_encryption_sdk.stream(source=io.BytesIO(ciphertext),
                                   keyring=keyring,
                                   mode="d") as decryptor:
        for chunk in decryptor:
            decrypted += chunk
    header_2 = decryptor.header

    assert decrypted == plaintext
    assert header_1.encryption_context == header_2.encryption_context
示例#27
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)
 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
示例#29
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 test_decryptor_deprecated_attributes(caplog, attribute, no_later_than):
    caplog.set_level(logging.WARNING)
    plaintext = exact_length_plaintext(100)
    key_provider = fake_kms_key_provider()
    ciphertext, _header = aws_encryption_sdk.encrypt(source=plaintext,
                                                     key_provider=key_provider,
                                                     frame_length=0)
    with aws_encryption_sdk.stream(mode="decrypt",
                                   source=ciphertext,
                                   key_provider=key_provider) as decryptor:
        decrypted = decryptor.read()

    assert decrypted == plaintext
    assert hasattr(decryptor, attribute)
    watch_string = "StreamDecryptor.{name} is deprecated and will be removed in {version}".format(
        name=attribute, version=no_later_than)
    assert watch_string in caplog.text
    assert aws_encryption_sdk.__version__ < no_later_than