diff --git a/examples/src/basic_file_encryption_with_multiple_providers.py b/examples/src/basic_file_encryption_with_multiple_providers.py index 375b1f6be..9edceef9e 100644 --- a/examples/src/basic_file_encryption_with_multiple_providers.py +++ b/examples/src/basic_file_encryption_with_multiple_providers.py @@ -130,4 +130,4 @@ def cycle_file(key_arn, source_plaintext_filename, botocore_session=None): pair in static_decryptor.header.encryption_context.items() for pair in encryptor.header.encryption_context.items() ) - return ciphertext_filename, cycled_kms_plaintext_filename, cycled_static_plaintext_filename + return (ciphertext_filename, cycled_kms_plaintext_filename, cycled_static_plaintext_filename) diff --git a/examples/src/one_kms_cmk.py b/examples/src/one_kms_cmk.py new file mode 100644 index 000000000..1ba1d869f --- /dev/null +++ b/examples/src/one_kms_cmk.py @@ -0,0 +1,48 @@ +# Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). You +# may not use this file except in compliance with the License. A copy of +# the License is located at +# +# http://aws.amazon.com/apache2.0/ +# +# or in the "license" file accompanying this file. This file is +# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF +# ANY KIND, either express or implied. See the License for the specific +# language governing permissions and limitations under the License. +"""Example showing basic encryption and decryption of a value already in memory using one KMS CMK.""" +import aws_encryption_sdk + + +def encrypt_decrypt(key_arn, source_plaintext, botocore_session=None): + """Encrypts and then decrypts a string under one KMS customer master key (CMK). + + :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 = aws_encryption_sdk.KMSMasterKeyProvider(**kwargs) + + # Encrypt the plaintext using the AWS Encryption SDK. It returns the encrypted message and the header + ciphertext, encrypted_message_header = aws_encryption_sdk.encrypt( + 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 = aws_encryption_sdk.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() + ) diff --git a/examples/src/one_kms_cmk_streaming_data.py b/examples/src/one_kms_cmk_streaming_data.py new file mode 100644 index 000000000..3edfa82ab --- /dev/null +++ b/examples/src/one_kms_cmk_streaming_data.py @@ -0,0 +1,59 @@ +# Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). You +# may not use this file except in compliance with the License. A copy of +# the License is located at +# +# http://aws.amazon.com/apache2.0/ +# +# or in the "license" file accompanying this file. This file is +# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF +# ANY KIND, either express or implied. See the License for the specific +# language governing permissions and limitations under the License. +"""Example showing basic encryption and decryption of streaming data in memory using one KMS CMK.""" +import filecmp + +import aws_encryption_sdk + + +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 diff --git a/examples/test/examples_test_utils.py b/examples/test/examples_test_utils.py index 669d8e823..0984ee684 100644 --- a/examples/test/examples_test_utils.py +++ b/examples/test/examples_test_utils.py @@ -17,4 +17,34 @@ os.environ["AWS_ENCRYPTION_SDK_EXAMPLES_TESTING"] = "yes" sys.path.extend([os.sep.join([os.path.dirname(__file__), "..", "..", "test", "integration"])]) +static_plaintext = ( + b"Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + b"Praesent non feugiat leo. Aenean iaculis tellus ut velit consectetur, " + b"quis convallis orci eleifend. Sed eu dictum sapien. Nulla facilisi. Suspendisse potenti. " + b"Proin vehicula vehicula maximus. Donec varius et elit vel rutrum. Nulla lacinia neque turpis," + b" quis consequat orci pharetra et. Etiam consequat ullamcorper mauris. Vivamus molestie mollis " + b"mauris a gravida. Curabitur sed bibendum nisl. Cras varius tortor non erat sodales, quis congue" + b" tellus laoreet. Etiam fermentum purus eu diam sagittis, vitae commodo est vehicula. " + b"Nulla feugiat viverra orci vel interdum. Quisque pulvinar elit eget nulla facilisis varius. " + b"Mauris at suscipit sem. Aliquam in purus ut velit fringilla volutpat id non mi. " + b"Curabitur quis nunc eleifend, ornare lectus non, fringilla quam. Nam maximus volutpat placerat. " + b"Nulla ullamcorper lorem velit, nec sagittis ex tristique posuere. Aliquam fringilla magna commodo" + b" libero faucibus tempor. Vestibulum non ligula tincidunt, finibus sapien in, sollicitudin " + b"ex. Pellentesque congue laoreet mi in condimentum. Cras convallis nisi ac nunc tincidunt " + b"venenatis. Suspendisse urna elit, cursus eu lacus a, aliquet porttitor mi. " + b"Nulla vel congue nibh, sed condimentum dui. Ut ante ligula, blandit eu finibus nec, " + b"scelerisque quis eros. Maecenas gravida odio eget nibh dictum, dictum varius lacus interdum. " + b"Integer quis nulla vulputate, rhoncus diam vitae, mollis mauris. Sed ut porttitor dolor. " + b"Fusce ut justo a ex bibendum imperdiet nec sit amet magna. Sed ullamcorper luctus augue, " + b"tempor viverra elit interdum sed. Cras sit amet arcu eu turpis molestie sollicitudin. " + b"Curabitur fermentum varius nibh, ut aliquet nisi. Aliquam id tempus tellus. " + b"Nulla porttitor nulla at nibh interdum, quis sollicitudin erat egestas. " + b"Ut blandit mauris quis efficitur efficitur. Morbi neque sapien, posuere ut aliquam eget, " + b"aliquam at velit. Morbi sit amet rhoncus felis, et hendrerit sem. Nulla porta dictum ligula " + b"eget iaculis. Cras lacinia ligula quis risus ultrices, sed consectetur metus imperdiet. " + b"Nullam id enim vestibulum nibh ultricies auctor. Morbi neque lacus, faucibus vitae commodo quis, " + b"malesuada sed velit." +) + + from integration_test_utils import get_cmk_arn # noqa pylint: disable=unused-import,import-error diff --git a/examples/test/test_i_basic_encryption.py b/examples/test/test_i_basic_encryption.py index db1e9292a..f2a4fab51 100644 --- a/examples/test/test_i_basic_encryption.py +++ b/examples/test/test_i_basic_encryption.py @@ -11,19 +11,17 @@ # ANY KIND, either express or implied. See the License for the specific # language governing permissions and limitations under the License. """Unit test suite for the Strings examples in the AWS-hosted documentation.""" -import os - import botocore.session import pytest from ..src.basic_encryption import cycle_string -from .examples_test_utils import get_cmk_arn +from .examples_test_utils import get_cmk_arn, static_plaintext pytestmark = [pytest.mark.examples] def test_cycle_string(): - plaintext = os.urandom(1024) + plaintext = static_plaintext cmk_arn = get_cmk_arn() cycle_string(key_arn=cmk_arn, source_plaintext=plaintext, botocore_session=botocore.session.Session()) diff --git a/examples/test/test_i_basic_file_encryption_with_multiple_providers.py b/examples/test/test_i_basic_file_encryption_with_multiple_providers.py index 0f91c2017..282a272ab 100644 --- a/examples/test/test_i_basic_file_encryption_with_multiple_providers.py +++ b/examples/test/test_i_basic_file_encryption_with_multiple_providers.py @@ -19,6 +19,7 @@ from ..src.basic_file_encryption_with_multiple_providers import cycle_file from .examples_test_utils import get_cmk_arn +from .examples_test_utils import static_plaintext pytestmark = [pytest.mark.examples] @@ -28,7 +29,7 @@ def test_cycle_file(): cmk_arn = get_cmk_arn() handle, filename = tempfile.mkstemp() with open(filename, "wb") as f: - f.write(os.urandom(1024)) + f.write(static_plaintext) try: new_files = cycle_file( key_arn=cmk_arn, source_plaintext_filename=filename, botocore_session=botocore.session.Session() diff --git a/examples/test/test_i_basic_file_encryption_with_raw_key_provider.py b/examples/test/test_i_basic_file_encryption_with_raw_key_provider.py index 6b744353e..710c0ccac 100644 --- a/examples/test/test_i_basic_file_encryption_with_raw_key_provider.py +++ b/examples/test/test_i_basic_file_encryption_with_raw_key_provider.py @@ -17,6 +17,7 @@ import pytest from ..src.basic_file_encryption_with_raw_key_provider import cycle_file +from .examples_test_utils import static_plaintext pytestmark = [pytest.mark.examples] @@ -25,7 +26,7 @@ def test_cycle_file(): handle, filename = tempfile.mkstemp() with open(filename, "wb") as f: - f.write(os.urandom(1024)) + f.write(static_plaintext) try: new_files = cycle_file(source_plaintext_filename=filename) for f in new_files: diff --git a/examples/test/test_i_one_kms_cmk.py b/examples/test/test_i_one_kms_cmk.py new file mode 100644 index 000000000..71ce74d3d --- /dev/null +++ b/examples/test/test_i_one_kms_cmk.py @@ -0,0 +1,29 @@ +# Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). You +# may not use this file except in compliance with the License. A copy of +# the License is located at +# +# http://aws.amazon.com/apache2.0/ +# +# or in the "license" file accompanying this file. This file is +# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF +# ANY KIND, either express or implied. See the License for the specific +# language governing permissions and limitations under the License. +"""Unit test suite for the encryption and decryption using one KMS CMK example.""" + +import botocore.session +import pytest + +from ..src.one_kms_cmk import encrypt_decrypt +from .examples_test_utils import get_cmk_arn +from .examples_test_utils import static_plaintext + + +pytestmark = [pytest.mark.examples] + + +def test_one_kms_cmk(): + plaintext = static_plaintext + cmk_arn = get_cmk_arn() + encrypt_decrypt(key_arn=cmk_arn, source_plaintext=plaintext, botocore_session=botocore.session.Session()) diff --git a/examples/test/test_i_one_kms_cmk_streaming_data.py b/examples/test/test_i_one_kms_cmk_streaming_data.py new file mode 100644 index 000000000..b22fa4232 --- /dev/null +++ b/examples/test/test_i_one_kms_cmk_streaming_data.py @@ -0,0 +1,40 @@ +# Copyright 2017-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). You +# may not use this file except in compliance with the License. A copy of +# the License is located at +# +# http://aws.amazon.com/apache2.0/ +# +# or in the "license" file accompanying this file. This file is +# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF +# ANY KIND, either express or implied. See the License for the specific +# language governing permissions and limitations under the License. +"""Unit test suite for the encryption and decryption of streaming data using one KMS CMK example.""" +import os +import tempfile + +import botocore.session +import pytest + +from ..src.one_kms_cmk_streaming_data import encrypt_decrypt_stream +from .examples_test_utils import get_cmk_arn, static_plaintext + + +pytestmark = [pytest.mark.examples] + + +def test_one_kms_cmk_streaming_data(): + cmk_arn = get_cmk_arn() + handle, filename = tempfile.mkstemp() + with open(filename, "wb") as f: + f.write(static_plaintext) + try: + new_files = encrypt_decrypt_stream( + key_arn=cmk_arn, source_plaintext_filename=filename, botocore_session=botocore.session.Session() + ) + for f in new_files: + os.remove(f) + finally: + os.close(handle) + os.remove(filename)