From ebbc26b1fb83d7e0bcba66c70012730350b6c60d Mon Sep 17 00:00:00 2001 From: Ritvik Kapila <61410899+RitvikKapila@users.noreply.github.com> Date: Wed, 5 Jun 2024 10:37:00 -0700 Subject: [PATCH 01/18] chore: performance tests for ESDK-python (#680) --- .gitignore | 6 + buildspec.yml | 8 + codebuild/py311/performance_tests_mpl.yml | 38 +++ codebuild/py312/performance_tests_mpl.yml | 38 +++ performance_tests/README.rst | 219 ++++++++++++++++++ performance_tests/__init__.py | 3 + performance_tests/consolidate_results.py | 49 ++++ performance_tests/pylintrc | 45 ++++ performance_tests/requirements.txt | 5 + performance_tests/requirements_mpl.txt | 1 + performance_tests/results/.gitkeep | 0 performance_tests/setup.cfg | 41 ++++ performance_tests/setup.py | 34 +++ .../__init__.py | 4 + .../keyrings/__init__.py | 3 + .../keyrings/aws_kms_keyring.py | 131 +++++++++++ .../keyrings/raw_aes_keyring.py | 85 +++++++ .../keyrings/raw_rsa_keyring.py | 79 +++++++ .../master_key_providers/__init__.py | 3 + .../aws_kms_master_key_provider.py | 69 ++++++ .../raw_aes_master_key_provider.py | 101 ++++++++ .../raw_rsa_master_key_provider.py | 101 ++++++++ .../utils/__init__.py | 3 + .../utils/util.py | 116 ++++++++++ performance_tests/test/keyrings/__init__.py | 3 + .../test/keyrings/test_aws_kms_keyring.py | 206 ++++++++++++++++ .../test/keyrings/test_raw_aes_keyring.py | 156 +++++++++++++ .../test/keyrings/test_raw_rsa_keyring.py | 163 +++++++++++++ .../test/master_key_providers/__init__.py | 3 + .../test_aws_kms_master_key_provider.py | 165 +++++++++++++ .../test_raw_aes_master_key_provider.py | 156 +++++++++++++ .../test_raw_rsa_master_key_provider.py | 156 +++++++++++++ performance_tests/test/resources/__init__.py | 3 + .../ciphertext/kms/ciphertext-data-empty.ct | Bin 0 -> 587 bytes .../ciphertext/kms/ciphertext-data-large.ct | Bin 0 -> 8619 bytes .../ciphertext/kms/ciphertext-data-medium.ct | Bin 0 -> 4587 bytes .../ciphertext/kms/ciphertext-data-small.ct | Bin 0 -> 623 bytes .../raw_aes/ciphertext-data-empty.ct | Bin 0 -> 454 bytes .../raw_aes/ciphertext-data-large.ct | Bin 0 -> 8486 bytes .../raw_aes/ciphertext-data-medium.ct | Bin 0 -> 4454 bytes .../raw_aes/ciphertext-data-small.ct | Bin 0 -> 490 bytes .../raw_rsa/ciphertext-data-empty.ct | Bin 0 -> 899 bytes .../raw_rsa/ciphertext-data-large.ct | Bin 0 -> 8931 bytes .../raw_rsa/ciphertext-data-medium.ct | Bin 0 -> 4899 bytes .../raw_rsa/ciphertext-data-small.ct | Bin 0 -> 935 bytes .../plaintext/plaintext-data-empty.dat | 0 .../plaintext/plaintext-data-large.dat | 21 ++ .../plaintext/plaintext-data-medium.dat | 11 + .../plaintext/plaintext-data-small.dat | 1 + performance_tests/tox.ini | 215 +++++++++++++++++ 50 files changed, 2441 insertions(+) create mode 100644 codebuild/py311/performance_tests_mpl.yml create mode 100644 codebuild/py312/performance_tests_mpl.yml create mode 100644 performance_tests/README.rst create mode 100644 performance_tests/__init__.py create mode 100644 performance_tests/consolidate_results.py create mode 100644 performance_tests/pylintrc create mode 100644 performance_tests/requirements.txt create mode 100644 performance_tests/requirements_mpl.txt create mode 100644 performance_tests/results/.gitkeep create mode 100644 performance_tests/setup.cfg create mode 100644 performance_tests/setup.py create mode 100644 performance_tests/src/aws_encryption_sdk_performance_tests/__init__.py create mode 100644 performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/__init__.py create mode 100644 performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/aws_kms_keyring.py create mode 100644 performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/raw_aes_keyring.py create mode 100644 performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/raw_rsa_keyring.py create mode 100644 performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/__init__.py create mode 100644 performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/aws_kms_master_key_provider.py create mode 100644 performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/raw_aes_master_key_provider.py create mode 100644 performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/raw_rsa_master_key_provider.py create mode 100644 performance_tests/src/aws_encryption_sdk_performance_tests/utils/__init__.py create mode 100644 performance_tests/src/aws_encryption_sdk_performance_tests/utils/util.py create mode 100644 performance_tests/test/keyrings/__init__.py create mode 100644 performance_tests/test/keyrings/test_aws_kms_keyring.py create mode 100644 performance_tests/test/keyrings/test_raw_aes_keyring.py create mode 100644 performance_tests/test/keyrings/test_raw_rsa_keyring.py create mode 100644 performance_tests/test/master_key_providers/__init__.py create mode 100644 performance_tests/test/master_key_providers/test_aws_kms_master_key_provider.py create mode 100644 performance_tests/test/master_key_providers/test_raw_aes_master_key_provider.py create mode 100644 performance_tests/test/master_key_providers/test_raw_rsa_master_key_provider.py create mode 100644 performance_tests/test/resources/__init__.py create mode 100644 performance_tests/test/resources/ciphertext/kms/ciphertext-data-empty.ct create mode 100644 performance_tests/test/resources/ciphertext/kms/ciphertext-data-large.ct create mode 100644 performance_tests/test/resources/ciphertext/kms/ciphertext-data-medium.ct create mode 100644 performance_tests/test/resources/ciphertext/kms/ciphertext-data-small.ct create mode 100644 performance_tests/test/resources/ciphertext/raw_aes/ciphertext-data-empty.ct create mode 100644 performance_tests/test/resources/ciphertext/raw_aes/ciphertext-data-large.ct create mode 100644 performance_tests/test/resources/ciphertext/raw_aes/ciphertext-data-medium.ct create mode 100644 performance_tests/test/resources/ciphertext/raw_aes/ciphertext-data-small.ct create mode 100644 performance_tests/test/resources/ciphertext/raw_rsa/ciphertext-data-empty.ct create mode 100644 performance_tests/test/resources/ciphertext/raw_rsa/ciphertext-data-large.ct create mode 100644 performance_tests/test/resources/ciphertext/raw_rsa/ciphertext-data-medium.ct create mode 100644 performance_tests/test/resources/ciphertext/raw_rsa/ciphertext-data-small.ct create mode 100644 performance_tests/test/resources/plaintext/plaintext-data-empty.dat create mode 100644 performance_tests/test/resources/plaintext/plaintext-data-large.dat create mode 100644 performance_tests/test/resources/plaintext/plaintext-data-medium.dat create mode 100644 performance_tests/test/resources/plaintext/plaintext-data-small.dat create mode 100644 performance_tests/tox.ini diff --git a/.gitignore b/.gitignore index 24df397ed..2843404d0 100644 --- a/.gitignore +++ b/.gitignore @@ -33,6 +33,12 @@ __pycache__ .pytest_cache # Ignore key materials generated by examples or tests test_keyrings/ +# Ignore results of performance test +performance_tests/results/*.csv +performance_tests/results/*.pstats +performance_tests/results/*.png +# Ignore the memory profile logs +mprofile_* # PyCharm .idea/ diff --git a/buildspec.yml b/buildspec.yml index 086743dbc..583fae56f 100644 --- a/buildspec.yml +++ b/buildspec.yml @@ -126,6 +126,10 @@ batch: buildspec: codebuild/py311/integ_mpl.yml env: image: aws/codebuild/standard:7.0 + - identifier: py311_performance_tests_mpl + buildspec: codebuild/py311/performance_tests_mpl.yml + env: + image: aws/codebuild/standard:7.0 - identifier: py311_examples buildspec: codebuild/py311/examples.yml env: @@ -212,6 +216,10 @@ batch: buildspec: codebuild/py312/integ_mpl.yml env: image: aws/codebuild/standard:7.0 + - identifier: py312_performance_tests_mpl + buildspec: codebuild/py312/performance_tests_mpl.yml + env: + image: aws/codebuild/standard:7.0 - identifier: py312_examples buildspec: codebuild/py312/examples.yml env: diff --git a/codebuild/py311/performance_tests_mpl.yml b/codebuild/py311/performance_tests_mpl.yml new file mode 100644 index 000000000..2debb1185 --- /dev/null +++ b/codebuild/py311/performance_tests_mpl.yml @@ -0,0 +1,38 @@ +# Runs the performance tests for the MPL in an environment with the MPL installed +version: 0.2 + +env: + variables: + # No TOXENV. This runs multiple environments. + REGION: "us-west-2" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + +phases: + install: + runtime-versions: + python: 3.11 + build: + commands: + - cd /root/.pyenv/plugins/python-build/../.. && git pull && cd - + - pyenv install --skip-existing 3.11.0 + - pyenv local 3.11.0 + - pip install --upgrade pip + - pip install setuptools + - pip install "tox < 4.0" + # Assume special role to access keystore + - TMP_ROLE=$(aws sts assume-role --role-arn "arn:aws:iam::370957321024:role/GitHub-CI-Public-ESDK-Python-Role-us-west-2" --role-session-name "CB-Py312ExamplesMpl") + - export TMP_ROLE + - export AWS_ACCESS_KEY_ID=$(echo "${TMP_ROLE}" | jq -r '.Credentials.AccessKeyId') + - export AWS_SECRET_ACCESS_KEY=$(echo "${TMP_ROLE}" | jq -r '.Credentials.SecretAccessKey') + - export AWS_SESSION_TOKEN=$(echo "${TMP_ROLE}" | jq -r '.Credentials.SessionToken') + - aws sts get-caller-identity + # Run MPL-specific tests with special role + - cd performance_tests/ + - tox -e py311-performance_tests-mpl diff --git a/codebuild/py312/performance_tests_mpl.yml b/codebuild/py312/performance_tests_mpl.yml new file mode 100644 index 000000000..97dbf359f --- /dev/null +++ b/codebuild/py312/performance_tests_mpl.yml @@ -0,0 +1,38 @@ +# Runs the performance tests for the MPL in an environment with the MPL installed +version: 0.2 + +env: + variables: + # No TOXENV. This runs multiple environments. + REGION: "us-west-2" + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >- + arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >- + arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >- + arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >- + arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7 + +phases: + install: + runtime-versions: + python: 3.12 + build: + commands: + - cd /root/.pyenv/plugins/python-build/../.. && git pull && cd - + - pyenv install --skip-existing 3.12.0 + - pyenv local 3.12.0 + - pip install --upgrade pip + - pip install setuptools + - pip install "tox < 4.0" + # Assume special role to access keystore + - TMP_ROLE=$(aws sts assume-role --role-arn "arn:aws:iam::370957321024:role/GitHub-CI-Public-ESDK-Python-Role-us-west-2" --role-session-name "CB-Py312ExamplesMpl") + - export TMP_ROLE + - export AWS_ACCESS_KEY_ID=$(echo "${TMP_ROLE}" | jq -r '.Credentials.AccessKeyId') + - export AWS_SECRET_ACCESS_KEY=$(echo "${TMP_ROLE}" | jq -r '.Credentials.SecretAccessKey') + - export AWS_SESSION_TOKEN=$(echo "${TMP_ROLE}" | jq -r '.Credentials.SessionToken') + - aws sts get-caller-identity + # Run MPL-specific tests with special role + - cd performance_tests/ + - tox -e py312-performance_tests-mpl diff --git a/performance_tests/README.rst b/performance_tests/README.rst new file mode 100644 index 000000000..ba9b89f15 --- /dev/null +++ b/performance_tests/README.rst @@ -0,0 +1,219 @@ +##################################### +aws-encryption-sdk performance tests +##################################### + +This module runs performance tests for the `AWS Encryption SDK Python`_. + +******** +Overview +******** + +This module tests the following keyrings / master key providers: + +1. KMS Keyring / KMS Master Key Provider +2. Raw AES Keyring / AES Master Key Provider +3. Raw RSA Keyring / RSA Master Key Provider +4. Hierarchy Keyring +5. Caching CMM + +For each test on the above keyrings / master key providers, this package measures: + +1. Execution time +2. Total memory consumption + +For each keyring / master key provider, the execution time and memory consumption +is measured for three operations: + +1. Create keyring / master key provider +2. Encrypt +3. Decrypt + +The usage of the performance tests is demonstrated through an `AWS KMS Keyring`_. +However, the procedure is the same for any keyring / master key provider, with slight +changes in the input arguments. + +The results for the performance test will be available in the results folder in the +performance_tests directory. + +********************** +Required Prerequisites +********************** + +* Python 3.8+ +* aws-encryption-sdk +* boto3 >= 1.10.0 +* click +* tqdm +* pytest + +Recommended Prerequisites +========================= + +* aws-cryptographic-material-providers: >= 1.0.0 + * Requires Python 3.11+. + +***** +Usage +***** + +Execution Time +============== + +Create Keyring +-------------- +To run the performance test for execution time, please use the +following commands in the performance_tests directory. + +.. code:: + + usage: python test/keyrings/test_aws_kms_keyring.py create + + Create a keyring to use for encryption and decryption. + + optional arguments: + -h, --help show this help message and exit. + --kms_key_id KMS_KEY_ID The KMS key ID you want to use. + --n_iters N_ITERS Number of iterations you want to + run the test for. For instance, + if n_iters = 100, this performance + test script will run the create_keyring + method 100 times and report the + execution time of each of the calls. + --output_file OUTPUT_FILE The output file for execution times + for each function call, + default='kms_keyring_create' in the + results folder. + +Encrypt +------- + +To run the performance test for execution time, please use the following +commands in the performance_tests directory: + +.. code:: + + usage: python test/keyrings/test_aws_kms_keyring.py encrypt + + optional arguments: + -h, --help show this help message and exit. + --plaintext_data_filename PLAINTEXT_DATA_FILENAME Filename containing plaintext data + you want to encrypt. + default='test/resources/plaintext/plaintext-data-medium.dat'. + You can choose to use any other plaintext + file as well. Some example plaintext + data files are present in the + 'test/resources' directory. + --kms_key_id KMS_KEY_ID The KMS key ID you want to use. + --n_iters N_ITERS Number of iterations you want to + run the test for. For instance, + if n_iters = 100, this performance + test script will run the create_keyring + method 100 times and report the + execution time of each of the calls. + --output_file OUTPUT_FILE The output file for execution times + for each function call, + default='kms_keyring_create' in the + results folder. + +Decrypt +------- + +To run the performance test for execution time, please use the +following commands in the performance_tests directory + +.. code:: + + usage: python test/keyrings/test_aws_kms_keyring.py decrypt + + optional arguments: + -h, --help show this help message and exit. + --ciphertext_data_filename CIPHERTEXT_DATA_FILENAME Filename containing ciphertext data + you want to decrypt. + default='test/resources/ciphertext/kms/ciphertext-data-medium.ct'. + You can choose to use any other + ciphertext file as well. Some example + ciphertext data files are present in + the 'test/resources' directory. + --kms_key_id KMS_KEY_ID The KMS key ID you want to use. + --n_iters N_ITERS Number of iterations you want to + run the test for. For instance, + if n_iters = 100, this performance + test script will run the create_keyring + method 100 times and report the + execution time of each of the calls. + --output_file OUTPUT_FILE The output file for execution times + for each function call, + default='kms_keyring_create' in the + results folder. + +Consolidate Time Results +======================== + +In order to find the minimum, maximum, average, 99th percentile and bottom +99th percentile trimmed average times from the n_iters runs, please use the +following script from the performance_tests directory with the csv file +containing times for each of the n_iters runs generated in the previous +"Execution Time" section: + +.. code:: + + usage: python consolidate_results.py results/kms_keyring_decrypt.csv + +Memory Consumption +================== + +To get the memory consumption, simply replace 'python' +with 'mprof run' in the previously mentioned commands. + +For example, if you want to calculate the memory consumption +of the encrypt function of a AWS KMS Keyring, simply write: + +.. code:: + + usage: mprof run test/keyrings/test_aws_kms_keyring.py encrypt + + +This should generate an mprofile log file in your current directory. +This mprofile log file contains the total memory consumed by the program +with respect to time elapsed. +To plot the memory consumption with respect to time, please use the following +command from the same directory + +.. code:: + + usage: mprof plot + + +This 'mprof plot' command will plot the most recent mprofile log file. + + +Performance Graph +================= + +To generate a performance graph, please use the following command +to generate the pstats log file by specifying the output pstats file +path. Here, 'results/kms_keyring_create.pstats' is set as the default +output file. + +.. code:: + + usage: python -m cProfile -o results/kms_keyring_create.pstats test/keyrings/test_aws_kms_keyring.py create + + +After generating the pstats file, please run the following command +to generate the performance graph. The output performance graph will +be a .png file that you specify. Here, 'results/kms_keyring_create.png' +is set as the default output file. + +.. code:: + + usage: gprof2dot -f pstats results/kms_keyring_create.pstats | dot -Tpng -o results/kms_keyring_create.png && eog results/kms_keyring_create.png + + +Note: This project does not adhere to semantic versioning; as such it +makes no guarantees that functionality will persist across major, +minor, or patch versions. +**DO NOT** take a standalone dependency on this library. + +.. _AWS Encryption SDK Python: https://github.com/aws/aws-encryption-sdk-python/ +.. _AWS KMS Keyring: https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-kms-keyring.html diff --git a/performance_tests/__init__.py b/performance_tests/__init__.py new file mode 100644 index 000000000..120179eda --- /dev/null +++ b/performance_tests/__init__.py @@ -0,0 +1,3 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Stub module indicator to make linter configuration simpler.""" diff --git a/performance_tests/consolidate_results.py b/performance_tests/consolidate_results.py new file mode 100644 index 000000000..2601417cc --- /dev/null +++ b/performance_tests/consolidate_results.py @@ -0,0 +1,49 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Script for consolidating results for execution times""" + +import argparse +import csv + +import numpy as np + + +def calculate_statistics(_csv_file): + """Calculate average, trimmed average, minimum, maximum and p99 statistics for execution times in a CSV file.""" + with open(_csv_file, 'r', encoding='utf-8') as file: + reader = csv.reader(file) + data = [float(row[0]) for row in reader] + + output_stats = {} + + # Calculate statistics + if data: + data = np.sort(data) + output_stats['total_entries'] = len(data) + output_stats['average'] = np.mean(data) + output_stats['trimmed_average_99_bottom'] = np.mean(data[0:int(0.99 * len(data))]) + output_stats['minimum'] = min(data) + output_stats['maximum'] = max(data) + output_stats['perc_99'] = np.percentile(data, 99) + return output_stats + + return None + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument('csv_file', + help='csv file containing the outputs of execution times for n_iter iterations') + args = parser.parse_args() + + statistics = calculate_statistics(args.csv_file) + if statistics: + print("CSV File:", args.csv_file) + print("Total Entries:", statistics['total_entries']) + print("Average:", statistics['average']) + print("Bottom 99th percentile trimmed average:", statistics['trimmed_average_99_bottom']) + print("Minimum:", statistics['minimum']) + print("Maximum:", statistics['maximum']) + print("99th percentile:", statistics['perc_99']) + else: + print("No data found in the CSV file.") diff --git a/performance_tests/pylintrc b/performance_tests/pylintrc new file mode 100644 index 000000000..8ed5cb105 --- /dev/null +++ b/performance_tests/pylintrc @@ -0,0 +1,45 @@ +[MESSAGE CONTROL] +# Disabling messages that either we don't care about we intentionally break. +disable = + import-error, # ignore mpl import errors + invalid-name, # we prefer long, descriptive, names for examples + bad-continuation, # we let black handle this + ungrouped-imports, # we let isort handle this + no-member, # breaks with attrs + no-self-use, # interesting to keep in mind for later refactoring, but not blocking + useless-object-inheritance, # we need to support Python 2, so no, not useless + duplicate-code, # some examples may be similar + too-few-public-methods, # does not allow value stores + too-many-locals, # examples may sometimes have more locals defined for clarity than would be appropriate in code + no-else-return, # we omit this on purpose for brevity where it would add no value + attribute-defined-outside-init, # breaks with attrs_post_init + abstract-method, # throws false positives on io.BaseIO grandchildren + redefined-outer-name, # we do this on purpose in multiple places + consider-using-f-string # disable until 2022-05-05; 6 months after 3.5 deprecation + +[BASIC] +# Allow function names up to 50 characters +function-rgx = [a-z_][a-z0-9_]{2,50}$ +# Allow method names up to 50 characters +method-rgx = [a-z_][a-z0-9_]{2,50}$ +# Allow class attribute names up to 50 characters +# Whitelist class attribute names: iv +class-attribute-rgx = (([A-Za-z_][A-Za-z0-9_]{2,50}|(__.*__))$)|(^iv$) +# Whitelist attribute names: iv +attr-rgx = ([a-z_][a-z0-9_]{2,30}$)|(^iv$) +# Whitelist argument names: iv, b +argument-rgx = ([a-z_][a-z0-9_]{2,30}$)|(^iv$)|(^b$) +# Whitelist variable names: iv, b, _b, x, y, r, s +variable-rgx = ([a-z_][a-z0-9_]{2,30}$)|(^iv$)|(^b$)|(^_b$)|(^x$)|(^y$)|(^r$)|(^s$) + +[VARIABLES] +additional-builtins = raw_input + +[DESIGN] +max-args = 10 + +[FORMAT] +max-line-length = 120 + +[REPORTS] +msg-template = {path}:{line}: [{msg_id}({symbol}), {obj}] {msg} diff --git a/performance_tests/requirements.txt b/performance_tests/requirements.txt new file mode 100644 index 000000000..0b879647f --- /dev/null +++ b/performance_tests/requirements.txt @@ -0,0 +1,5 @@ +attrs >= 17.4.0 +aws-encryption-sdk>=2.3.0 +pytest>=3.3.1 +tqdm +click diff --git a/performance_tests/requirements_mpl.txt b/performance_tests/requirements_mpl.txt new file mode 100644 index 000000000..209e10f2c --- /dev/null +++ b/performance_tests/requirements_mpl.txt @@ -0,0 +1 @@ +aws-cryptographic-material-providers @ git+https://github.com/aws/aws-cryptographic-material-providers-library.git@lucmcdon/python-mpl#subdirectory=AwsCryptographicMaterialProviders/runtimes/python \ No newline at end of file diff --git a/performance_tests/results/.gitkeep b/performance_tests/results/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/performance_tests/setup.cfg b/performance_tests/setup.cfg new file mode 100644 index 000000000..c584a25bd --- /dev/null +++ b/performance_tests/setup.cfg @@ -0,0 +1,41 @@ +[wheel] +universal = 1 + +[metadata] +license_file = LICENSE + +[coverage:run] +branch = True + +[coverage:report] +show_missing = True + +[mypy] +ignore_missing_imports = True + +[flake8] +max_complexity = 10 +max_line_length = 120 +import_order_style = google +application_import_names = aws_encryption_sdk_cli +builtins = raw_input +ignore = + # Ignoring D205 and D400 because of false positives + D205, D400, + # E203 is not PEP8 compliant https://github.com/ambv/black#slices + E203, + # W503 is not PEP8 compliant https://github.com/ambv/black#line-breaks--binary-operators + W503 + +[doc8] +max-line-length = 120 + +[isort] +line_length = 120 +# https://github.com/timothycrosley/isort#multi-line-output-modes +multi_line_output = 3 +include_trailing_comma = True +force_grid_wrap = 0 +combine_as_imports = True +not_skip = __init__.py +known_third_party = attr,aws_encryption_sdk,pytest,setuptools,six diff --git a/performance_tests/setup.py b/performance_tests/setup.py new file mode 100644 index 000000000..702813509 --- /dev/null +++ b/performance_tests/setup.py @@ -0,0 +1,34 @@ +"""Performance test for the AWS Encryption SDK for Python.""" +import os +import re + +from setuptools import find_packages, setup + +VERSION_RE = re.compile(r"""__version__ = ['"]([0-9.]+)['"]""") +HERE = os.path.abspath(os.path.dirname(__file__)) + + +def read(*args): + """Read complete file contents.""" + return open(os.path.join(HERE, *args), encoding="utf-8").read() # pylint: disable=consider-using-with + + +def get_version(): + """Read the version from this module.""" + init = read("src", "aws_encryption_sdk_performance_tests", "__init__.py") + return VERSION_RE.search(init).group(1) + + +setup( + name="aws-encryption-sdk-performance-tests", + packages=find_packages("src"), + package_dir={"": "src"}, + author="Amazon Web Services", + maintainer="Amazon Web Services", + author_email="aws-cryptools@amazon.com", + url="https://github.com/awslabs/aws-encryption-sdk-python", + description="Performance tests for the AWS Encryption SDK for Python", + keywords="aws-encryption-sdk aws kms encryption", + license="Apache License 2.0", + version=get_version(), +) diff --git a/performance_tests/src/aws_encryption_sdk_performance_tests/__init__.py b/performance_tests/src/aws_encryption_sdk_performance_tests/__init__.py new file mode 100644 index 000000000..cf1bf0fb4 --- /dev/null +++ b/performance_tests/src/aws_encryption_sdk_performance_tests/__init__.py @@ -0,0 +1,4 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Stub module indicator to make linter configuration simpler.""" +__version__ = "0.1.0" diff --git a/performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/__init__.py b/performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/__init__.py new file mode 100644 index 000000000..120179eda --- /dev/null +++ b/performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/__init__.py @@ -0,0 +1,3 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Stub module indicator to make linter configuration simpler.""" diff --git a/performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/aws_kms_keyring.py b/performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/aws_kms_keyring.py new file mode 100644 index 000000000..e846ec695 --- /dev/null +++ b/performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/aws_kms_keyring.py @@ -0,0 +1,131 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Performance tests for the AWS KMS keyring.""" + +import aws_encryption_sdk +import boto3 +from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig +from aws_cryptographic_materialproviders.mpl.models import CreateAwsKmsKeyringInput +from aws_cryptographic_materialproviders.mpl.references import IKeyring + + +def create_keyring( + kms_key_id: str +): + """Demonstrate how to create an AWS KMS keyring. + + Usage: create_keyring(kms_key_id) + :param kms_key_id: KMS Key identifier for the KMS key you want to use. + :type kms_key_id: string + + For more information on KMS Key identifiers, see + https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id + """ + # Create a boto3 client for KMS. + kms_client = create_kms_client() + + # Create a KMS keyring + mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + config=MaterialProvidersConfig() + ) + + keyring_input: CreateAwsKmsKeyringInput = CreateAwsKmsKeyringInput( + kms_key_id=kms_key_id, + kms_client=kms_client + ) + + keyring: IKeyring = mat_prov.create_aws_kms_keyring( + input=keyring_input + ) + + return keyring + + +def create_kms_client(aws_region="us-west-2"): + """Create an AWS KMS client. + + Usage: create_kms_client(aws_region) + :param aws_region: AWS region to use for KMS client. + :type aws_region: string + """ + # Create a boto3 client for KMS. + kms_client = boto3.client('kms', region_name=aws_region) + + return kms_client + + +def create_keyring_given_kms_client( + kms_key_id: str, + kms_client: boto3.client, +): + """Demonstrate how to create an AWS KMS keyring with given KMS client. + + Usage: create_keyring(kms_key_id, kms_client) + :param kms_key_id: KMS Key identifier for the KMS key you want to use. + :type kms_key_id: string + :param kms_client: boto3 client for KMS. + :type kms_client: boto3.client + + For more information on KMS Key identifiers, see + https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id + """ + # Create a KMS keyring + mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + config=MaterialProvidersConfig() + ) + + keyring_input: CreateAwsKmsKeyringInput = CreateAwsKmsKeyringInput( + kms_key_id=kms_key_id, + kms_client=kms_client + ) + + keyring: IKeyring = mat_prov.create_aws_kms_keyring( + input=keyring_input + ) + + return keyring + + +def encrypt_using_keyring( + plaintext_data: bytes, + keyring: IKeyring +): + """Demonstrate how to encrypt plaintext data using an AWS KMS keyring. + + Usage: encrypt_using_keyring(plaintext_data, keyring) + :param plaintext_data: plaintext data you want to encrypt + :type: bytes + :param keyring: Keyring to use for encryption. + :type keyring: IKeyring + """ + client = aws_encryption_sdk.EncryptionSDKClient() + + ciphertext_data, _ = client.encrypt( + source=plaintext_data, + keyring=keyring + ) + + return ciphertext_data + + +def decrypt_using_keyring( + ciphertext_data: bytes, + keyring: IKeyring +): + """Demonstrate how to decrypt ciphertext data using an AWS KMS keyring. + + Usage: decrypt_using_keyring(ciphertext_data, keyring) + :param ciphertext_data: ciphertext data you want to decrypt + :type: bytes + :param keyring: Keyring to use for decryption. + :type keyring: IKeyring + """ + client = aws_encryption_sdk.EncryptionSDKClient() + + decrypted_plaintext_data, _ = client.decrypt( + source=ciphertext_data, + keyring=keyring + ) + + return decrypted_plaintext_data diff --git a/performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/raw_aes_keyring.py b/performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/raw_aes_keyring.py new file mode 100644 index 000000000..a849b1a7f --- /dev/null +++ b/performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/raw_aes_keyring.py @@ -0,0 +1,85 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Performance tests for the Raw AES keyring.""" + +import aws_encryption_sdk +from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig +from aws_cryptographic_materialproviders.mpl.models import AesWrappingAlg, CreateRawAesKeyringInput +from aws_cryptographic_materialproviders.mpl.references import IKeyring + +from ..utils.util import PerfTestUtils + + +def create_keyring(): + """Demonstrate how to create a Raw AES keyring. + + Usage: create_keyring() + """ + key_name_space = "Some managed raw keys" + key_name = "My 256-bit AES wrapping key" + + # Here, the input to secrets.token_bytes() = 32 bytes = 256 bits + # We fix the static key in order to make the test deterministic + static_key = PerfTestUtils.DEFAULT_AES_256_STATIC_KEY + + mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + config=MaterialProvidersConfig() + ) + + keyring_input: CreateRawAesKeyringInput = CreateRawAesKeyringInput( + key_namespace=key_name_space, + key_name=key_name, + wrapping_key=static_key, + wrapping_alg=AesWrappingAlg.ALG_AES256_GCM_IV12_TAG16 + ) + + keyring: IKeyring = mat_prov.create_raw_aes_keyring( + input=keyring_input + ) + + return keyring + + +def encrypt_using_keyring( + plaintext_data: bytes, + keyring: IKeyring +): + """Demonstrate how to encrypt plaintext data using a Raw AES keyring. + + Usage: encrypt_using_keyring(plaintext_data, keyring) + :param plaintext_data: plaintext data you want to encrypt + :type: bytes + :param keyring: Keyring to use for encryption. + :type keyring: IKeyring + """ + client = aws_encryption_sdk.EncryptionSDKClient() + + ciphertext_data, _ = client.encrypt( + source=plaintext_data, + keyring=keyring + ) + + return ciphertext_data + + +def decrypt_using_keyring( + ciphertext_data: bytes, + keyring: IKeyring +): + """Demonstrate how to decrypt ciphertext data using a Raw AES keyring. + + Usage: decrypt_using_keyring(ciphertext_data, keyring) + :param ciphertext_data: ciphertext data you want to decrypt + :type: bytes + :param keyring: Keyring to use for decryption. + :type keyring: IKeyring + """ + client = aws_encryption_sdk.EncryptionSDKClient() + + decrypted_plaintext_data, _ = client.decrypt( + source=ciphertext_data, + keyring=keyring + ) + + return decrypted_plaintext_data diff --git a/performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/raw_rsa_keyring.py b/performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/raw_rsa_keyring.py new file mode 100644 index 000000000..6eed281bd --- /dev/null +++ b/performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/raw_rsa_keyring.py @@ -0,0 +1,79 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Performance tests for the Raw RSA keyring.""" +import aws_encryption_sdk +from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig +from aws_cryptographic_materialproviders.mpl.models import CreateRawRsaKeyringInput, PaddingScheme +from aws_cryptographic_materialproviders.mpl.references import IKeyring + + +def create_keyring(public_key, private_key): + """Demonstrate how to create a Raw RSA keyring using the key pair. + + Usage: create_keyring(public_key, private_key) + """ + key_name_space = "Some managed raw keys" + key_name = "My 4096-bit RSA wrapping key" + + mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + config=MaterialProvidersConfig() + ) + + keyring_input: CreateRawRsaKeyringInput = CreateRawRsaKeyringInput( + key_namespace=key_name_space, + key_name=key_name, + padding_scheme=PaddingScheme.OAEP_SHA256_MGF1, + public_key=public_key, + private_key=private_key + ) + + keyring: IKeyring = mat_prov.create_raw_rsa_keyring( + input=keyring_input + ) + + return keyring + + +def encrypt_using_keyring( + plaintext_data: bytes, + keyring: IKeyring +): + """Demonstrate how to encrypt plaintext data using a Raw RSA keyring. + + Usage: encrypt_using_keyring(plaintext_data, keyring) + :param plaintext_data: plaintext data you want to encrypt + :type: bytes + :param keyring: Keyring to use for encryption. + :type keyring: IKeyring + """ + client = aws_encryption_sdk.EncryptionSDKClient() + + ciphertext_data, _ = client.encrypt( + source=plaintext_data, + keyring=keyring + ) + + return ciphertext_data + + +def decrypt_using_keyring( + ciphertext_data: bytes, + keyring: IKeyring +): + """Demonstrate how to decrypt ciphertext data using a Raw RSA keyring. + + Usage: decrypt_using_keyring(ciphertext_data, keyring) + :param ciphertext_data: ciphertext data you want to decrypt + :type: bytes + :param keyring: Keyring to use for decryption. + :type keyring: IKeyring + """ + client = aws_encryption_sdk.EncryptionSDKClient() + + decrypted_plaintext_data, _ = client.decrypt( + source=ciphertext_data, + keyring=keyring + ) + + return decrypted_plaintext_data diff --git a/performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/__init__.py b/performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/__init__.py new file mode 100644 index 000000000..120179eda --- /dev/null +++ b/performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/__init__.py @@ -0,0 +1,3 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Stub module indicator to make linter configuration simpler.""" diff --git a/performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/aws_kms_master_key_provider.py b/performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/aws_kms_master_key_provider.py new file mode 100644 index 000000000..c3136a5c7 --- /dev/null +++ b/performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/aws_kms_master_key_provider.py @@ -0,0 +1,69 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Performance tests for the AWS KMS master key provider.""" + +import aws_encryption_sdk + + +def create_key_provider( + kms_key_id: str +): + """Demonstrate how to create an AWS KMS master key-provider. + + Usage: create_key_provider(kms_key_id) + :param kms_key_id: KMS Key identifier for the KMS key you want to use. + :type kms_key_id: string + + For more information on KMS Key identifiers, see + https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id + """ + # Create a KMS master key-provider. + key_provider = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider(key_ids=[ + kms_key_id, + ]) + + return key_provider + + +def encrypt_using_key_provider( + plaintext_data: bytes, + key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider +): + """Demonstrate how to encrypt plaintext data using an AWS KMS master key-provider. + + Usage: encrypt_using_key_provider(plaintext_data, key_provider) + :param plaintext_data: plaintext data you want to encrypt + :type: bytes + :param key_provider: Master key provider to use for encryption. + :type key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider + """ + client = aws_encryption_sdk.EncryptionSDKClient() + + ciphertext_data, _ = client.encrypt( + source=plaintext_data, + key_provider=key_provider + ) + + return ciphertext_data + + +def decrypt_using_key_provider( + ciphertext_data: bytes, + key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider +): + """Demonstrate how to decrypt ciphertext data using an AWS KMS master key-provider. + + Usage: decrypt_using_key_provider(ciphertext_data, key_provider) + :param ciphertext_data: ciphertext data you want to decrypt + :type: bytes + :param key_provider: Master key provider to use for decryption. + :type key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider + """ + client = aws_encryption_sdk.EncryptionSDKClient() + + decrypted_plaintext_data, _ = client.decrypt( + source=ciphertext_data, + key_provider=key_provider + ) + + return decrypted_plaintext_data diff --git a/performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/raw_aes_master_key_provider.py b/performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/raw_aes_master_key_provider.py new file mode 100644 index 000000000..42d071dcf --- /dev/null +++ b/performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/raw_aes_master_key_provider.py @@ -0,0 +1,101 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Performance tests for the Raw AES master key provider.""" + +import aws_encryption_sdk +from aws_encryption_sdk.identifiers import EncryptionKeyType, WrappingAlgorithm +from aws_encryption_sdk.internal.crypto.wrapping_keys import WrappingKey +from aws_encryption_sdk.key_providers.raw import RawMasterKeyProvider + +from ..utils.util import PerfTestUtils + + +class StaticRandomMasterKeyProvider(RawMasterKeyProvider): + """Generates 256-bit keys for each unique key ID.""" + + # The Provider ID (or Provider) field in the JceMasterKey and RawMasterKey is + # equivalent to key namespace in the Raw keyrings + provider_id = "Some managed raw keys" + + def __init__(self, **kwargs): # pylint: disable=unused-argument + """Initialize empty map of keys.""" + self._static_keys = {} + + def _get_raw_key(self, key_id): + """Returns a static, randomly-generated symmetric key for the specified key ID. + + :param str key_id: Key ID + :returns: Wrapping key that contains the specified static key + :rtype: :class:`aws_encryption_sdk.internal.crypto.WrappingKey` + """ + try: + static_key = self._static_keys[key_id] + except KeyError: + # We fix the static key in order to make the test deterministic + # In practice, you should get this key from a secure key management system such as an HSM. + static_key = PerfTestUtils.DEFAULT_AES_256_STATIC_KEY + self._static_keys[key_id] = static_key + return WrappingKey( + wrapping_algorithm=WrappingAlgorithm.AES_256_GCM_IV12_TAG16_NO_PADDING, + wrapping_key=static_key, + wrapping_key_type=EncryptionKeyType.SYMMETRIC, + ) + + +def create_key_provider(): + """Demonstrate how to create a Raw AES master key-provider. + + Usage: create_key_provider() + """ + # Create a Raw AES master key-provider. + + # The Key ID field in the JceMasterKey and RawMasterKey is equivalent to key name in the Raw keyrings + key_id = "My 256-bit AES wrapping key" + key_provider = StaticRandomMasterKeyProvider() + key_provider.add_master_key(key_id) + + return key_provider + + +def encrypt_using_key_provider( + plaintext_data: bytes, + key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider +): + """Demonstrate how to encrypt plaintext data using a Raw AES master key-provider. + + Usage: encrypt_using_key_provider(plaintext_data, key_provider) + :param plaintext_data: plaintext data you want to encrypt + :type: bytes + :param key_provider: Master key provider to use for encryption. + :type key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider + """ + client = aws_encryption_sdk.EncryptionSDKClient() + + ciphertext_data, _ = client.encrypt( + source=plaintext_data, + key_provider=key_provider + ) + + return ciphertext_data + + +def decrypt_using_key_provider( + ciphertext_data: bytes, + key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider +): + """Demonstrate how to decrypt ciphertext data using a Raw AES master key-provider. + + Usage: decrypt_using_key_provider(ciphertext_data, key_provider) + :param ciphertext_data: ciphertext data you want to decrypt + :type: bytes + :param key_provider: Master key provider to use for decryption. + :type key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider + """ + client = aws_encryption_sdk.EncryptionSDKClient() + + decrypted_plaintext_data, _ = client.decrypt( + source=ciphertext_data, + key_provider=key_provider + ) + + return decrypted_plaintext_data diff --git a/performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/raw_rsa_master_key_provider.py b/performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/raw_rsa_master_key_provider.py new file mode 100644 index 000000000..b52b78735 --- /dev/null +++ b/performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/raw_rsa_master_key_provider.py @@ -0,0 +1,101 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Performance tests for the Raw RSA master key provider.""" + +import aws_encryption_sdk +from aws_encryption_sdk.identifiers import EncryptionKeyType, WrappingAlgorithm +from aws_encryption_sdk.internal.crypto.wrapping_keys import WrappingKey +from aws_encryption_sdk.key_providers.raw import RawMasterKeyProvider + +from aws_encryption_sdk_performance_tests.utils.util import PerfTestUtils + + +class StaticRandomMasterKeyProvider(RawMasterKeyProvider): + """Randomly generates and provides 4096-bit RSA keys consistently per unique key id.""" + + # The Provider ID (or Provider) field in the JceMasterKey and RawMasterKey is + # equivalent to key namespace in the Raw keyrings + provider_id = "Some managed raw keys" + + def __init__(self, **kwargs): # pylint: disable=unused-argument + """Initialize empty map of keys.""" + self._static_keys = {} + + def _get_raw_key(self, key_id): + """Retrieves a static, randomly generated, RSA key for the specified key id. + + :param str key_id: User-defined ID for the static key + :returns: Wrapping key that contains the specified static key + :rtype: :class:`aws_encryption_sdk.internal.crypto.WrappingKey` + """ + try: + static_key = self._static_keys[key_id] + except KeyError: + # We fix the static key in order to make the test deterministic + # In practice, you should get this key from a secure key management system such as an HSM. + static_key = PerfTestUtils.DEFAULT_RSA_PRIVATE_KEY + self._static_keys[key_id] = static_key + return WrappingKey( + wrapping_algorithm=WrappingAlgorithm.RSA_OAEP_SHA256_MGF1, + wrapping_key=static_key, + wrapping_key_type=EncryptionKeyType.PRIVATE, + ) + + +def create_key_provider(): + """Demonstrate how to create a Raw RSA master key-provider. + + Usage: create_key_provider() + """ + # Create a Raw RSA master key-provider. + + # The Key ID field in the JceMasterKey and RawMasterKey is equivalent to key name in the Raw keyrings + key_id = "My 4096-bit RSA wrapping key" + key_provider = StaticRandomMasterKeyProvider() + key_provider.add_master_key(key_id) + + return key_provider + + +def encrypt_using_key_provider( + plaintext_data: bytes, + key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider +): + """Demonstrate how to encrypt plaintext data using a Raw RSA master key-provider. + + Usage: encrypt_using_key_provider(plaintext_data, key_provider) + :param plaintext_data: plaintext data you want to encrypt + :type: bytes + :param key_provider: Master key provider to use for encryption. + :type key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider + """ + client = aws_encryption_sdk.EncryptionSDKClient() + + ciphertext_data, _ = client.encrypt( + source=plaintext_data, + key_provider=key_provider + ) + + return ciphertext_data + + +def decrypt_using_key_provider( + ciphertext_data: bytes, + key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider +): + """Demonstrate how to decrypt ciphertext data using a Raw RSA master key-provider. + + Usage: decrypt_using_key_provider(ciphertext_data, key_provider) + :param ciphertext_data: ciphertext data you want to decrypt + :type: bytes + :param key_provider: Master key provider to use for decryption. + :type key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider + """ + client = aws_encryption_sdk.EncryptionSDKClient() + + decrypted_plaintext_data, _ = client.decrypt( + source=ciphertext_data, + key_provider=key_provider + ) + + return decrypted_plaintext_data diff --git a/performance_tests/src/aws_encryption_sdk_performance_tests/utils/__init__.py b/performance_tests/src/aws_encryption_sdk_performance_tests/utils/__init__.py new file mode 100644 index 000000000..120179eda --- /dev/null +++ b/performance_tests/src/aws_encryption_sdk_performance_tests/utils/__init__.py @@ -0,0 +1,3 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Stub module indicator to make linter configuration simpler.""" diff --git a/performance_tests/src/aws_encryption_sdk_performance_tests/utils/util.py b/performance_tests/src/aws_encryption_sdk_performance_tests/utils/util.py new file mode 100644 index 000000000..52914b76a --- /dev/null +++ b/performance_tests/src/aws_encryption_sdk_performance_tests/utils/util.py @@ -0,0 +1,116 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Utility functions for AWS Encryption SDK performance tests.""" + + +class PerfTestUtils: + """Utility functions for AWS Encryption SDK performance tests.""" + DEFAULT_N_ITERS = 100 + DEFAULT_TESTING_N_ITERS = 1 + DEFAULT_FILE_SIZE = 'medium' + DEFAULT_AES_256_STATIC_KEY = \ + b'_\xcf"\x82\x03\x12\x9d\x00\x8a\xed\xaf\xe4\x80\x1d\x00t\xa6P\xac\xb6\xfe\xc5\xf6/{\xe7\xaaO\x01\x13W\x85' + DEFAULT_RSA_PUBLIC_KEY = bytes("-----BEGIN PUBLIC KEY-----\n" + + "MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxwWEEtEofjwaoo3WO79D\n" + + "hntoPf2APlY5yzlqm6ZvMyaazlwetkAzLSn5GB4hjKZaf043BfADJEdwXMHn8/UN\n" + + "up0BfUj8PfGn/b8cL78CTnvFZd/7WxQh6tUnfLX7BMiccHMb9OHhRy5PrTSuj6Um\n" + + "wwhBadL+Lc23DGl2cyN9SjGuYWWQ1IHGFA4/2EQr+Ez4LpebZqwXgv0iLuApte1q\n" + + "vGl6zOhByxi1N/ORVEscLT82+L+F3STgeTYA1CaoLFQ0y9ybx+7UUfEfKxhGoGEO\n" + + "XEOTuRBdLE2Jm8xaBODLqfiXr0z62VhTpRs4CYYTGHTLFCJHqeH7R2fwvwoG1nIg\n" + + "QzWSyyapK7d5MLn3rF3ManjZhvlyHK1wqa7nWVpo+jq1Py+HWLAtU8FY0br6wnOR\n" + + "3jjPGk0N4//iDnxNN+kpDxFnHEvxe3eJKWnbw0GR9+BGj32O+wRMtGyfRTzkoD/E\n" + + "EqIRlDzdtYCAtFW0HUsdQwL+ssDjEQ0+lqvEQrwTU1WBZiBQhEmzksAowHAcNIT+\n" + + "Fz7mvIlpEETNOQbsJkoXdEkhJXljh5UYmH1cB5al1MJf/5ea5Xb2HfH5WkMy4+eS\n" + + "V68V+tXv3ZthTe2bCk9rQTH9FWKLIYJyZfv8WAIxSWEEsyk5b+7WUGmvtm/nPJ4Z\n" + + "RfzkXoBJqJiSiPYCM0+jG4sCAwEAAQ==\n" + + "-----END PUBLIC KEY-----\n", 'utf-8') + + DEFAULT_RSA_PRIVATE_KEY = bytes("-----BEGIN PRIVATE KEY-----\n" + + "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\n" + + "A/DHJmMI5bKETJyj1GhBE9LqypAI1Bo=\n" + + "-----END PRIVATE KEY-----\n", "utf-8") + + DEFAULT_ENCRYPTION_CONTEXT = { + "tenant": "TenantA", + "encryption": "context", + "is not": "secret", + "but adds": "useful metadata", + "that can help you": "be confident that", + "the data you are handling": "is what you think it is", + } + + DEFAULT_BRANCH_KEY_ID_A = 'a52dfaad-7dbd-4430-a1fd-abaa5299da07' + + DEFAULT_BRANCH_KEY_ID_B = '8ba79cef-581c-4125-9292-b057a29d42d7' + + @staticmethod + def read_file(filename): + """Returns the contents of the file.""" + with open(filename, 'rb') as file: + return file.read() + + @staticmethod + def get_rsa_key_from_file(filename): + """Returns the RSA key""" + with open(filename, "r", encoding='utf-8') as f: + key = f.read() + + # Convert the key from a string to bytes + key = bytes(key, 'utf-8') + + return key + + @staticmethod + def write_time_list_to_csv(time_list, filename): + """Writes the time list to a CSV file.""" + with open(filename + '.csv', 'w', encoding='utf-8') as myfile: + for time in time_list: + myfile.write(str(time) + '\n') diff --git a/performance_tests/test/keyrings/__init__.py b/performance_tests/test/keyrings/__init__.py new file mode 100644 index 000000000..120179eda --- /dev/null +++ b/performance_tests/test/keyrings/__init__.py @@ -0,0 +1,3 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Stub module indicator to make linter configuration simpler.""" diff --git a/performance_tests/test/keyrings/test_aws_kms_keyring.py b/performance_tests/test/keyrings/test_aws_kms_keyring.py new file mode 100644 index 000000000..950a2a82e --- /dev/null +++ b/performance_tests/test/keyrings/test_aws_kms_keyring.py @@ -0,0 +1,206 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""This is a performance test for creating the AWS KMS keyring.""" + +import os +import time + +import click +import click.testing +import pytest +from tqdm import tqdm + +from aws_encryption_sdk_performance_tests.keyrings.aws_kms_keyring import ( + create_keyring, + create_keyring_given_kms_client, + create_kms_client, + decrypt_using_keyring, + encrypt_using_keyring, +) +from aws_encryption_sdk_performance_tests.utils.util import PerfTestUtils + +MODULE_ABS_PATH = os.path.abspath(__file__) + + +@click.group() +def create_kms_keyring(): + """Click group helper function""" + + +@create_kms_keyring.command() +@click.option('--kms_key_id', + default='arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f') +@click.option('--n_iters', + default=PerfTestUtils.DEFAULT_N_ITERS) +@click.option('--output_file', + default='/'.join(MODULE_ABS_PATH.split("/")[:-3]) + '/results/kms_keyring_create') +def create( + kms_key_id: str, + n_iters: int, + output_file: str +): + """Performance test for the create_keyring function.""" + time_list = [] + for _ in tqdm(range(n_iters)): + curr_time = time.time() + + create_keyring(kms_key_id) + + # calculate elapsed time in milliseconds + elapsed_time = (time.time() - curr_time) * 1000 + time_list.append(elapsed_time) + PerfTestUtils.write_time_list_to_csv(time_list, output_file) + + +@click.group() +def create_kms_keyring_given_kms_client(): + """Click group helper function""" + + +@create_kms_keyring_given_kms_client.command() +@click.option('--kms_key_id', + default='arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f') +@click.option('--n_iters', + default=PerfTestUtils.DEFAULT_N_ITERS) +@click.option('--output_file', + default='/'.join(MODULE_ABS_PATH.split("/")[:-3]) + '/results/kms_keyring_create_given_kms_client') +def create_given_kms_client( + kms_key_id: str, + n_iters: int, + output_file: str +): + """Performance test for the create_keyring function.""" + kms_client = create_kms_client() + time_list = [] + for _ in tqdm(range(n_iters)): + curr_time = time.time() + + create_keyring_given_kms_client(kms_key_id, kms_client) + + # calculate elapsed time in milliseconds + elapsed_time = (time.time() - curr_time) * 1000 + time_list.append(elapsed_time) + + PerfTestUtils.write_time_list_to_csv(time_list, output_file) + + +@click.group() +def encrypt_kms_keyring(): + """Click group helper function""" + + +@encrypt_kms_keyring.command() +@click.option('--plaintext_data_filename', + default='/'.join(MODULE_ABS_PATH.split("/")[:-2]) + '/resources/plaintext/plaintext-data-' + + PerfTestUtils.DEFAULT_FILE_SIZE + '.dat') +@click.option('--kms_key_id', + default='arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f') +@click.option('--n_iters', + default=PerfTestUtils.DEFAULT_N_ITERS) +@click.option('--output_file', + default='/'.join(MODULE_ABS_PATH.split("/")[:-3]) + '/results/kms_keyring_encrypt') +def encrypt( + plaintext_data_filename: str, + kms_key_id: str, + n_iters: int, + output_file: str +): + """Performance test for the encrypt_using_keyring function.""" + plaintext_data = PerfTestUtils.read_file(plaintext_data_filename) + + keyring = create_keyring(kms_key_id) + time_list = [] + + for _ in tqdm(range(n_iters)): + curr_time = time.time() + + encrypt_using_keyring(plaintext_data, keyring) + + # calculate elapsed time in milliseconds + elapsed_time = (time.time() - curr_time) * 1000 + time_list.append(elapsed_time) + + PerfTestUtils.write_time_list_to_csv(time_list, output_file) + + +@click.group() +def decrypt_kms_keyring(): + """Click group helper function""" + + +@decrypt_kms_keyring.command() +@click.option('--ciphertext_data_filename', + default='/'.join(MODULE_ABS_PATH.split("/")[:-2]) + '/resources/ciphertext/kms/ciphertext-data-' + + PerfTestUtils.DEFAULT_FILE_SIZE + '.ct') +@click.option('--kms_key_id', + default='arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f') +@click.option('--n_iters', + default=PerfTestUtils.DEFAULT_N_ITERS) +@click.option('--output_file', + default='/'.join(MODULE_ABS_PATH.split("/")[:-3]) + '/results/kms_keyring_decrypt') +def decrypt( + ciphertext_data_filename: str, + kms_key_id: str, + n_iters: int, + output_file: str +): + """Performance test for the decrypt_using_keyring function.""" + ciphertext_data = PerfTestUtils.read_file(ciphertext_data_filename) + + keyring = create_keyring(kms_key_id) + time_list = [] + + for _ in tqdm(range(n_iters)): + curr_time = time.time() + + decrypt_using_keyring(ciphertext_data, keyring) + + # calculate elapsed time in milliseconds + elapsed_time = (time.time() - curr_time) * 1000 + time_list.append(elapsed_time) + + PerfTestUtils.write_time_list_to_csv(time_list, output_file) + + +kms_keyring_test = click.CommandCollection(sources=[create_kms_keyring, + create_kms_keyring_given_kms_client, + encrypt_kms_keyring, + decrypt_kms_keyring]) + + +@pytest.fixture +def runner(): + """Click runner""" + return click.testing.CliRunner() + + +def test_create(runner): + """Test the create_keyring function""" + result = runner.invoke(create_kms_keyring.commands['create'], + ['--n_iters', PerfTestUtils.DEFAULT_TESTING_N_ITERS]) + assert result.exit_code == 0 + + +def test_create_given_kms_client(runner): + """Test the create_keyring_given_kms_client function""" + result = runner.invoke(create_kms_keyring_given_kms_client.commands['create-given-kms-client'], + ['--n_iters', PerfTestUtils.DEFAULT_TESTING_N_ITERS]) + assert result.exit_code == 0 + + +def test_encrypt(runner): + """Test the encrypt_using_keyring function""" + result = runner.invoke(encrypt_kms_keyring.commands['encrypt'], + ['--n_iters', PerfTestUtils.DEFAULT_TESTING_N_ITERS]) + assert result.exit_code == 0 + + +def test_decrypt(runner): + """Test the decrypt_using_keyring function""" + result = runner.invoke(decrypt_kms_keyring.commands['decrypt'], + ['--n_iters', PerfTestUtils.DEFAULT_TESTING_N_ITERS]) + assert result.exit_code == 0 + + +if __name__ == "__main__": + kms_keyring_test() diff --git a/performance_tests/test/keyrings/test_raw_aes_keyring.py b/performance_tests/test/keyrings/test_raw_aes_keyring.py new file mode 100644 index 000000000..1e1da428a --- /dev/null +++ b/performance_tests/test/keyrings/test_raw_aes_keyring.py @@ -0,0 +1,156 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""This is a performance test for creating the Raw AES keyring.""" + +import os +import time + +import click +import click.testing +import pytest +from tqdm import tqdm + +from aws_encryption_sdk_performance_tests.keyrings.raw_aes_keyring import ( + create_keyring, + decrypt_using_keyring, + encrypt_using_keyring, +) +from aws_encryption_sdk_performance_tests.utils.util import PerfTestUtils + +MODULE_ABS_PATH = os.path.abspath(__file__) + + +@click.group() +def create_raw_aes_keyring(): + """Click group helper function""" + + +@create_raw_aes_keyring.command() +@click.option('--n_iters', + default=PerfTestUtils.DEFAULT_N_ITERS) +@click.option('--output_file', + default='/'.join(MODULE_ABS_PATH.split("/")[:-3]) + '/results/raw_aes_keyring_create') +def create( + n_iters: int, + output_file: str +): + """Performance test for the create_keyring function.""" + time_list = [] + for _ in tqdm(range(n_iters)): + curr_time = time.time() + + create_keyring() + + # calculate elapsed time in milliseconds + elapsed_time = (time.time() - curr_time) * 1000 + time_list.append(elapsed_time) + + PerfTestUtils.write_time_list_to_csv(time_list, output_file) + + +@click.group() +def encrypt_raw_aes_keyring(): + """Click group helper function""" + + +@encrypt_raw_aes_keyring.command() +@click.option('--plaintext_data_filename', + default='/'.join(MODULE_ABS_PATH.split("/")[:-2]) + '/resources/plaintext/plaintext-data-' + + PerfTestUtils.DEFAULT_FILE_SIZE + '.dat') +@click.option('--n_iters', + default=PerfTestUtils.DEFAULT_N_ITERS) +@click.option('--output_file', + default='/'.join(MODULE_ABS_PATH.split("/")[:-3]) + '/results/raw_aes_keyring_encrypt') +def encrypt( + plaintext_data_filename: str, + n_iters: int, + output_file: str +): + """Performance test for the encrypt_using_keyring function.""" + plaintext_data = PerfTestUtils.read_file(plaintext_data_filename) + + keyring = create_keyring() + time_list = [] + + for _ in tqdm(range(n_iters)): + curr_time = time.time() + + encrypt_using_keyring(plaintext_data, keyring) + + # calculate elapsed time in milliseconds + elapsed_time = (time.time() - curr_time) * 1000 + time_list.append(elapsed_time) + + PerfTestUtils.write_time_list_to_csv(time_list, output_file) + + +@click.group() +def decrypt_raw_aes_keyring(): + """Click group helper function""" + + +@decrypt_raw_aes_keyring.command() +@click.option('--ciphertext_data_filename', + default='/'.join(MODULE_ABS_PATH.split("/")[:-2]) + '/resources/ciphertext/raw_aes/ciphertext-data-' + + PerfTestUtils.DEFAULT_FILE_SIZE + '.ct') +@click.option('--n_iters', + default=PerfTestUtils.DEFAULT_N_ITERS) +@click.option('--output_file', + default='/'.join(MODULE_ABS_PATH.split("/")[:-3]) + '/results/raw_aes_keyring_decrypt') +def decrypt( + ciphertext_data_filename: str, + n_iters: int, + output_file: str +): + """Performance test for the decrypt_using_keyring function.""" + ciphertext_data = PerfTestUtils.read_file(ciphertext_data_filename) + + keyring = create_keyring() + time_list = [] + + for _ in tqdm(range(n_iters)): + curr_time = time.time() + + decrypt_using_keyring(ciphertext_data, keyring) + + # calculate elapsed time in milliseconds + elapsed_time = (time.time() - curr_time) * 1000 + time_list.append(elapsed_time) + + PerfTestUtils.write_time_list_to_csv(time_list, output_file) + + +raw_aes_keyring_test = click.CommandCollection(sources=[create_raw_aes_keyring, + encrypt_raw_aes_keyring, + decrypt_raw_aes_keyring]) + + +@pytest.fixture +def runner(): + """Click runner""" + return click.testing.CliRunner() + + +def test_create(runner): + """Test the create_keyring function""" + result = runner.invoke(create_raw_aes_keyring.commands['create'], + ['--n_iters', PerfTestUtils.DEFAULT_TESTING_N_ITERS]) + assert result.exit_code == 0 + + +def test_encrypt(runner): + """Test the encrypt_using_keyring function""" + result = runner.invoke(encrypt_raw_aes_keyring.commands['encrypt'], + ['--n_iters', PerfTestUtils.DEFAULT_TESTING_N_ITERS]) + assert result.exit_code == 0 + + +def test_decrypt(runner): + """Test the decrypt_using_keyring function""" + result = runner.invoke(decrypt_raw_aes_keyring.commands['decrypt'], + ['--n_iters', PerfTestUtils.DEFAULT_TESTING_N_ITERS]) + assert result.exit_code == 0 + + +if __name__ == "__main__": + raw_aes_keyring_test() diff --git a/performance_tests/test/keyrings/test_raw_rsa_keyring.py b/performance_tests/test/keyrings/test_raw_rsa_keyring.py new file mode 100644 index 000000000..476701ac0 --- /dev/null +++ b/performance_tests/test/keyrings/test_raw_rsa_keyring.py @@ -0,0 +1,163 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""This is a performance test for creating the Raw RSA keyring.""" + +import os +import time + +import click +import click.testing +import pytest +from tqdm import tqdm + +from aws_encryption_sdk_performance_tests.keyrings.raw_rsa_keyring import ( + create_keyring, + decrypt_using_keyring, + encrypt_using_keyring, +) +from aws_encryption_sdk_performance_tests.utils.util import PerfTestUtils + +MODULE_ABS_PATH = os.path.abspath(__file__) + + +@click.group() +def create_raw_rsa_keyring(): + """Click group helper function""" + + +@create_raw_rsa_keyring.command() +@click.option('--n_iters', + default=PerfTestUtils.DEFAULT_N_ITERS) +@click.option('--output_file', + default='/'.join(MODULE_ABS_PATH.split("/")[:-3]) + '/results/raw_rsa_keyring_create') +def create( + n_iters: int, + output_file: str +): + """Performance test for the create_keyring function.""" + public_key = PerfTestUtils.DEFAULT_RSA_PUBLIC_KEY + private_key = PerfTestUtils.DEFAULT_RSA_PRIVATE_KEY + + time_list = [] + for _ in tqdm(range(n_iters)): + curr_time = time.time() + + create_keyring(public_key, private_key) + + # calculate elapsed time in milliseconds + elapsed_time = (time.time() - curr_time) * 1000 + time_list.append(elapsed_time) + + PerfTestUtils.write_time_list_to_csv(time_list, output_file) + + +@click.group() +def encrypt_raw_rsa_keyring(): + """Click group helper function""" + + +@encrypt_raw_rsa_keyring.command() +@click.option('--plaintext_data_filename', + default='/'.join(MODULE_ABS_PATH.split("/")[:-2]) + '/resources/plaintext/plaintext-data-' + + PerfTestUtils.DEFAULT_FILE_SIZE + '.dat') +@click.option('--n_iters', + default=PerfTestUtils.DEFAULT_N_ITERS) +@click.option('--output_file', + default='/'.join(MODULE_ABS_PATH.split("/")[:-3]) + '/results/raw_rsa_keyring_encrypt') +def encrypt( + plaintext_data_filename: str, + n_iters: int, + output_file: str +): + """Performance test for the encrypt_using_keyring function.""" + public_key = PerfTestUtils.DEFAULT_RSA_PUBLIC_KEY + private_key = PerfTestUtils.DEFAULT_RSA_PRIVATE_KEY + plaintext_data = PerfTestUtils.read_file(plaintext_data_filename) + + keyring = create_keyring(public_key, private_key) + time_list = [] + + for _ in tqdm(range(n_iters)): + curr_time = time.time() + + encrypt_using_keyring(plaintext_data, keyring) + + # calculate elapsed time in milliseconds + elapsed_time = (time.time() - curr_time) * 1000 + time_list.append(elapsed_time) + + PerfTestUtils.write_time_list_to_csv(time_list, output_file) + + +@click.group() +def decrypt_raw_rsa_keyring(): + """Click group helper function""" + + +@decrypt_raw_rsa_keyring.command() +@click.option('--ciphertext_data_filename', + default='/'.join(MODULE_ABS_PATH.split("/")[:-2]) + '/resources/ciphertext/raw_rsa/ciphertext-data-' + + PerfTestUtils.DEFAULT_FILE_SIZE + '.ct') +@click.option('--n_iters', + default=PerfTestUtils.DEFAULT_N_ITERS) +@click.option('--output_file', + default='/'.join(MODULE_ABS_PATH.split("/")[:-3]) + '/results/raw_rsa_keyring_decrypt') +def decrypt( + ciphertext_data_filename: str, + n_iters: int, + output_file: str +): + """Performance test for the decrypt_using_keyring function.""" + public_key = PerfTestUtils.DEFAULT_RSA_PUBLIC_KEY + private_key = PerfTestUtils.DEFAULT_RSA_PRIVATE_KEY + ciphertext_data = PerfTestUtils.read_file(ciphertext_data_filename) + + keyring = create_keyring(public_key, private_key) + time_list = [] + + for _ in tqdm(range(n_iters)): + curr_time = time.time() + + decrypt_using_keyring(ciphertext_data, keyring) + + # calculate elapsed time in milliseconds + elapsed_time = (time.time() - curr_time) * 1000 + time_list.append(elapsed_time) + + PerfTestUtils.write_time_list_to_csv(time_list, output_file) + + +raw_rsa_keyring_test = click.CommandCollection(sources=[create_raw_rsa_keyring, + encrypt_raw_rsa_keyring, + decrypt_raw_rsa_keyring]) + + +@pytest.fixture +def runner(): + """Click runner""" + return click.testing.CliRunner() + + +def test_create(runner): + """Test the create_keyring function""" + result = runner.invoke(create_raw_rsa_keyring.commands['create'], + ['--n_iters', PerfTestUtils.DEFAULT_TESTING_N_ITERS]) + assert result.exit_code == 0 + + +def test_encrypt(runner): + """Test the encrypt_using_keyring function""" + result = runner.invoke(encrypt_raw_rsa_keyring.commands['encrypt'], + ['--n_iters', PerfTestUtils.DEFAULT_TESTING_N_ITERS]) + assert result.exit_code == 0 + + +def test_decrypt(runner): + """Test the decrypt_using_keyring function""" + result = runner.invoke(decrypt_raw_rsa_keyring.commands['decrypt'], + ['--n_iters', PerfTestUtils.DEFAULT_TESTING_N_ITERS]) + assert result.exit_code == 0 + + +if __name__ == "__main__": + raw_rsa_keyring_test() diff --git a/performance_tests/test/master_key_providers/__init__.py b/performance_tests/test/master_key_providers/__init__.py new file mode 100644 index 000000000..120179eda --- /dev/null +++ b/performance_tests/test/master_key_providers/__init__.py @@ -0,0 +1,3 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Stub module indicator to make linter configuration simpler.""" diff --git a/performance_tests/test/master_key_providers/test_aws_kms_master_key_provider.py b/performance_tests/test/master_key_providers/test_aws_kms_master_key_provider.py new file mode 100644 index 000000000..b869245b5 --- /dev/null +++ b/performance_tests/test/master_key_providers/test_aws_kms_master_key_provider.py @@ -0,0 +1,165 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""This is a performance test for creating the AWS KMS Master key-provider.""" + +import os +import time + +import click +import click.testing +import pytest +from tqdm import tqdm + +from aws_encryption_sdk_performance_tests.master_key_providers.aws_kms_master_key_provider import ( + create_key_provider, + decrypt_using_key_provider, + encrypt_using_key_provider, +) +from aws_encryption_sdk_performance_tests.utils.util import PerfTestUtils + +MODULE_ABS_PATH = os.path.abspath(__file__) + + +@click.group() +def create_kms_key_provider(): + """Click group helper function""" + + +@create_kms_key_provider.command() +@click.option('--kms_key_id', + default='arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f') +@click.option('--n_iters', + default=PerfTestUtils.DEFAULT_N_ITERS) +@click.option('--output_file', + default='/'.join(MODULE_ABS_PATH.split("/")[:-3]) + '/results/kms_key_provider_create') +def create( + kms_key_id: str, + n_iters: int, + output_file: str +): + """Performance test for the create_key_provider function.""" + time_list = [] + for _ in tqdm(range(n_iters)): + curr_time = time.time() + + create_key_provider(kms_key_id) + + # calculate elapsed time in milliseconds + elapsed_time = (time.time() - curr_time) * 1000 + time_list.append(elapsed_time) + + PerfTestUtils.write_time_list_to_csv(time_list, output_file) + + +@click.group() +def encrypt_kms_key_provider(): + """Click group helper function""" + + +@encrypt_kms_key_provider.command() +@click.option('--plaintext_data_filename', + default='/'.join(MODULE_ABS_PATH.split("/")[:-2]) + '/resources/plaintext/plaintext-data-' + + PerfTestUtils.DEFAULT_FILE_SIZE + '.dat') +@click.option('--kms_key_id', + default='arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f') +@click.option('--n_iters', + default=PerfTestUtils.DEFAULT_N_ITERS) +@click.option('--output_file', + default='/'.join(MODULE_ABS_PATH.split("/")[:-3]) + '/results/kms_key_provider_encrypt') +def encrypt( + plaintext_data_filename: str, + kms_key_id: str, + n_iters: int, + output_file: str +): + """Performance test for the encrypt_using_key_provider function.""" + plaintext_data = PerfTestUtils.read_file(plaintext_data_filename) + + key_provider = create_key_provider(kms_key_id) + time_list = [] + + for _ in tqdm(range(n_iters)): + curr_time = time.time() + + encrypt_using_key_provider(plaintext_data, key_provider) + + # calculate elapsed time in milliseconds + elapsed_time = (time.time() - curr_time) * 1000 + time_list.append(elapsed_time) + + PerfTestUtils.write_time_list_to_csv(time_list, output_file) + + +@click.group() +def decrypt_kms_key_provider(): + """Click group helper function""" + + +@decrypt_kms_key_provider.command() +@click.option('--ciphertext_data_filename', + default='/'.join(MODULE_ABS_PATH.split("/")[:-2]) + '/resources/ciphertext/kms/ciphertext-data-' + + PerfTestUtils.DEFAULT_FILE_SIZE + '.ct') +@click.option('--kms_key_id', + default='arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f') +@click.option('--n_iters', + default=PerfTestUtils.DEFAULT_N_ITERS) +@click.option('--output_file', + default='/'.join(MODULE_ABS_PATH.split("/")[:-3]) + '/results/kms_key_provider_decrypt') +def decrypt( + ciphertext_data_filename: str, + kms_key_id: str, + n_iters: int, + output_file: str +): + """Performance test for the decrypt_using_key_provider function.""" + ciphertext_data = PerfTestUtils.read_file(ciphertext_data_filename) + + key_provider = create_key_provider(kms_key_id) + time_list = [] + + for _ in tqdm(range(n_iters)): + curr_time = time.time() + + decrypt_using_key_provider(ciphertext_data, key_provider) + + # calculate elapsed time in milliseconds + elapsed_time = (time.time() - curr_time) * 1000 + time_list.append(elapsed_time) + + PerfTestUtils.write_time_list_to_csv(time_list, output_file) + + +kms_key_provider_test = click.CommandCollection(sources=[create_kms_key_provider, + encrypt_kms_key_provider, + decrypt_kms_key_provider]) + + +@pytest.fixture +def runner(): + """Click runner""" + return click.testing.CliRunner() + + +def test_create(runner): + """Test the create_key_provider function""" + result = runner.invoke(create_kms_key_provider.commands['create'], + ['--n_iters', PerfTestUtils.DEFAULT_TESTING_N_ITERS]) + assert result.exit_code == 0 + + +def test_encrypt(runner): + """Test the encrypt_using_key_provider function""" + result = runner.invoke(encrypt_kms_key_provider.commands['encrypt'], + ['--n_iters', PerfTestUtils.DEFAULT_TESTING_N_ITERS]) + assert result.exit_code == 0 + + +def test_decrypt(runner): + """Test the decrypt_using_key_provider function""" + result = runner.invoke(decrypt_kms_key_provider.commands['decrypt'], + ['--n_iters', PerfTestUtils.DEFAULT_TESTING_N_ITERS]) + assert result.exit_code == 0 + + +if __name__ == "__main__": + kms_key_provider_test() diff --git a/performance_tests/test/master_key_providers/test_raw_aes_master_key_provider.py b/performance_tests/test/master_key_providers/test_raw_aes_master_key_provider.py new file mode 100644 index 000000000..375eca2ef --- /dev/null +++ b/performance_tests/test/master_key_providers/test_raw_aes_master_key_provider.py @@ -0,0 +1,156 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""This is a performance test for creating the Raw AES Master key-provider.""" + +import os +import time + +import click +import click.testing +import pytest +from tqdm import tqdm + +from aws_encryption_sdk_performance_tests.master_key_providers.raw_aes_master_key_provider import ( + create_key_provider, + decrypt_using_key_provider, + encrypt_using_key_provider, +) +from aws_encryption_sdk_performance_tests.utils.util import PerfTestUtils + +MODULE_ABS_PATH = os.path.abspath(__file__) + + +@click.group() +def create_raw_aes_key_provider(): + """Click group helper function""" + + +@create_raw_aes_key_provider.command() +@click.option('--n_iters', + default=PerfTestUtils.DEFAULT_N_ITERS) +@click.option('--output_file', + default='/'.join(MODULE_ABS_PATH.split("/")[:-3]) + '/results/raw_aes_key_provider_create') +def create( + n_iters: int, + output_file: str +): + """Performance test for the create_key_provider function.""" + time_list = [] + for _ in tqdm(range(n_iters)): + curr_time = time.time() + + create_key_provider() + + # calculate elapsed time in milliseconds + elapsed_time = (time.time() - curr_time) * 1000 + time_list.append(elapsed_time) + + PerfTestUtils.write_time_list_to_csv(time_list, output_file) + + +@click.group() +def encrypt_raw_aes_key_provider(): + """Click group helper function""" + + +@encrypt_raw_aes_key_provider.command() +@click.option('--plaintext_data_filename', + default='/'.join(MODULE_ABS_PATH.split("/")[:-2]) + '/resources/plaintext/plaintext-data-' + + PerfTestUtils.DEFAULT_FILE_SIZE + '.dat') +@click.option('--n_iters', + default=PerfTestUtils.DEFAULT_N_ITERS) +@click.option('--output_file', + default='/'.join(MODULE_ABS_PATH.split("/")[:-3]) + '/results/raw_aes_key_provider_encrypt') +def encrypt( + plaintext_data_filename: str, + n_iters: int, + output_file: str +): + """Performance test for the encrypt_using_key_provider function.""" + plaintext_data = PerfTestUtils.read_file(plaintext_data_filename) + + key_provider = create_key_provider() + time_list = [] + + for _ in tqdm(range(n_iters)): + curr_time = time.time() + + encrypt_using_key_provider(plaintext_data, key_provider) + + # calculate elapsed time in milliseconds + elapsed_time = (time.time() - curr_time) * 1000 + time_list.append(elapsed_time) + + PerfTestUtils.write_time_list_to_csv(time_list, output_file) + + +@click.group() +def decrypt_raw_aes_key_provider(): + """Click group helper function""" + + +@decrypt_raw_aes_key_provider.command() +@click.option('--ciphertext_data_filename', + default='/'.join(MODULE_ABS_PATH.split("/")[:-2]) + '/resources/ciphertext/raw_aes/ciphertext-data-' + + PerfTestUtils.DEFAULT_FILE_SIZE + '.ct') +@click.option('--n_iters', + default=PerfTestUtils.DEFAULT_N_ITERS) +@click.option('--output_file', + default='/'.join(MODULE_ABS_PATH.split("/")[:-3]) + '/results/raw_aes_key_provider_decrypt') +def decrypt( + ciphertext_data_filename: str, + n_iters: int, + output_file: str +): + """Performance test for the decrypt_using_key_provider function.""" + ciphertext_data = PerfTestUtils.read_file(ciphertext_data_filename) + + key_provider = create_key_provider() + time_list = [] + + for _ in tqdm(range(n_iters)): + curr_time = time.time() + + decrypt_using_key_provider(ciphertext_data, key_provider) + + # calculate elapsed time in milliseconds + elapsed_time = (time.time() - curr_time) * 1000 + time_list.append(elapsed_time) + + PerfTestUtils.write_time_list_to_csv(time_list, output_file) + + +raw_aes_key_provider_test = click.CommandCollection(sources=[create_raw_aes_key_provider, + encrypt_raw_aes_key_provider, + decrypt_raw_aes_key_provider]) + + +@pytest.fixture +def runner(): + """Click runner""" + return click.testing.CliRunner() + + +def test_create(runner): + """Test the create_key_provider function""" + result = runner.invoke(create_raw_aes_key_provider.commands['create'], + ['--n_iters', PerfTestUtils.DEFAULT_TESTING_N_ITERS]) + assert result.exit_code == 0 + + +def test_encrypt(runner): + """Test the encrypt_using_key_provider function""" + result = runner.invoke(encrypt_raw_aes_key_provider.commands['encrypt'], + ['--n_iters', PerfTestUtils.DEFAULT_TESTING_N_ITERS]) + assert result.exit_code == 0 + + +def test_decrypt(runner): + """Test the decrypt_using_key_provider function""" + result = runner.invoke(decrypt_raw_aes_key_provider.commands['decrypt'], + ['--n_iters', PerfTestUtils.DEFAULT_TESTING_N_ITERS]) + assert result.exit_code == 0 + + +if __name__ == "__main__": + raw_aes_key_provider_test() diff --git a/performance_tests/test/master_key_providers/test_raw_rsa_master_key_provider.py b/performance_tests/test/master_key_providers/test_raw_rsa_master_key_provider.py new file mode 100644 index 000000000..5d6db861a --- /dev/null +++ b/performance_tests/test/master_key_providers/test_raw_rsa_master_key_provider.py @@ -0,0 +1,156 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""This is a performance test for creating the Raw RSA Master key-provider.""" + +import os +import time + +import click +import click.testing +import pytest +from tqdm import tqdm + +from aws_encryption_sdk_performance_tests.master_key_providers.raw_rsa_master_key_provider import ( + create_key_provider, + decrypt_using_key_provider, + encrypt_using_key_provider, +) +from aws_encryption_sdk_performance_tests.utils.util import PerfTestUtils + +MODULE_ABS_PATH = os.path.abspath(__file__) + + +@click.group() +def create_raw_rsa_key_provider(): + """Click group helper function""" + + +@create_raw_rsa_key_provider.command() +@click.option('--n_iters', + default=PerfTestUtils.DEFAULT_N_ITERS) +@click.option('--output_file', + default='/'.join(MODULE_ABS_PATH.split("/")[:-3]) + '/results/raw_rsa_key_provider_create') +def create( + n_iters: int, + output_file: str +): + """Performance test for the create_key_provider function.""" + time_list = [] + for _ in tqdm(range(n_iters)): + curr_time = time.time() + + create_key_provider() + + # calculate elapsed time in milliseconds + elapsed_time = (time.time() - curr_time) * 1000 + time_list.append(elapsed_time) + + PerfTestUtils.write_time_list_to_csv(time_list, output_file) + + +@click.group() +def encrypt_raw_rsa_key_provider(): + """Click group helper function""" + + +@encrypt_raw_rsa_key_provider.command() +@click.option('--plaintext_data_filename', + default='/'.join(MODULE_ABS_PATH.split("/")[:-2]) + '/resources/plaintext/plaintext-data-' + + PerfTestUtils.DEFAULT_FILE_SIZE + '.dat') +@click.option('--n_iters', + default=PerfTestUtils.DEFAULT_N_ITERS) +@click.option('--output_file', + default='/'.join(MODULE_ABS_PATH.split("/")[:-3]) + '/results/raw_rsa_key_provider_encrypt') +def encrypt( + plaintext_data_filename: str, + n_iters: int, + output_file: str +): + """Performance test for the encrypt_using_key_provider function.""" + plaintext_data = PerfTestUtils.read_file(plaintext_data_filename) + + key_provider = create_key_provider() + time_list = [] + + for _ in tqdm(range(n_iters)): + curr_time = time.time() + + encrypt_using_key_provider(plaintext_data, key_provider) + + # calculate elapsed time in milliseconds + elapsed_time = (time.time() - curr_time) * 1000 + time_list.append(elapsed_time) + + PerfTestUtils.write_time_list_to_csv(time_list, output_file) + + +@click.group() +def decrypt_raw_rsa_key_provider(): + """Click group helper function""" + + +@decrypt_raw_rsa_key_provider.command() +@click.option('--ciphertext_data_filename', + default='/'.join(MODULE_ABS_PATH.split("/")[:-2]) + '/resources/ciphertext/raw_rsa/ciphertext-data-' + + PerfTestUtils.DEFAULT_FILE_SIZE + '.ct') +@click.option('--n_iters', + default=PerfTestUtils.DEFAULT_N_ITERS) +@click.option('--output_file', + default='/'.join(MODULE_ABS_PATH.split("/")[:-3]) + '/results/raw_rsa_key_provider_decrypt') +def decrypt( + ciphertext_data_filename: str, + n_iters: int, + output_file: str +): + """Performance test for the decrypt_using_key_provider function.""" + ciphertext_data = PerfTestUtils.read_file(ciphertext_data_filename) + + key_provider = create_key_provider() + time_list = [] + + for _ in tqdm(range(n_iters)): + curr_time = time.time() + + decrypt_using_key_provider(ciphertext_data, key_provider) + + # calculate elapsed time in milliseconds + elapsed_time = (time.time() - curr_time) * 1000 + time_list.append(elapsed_time) + + PerfTestUtils.write_time_list_to_csv(time_list, output_file) + + +raw_rsa_key_provider_test = click.CommandCollection(sources=[create_raw_rsa_key_provider, + encrypt_raw_rsa_key_provider, + decrypt_raw_rsa_key_provider]) + + +@pytest.fixture +def runner(): + """Click runner""" + return click.testing.CliRunner() + + +def test_create(runner): + """Test the create_key_provider function""" + result = runner.invoke(create_raw_rsa_key_provider.commands['create'], + ['--n_iters', PerfTestUtils.DEFAULT_TESTING_N_ITERS]) + assert result.exit_code == 0 + + +def test_encrypt(runner): + """Test the encrypt_using_key_provider function""" + result = runner.invoke(encrypt_raw_rsa_key_provider.commands['encrypt'], + ['--n_iters', PerfTestUtils.DEFAULT_TESTING_N_ITERS]) + assert result.exit_code == 0 + + +def test_decrypt(runner): + """Test the decrypt_using_key_provider function""" + result = runner.invoke(decrypt_raw_rsa_key_provider.commands['decrypt'], + ['--n_iters', PerfTestUtils.DEFAULT_TESTING_N_ITERS]) + assert result.exit_code == 0 + + +if __name__ == "__main__": + raw_rsa_key_provider_test() diff --git a/performance_tests/test/resources/__init__.py b/performance_tests/test/resources/__init__.py new file mode 100644 index 000000000..120179eda --- /dev/null +++ b/performance_tests/test/resources/__init__.py @@ -0,0 +1,3 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Stub module indicator to make linter configuration simpler.""" diff --git a/performance_tests/test/resources/ciphertext/kms/ciphertext-data-empty.ct b/performance_tests/test/resources/ciphertext/kms/ciphertext-data-empty.ct new file mode 100644 index 0000000000000000000000000000000000000000..18f1696874059d7bc64600dfae68f89a2a262f9e GIT binary patch literal 587 zcmZQ#typC1*|SBNH>m&Yq8iz2~2yypTmG|C1r-_NVh0;u#njL=(%4b(4!K z3rg~J3rdr6GLv<)Q!5!<94)ky%KZWg(o-#5z0520vs?^=!i=IS(j85c%~JF7GQxvB zEz14;OFb%#!m*9;5@mrPl^_`QtcOP}rqd-u%c-y*`m zz))vU!^WxA=F#?@myw-qLB2sQ6C;B`211O{K#q+wq0NIam6?T6&p?ocr}KZ(hSe`K z7P;)|=wf0NXs{NjFR|-v581ub%aHqAxQDC6)a4CM)6QNze!z1>v%vb9>jbTwPESkj zyFAzGjMzkroSHpLbx&<*{9>%%!ouHU>2x zTIZp7RIqJRuj$>%SL+|lc^kQY%BN#Tbp8VY(CLgo3)1 literal 0 HcmV?d00001 diff --git a/performance_tests/test/resources/ciphertext/kms/ciphertext-data-large.ct b/performance_tests/test/resources/ciphertext/kms/ciphertext-data-large.ct new file mode 100644 index 0000000000000000000000000000000000000000..076926bfb29ea579b6decde9b556366fc845ec1b GIT binary patch literal 8619 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 literal 0 HcmV?d00001 diff --git a/performance_tests/test/resources/ciphertext/kms/ciphertext-data-medium.ct b/performance_tests/test/resources/ciphertext/kms/ciphertext-data-medium.ct new file mode 100644 index 0000000000000000000000000000000000000000..a954c7134cf35f43723c446ecd912460ba8213ec GIT binary patch literal 4587 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 we9;}@ZG7#r6P~g^U}Pv#&+rQUwB+T{+ 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 UqpSaVSDwuHE*52Gm|5trYCM)!R{#J2 literal 0 HcmV?d00001 diff --git a/performance_tests/test/resources/ciphertext/raw_aes/ciphertext-data-medium.ct b/performance_tests/test/resources/ciphertext/raw_aes/ciphertext-data-medium.ct new file mode 100644 index 0000000000000000000000000000000000000000..e62387249c756424277b3029e6db0ad58591826f GIT binary patch literal 4454 zcmV-s5t;4+1$Yw{{ts}sCFsTUNLf1Af0V}r7mhVx!S`DW(lB|@hF$<)0096MVRv&a zV{&qK~c4BQyZ&gDwYjIabLV7P`NmFBTLUTAqM`|@fQ%E^+ zYeP|TLn~!YHa1CBG&E^tW_36@a$ATl*JEn;bOAVEb_Aa`n+afB*mh35S`Ee(a(p5CW@-b(;NU_S^ zKn&jZ$cEFi5mSqAdIvo&c@Wg&3v`d@N{&2yxJ#TG3Atx98IX2}Kecc7EAI$D-;)hz z&bzZ;cTxBNHP=1KEa02|WDA+;L0Eev7!y4Qm>yeG6fz*a1|n#4b0M=gMV=$(t>HwE z-xcj=S<>i+qKzHVs9H&U5qEOlOKFO^=lP*2*J`}_lzudtDXbXIj{{e^!ouQIlc+{q zgYV|`ei-&#cDnbYm~msNFi72Z(%pI0f)vim0&(pC=)}WOClhfs`*OATpPoG9;IcWF z%s}Af^jL>U&WbSAm;B8BWA`?(#u4YnxRaC+c-|P`jHAxqArpC2R6U)pH%i%KrBA!c z5j#DJkmFBJ)pNK;(Wc%?D?xpE~?#jaj(97#%DZrLneeu2+ z|9aN$8JbAWN&hL0UXgU-^Q1A~^`u@UKX`Dy+!DOVTE!N&ycjs)%gZZ-GYLd-7APnv zBOTqA!cYIuaJn}on8^kCiLR6-4l*Eoqni1OQ8W{bu##N#ij**kr~*B_B{+!WSyTSw zw9y;Vv5|>ROL^*uA66?Z5r1!zkmSGlt(0Js;4|BGk3fz~sG=kN4bD;9_W=+)uj%7t zQip?zg|Ac^7OPw;O1IsuaLse1p?>U7`XF%nGXD20fi1CouMAb#qSBK|YxU}LO-Unn z{}z4GU7}34c@ZZ^xkFqT3z>AF&~|$%ptYjPDA4&YeS-t+&C>2jIW-bHHvV@xMm*LX zG8m|vZqTeJsl!EhZJxMJ7D<*sED#5q#Q57h$P$AytX()zKT5 zw(T3KtP&=yAQtTZV(~i4l-af7^ESRWXl&aF8`0m5o={|asP!~$m517{H0$)ydUX2w4wOQyMd9mz#kyqy$E-fMbV+#t0W*80uva;;Z@MK$#>hAyEU%@dmb6Z88W5BUQ|%ie6T{UNTl-N6o$3Cu@0qp0 z?jhQ8LoJI82bK>~Hj%gGCW>}Y_Kyg+Kc5cGRkGtpgvPdrlN(WPZB@nrK$It~Emfy= z&6eCIEr*GO4I_9IvL2u|DM05nWeCtoqyWNTxdkGH3bq|FA&xsGBQrgdn>Pc7g)l+( ze=?$K9@CoUD0X8^&@g#sh+uJj(o`8Jb0|DDED6#VY;UTKR2Niu!qNB{2?*h=)96zZ zdF-)L)9FqFlDc4Z(mlIq*|8i>CERA^uQl1iXml``U|{?H;z|POI26`s8p!kkOGoou ze?NpX9S{wA#yxk&mDJ-=_ZdDhrn;dGfk9JVK7%HMU$b~G%25}#FFO%}qg=1=L=%g; zL1TYa)859m6qj;T0F^9GS@P$Sg*}2tCsL12*nZ5U(| zZ8{bd73?1K#vJCFPIBACyE)%ssik#6`+O6bk_C^frCr|ID!Nn|b2kfN=sK?#Ucjg4 z9wf&+XJWu-Qc|N@^xyok>@$48RgvPJWf>Ld;EL(O5e&0uG`;DYcHxy0hkWeGDy1wQ z3BTEynsRyK--^u+k;oH*VcmkEXdC;HNPi_+%F3;P3e_b%Bvrr&Ybh$4-G$ewxPBi#HO4_BF;#*6dHnk}C)y`pQ_CjH)ZeJ*jvDpFA+t7U62w=3=|n4J zqs(9e=8!jwOPOQ3P>alUakD+x%6xBtcHlksxZ3;uvAgYe!Zd+kFX-O!t`ev-t5ItTEmpbkgnuBXY%}Mg z#*Vo1*~_L|fJ~vCCXOC%ErE=rt^$=60rYSd-$QSL(>MQCR{myRSUZ;vGpX>A)3rZn zQ|P$8N(OrE+$wLIu|+NP7|*zLIet zLo4pyuTtf&$NOeOyZ$4r9#SOUvLCNbOEFQF1>ATcA0Hwrridb-XxXEp0}me!|r-i6kAVz62Ak z`8q~(!e7dAXj;QrM+!Y~*zJ-!t?Rh@S>r*>Ia!GDGm>@CjK1=5pIDc=*aPMBkwtaj zQbLj_PWNpJm-Wu$DDN|zLXF=b%Ey)e68?^7$M7G~yk0pty{ zVeWd?H>--Wpz162w*`9blE)^KVTTOsb8T_5$P} zv?>jGvNT{}xeI})I$*aGQ*uJ+jJqF1Li_Nf--qaQ1{?U7jrZ1*TtjV@(|i zYj?(wd-=amVS;=;X)?q++&0R+`W88dVGi+=&t+a96{yGLCSGsdhA_SL;rPj(+1Wxb z{lQOmjjQMD>6lbCQA{ZnSBt;y>td(yP<;-L7z+RGq1C?c%n1|bWx~1ll)3-yQfEoU zRXd~-{QDZ~AJu^XsOs+=`9xz~^IC8mcd1Bfy21ppx{g=hjrpW1{+At3{tr9I3Sdd}!gf1k zknVAcdcvdmWb)8VWF`Tp2hi}cMVY7!)3A=;5f;@#mwW-AR{%j9MWZ6(8TBC~nf*-s zaMM60Pp77i!F&u8boM|)g`{mFPkDFE-dt!>Wba$SCr=n-pl1(j<P5xLdFtE*jeE-0JwKxHhkY;_~KCw z-{QA=GY3YPi(PCu-bZ7%f}gg3p&z}-nIozn&m+_1T#V~TBP`v>B1Houn${gbEnb&J z6B}@q{`F1)uyWvMe#88#XA&(6BuC28Hys=gPsTR2NOBQIS(PH9%kvCpIMalFqD1Jv zwOmC^I|8;4NCNxo_3d*_>vTt$92s~cD)Uh6M68$&&R&i49!yH5MzTjuDNco~c#D(& zLpSxvEqOOylKgS$d)fmlFw-z0Ubd*5wK%ptn|(HnDY+mf9%s2uCYw-$i0dg+O!Ey7 zRiVLuQA$kRxd%$|ZPk?vUFJ|7#SSJ5!+I{x&p=e(_2}N*geP;Dckfp^3YpYE#4@b} zu;VOfVfd8?D5;(=A)3ktA^LFoLp>6BI~%;Qm5k{o;udFQHUITU0GJSLzY*n1!xqkg z7#Yz6iavDk$2*bq0TZXQR^P@$609)rhho`Z9z12lQI z^8H4;$TyeU$Y0bRLr`_5_O=dfweZ;)SIkc}pkE-NKbNT#KOKxgZWQI-^8aVf-4Mo# zJ4|Drkqa-&bL!K78!WqBS9(l!d*iU@{Qcq*?FyZI{5KHKYC&T8Rql{?|G#Wx6ItUY zyE0wy5E^M;=aQh_A5`4ve0XeUZh~SDMY25H_UBXD1edZ%Lm_LfLMLccNcE*1LGNV|iXzHzuhb*hMxHt6919WL%6I?6~1pOrBI)DZV!}NtQ9-bIh14nNA7^bpZVHb-%0B0~|0xTZee@l;HH_$Qh*i$n3l+R&|PRunpy8Oka`IEu@)gOA3_&ctyWGt`R+-Ecm_rW(Zup%-Q=Rm zf|7jQg3_d%%w*l{)Jg^yM>D^m($Fwt{enoB(g;HXXA6^vuu`w^aEqk8^w1Qyie#5c zpI{>|@1%5>D36j%BV(s<{{k~_|IlO)ud)J*f^u71knzF!xv2`diFt|XsVNFYiRB7F z(~BAOeJd4=OwDwYGD{R3U4s?MixLY8GV{_wvJ4Ci4M5EE<(GoTms>X?V=ppxGZ;*q zx&D9niFehe8NpYjyW|)a_pXzVIQno`+qDnNWPTL22_@Zlz}L1>`Q*E`m!?!zzh+`! z5Ma0z>>Ct+k@LDf-!!Ku$KG8qoseo|6Y}?8dnebwbDq}hrxMx!AO1B@&DP)k?5Ar1 zQU8GeXf-1c!vKh_vax2#ku`4}4`gh4r}^A%-wizj4Gz)2XLi3yxy~cINdK;uz~5~r zY4yzk4A^*|@o!#QZ7_3s9`H}7EfxUcjmj(l literal 0 HcmV?d00001 diff --git a/performance_tests/test/resources/ciphertext/raw_rsa/ciphertext-data-empty.ct b/performance_tests/test/resources/ciphertext/raw_rsa/ciphertext-data-empty.ct new file mode 100644 index 0000000000000000000000000000000000000000..202643e9a47c3d902e31641767e837dbab65aaaa GIT binary patch literal 899 zcmV-}1AP1f1$a;k*Y6C|%Vu~O9PME8#TMGv-D56&of(URe4oUhO)&sp0096MVRv&a zV{&qK~dUZK(NlRj9I7%>bPEKiKNH=6ectT_^S4Ar}YDY3h zD`rGTX*5}6c5G-yWi(-7M=>ixVMc3Xd16;raCJ&yQ9V5X0RRVQ_G1Zf78CWqASsUpQlUu^)lm4R@Xf z3()wGI&o41BK?E3)<7oi^$-i}~GmK=OFN?HzBcx4;+(`3b@*q0?IB4*n5? z>9V$X=XZUpek$EzX&HROH09VgaGQY%PeoC{IMv&rDxyR(gC9tKIdcJ!@x9>?NU2ma zxF6|b+RLMB%Uu1@*L|9USt6u}NFiZL5ZQBwY*X;@T_-}I1%b{ZJP6cwyD$Du0}6Ub3(Gb$GZz}CX7^U? zN6SYN#JbaH(HM@Ffm?F5W|bxjOR}~7>e$$X8WnblyBzJYuidn-vzg@u#OcHqJEXRrfQ8q!b*QKi36DF~>EC^s z5>($+#m=(GPG46}z^aY*wc^nS&YJnlT2#!}-$qum)QPd>;_>sNL%y{O{{ktH;aBa0 zj8;i|0kc`yjGG7Wnit~6)?RL>tS9|^enhQy*94~+0ssII0I8@V{w5l%yy=9znPr}4 z(CW?RNfD!_?Vwv%cmW|R^O-LUpXR@Mp4PBCzlA6xXaE2I{{R300RR910000000000 z0RR910PvOk%5-wF>4(^>4Dnz@AOL4DWdbn(nI{|Z=WlyJzsROUf%}!7NJDYF5tf_- za^SO;L`WdC%_g6;r^9HSV{j@1$F+cl0x*4r?|Sl{+298nR<-|k#Esi>(tjA=Y#&$k Z4Q=Y&cGne<@Mn1}3)%96i?ANx>G00Sq__Y8 literal 0 HcmV?d00001 diff --git a/performance_tests/test/resources/ciphertext/raw_rsa/ciphertext-data-large.ct b/performance_tests/test/resources/ciphertext/raw_rsa/ciphertext-data-large.ct new file mode 100644 index 0000000000000000000000000000000000000000..259d83ea5ae956148020b4f61061e0932dfc0d6e GIT binary patch literal 8931 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 J#Rbn%t$1*ovReQE literal 0 HcmV?d00001 diff --git a/performance_tests/test/resources/plaintext/plaintext-data-empty.dat b/performance_tests/test/resources/plaintext/plaintext-data-empty.dat new file mode 100644 index 000000000..e69de29bb diff --git a/performance_tests/test/resources/plaintext/plaintext-data-large.dat b/performance_tests/test/resources/plaintext/plaintext-data-large.dat new file mode 100644 index 000000000..22bad9f3f --- /dev/null +++ b/performance_tests/test/resources/plaintext/plaintext-data-large.dat @@ -0,0 +1,21 @@ +Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Et netus et malesuada fames. Bibendum enim facilisis gravida neque convallis. Tortor consequat id porta nibh venenatis cras. Lacus sed viverra tellus in hac habitasse platea dictumst. Ipsum dolor sit amet consectetur adipiscing elit pellentesque. Risus pretium quam vulputate dignissim suspendisse in. Ante in nibh mauris cursus mattis molestie a iaculis at. Nulla porttitor massa id neque aliquam vestibulum morbi blandit. Urna et pharetra pharetra massa massa ultricies mi quis. Leo duis ut diam quam nulla porttitor massa id. Vitae suscipit tellus mauris a diam maecenas sed enim ut. + +Non nisi est sit amet facilisis magna etiam tempor. Mi bibendum neque egestas congue quisque egestas diam in arcu. Volutpat est velit egestas dui id ornare arcu odio ut. Amet tellus cras adipiscing enim eu turpis egestas. Tortor dignissim convallis aenean et tortor at risus viverra. Interdum consectetur libero id faucibus nisl tincidunt eget. In eu mi bibendum neque egestas congue quisque egestas. Pellentesque habitant morbi tristique senectus et netus et malesuada fames. Leo vel orci porta non pulvinar. Amet massa vitae tortor condimentum. Malesuada fames ac turpis egestas maecenas pharetra. Feugiat nibh sed pulvinar proin gravida hendrerit lectus a. Quam elementum pulvinar etiam non quam lacus. Accumsan in nisl nisi scelerisque eu ultrices. Pretium aenean pharetra magna ac placerat vestibulum. Dui faucibus in ornare quam viverra orci sagittis eu volutpat. Amet venenatis urna cursus eget nunc scelerisque viverra mauris in. Penatibus et magnis dis parturient montes nascetur ridiculus mus mauris. Quis commodo odio aenean sed adipiscing diam donec adipiscing tristique. + +Leo a diam sollicitudin tempor id. Tempor orci eu lobortis elementum nibh. Sit amet commodo nulla facilisi nullam vehicula. Hendrerit gravida rutrum quisque non tellus. Diam vulputate ut pharetra sit. Semper feugiat nibh sed pulvinar proin gravida hendrerit lectus a. Tempus iaculis urna id volutpat lacus laoreet non curabitur gravida. Porttitor lacus luctus accumsan tortor posuere ac ut consequat semper. Tortor vitae purus faucibus ornare. Risus viverra adipiscing at in tellus integer. Suspendisse potenti nullam ac tortor vitae purus faucibus ornare suspendisse. Facilisis sed odio morbi quis commodo odio aenean sed. At auctor urna nunc id. Ac tortor vitae purus faucibus ornare suspendisse sed nisi. Suspendisse interdum consectetur libero id faucibus nisl. Tellus id interdum velit laoreet id. Mus mauris vitae ultricies leo integer. Metus vulputate eu scelerisque felis imperdiet proin. + +Venenatis cras sed felis eget velit aliquet sagittis id. Turpis cursus in hac habitasse. Magna fringilla urna porttitor rhoncus dolor purus non. In tellus integer feugiat scelerisque varius morbi. Tortor consequat id porta nibh venenatis cras sed. Ut sem viverra aliquet eget sit amet tellus cras. Semper risus in hendrerit gravida. Libero enim sed faucibus turpis in. Ultricies leo integer malesuada nunc vel risus commodo. Ipsum dolor sit amet consectetur adipiscing elit pellentesque habitant. Varius duis at consectetur lorem donec massa sapien faucibus et. Ornare arcu dui vivamus arcu felis bibendum ut tristique et. + +Diam quis enim lobortis scelerisque fermentum dui faucibus in. Cursus mattis molestie a iaculis at erat. Diam sit amet nisl suscipit adipiscing. Ultrices dui sapien eget mi proin sed libero. Purus ut faucibus pulvinar elementum integer enim neque. Ultricies mi quis hendrerit dolor magna eget. Morbi tincidunt ornare massa eget. Mauris cursus mattis molestie a iaculis at erat pellentesque. Phasellus vestibulum lorem sed risus. Sodales ut etiam sit amet nisl purus in. Habitant morbi tristique senectus et netus et. Consectetur lorem donec massa sapien faucibus et molestie. + +Montes nascetur ridiculus mus mauris vitae ultricies. Lectus urna duis convallis convallis. Pulvinar proin gravida hendrerit lectus. Semper auctor neque vitae tempus quam pellentesque nec. Donec pretium vulputate sapien nec. Id aliquet lectus proin nibh nisl. Enim ut sem viverra aliquet eget sit amet tellus. Vel orci porta non pulvinar neque laoreet suspendisse interdum consectetur. Feugiat vivamus at augue eget arcu dictum varius. Venenatis tellus in metus vulputate eu. Aliquam vestibulum morbi blandit cursus risus at ultrices mi tempus. Id venenatis a condimentum vitae. Lorem mollis aliquam ut porttitor leo a diam sollicitudin tempor. Rhoncus est pellentesque elit ullamcorper dignissim cras tincidunt lobortis. + +Nisi scelerisque eu ultrices vitae. Eu feugiat pretium nibh ipsum consequat nisl vel pretium. Commodo ullamcorper a lacus vestibulum sed arcu non odio. Sit amet cursus sit amet dictum. Fermentum iaculis eu non diam. Quis imperdiet massa tincidunt nunc pulvinar. Tempor commodo ullamcorper a lacus vestibulum sed. Venenatis urna cursus eget nunc scelerisque viverra mauris in. Vulputate mi sit amet mauris commodo quis imperdiet massa. Non nisi est sit amet facilisis magna etiam tempor orci. Consectetur libero id faucibus nisl tincidunt eget nullam. Sit amet risus nullam eget felis eget nunc. Aliquet porttitor lacus luctus accumsan. Vitae congue eu consequat ac felis donec. Vehicula ipsum a arcu cursus vitae congue mauris rhoncus. Fringilla phasellus faucibus scelerisque eleifend donec pretium vulputate. + +Massa eget egestas purus viverra. Nunc sed augue lacus viverra vitae congue eu consequat. Lectus quam id leo in. Augue eget arcu dictum varius duis. Nulla facilisi cras fermentum odio eu feugiat pretium. Adipiscing diam donec adipiscing tristique risus. Imperdiet dui accumsan sit amet. Volutpat commodo sed egestas egestas fringilla phasellus faucibus scelerisque. Dolor sit amet consectetur adipiscing elit duis. In fermentum et sollicitudin ac orci phasellus egestas tellus rutrum. Ridiculus mus mauris vitae ultricies leo integer malesuada. Nulla pharetra diam sit amet nisl. Nec dui nunc mattis enim ut tellus. Morbi non arcu risus quis varius quam quisque. Ac auctor augue mauris augue neque gravida in fermentum et. Morbi tincidunt augue interdum velit euismod. Sem viverra aliquet eget sit amet tellus cras adipiscing enim. Volutpat commodo sed egestas egestas fringilla phasellus faucibus scelerisque. Odio facilisis mauris sit amet. Amet mattis vulputate enim nulla aliquet. + +Nisi vitae suscipit tellus mauris a diam maecenas sed enim. Venenatis urna cursus eget nunc scelerisque viverra. Neque egestas congue quisque egestas diam in. Adipiscing vitae proin sagittis nisl. Sodales neque sodales ut etiam sit. Non consectetur a erat nam at. Ac felis donec et odio. Adipiscing tristique risus nec feugiat in fermentum posuere urna. Ultrices in iaculis nunc sed augue lacus viverra vitae. Enim sit amet venenatis urna. Amet consectetur adipiscing elit pellentesque. + +Venenatis a condimentum vitae sapien pellentesque. Ut faucibus pulvinar elementum integer enim neque. Nisl nunc mi ipsum faucibus vitae aliquet. Netus et malesuada fames ac. Et odio pellentesque diam volutpat commodo sed egestas egestas fringilla. Ut diam quam nulla porttitor massa id. Id donec ultrices tincidunt arcu non sodales neque sodales ut. Viverra ipsum nunc aliquet bibendum enim. Lacus vestibulum sed arcu non odio. Lobortis mattis aliquam faucibus purus in massa tempor. Tortor at auctor urna nunc id cursus metus aliquam eleifend. Ornare suspendisse sed nisi lacus sed viverra tellus in. Tristique magna sit amet purus gravida quis. At ultrices mi tempus imperdiet nulla malesuada. Erat imperdiet sed euismod nisi. Eleifend donec pretium vulputate sapien nec sagittis aliquam malesuada. Fermentum dui faucibus in ornare quam viverra orci sagittis. Nec dui nunc mattis enim ut tellus elementum sagittis. + +Suspendisse interdum consectetur libero id faucibus nisl. Bibendum enim facilisis gravida neque convallis. Nisi vitae suscipit tellus mauris a. Massa ultricies mi quis hendreri. \ No newline at end of file diff --git a/performance_tests/test/resources/plaintext/plaintext-data-medium.dat b/performance_tests/test/resources/plaintext/plaintext-data-medium.dat new file mode 100644 index 000000000..3313ba519 --- /dev/null +++ b/performance_tests/test/resources/plaintext/plaintext-data-medium.dat @@ -0,0 +1,11 @@ +Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Et netus et malesuada fames. Bibendum enim facilisis gravida neque convallis. Tortor consequat id porta nibh venenatis cras. Lacus sed viverra tellus in hac habitasse platea dictumst. Ipsum dolor sit amet consectetur adipiscing elit pellentesque. Risus pretium quam vulputate dignissim suspendisse in. Ante in nibh mauris cursus mattis molestie a iaculis at. Nulla porttitor massa id neque aliquam vestibulum morbi blandit. Urna et pharetra pharetra massa massa ultricies mi quis. Leo duis ut diam quam nulla porttitor massa id. Vitae suscipit tellus mauris a diam maecenas sed enim ut. + +Non nisi est sit amet facilisis magna etiam tempor. Mi bibendum neque egestas congue quisque egestas diam in arcu. Volutpat est velit egestas dui id ornare arcu odio ut. Amet tellus cras adipiscing enim eu turpis egestas. Tortor dignissim convallis aenean et tortor at risus viverra. Interdum consectetur libero id faucibus nisl tincidunt eget. In eu mi bibendum neque egestas congue quisque egestas. Pellentesque habitant morbi tristique senectus et netus et malesuada fames. Leo vel orci porta non pulvinar. Amet massa vitae tortor condimentum. Malesuada fames ac turpis egestas maecenas pharetra. Feugiat nibh sed pulvinar proin gravida hendrerit lectus a. Quam elementum pulvinar etiam non quam lacus. Accumsan in nisl nisi scelerisque eu ultrices. Pretium aenean pharetra magna ac placerat vestibulum. Dui faucibus in ornare quam viverra orci sagittis eu volutpat. Amet venenatis urna cursus eget nunc scelerisque viverra mauris in. Penatibus et magnis dis parturient montes nascetur ridiculus mus mauris. Quis commodo odio aenean sed adipiscing diam donec adipiscing tristique. + +Leo a diam sollicitudin tempor id. Tempor orci eu lobortis elementum nibh. Sit amet commodo nulla facilisi nullam vehicula. Hendrerit gravida rutrum quisque non tellus. Diam vulputate ut pharetra sit. Semper feugiat nibh sed pulvinar proin gravida hendrerit lectus a. Tempus iaculis urna id volutpat lacus laoreet non curabitur gravida. Porttitor lacus luctus accumsan tortor posuere ac ut consequat semper. Tortor vitae purus faucibus ornare. Risus viverra adipiscing at in tellus integer. Suspendisse potenti nullam ac tortor vitae purus faucibus ornare suspendisse. Facilisis sed odio morbi quis commodo odio aenean sed. At auctor urna nunc id. Ac tortor vitae purus faucibus ornare suspendisse sed nisi. Suspendisse interdum consectetur libero id faucibus nisl. Tellus id interdum velit laoreet id. Mus mauris vitae ultricies leo integer. Metus vulputate eu scelerisque felis imperdiet proin. + +Venenatis cras sed felis eget velit aliquet sagittis id. Turpis cursus in hac habitasse. Magna fringilla urna porttitor rhoncus dolor purus non. In tellus integer feugiat scelerisque varius morbi. Tortor consequat id porta nibh venenatis cras sed. Ut sem viverra aliquet eget sit amet tellus cras. Semper risus in hendrerit gravida. Libero enim sed faucibus turpis in. Ultricies leo integer malesuada nunc vel risus commodo. Ipsum dolor sit amet consectetur adipiscing elit pellentesque habitant. Varius duis at consectetur lorem donec massa sapien faucibus et. Ornare arcu dui vivamus arcu felis bibendum ut tristique et. + +Diam quis enim lobortis scelerisque fermentum dui faucibus in. Cursus mattis molestie a iaculis at erat. Diam sit amet nisl suscipit adipiscing. Ultrices dui sapien eget mi proin sed libero. Purus ut faucibus pulvinar elementum integer enim neque. Ultricies mi quis hendrerit dolor magna eget. Morbi tincidunt ornare massa eget. Mauris cursus mattis molestie a iaculis at erat pellentesque. Phasellus vestibulum lorem sed risus. Sodales ut etiam sit amet nisl purus in. Habitant morbi tristique senectus et netus et. Consectetur lorem donec massa sapien faucibus et molestie. + +Montes nascetur ridiculus mus mauris vitae ultricies. Lectus urna duis convallis convallis. Pulvinar pr. \ No newline at end of file diff --git a/performance_tests/test/resources/plaintext/plaintext-data-small.dat b/performance_tests/test/resources/plaintext/plaintext-data-small.dat new file mode 100644 index 000000000..b8475e61f --- /dev/null +++ b/performance_tests/test/resources/plaintext/plaintext-data-small.dat @@ -0,0 +1 @@ +Lorem ipsum dolor sit amet, consect. \ No newline at end of file diff --git a/performance_tests/tox.ini b/performance_tests/tox.ini new file mode 100644 index 000000000..1b7d073aa --- /dev/null +++ b/performance_tests/tox.ini @@ -0,0 +1,215 @@ +[tox] +envlist = + # The performance tests only work for python 3.11 and 3.12 + py{311,312}-performance_tests-mpl + bandit, doc8 + ; {flake8, pylint}{,-tests}, + isort-check, black-check, + # prone to false positives + vulture + +# Additional test environments: +# +# linters :: Runs all linters over all source code. +# linters-tests :: Runs all linters over all tests. + +# Autoformatter helper environments: +# +# autoformat : Apply all autoformatters +# +# black-check : Check for "black" issues +# blacken : Fix all "black" issues +# +# isort-seed : Generate a known_third_party list for isort. +# NOTE: make the "known_third_party = " line in setup.cfg before running this +# NOTE: currently it incorrectly identifies this library too; make sure you remove it +# isort-check : Check for isort issues +# isort : Fix isort issues + +# Operational helper environments: +# +# build :: Builds source and wheel dist files. +# test-release :: Builds dist files and uploads to testpypi pypirc profile. +# release :: Builds dist files and uploads to pypi pypirc profile. + +[testenv:base-command] +commands = pytest test/ +deps = + click + + +[testenv] +passenv = + # Pass through AWS credentials + AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN \ + # AWS Role access in CodeBuild is via the contaner URI + AWS_CONTAINER_CREDENTIALS_RELATIVE_URI \ + # Pass through AWS profile name (useful for local testing) + AWS_PROFILE +sitepackages = False +deps = + -rrequirements.txt + # Install the MPL requirements if the `-mpl` suffix is present + mpl: -rrequirements_mpl.txt + .. +commands = + performance_tests: {[testenv:base-command]commands} + +[testenv:blacken-src] +basepython = python3 +deps = -r../dev_requirements/linter-requirements.txt +commands = + black --line-length 120 \ + src/aws_encryption_sdk_performance_tests/ \ + setup.py \ + test/ \ + {posargs} + +# Linters +[testenv:flake8] +basepython = python3 +deps = -r../dev_requirements/linter-requirements.txt +commands = + flake8 \ + src/aws_encryption_sdk_performance_tests/ \ + setup.py \ + {posargs} + +[testenv:flake8-tests] +basepython = {[testenv:flake8]basepython} +deps = -r../dev_requirements/linter-requirements.txt +commands = + flake8 \ + # Ignore F811 redefinition errors in tests (breaks with pytest-mock use) + # E203 is not PEP8 compliant https://github.com/ambv/black#slices + # W503 is not PEP8 compliant https://github.com/ambv/black#line-breaks--binary-operators + --ignore F811,E203,W503,D \ + test/ + +[testenv:pylint] +basepython = python3 +deps = + -r../dev_requirements/linter-requirements.txt +commands = + pylint \ + --rcfile=pylintrc \ + src/aws_encryption_sdk_performance_tests/ \ + setup.py \ + {posargs} + +[testenv:pylint-tests] +basepython = {[testenv:pylint]basepython} +deps = {[testenv:pylint]deps} +commands = + pylint \ + --rcfile=pylintrc \ + test/ \ + {posargs} + +[testenv:blacken] +basepython = python3 +deps = + {[testenv:blacken-src]deps} +commands = + {[testenv:blacken-src]commands} + +[testenv:black-check] +basepython = python3 +deps = + {[testenv:blacken]deps} +commands = + {[testenv:blacken-src]commands} --diff + +[testenv:isort-seed] +basepython = python3 +deps = -r../dev_requirements/linter-requirements.txt +commands = seed-isort-config + +[testenv:isort] +basepython = python3 +deps = -r../dev_requirements/linter-requirements.txt +commands = isort -rc \ + src \ + test \ + setup.py \ + {posargs} + +[testenv:isort-check] +basepython = python3 +deps = {[testenv:isort]deps} +commands = {[testenv:isort]commands} -c + +[testenv:autoformat] +basepython = python3 +deps = + {[testenv:blacken]deps} + {[testenv:isort]deps} + .. +commands = + {[testenv:blacken]commands} + {[testenv:isort]commands} + +[testenv:doc8] +basepython = python3 +deps = -r../dev_requirements/linter-requirements.txt +commands = doc8 README.rst + +[testenv:readme] +basepython = python3 +deps = -r../dev_requirements/linter-requirements.txt +commands = python setup.py check -r -s + +[testenv:bandit] +basepython = python3 +deps = -r../dev_requirements/linter-requirements.txt +commands = bandit -r src/aws_encryption_sdk_performance_tests/ + +[testenv:linters] +basepython = python3 +deps = + {[testenv:flake8]deps} + {[testenv:pylint]deps} + {[testenv:doc8]deps} + {[testenv:readme]deps} + {[testenv:bandit]deps} +commands = + {[testenv:flake8]commands} + {[testenv:pylint]commands} + {[testenv:doc8]commands} + {[testenv:readme]commands} + {[testenv:bandit]commands} + +# Release tooling +[testenv:park] +basepython = python3 +skip_install = true +deps = -r../dev_requirements/release-requirements.txt +commands = python setup.py park + +[testenv:build] +basepython = python3 +skip_install = true +deps = + -r../dev_requirements/release-requirements.txt +commands = + python setup.py sdist bdist_wheel + +[testenv:test-release] +basepython = python3 +skip_install = true +deps = + {[testenv:build]deps} + twine +commands = + {[testenv:build]commands} + twine upload --skip-existing --repository testpypi dist/* + +[testenv:release] +basepython = python3 +skip_install = true +deps = + {[testenv:build]deps} + twine +commands = + {[testenv:build]commands} + twine upload --skip-existing --repository pypi dist/* From 39d449883c230a008238a139306085abf90e633c Mon Sep 17 00:00:00 2001 From: Ritvik Kapila <61410899+RitvikKapila@users.noreply.github.com> Date: Fri, 7 Jun 2024 13:57:34 -0700 Subject: [PATCH 02/18] chore(performance_tests): added hierarchy keyring and caching cmm tests (#686) --- .../keyrings/hierarchy_keyring.py | 128 ++++++++++++ .../keyrings/raw_aes_keyring.py | 1 - .../aws_kms_master_key_provider.py | 8 +- .../master_key_providers/caching_cmm.py | 85 ++++++++ .../raw_aes_master_key_provider.py | 10 +- .../raw_rsa_master_key_provider.py | 10 +- .../utils/util.py | 4 +- .../test/keyrings/test_hierarchy_keyring.py | 174 +++++++++++++++++ .../test_aws_kms_master_key_provider.py | 2 +- .../master_key_providers/test_caching_cmm.py | 183 ++++++++++++++++++ .../test_raw_aes_master_key_provider.py | 2 +- .../test_raw_rsa_master_key_provider.py | 2 +- .../caching_cmm/ciphertext-data-empty.ct | Bin 0 -> 587 bytes .../caching_cmm/ciphertext-data-large.ct | Bin 0 -> 8619 bytes .../caching_cmm/ciphertext-data-medium.ct | Bin 0 -> 4587 bytes .../caching_cmm/ciphertext-data-small.ct | Bin 0 -> 623 bytes .../hierarchy/ciphertext-data-empty.ct | Bin 0 -> 654 bytes .../hierarchy/ciphertext-data-large.ct | Bin 0 -> 8686 bytes .../hierarchy/ciphertext-data-medium.ct | Bin 0 -> 4654 bytes .../hierarchy/ciphertext-data-small.ct | Bin 0 -> 690 bytes 20 files changed, 588 insertions(+), 21 deletions(-) create mode 100644 performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/hierarchy_keyring.py create mode 100644 performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/caching_cmm.py create mode 100644 performance_tests/test/keyrings/test_hierarchy_keyring.py create mode 100644 performance_tests/test/master_key_providers/test_caching_cmm.py create mode 100644 performance_tests/test/resources/ciphertext/caching_cmm/ciphertext-data-empty.ct create mode 100644 performance_tests/test/resources/ciphertext/caching_cmm/ciphertext-data-large.ct create mode 100644 performance_tests/test/resources/ciphertext/caching_cmm/ciphertext-data-medium.ct create mode 100644 performance_tests/test/resources/ciphertext/caching_cmm/ciphertext-data-small.ct create mode 100644 performance_tests/test/resources/ciphertext/hierarchy/ciphertext-data-empty.ct create mode 100644 performance_tests/test/resources/ciphertext/hierarchy/ciphertext-data-large.ct create mode 100644 performance_tests/test/resources/ciphertext/hierarchy/ciphertext-data-medium.ct create mode 100644 performance_tests/test/resources/ciphertext/hierarchy/ciphertext-data-small.ct diff --git a/performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/hierarchy_keyring.py b/performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/hierarchy_keyring.py new file mode 100644 index 000000000..b1bdc6913 --- /dev/null +++ b/performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/hierarchy_keyring.py @@ -0,0 +1,128 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Performance tests for the hierarchy keyring.""" + +import aws_encryption_sdk +import boto3 +from aws_cryptographic_materialproviders.keystore import KeyStore +from aws_cryptographic_materialproviders.keystore.config import KeyStoreConfig +from aws_cryptographic_materialproviders.keystore.models import KMSConfigurationKmsKeyArn +from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig +from aws_cryptographic_materialproviders.mpl.models import ( + CacheTypeDefault, + CreateAwsKmsHierarchicalKeyringInput, + DefaultCache, +) +from aws_cryptographic_materialproviders.mpl.references import IKeyring + +from ..utils.util import PerfTestUtils + + +def create_keyring( + key_store_table_name: str, + logical_key_store_name: str, + kms_key_id: str, + branch_key_id: str = PerfTestUtils.DEFAULT_BRANCH_KEY_ID +): + """Demonstrate how to create a hierarchy keyring. + + Usage: create_keyring(key_store_table_name, logical_key_store_name, kms_key_id, branch_key_id) + :param key_store_table_name: Name of the KeyStore DynamoDB table. + :type key_store_table_name: string + :param logical_key_store_name: Logical name of the KeyStore. + :type logical_key_store_name: string + :param kms_key_id: KMS Key identifier for the KMS key you want to use. + :type kms_key_id: string + :param branch_key_id: Branch key you want to use for the hierarchy keyring. + :type branch_key_id: string + + For more information on KMS Key identifiers, see + https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id + """ + # Create boto3 clients for DynamoDB and KMS. + ddb_client = boto3.client('dynamodb', region_name="us-west-2") + kms_client = boto3.client('kms', region_name="us-west-2") + + # Configure your KeyStore resource. + # This SHOULD be the same configuration that you used + # to initially create and populate your KeyStore. + keystore: KeyStore = KeyStore( + config=KeyStoreConfig( + ddb_client=ddb_client, + ddb_table_name=key_store_table_name, + logical_key_store_name=logical_key_store_name, + kms_client=kms_client, + kms_configuration=KMSConfigurationKmsKeyArn( + value=kms_key_id + ), + ) + ) + + # Create the Hierarchical Keyring. + mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + config=MaterialProvidersConfig() + ) + + keyring_input: CreateAwsKmsHierarchicalKeyringInput = CreateAwsKmsHierarchicalKeyringInput( + key_store=keystore, + branch_key_id=branch_key_id, + ttl_seconds=600, + cache=CacheTypeDefault( + value=DefaultCache( + entry_capacity=100 + ) + ), + ) + + keyring: IKeyring = mat_prov.create_aws_kms_hierarchical_keyring( + input=keyring_input + ) + + return keyring + + +def encrypt_using_keyring( + plaintext_data: bytes, + keyring: IKeyring +): + """Demonstrate how to encrypt plaintext data using a hierarchy keyring. + + Usage: encrypt_using_keyring(plaintext_data, keyring) + :param plaintext_data: plaintext data you want to encrypt + :type: bytes + :param keyring: Keyring to use for encryption. + :type keyring: IKeyring + """ + client = aws_encryption_sdk.EncryptionSDKClient() + + ciphertext_data, _ = client.encrypt( + source=plaintext_data, + keyring=keyring, + encryption_context=PerfTestUtils.DEFAULT_ENCRYPTION_CONTEXT + ) + + return ciphertext_data + + +def decrypt_using_keyring( + ciphertext_data: bytes, + keyring: IKeyring +): + """Demonstrate how to decrypt ciphertext data using a hierarchy keyring. + + Usage: decrypt_using_keyring(ciphertext_data, keyring) + :param ciphertext_data: ciphertext data you want to decrypt + :type: bytes + :param keyring: Keyring to use for decryption. + :type keyring: IKeyring + """ + client = aws_encryption_sdk.EncryptionSDKClient() + + decrypted_plaintext_data, _ = client.decrypt( + source=ciphertext_data, + keyring=keyring, + encryption_context=PerfTestUtils.DEFAULT_ENCRYPTION_CONTEXT + ) + + return decrypted_plaintext_data diff --git a/performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/raw_aes_keyring.py b/performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/raw_aes_keyring.py index a849b1a7f..a2a3c9ab1 100644 --- a/performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/raw_aes_keyring.py +++ b/performance_tests/src/aws_encryption_sdk_performance_tests/keyrings/raw_aes_keyring.py @@ -19,7 +19,6 @@ def create_keyring(): key_name_space = "Some managed raw keys" key_name = "My 256-bit AES wrapping key" - # Here, the input to secrets.token_bytes() = 32 bytes = 256 bits # We fix the static key in order to make the test deterministic static_key = PerfTestUtils.DEFAULT_AES_256_STATIC_KEY diff --git a/performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/aws_kms_master_key_provider.py b/performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/aws_kms_master_key_provider.py index c3136a5c7..023cd5942 100644 --- a/performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/aws_kms_master_key_provider.py +++ b/performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/aws_kms_master_key_provider.py @@ -8,7 +8,7 @@ def create_key_provider( kms_key_id: str ): - """Demonstrate how to create an AWS KMS master key-provider. + """Demonstrate how to create an AWS KMS master key provider. Usage: create_key_provider(kms_key_id) :param kms_key_id: KMS Key identifier for the KMS key you want to use. @@ -17,7 +17,7 @@ def create_key_provider( For more information on KMS Key identifiers, see https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id """ - # Create a KMS master key-provider. + # Create a KMS master key provider. key_provider = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider(key_ids=[ kms_key_id, ]) @@ -29,7 +29,7 @@ def encrypt_using_key_provider( plaintext_data: bytes, key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider ): - """Demonstrate how to encrypt plaintext data using an AWS KMS master key-provider. + """Demonstrate how to encrypt plaintext data using an AWS KMS master key provider. Usage: encrypt_using_key_provider(plaintext_data, key_provider) :param plaintext_data: plaintext data you want to encrypt @@ -51,7 +51,7 @@ def decrypt_using_key_provider( ciphertext_data: bytes, key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider ): - """Demonstrate how to decrypt ciphertext data using an AWS KMS master key-provider. + """Demonstrate how to decrypt ciphertext data using an AWS KMS master key provider. Usage: decrypt_using_key_provider(ciphertext_data, key_provider) :param ciphertext_data: ciphertext data you want to decrypt diff --git a/performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/caching_cmm.py b/performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/caching_cmm.py new file mode 100644 index 000000000..7199c50bf --- /dev/null +++ b/performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/caching_cmm.py @@ -0,0 +1,85 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Performance tests for the Caching Cryptographic Materials Manager (CMM) with KMS Master Key Provider.""" + +import aws_encryption_sdk + + +def create_cmm( + kms_key_id: str, + max_age_in_cache: float, + cache_capacity: int +): + """Demonstrate how to create a Caching CMM. + + Usage: create_cmm(kms_key_id, max_age_in_cache, cache_capacity) + :param kms_key_id: Amazon Resource Name (ARN) of the KMS customer master key + :type kms_key_id: str + :param max_age_in_cache: Maximum time in seconds that a cached entry can be used + :type max_age_in_cache: float + :param cache_capacity: Maximum number of entries to retain in cache at once + :type cache_capacity: int + """ + # Security thresholds + # Max messages (or max bytes per) data key are optional + max_messages_encrypted = 100 + + # Create a master key provider for the KMS customer master key (CMK) + key_provider = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider(key_ids=[kms_key_id]) + + # Create a local cache + cache = aws_encryption_sdk.LocalCryptoMaterialsCache(cache_capacity) + + # Create a caching CMM + caching_cmm = aws_encryption_sdk.CachingCryptoMaterialsManager( + master_key_provider=key_provider, + cache=cache, + max_age=max_age_in_cache, + max_messages_encrypted=max_messages_encrypted, + ) + + return caching_cmm + + +def encrypt_using_cmm( + plaintext_data: bytes, + caching_cmm: aws_encryption_sdk.materials_managers.base.CryptoMaterialsManager +): + """Demonstrate how to encrypt plaintext data using a Caching CMM. + + Usage: encrypt_using_cmm(plaintext_data, caching_cmm) + :param plaintext_data: plaintext data you want to encrypt + :type: bytes + :param caching_cmm: Crypto Materials Manager to use for encryption. + :type caching_cmm: aws_encryption_sdk.materials_managers.base.CryptoMaterialsManager + """ + client = aws_encryption_sdk.EncryptionSDKClient() + + ciphertext_data, _ = client.encrypt( + source=plaintext_data, + materials_manager=caching_cmm + ) + + return ciphertext_data + + +def decrypt_using_cmm( + ciphertext_data: bytes, + caching_cmm: aws_encryption_sdk.materials_managers.base.CryptoMaterialsManager +): + """Demonstrate how to decrypt ciphertext data using a Caching CMM. + + Usage: decrypt_using_cmm(ciphertext_data, caching_cmm) + :param ciphertext_data: ciphertext data you want to decrypt + :type: bytes + :param caching_cmm: Crypto Materials Manager to use for encryption. + :type caching_cmm: aws_encryption_sdk.materials_managers.base.CryptoMaterialsManager + """ + client = aws_encryption_sdk.EncryptionSDKClient() + + decrypted_plaintext_data, _ = client.decrypt( + source=ciphertext_data, + materials_manager=caching_cmm + ) + + return decrypted_plaintext_data diff --git a/performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/raw_aes_master_key_provider.py b/performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/raw_aes_master_key_provider.py index 42d071dcf..de0188c5e 100644 --- a/performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/raw_aes_master_key_provider.py +++ b/performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/raw_aes_master_key_provider.py @@ -43,13 +43,13 @@ def _get_raw_key(self, key_id): def create_key_provider(): - """Demonstrate how to create a Raw AES master key-provider. + """Demonstrate how to create a Raw AES master key provider. Usage: create_key_provider() """ - # Create a Raw AES master key-provider. + # Create a Raw AES master key provider. - # The Key ID field in the JceMasterKey and RawMasterKey is equivalent to key name in the Raw keyrings + # The Key ID field in the JceMasterKey and RawMasterKey is equivalent to key name in the Raw keyrings key_id = "My 256-bit AES wrapping key" key_provider = StaticRandomMasterKeyProvider() key_provider.add_master_key(key_id) @@ -61,7 +61,7 @@ def encrypt_using_key_provider( plaintext_data: bytes, key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider ): - """Demonstrate how to encrypt plaintext data using a Raw AES master key-provider. + """Demonstrate how to encrypt plaintext data using a Raw AES master key provider. Usage: encrypt_using_key_provider(plaintext_data, key_provider) :param plaintext_data: plaintext data you want to encrypt @@ -83,7 +83,7 @@ def decrypt_using_key_provider( ciphertext_data: bytes, key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider ): - """Demonstrate how to decrypt ciphertext data using a Raw AES master key-provider. + """Demonstrate how to decrypt ciphertext data using a Raw AES master key provider. Usage: decrypt_using_key_provider(ciphertext_data, key_provider) :param ciphertext_data: ciphertext data you want to decrypt diff --git a/performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/raw_rsa_master_key_provider.py b/performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/raw_rsa_master_key_provider.py index b52b78735..cdbe24110 100644 --- a/performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/raw_rsa_master_key_provider.py +++ b/performance_tests/src/aws_encryption_sdk_performance_tests/master_key_providers/raw_rsa_master_key_provider.py @@ -43,13 +43,13 @@ def _get_raw_key(self, key_id): def create_key_provider(): - """Demonstrate how to create a Raw RSA master key-provider. + """Demonstrate how to create a Raw RSA master key provider. Usage: create_key_provider() """ - # Create a Raw RSA master key-provider. + # Create a Raw RSA master key provider. - # The Key ID field in the JceMasterKey and RawMasterKey is equivalent to key name in the Raw keyrings + # The Key ID field in the JceMasterKey and RawMasterKey is equivalent to key name in the Raw keyrings key_id = "My 4096-bit RSA wrapping key" key_provider = StaticRandomMasterKeyProvider() key_provider.add_master_key(key_id) @@ -61,7 +61,7 @@ def encrypt_using_key_provider( plaintext_data: bytes, key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider ): - """Demonstrate how to encrypt plaintext data using a Raw RSA master key-provider. + """Demonstrate how to encrypt plaintext data using a Raw RSA master key provider. Usage: encrypt_using_key_provider(plaintext_data, key_provider) :param plaintext_data: plaintext data you want to encrypt @@ -83,7 +83,7 @@ def decrypt_using_key_provider( ciphertext_data: bytes, key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider ): - """Demonstrate how to decrypt ciphertext data using a Raw RSA master key-provider. + """Demonstrate how to decrypt ciphertext data using a Raw RSA master key provider. Usage: decrypt_using_key_provider(ciphertext_data, key_provider) :param ciphertext_data: ciphertext data you want to decrypt diff --git a/performance_tests/src/aws_encryption_sdk_performance_tests/utils/util.py b/performance_tests/src/aws_encryption_sdk_performance_tests/utils/util.py index 52914b76a..9100ef12e 100644 --- a/performance_tests/src/aws_encryption_sdk_performance_tests/utils/util.py +++ b/performance_tests/src/aws_encryption_sdk_performance_tests/utils/util.py @@ -87,9 +87,7 @@ class PerfTestUtils: "the data you are handling": "is what you think it is", } - DEFAULT_BRANCH_KEY_ID_A = 'a52dfaad-7dbd-4430-a1fd-abaa5299da07' - - DEFAULT_BRANCH_KEY_ID_B = '8ba79cef-581c-4125-9292-b057a29d42d7' + DEFAULT_BRANCH_KEY_ID = 'a52dfaad-7dbd-4430-a1fd-abaa5299da07' @staticmethod def read_file(filename): diff --git a/performance_tests/test/keyrings/test_hierarchy_keyring.py b/performance_tests/test/keyrings/test_hierarchy_keyring.py new file mode 100644 index 000000000..e890c2a18 --- /dev/null +++ b/performance_tests/test/keyrings/test_hierarchy_keyring.py @@ -0,0 +1,174 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""This is a performance test for creating the hierarchy keyring.""" + +import os +import time + +import click +import click.testing +import pytest +from tqdm import tqdm + +from aws_encryption_sdk_performance_tests.keyrings.hierarchy_keyring import ( + create_keyring, + decrypt_using_keyring, + encrypt_using_keyring, +) +from aws_encryption_sdk_performance_tests.utils.util import PerfTestUtils + +MODULE_ABS_PATH = os.path.abspath(__file__) + + +@click.group() +def create_hierarchy_keyring(): + """Click group helper function""" + + +@create_hierarchy_keyring.command() +@click.option('--key_store_table_name', + default='KeyStoreDdbTable') +@click.option('--kms_key_id', + default='arn:aws:kms:us-west-2:370957321024:key/9d989aa2-2f9c-438c-a745-cc57d3ad0126') +@click.option('--n_iters', + default=PerfTestUtils.DEFAULT_N_ITERS) +@click.option('--output_file', + default='/'.join(MODULE_ABS_PATH.split("/")[:-3]) + '/results/hierarchy_keyring_create') +def create( + key_store_table_name: str, + kms_key_id: str, + n_iters: int, + output_file: str +): + """Performance test for the create_keyring function.""" + time_list = [] + for _ in tqdm(range(n_iters)): + curr_time = time.time() + + create_keyring(key_store_table_name, key_store_table_name, kms_key_id) + + # calculate elapsed time in milliseconds + elapsed_time = (time.time() - curr_time) * 1000 + time_list.append(elapsed_time) + + PerfTestUtils.write_time_list_to_csv(time_list, output_file) + + +@click.group() +def encrypt_hierarchy_keyring(): + """Click group helper function""" + + +@encrypt_hierarchy_keyring.command() +@click.option('--plaintext_data_filename', + default='/'.join(MODULE_ABS_PATH.split("/")[:-2]) + '/resources/plaintext/plaintext-data-' + + PerfTestUtils.DEFAULT_FILE_SIZE + '.dat') +@click.option('--key_store_table_name', + default='KeyStoreDdbTable') +@click.option('--kms_key_id', + default='arn:aws:kms:us-west-2:370957321024:key/9d989aa2-2f9c-438c-a745-cc57d3ad0126') +@click.option('--n_iters', + default=PerfTestUtils.DEFAULT_N_ITERS) +@click.option('--output_file', + default='/'.join(MODULE_ABS_PATH.split("/")[:-3]) + '/results/hierarchy_keyring_encrypt') +def encrypt( + plaintext_data_filename: str, + key_store_table_name: str, + kms_key_id: str, + n_iters: int, + output_file: str +): + """Performance test for the encrypt_using_keyring function.""" + plaintext_data = PerfTestUtils.read_file(plaintext_data_filename) + + keyring = create_keyring(key_store_table_name, key_store_table_name, kms_key_id) + time_list = [] + + for _ in tqdm(range(n_iters)): + curr_time = time.time() + + encrypt_using_keyring(plaintext_data, keyring) + + # calculate elapsed time in milliseconds + elapsed_time = (time.time() - curr_time) * 1000 + time_list.append(elapsed_time) + + PerfTestUtils.write_time_list_to_csv(time_list, output_file) + + +@click.group() +def decrypt_hierarchy_keyring(): + """Click group helper function""" + + +@decrypt_hierarchy_keyring.command() +@click.option('--ciphertext_data_filename', + default='/'.join(MODULE_ABS_PATH.split("/")[:-2]) + '/resources/ciphertext/hierarchy/ciphertext-data-' + + PerfTestUtils.DEFAULT_FILE_SIZE + '.ct') +@click.option('--key_store_table_name', + default='KeyStoreDdbTable') +@click.option('--kms_key_id', + default='arn:aws:kms:us-west-2:370957321024:key/9d989aa2-2f9c-438c-a745-cc57d3ad0126') +@click.option('--n_iters', + default=PerfTestUtils.DEFAULT_N_ITERS) +@click.option('--output_file', + default='/'.join(MODULE_ABS_PATH.split("/")[:-3]) + '/results/hierarchy_keyring_decrypt') +def decrypt( + ciphertext_data_filename: str, + key_store_table_name: str, + kms_key_id: str, + n_iters: int, + output_file: str +): + """Performance test for the decrypt_using_keyring function.""" + ciphertext_data = PerfTestUtils.read_file(ciphertext_data_filename) + + keyring = create_keyring(key_store_table_name, key_store_table_name, kms_key_id) + time_list = [] + + for _ in tqdm(range(n_iters)): + curr_time = time.time() + + decrypt_using_keyring(ciphertext_data, keyring) + + # calculate elapsed time in milliseconds + elapsed_time = (time.time() - curr_time) * 1000 + time_list.append(elapsed_time) + + PerfTestUtils.write_time_list_to_csv(time_list, output_file) + + +hierarchy_keyring_test = click.CommandCollection(sources=[create_hierarchy_keyring, + encrypt_hierarchy_keyring, + decrypt_hierarchy_keyring]) + + +@pytest.fixture +def runner(): + """Click runner""" + return click.testing.CliRunner() + + +def test_create(runner): + """Test the create_keyring function""" + result = runner.invoke(create_hierarchy_keyring.commands['create'], + ['--n_iters', PerfTestUtils.DEFAULT_TESTING_N_ITERS]) + assert result.exit_code == 0 + + +def test_encrypt(runner): + """Test the encrypt_using_keyring function""" + result = runner.invoke(encrypt_hierarchy_keyring.commands['encrypt'], + ['--n_iters', PerfTestUtils.DEFAULT_TESTING_N_ITERS]) + assert result.exit_code == 0 + + +def test_decrypt(runner): + """Test the decrypt_using_keyring function""" + result = runner.invoke(decrypt_hierarchy_keyring.commands['decrypt'], + ['--n_iters', PerfTestUtils.DEFAULT_TESTING_N_ITERS]) + assert result.exit_code == 0 + + +if __name__ == "__main__": + hierarchy_keyring_test() diff --git a/performance_tests/test/master_key_providers/test_aws_kms_master_key_provider.py b/performance_tests/test/master_key_providers/test_aws_kms_master_key_provider.py index b869245b5..c7b665857 100644 --- a/performance_tests/test/master_key_providers/test_aws_kms_master_key_provider.py +++ b/performance_tests/test/master_key_providers/test_aws_kms_master_key_provider.py @@ -1,6 +1,6 @@ # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0 -"""This is a performance test for creating the AWS KMS Master key-provider.""" +"""This is a performance test for creating the AWS KMS Master key provider.""" import os import time diff --git a/performance_tests/test/master_key_providers/test_caching_cmm.py b/performance_tests/test/master_key_providers/test_caching_cmm.py new file mode 100644 index 000000000..f8552f96e --- /dev/null +++ b/performance_tests/test/master_key_providers/test_caching_cmm.py @@ -0,0 +1,183 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""This is a performance test for creating a Caching CMM.""" + +import os +import time + +import click +import click.testing +import pytest +from tqdm import tqdm + +from aws_encryption_sdk_performance_tests.master_key_providers.caching_cmm import ( + create_cmm, + decrypt_using_cmm, + encrypt_using_cmm, +) +from aws_encryption_sdk_performance_tests.utils.util import PerfTestUtils + +MODULE_ABS_PATH = os.path.abspath(__file__) + + +@click.group() +def create_caching_cmm(): + """Click group helper function""" + + +@create_caching_cmm.command() +@click.option('--kms_key_id', + default='arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f') +@click.option('--max_age_in_cache', + default=10.0) +@click.option('--cache_capacity', + default=10) +@click.option('--n_iters', + default=PerfTestUtils.DEFAULT_N_ITERS) +@click.option('--output_file', + default='/'.join(MODULE_ABS_PATH.split("/")[:-3]) + '/results/caching_cmm_create') +def create( + kms_key_id: str, + max_age_in_cache: float, + cache_capacity: int, + n_iters: int, + output_file: str +): + """Performance test for the create_cmm function.""" + time_list = [] + for _ in tqdm(range(n_iters)): + curr_time = time.time() + + create_cmm(kms_key_id, max_age_in_cache, cache_capacity) + + # calculate elapsed time in milliseconds + elapsed_time = (time.time() - curr_time) * 1000 + time_list.append(elapsed_time) + + PerfTestUtils.write_time_list_to_csv(time_list, output_file) + + +@click.group() +def encrypt_caching_cmm(): + """Click group helper function""" + + +@encrypt_caching_cmm.command() +@click.option('--plaintext_data_filename', + default='/'.join(MODULE_ABS_PATH.split("/")[:-2]) + '/resources/plaintext/plaintext-data-' + + PerfTestUtils.DEFAULT_FILE_SIZE + '.dat') +@click.option('--kms_key_id', + default='arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f') +@click.option('--max_age_in_cache', + default=10.0) +@click.option('--cache_capacity', + default=10) +@click.option('--n_iters', + default=PerfTestUtils.DEFAULT_N_ITERS) +@click.option('--output_file', + default='/'.join(MODULE_ABS_PATH.split("/")[:-3]) + '/results/caching_cmm_encrypt') +def encrypt( + plaintext_data_filename: str, + kms_key_id: str, + max_age_in_cache: float, + cache_capacity: int, + n_iters: int, + output_file: str +): + """Performance test for the encrypt_using_cmm function.""" + plaintext_data = PerfTestUtils.read_file(plaintext_data_filename) + + caching_cmm = create_cmm(kms_key_id, max_age_in_cache, cache_capacity) + time_list = [] + + for _ in tqdm(range(n_iters)): + curr_time = time.time() + + encrypt_using_cmm(plaintext_data, caching_cmm) + + # calculate elapsed time in milliseconds + elapsed_time = (time.time() - curr_time) * 1000 + time_list.append(elapsed_time) + + PerfTestUtils.write_time_list_to_csv(time_list, output_file) + + +@click.group() +def decrypt_caching_cmm(): + """Click group helper function""" + + +@decrypt_caching_cmm.command() +@click.option('--ciphertext_data_filename', + default='/'.join(MODULE_ABS_PATH.split("/")[:-2]) + '/resources/ciphertext/caching_cmm/ciphertext-data-' + + PerfTestUtils.DEFAULT_FILE_SIZE + '.ct') +@click.option('--kms_key_id', + default='arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f') +@click.option('--max_age_in_cache', + default=10.0) +@click.option('--cache_capacity', + default=10) +@click.option('--n_iters', + default=PerfTestUtils.DEFAULT_N_ITERS) +@click.option('--output_file', + default='/'.join(MODULE_ABS_PATH.split("/")[:-3]) + '/results/caching_cmm_decrypt') +def decrypt( + ciphertext_data_filename: str, + kms_key_id: str, + max_age_in_cache: float, + cache_capacity: int, + n_iters: int, + output_file: str +): + """Performance test for the decrypt_using_cmm function.""" + ciphertext_data = PerfTestUtils.read_file(ciphertext_data_filename) + + caching_cmm = create_cmm(kms_key_id, max_age_in_cache, cache_capacity) + time_list = [] + + for _ in tqdm(range(n_iters)): + curr_time = time.time() + + decrypt_using_cmm(ciphertext_data, caching_cmm) + + # calculate elapsed time in milliseconds + elapsed_time = (time.time() - curr_time) * 1000 + time_list.append(elapsed_time) + + PerfTestUtils.write_time_list_to_csv(time_list, output_file) + + +caching_cmm_test = click.CommandCollection(sources=[create_caching_cmm, + encrypt_caching_cmm, + decrypt_caching_cmm]) + + +@pytest.fixture +def runner(): + """Click runner""" + return click.testing.CliRunner() + + +def test_create(runner): + """Test the create_cmm function""" + result = runner.invoke(create_caching_cmm.commands['create'], + ['--n_iters', PerfTestUtils.DEFAULT_TESTING_N_ITERS]) + assert result.exit_code == 0 + + +def test_encrypt(runner): + """Test the encrypt_using_cmm function""" + result = runner.invoke(encrypt_caching_cmm.commands['encrypt'], + ['--n_iters', PerfTestUtils.DEFAULT_TESTING_N_ITERS]) + assert result.exit_code == 0 + + +def test_decrypt(runner): + """Test the decrypt_using_cmm function""" + result = runner.invoke(decrypt_caching_cmm.commands['decrypt'], + ['--n_iters', PerfTestUtils.DEFAULT_TESTING_N_ITERS]) + assert result.exit_code == 0 + + +if __name__ == "__main__": + caching_cmm_test() diff --git a/performance_tests/test/master_key_providers/test_raw_aes_master_key_provider.py b/performance_tests/test/master_key_providers/test_raw_aes_master_key_provider.py index 375eca2ef..cf39963bf 100644 --- a/performance_tests/test/master_key_providers/test_raw_aes_master_key_provider.py +++ b/performance_tests/test/master_key_providers/test_raw_aes_master_key_provider.py @@ -1,6 +1,6 @@ # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0 -"""This is a performance test for creating the Raw AES Master key-provider.""" +"""This is a performance test for creating the Raw AES Master key provider.""" import os import time diff --git a/performance_tests/test/master_key_providers/test_raw_rsa_master_key_provider.py b/performance_tests/test/master_key_providers/test_raw_rsa_master_key_provider.py index 5d6db861a..63b00a0e3 100644 --- a/performance_tests/test/master_key_providers/test_raw_rsa_master_key_provider.py +++ b/performance_tests/test/master_key_providers/test_raw_rsa_master_key_provider.py @@ -1,6 +1,6 @@ # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0 -"""This is a performance test for creating the Raw RSA Master key-provider.""" +"""This is a performance test for creating the Raw RSA Master key provider.""" import os import time diff --git a/performance_tests/test/resources/ciphertext/caching_cmm/ciphertext-data-empty.ct b/performance_tests/test/resources/ciphertext/caching_cmm/ciphertext-data-empty.ct new file mode 100644 index 0000000000000000000000000000000000000000..5bfb39a4ef910764c629a850f8f51b4631306ee9 GIT binary patch literal 587 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 V-X-*L3)Ww3h#M2;#hI&ZLd6QKdcyz! literal 0 HcmV?d00001 diff --git a/performance_tests/test/resources/ciphertext/caching_cmm/ciphertext-data-small.ct b/performance_tests/test/resources/ciphertext/caching_cmm/ciphertext-data-small.ct new file mode 100644 index 0000000000000000000000000000000000000000..63dac90b7e752819bd5740db6d3f7d3a3cb73a65 GIT binary patch literal 623 zcmZQ#t+=k}wKe7Pg1*9K(sA3qFHtz?I*0eWX1hk=@r;>w_SWxWh-YAA5KSyE)=e&| zEGWs>EhtUO$xPPGPOW5caWvPj3`>b9Eh@}$3QjX9^>lVkinKH{tSs|!^U5?Sa&#{7 ztTa!IOwIB4&36j&aQ8_oG&Rlg&oS2yC`oqHcX70}1scx|GCn)En87=-D9;MWu>x|e zN{e;NQ;SPMHB~WkNP7HcRa02?-eQSQNEN?w`lp z4|5KyO#D!C+apI}G|Om=?aWx{i|wE zRLcrKli9d#?UkG-U;a{~S zkJTGO@9vR2(6qNp?xnok;r~lx&htKhW98{NuW_^8{*rmq-DW&tNH<7jGVs!B&^7YR zIqQ45-#?rCY{JPW7kd(I96X$d)4F<%OUxL$&g{W+`Wy7 y`)l`{P%)ijlvKB4V)ON&#}N^=x) zQ%e$45=#;pxKi`Lwr1w%F|a4+=ar;ZlrXSm7AxfC1L@+_yhyOc;Z6n2cwOfmXx)W2k>~wK4xNI5MT(Mto1Wc_{SZg9~tG&wZ1X8B^Ca< zI(?q}XJ3rXQa$tMsj*R)y;h~qIQe(Y(QEQ5o&SM=fdS|z1OT(|we0+ROKt1TAb01N z43D4ZFr*u#G8r)DuF;8~-?QM);oy+ZC*)`JvDNDS&wAIZ-2PHiaNXA{@&y7$&~r~RHY%?PsUW~ PN2N7q=$;rmEe^6F+=&Sg_E%s8Iyvjc~z_FjqK~D_BfWYA{k&K}l;_G;wWFYHLMlWm;HJb3;T*cSUt^ zRC!KVR(3BmL@;)AR8cT#MPf^1Zc<`SICE)lZ)8$PXFWXt2x4_~AYo)=a{v!@b7f|A zY#?oAbYWy+bYTDrWo~0~d2n=TZ*BkwV{dMBWq5P|25EC3Zf|q|26JU&a%FS?26Sa^ zVQzE)2UKNlVQzFm01$Mp z01;t#b1iFab1i6TWpZJ1V`zB*Bw;l&WM*MuWGy#jVq`5eG&3+QVKHW8En#9|VKp*2 zIb>llHvn8qVEAa6K9sGyWr*f{FZg&AR}+tCM2x~(uKn;4t4M8;{z}-JQb7~4l}}(U z`sQKxm(sm6%L5KaMcTDHcu-*>lUVZB)Fg|xxs}%`>eQLTsAJDC4qYKnZr`o~000mG zJY(`y*ayl12Ign5os^h3)<)WSvQY0iw!xUJY}hZ4!m9YJRl+dsmnQJoGe6#Yq`nL7!9DNfOdn zs$wRt^|ith=xKvVI8|T_-bKDLds+&=*r-jVL-lpQJ_!2LuCsY!HwpWT@9{V*mwMCo z-FS2EJ&aQq#j^#|DRmaW7X>r}FpW`|O>0J(Bke~Q$~ajPRmXCYUMc$KwMeytFcxMc zpGe!)=Lhc3p99KiLwTn%AWdwNMxaE_fBh@V7GAeIcMX#NBiEvw?Z`b@7!=jR@xnyT zRqaV?5{;LdC!v;42m8ewJavyPtM5V;sNyrmieoWPEyLb6=`mH@VJMU0kF+i;Cxca$ z(H_2eT6F22BS&(e*QUY+3tE({YV1PF@0#R8#@6=idl=;_1zWo1$`ns#k2H_9gm8ON z8gZDacwY&8x}a2aO=d1%EFR`=7j*sgzk<7}jj`+8Ngg%z6Shi&4rftH8tV7eFCuVN z?!cj)+ELdrI$iBZ8bWpCChNq5>6NuB-yiBcR1WwJAc^@7)EeBy#o*xF#Boo z4d{snP8&rsXl!oEEC08>^z@ssZ`B+mt}F?fDay^Z=h(`wx>kc<(oStm9IHnv2fs0= zQj>2^TjwC;^fu@O)Uask8eoBc`y?^|Lfos8NL`q5x=LIHE>6glDOM@!N+@La_V+(_ znK~Akd@AR?K_oNSZh==qDKsM%gK0eJtCw_n9<%6S?&Zxa|0^5K$tm&J;Ddps{fN+E zqPe~hw$s|{obnC@;HgK`N>e6mG25B?$wjG`Ff+y|lpqy$D&d0=WLMF zRzwjCyCNJkj zU38v8f@0F{3=A*)iG&Cib$FaBIqA@p5jpSP8{$z=w01@N&3gX$<5Nl-j^5%aazR9L z4(6}Ny^#5Ti(jsq=V%R#yEy@wlc7}(V5=`q;I{oqtTo&JRo4V=(^U4Y!aXBLKbGWr z4x)hL|B40g-%6xnnfXs79qzW_-et^-1!jHh+$6IqkGCU_bg2WvR}d;Ge*ab)X2>Bh zbaS(d#IdV`rahE%8Ioz3y1l(dAObyg?cQ`T++%6#lt}R83GiWQc&%zJ`v!e z(mIhpVv3-ED}s#8!;?ZSTU_KGv|H`1ci7rnzd8yo;rdwv$Nei4_U3q>3>GV2o>*AA zI>lD<^e7wYdGJZUo+h)O)tq!A|>NHWH&3`EQ5s!R2u9~P+Vz&8^lrFQQ z|FMFH10*U(5_nao0wwCdPD~vCd0-JH{!qM#MRYi0p{8?js?ls@x@o?v2hj+ZNXkc0#NNUz zbJLk(%bR4<>Dne1)M4s2C`*OZEn^$A%IZt7oc`L!%aP^MfDMnBqYa^)2u>NI3>fuZ4RU5R?XE$fervux>fbr2XZvp zk*K5v5U|K!3`R!C@&O-1;I!#BuaT*{?P5kt;0~-YI0Z9Gy-mUn)zn$Ww>dk*fXkAI zOzEIn-ll={!QPyd@Fg&Zw+6sI#EwQ6GsL6M7)x=2mFx`lWtJ7RMSMFvDqUXnLW!rP z=>amwMB35AVgM~0SQ@?dF$A~CjH(6XtA3+VvsD`DH>$VMCdsr=Afd0VM)(Ynpc6G^ z-FQ64hx7Q@T}1!byt0~nl&3@FW-cGsx6npev4Q)&bSBh1Ugdm9}Yk|@acEIj6=VV zg9+AnYcA3P6%95qj104jHcf;;p!)&uk9EKMnbO51XodVoO2^o~5X>K!hzN++<*t`T zauPtltyIEIy3k%kFlWBW&&2i6rMhMNU3}+o9~0?$g^fUyaSP#n+ZCYKd~8z9!W-;) zjbO)E-yuhdbvduBWQskB4~F-57{Z}v>r_+K4Je6m{kr*-7W^3TZJQa<6%5uX--9HW zyYwL6d*}PJS`9xlM@LDYW&jwy4~vQ)?eF*m+o!Xx#GI-AURd&kKm@U)A9$-}5baL^ zjdBIGA)?6wM{o&n943r<&eY`muV%cUZRK2lw`<21r8W%rd7UyzL~!NHcb80Pnq$^o zoJ(0qV7?nheE8?F2VM>cm=gh#JUNm%`Lu}}Iy*=>kPn_KO@SlcIrV3vWY*$S7G9-~ zm1)tgxczsQc_zl!BW|nR93%z{Y(o$}l&Ftl`W%!ji>V#LCX2aTjDw@2TM?)fCnEz{l_IN6sVQ$6M9(%!K}}_CD)7=Htt^c+@o`dLMNmJS|qmouNg@@ z`CeypQ?&LU%_z+HW7;M@$Pp+XHG!u#1+LV|HHewGNfGuPQ5g^k1dH*7MloS6QBM#bQ2C*WP7HE>+z#2xYQrIsK(?sJX86c7ee$Ut1J zWCrj9Sco-Sf8m;|GLS9{u!8$yiTAMg8W0-Mp9r69c|-#JnZq#z!q+3sWnuyIEqE-` zPgU{gC#9rI9wE5-YEjx0t#-c{Sc2;emFZ871{6^=-E-~0N{xcgC6V0O7Xr8p=ujfq zO((KIpiH{)V0s8C46}Jo#n%GQx1w8+q9M+MlY(dkv8o~SbxgNk$~znV=wmp+u$tcz z`s$g$y1kPCM1b2;LzEu%t$cL3s4}irxVGPj6;}wTnY7X@d+A`@&g8*Q}{@R8o*7yp1`S6(acAY)oq}>++64u!t(}m!~)h9-u!0BLJiMDcL zgdwshO27{LpT`_YRE${Rgi-o)o-RTLfgo?f2G!8o*2p$y+h3zx_)=)YjCU#P+-He< zjFg;u2UwkEH7L>pMnL8aK?VVF+?kaYPC@k+y@5J1kc+dujN!daqOmAg_KwIN{dUe~ z!rz@aJ=BDXtCLxJQQ7OTJ)lx7fQ)q*pKm^-PO_L3;Q55(PDvW$+b=HLBM z*AOWJqnyAx@5Caqa$bx%;p@OPDM$HjUAMFx+vih&Q^e^NG$S7!T#VCog?S&m?2DA>Su-mvM}%6r9H0}l2#mOdmv$Jz>~64DDUhdjIG)w# zTOjyIoD(>$n#d=iM5rLBj^b#-@i{eqJnFRJHm(* zLuel+1BFLB;09L*TVkUesVjKIjeeC#%sMa~&Nd$h%to`}UCn_YK&@glbf^NtP!p~+ z8HNp=tD?+4^B8O4-~1x0km0)U6@hPb7kja&i^rzwwo>&xw|4FL(QXY5y7jIVq65>1 zO2X`tIIoR0P!kZewzz+W;vBxvyg-E^XqVh9N}kc{K_ z6C~qX3p6NBmSL^!w|>R%Xw#S+jRRVgWW_S}x^tQU%o1>2H-q-_H}+ooA^&4vPxITEiN=cJC=R3RmFp5tll4zV{KYYx`p zz3_i9vxGG5H|qs_1iMNwbdmT^g8Os0RB?||qh_Yge`vrANjU5yQ7gxayNfwS#1-(S zcsL)h_i4}G&*c+-yhR~JX|n%zzyB{DhB|9tB-kzs>{6SVRd|dfHAM zam82-0u3$cN(A~SgIWULqZw2t5zMUC*~Z3MRzGZ$mA-RM39|rU{17aDi+;-$4vPml zL3(wWPaSdlr}AY@=#HO7ZEGDf+Q4^ch1h7WSl9Tre`$9R4Q5&%`My>y76-l-Qc57& z8f%&agM;CQ9M)>$kZQdA#Nxq%Qd|*-8uVTQjJk<=6+rft5reBwwioDSAO9_`LVcwn zv9OEgQ|(UAjABK7y6qk&ZN|0Um@bS0+qyGPod%bR0I+m91Nb*@sJKJFO63y@=-o;_ z`3#-)(+D6bCb#hSYdi25|NsC000002000000000000002000j_PxC#|DmeW}osYQQ zEA6i9va~G0`044K3o@z)jg+?m>XcPt1r-ADKq$zzH_-;i@s#LP&|jg=h4pU%#EPQ@ z838#s9Mu&R+(ywP>}!0PpO{oWQcY$!5p*Aq)uU)d6*1mYuvfK2qBvMB79N^L-I$Qs zo3683)S6MUDyEUapiLSUZ>Wl_E8t07fH~)Z4

JYO(+TJbO_}u7^|V49O9TF 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 B55NEb literal 0 HcmV?d00001 From 3476816c644a6d85f4ead68aa6f07acc3a0feffa Mon Sep 17 00:00:00 2001 From: Ritvik Kapila <61410899+RitvikKapila@users.noreply.github.com> Date: Thu, 13 Jun 2024 10:58:52 -0700 Subject: [PATCH 03/18] =?UTF-8?q?chore(migration=20examples):=20added=20KM?= =?UTF-8?q?S,=20raw=20AES=20and=20raw=20RSA=20keyring/MKP=E2=80=A6=20(#687?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/src/migration/README.rst | 19 ++ .../migration_aws_kms_key_example.py | 166 +++++++++++ .../migration_raw_aes_key_example.py | 207 ++++++++++++++ .../migration_raw_rsa_key_example.py | 259 ++++++++++++++++++ ...migration_set_commitment_policy_example.py | 0 examples/test/migration/__init__.py | 3 + .../test_i_migration_aws_kms_key_example.py | 16 ++ .../test_i_migration_raw_aes_key_example.py | 15 + .../test_i_migration_raw_rsa_key_example.py | 15 + ...migration_set_commitment_policy_example.py | 2 +- 10 files changed, 701 insertions(+), 1 deletion(-) create mode 100644 examples/src/migration/README.rst create mode 100644 examples/src/migration/migration_aws_kms_key_example.py create mode 100644 examples/src/migration/migration_raw_aes_key_example.py create mode 100644 examples/src/migration/migration_raw_rsa_key_example.py rename examples/src/{ => migration}/migration_set_commitment_policy_example.py (100%) create mode 100644 examples/test/migration/__init__.py create mode 100644 examples/test/migration/test_i_migration_aws_kms_key_example.py create mode 100644 examples/test/migration/test_i_migration_raw_aes_key_example.py create mode 100644 examples/test/migration/test_i_migration_raw_rsa_key_example.py rename examples/test/{ => migration}/test_i_migration_set_commitment_policy_example.py (83%) diff --git a/examples/src/migration/README.rst b/examples/src/migration/README.rst new file mode 100644 index 000000000..41d3f5515 --- /dev/null +++ b/examples/src/migration/README.rst @@ -0,0 +1,19 @@ +################## +Migration Examples +################## + +The `Encryption SDK for Python`_ now uses the `AWS Cryptographic Material Providers Library`_. The MPL abstracts lower +level cryptographic materials management of encryption and decryption materials. + +This directory contains migration examples for: + +#. Moving to Keyrings from Master Key Providers: + * Migration example to AWS KMS keyring from AWS KMS Master Key Provider. + * Migration example to Raw AES keyring from Raw AES Master Key Provider. + * Migration example to Raw RSA keyring from Raw RSA Master Key Provider. + +#. Migration to newer versions of the ESDK (4.x+) from 1.x versions: + * Setting a 'CommitmentPolicy' during migration - If you have messages encrypted with 1.x versions of the ESDK (i.e. not using key commitment) and want to migrate to encrypt with key commitment using the keyring providers introduced in ESDK 4.x, this example will guide you on how to decrypt those messages using the new version of the ESDK. + +.. _AWS Cryptographic Material Providers Library: https://github.com/aws/aws-cryptographic-material-providers-library +.. _Encryption SDK for Python: https://github.com/aws/aws-encryption-sdk-python/tree/9c34aad60fc918c1a9186ec5215a451e8bfd0f65 \ No newline at end of file diff --git a/examples/src/migration/migration_aws_kms_key_example.py b/examples/src/migration/migration_aws_kms_key_example.py new file mode 100644 index 000000000..28b8193e3 --- /dev/null +++ b/examples/src/migration/migration_aws_kms_key_example.py @@ -0,0 +1,166 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +""" +This is a migration example for moving to the AWS KMS Keyring from AWS KMS master key provider (MKP) + +The AWS KMS keyring uses symmetric encryption KMS keys to generate, encrypt and +decrypt data keys. This example creates a KMS Keyring and KMS MKP and +then encrypts a custom input EXAMPLE_DATA with the same encryption context using both +the keyring and MKP. The example then decrypts the ciphertexts using both keyring and MKPs. +This example also includes some sanity checks for demonstration: +1. Decryption of these ciphertexts encrypted using keyring and MKP + is possible using both KMS keyring and KMS MKP +2. Both decrypted plaintexts are same and match EXAMPLE_DATA +These sanity checks are for demonstration in the example only. You do not need these in your code. + +Note: The ciphertexts obtained by encrypting EXAMPLE_DATA using keyring and MKP are not +the same because the ESDK generates different data keys each time for encryption of the data. +But both ciphertexts when decrypted using keyring and MKP should give the same plaintext result. + +For more information on how to use KMS keyrings, see +https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-kms-keyring.html +""" +import boto3 +from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig +from aws_cryptographic_materialproviders.mpl.models import CreateAwsKmsKeyringInput +from aws_cryptographic_materialproviders.mpl.references import IKeyring +from typing import Dict # noqa pylint: disable=wrong-import-order + +import aws_encryption_sdk + +EXAMPLE_DATA: bytes = b"Hello World" + +DEFAULT_ENCRYPTION_CONTEXT : Dict[str, str] = { + "encryption": "context", + "is not": "secret", + "but adds": "useful metadata", + "that can help you": "be confident that", + "the data you are handling": "is what you think it is", +} + + +def create_keyring( + kms_key_id: str, + aws_region="us-west-2" +): + """Demonstrate how to create an AWS KMS keyring. + + Usage: create_keyring(kms_key_id) + :param kms_key_id: KMS Key identifier for the KMS key you want to use. + :type kms_key_id: string + + For more information on KMS Key identifiers, see + https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id + """ + # Create a boto3 client for KMS. + kms_client = boto3.client('kms', region_name=aws_region) + + # Create a KMS keyring + mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + config=MaterialProvidersConfig() + ) + + keyring_input: CreateAwsKmsKeyringInput = CreateAwsKmsKeyringInput( + kms_key_id=kms_key_id, + kms_client=kms_client + ) + + keyring: IKeyring = mat_prov.create_aws_kms_keyring( + input=keyring_input + ) + + return keyring + + +def create_key_provider( + kms_key_id: str +): + """Demonstrate how to create an AWS KMS master key provider. + + Usage: create_key_provider(kms_key_id) + :param kms_key_id: KMS Key identifier for the KMS key you want to use. + :type kms_key_id: string + + For more information on KMS Key identifiers, see + https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id + """ + # Create a KMS master key provider. + key_provider = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider(key_ids=[ + kms_key_id, + ]) + + return key_provider + + +def migration_aws_kms_key( + kms_key_id: str +): + """Demonstrate a migration example for moving to an AWS KMS keyring from AWS KMS MKP. + + Usage: migration_aws_kms_key(kms_key_id) + :param kms_key_id: KMS Key identifier for the KMS key you want to use for encryption and + decryption of your data keys. + :type kms_key_id: string + + For more information on KMS Key identifiers, see + https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id + """ + client = aws_encryption_sdk.EncryptionSDKClient() + + # 1a. Create a AWS KMS Keyring + aws_kms_keyring = create_keyring(kms_key_id=kms_key_id) + + # 1b. Create a AWS KMS Master Key Provider + aws_kms_master_key_provider = create_key_provider(kms_key_id=kms_key_id) + + # 2a. Encrypt EXAMPLE_DATA using AWS KMS Keyring + ciphertext_keyring, _ = client.encrypt( + source=EXAMPLE_DATA, + keyring=aws_kms_keyring, + encryption_context=DEFAULT_ENCRYPTION_CONTEXT + ) + + # 2b. Encrypt EXAMPLE_DATA using AWS KMS Master Key Provider + ciphertext_mkp, _ = client.encrypt( + source=EXAMPLE_DATA, + key_provider=aws_kms_master_key_provider, + encryption_context=DEFAULT_ENCRYPTION_CONTEXT + ) + + # Note: The ciphertexts obtained by encrypting EXAMPLE_DATA using keyring and MKP + # (that is ciphertext_keyring and ciphertext_mkp) are not the same because the ESDK + # generates different data keys each time for encryption of the data. But both + # ciphertexts when decrypted using keyring and MKP should give the same plaintext result. + + # 3. Decrypt the ciphertext_keyring using both the keyring and MKP and ensure the + # resulting plaintext is the same and also equal to EXAMPLE_DATA + decrypted_ciphertext_keyring_using_keyring, _ = client.decrypt( + source=ciphertext_keyring, + keyring=aws_kms_keyring + ) + + decrypted_ciphertext_keyring_using_mkp, _ = client.decrypt( + source=ciphertext_keyring, + key_provider=aws_kms_master_key_provider + ) + + assert decrypted_ciphertext_keyring_using_keyring == decrypted_ciphertext_keyring_using_mkp \ + and decrypted_ciphertext_keyring_using_keyring == EXAMPLE_DATA, \ + "Decrypted outputs using keyring and master key provider are not the same" + + # 4. Decrypt the ciphertext_mkp using both the keyring and MKP and ensure the + # resulting plaintext is the same and also equal to EXAMPLE_DATA + decrypted_ciphertext_mkp_using_keyring, _ = client.decrypt( + source=ciphertext_mkp, + keyring=aws_kms_keyring + ) + + decrypted_ciphertext_mkp_using_mkp, _ = client.decrypt( + source=ciphertext_mkp, + key_provider=aws_kms_master_key_provider + ) + + assert decrypted_ciphertext_mkp_using_keyring == decrypted_ciphertext_mkp_using_mkp \ + and decrypted_ciphertext_mkp_using_keyring == EXAMPLE_DATA, \ + "Decrypted outputs using keyring and master key provider are not the same" diff --git a/examples/src/migration/migration_raw_aes_key_example.py b/examples/src/migration/migration_raw_aes_key_example.py new file mode 100644 index 000000000..772f83cf5 --- /dev/null +++ b/examples/src/migration/migration_raw_aes_key_example.py @@ -0,0 +1,207 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +""" +This is a migration example for moving to the Raw AES Keyring from Raw AES master key provider (MKP) + +The Raw AES keyring lets you use an AES symmetric key that you provide as a wrapping key that +protects your data key. You need to generate, store, and protect the key material, +preferably in a hardware security module (HSM) or key management system. Use a Raw AES keyring +when you need to provide the wrapping key and encrypt the data keys locally or offline. + +This example creates a Raw AES Keyring and Raw AES MKP and +then encrypts a custom input EXAMPLE_DATA with the same encryption context using both +the keyring and MKP. The example then decrypts the ciphertexts using both keyring and MKPs. +This example also includes some sanity checks for demonstration: +1. Decryption of these ciphertexts encrypted using keyring and MKP + is possible using both Raw AES keyring and Raw AES MKP +2. Both decrypted plaintexts are same and match EXAMPLE_DATA +These sanity checks are for demonstration in the example only. You do not need these in your code. + +Note: The ciphertexts obtained by encrypting EXAMPLE_DATA using keyring and MKP are not +the same because the ESDK generates different data keys each time for encryption of the data. +But both ciphertexts when decrypted using keyring and MKP will give the same plaintext result. + +For more information on how to use Raw AES keyrings, see +https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-raw-aes-keyring.html +""" +import secrets + +from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig +from aws_cryptographic_materialproviders.mpl.models import AesWrappingAlg, CreateRawAesKeyringInput +from aws_cryptographic_materialproviders.mpl.references import IKeyring +from typing import Dict # noqa pylint: disable=wrong-import-order + +import aws_encryption_sdk +from aws_encryption_sdk.identifiers import EncryptionKeyType, WrappingAlgorithm +from aws_encryption_sdk.internal.crypto.wrapping_keys import WrappingKey +from aws_encryption_sdk.key_providers.raw import RawMasterKeyProvider + +EXAMPLE_DATA: bytes = b"Hello World" + +DEFAULT_ENCRYPTION_CONTEXT : Dict[str, str] = { + "encryption": "context", + "is not": "secret", + "but adds": "useful metadata", + "that can help you": "be confident that", + "the data you are handling": "is what you think it is", +} + +DEFAULT_AES_256_STATIC_KEY = secrets.token_bytes(32) + +# The key namespace in the Raw keyrings is equivalent to Provider ID (or Provider) field +# in the Raw Master Key Providers +DEFAULT_KEY_NAME_SPACE = "Some managed raw keys" + +# The key name in the Raw keyrings is equivalent to the Key ID field +# in the Raw Master Key Providers +DEFAULT_KEY_NAME = "My 256-bit AES wrapping key" + + +def create_keyring(): + """Demonstrate how to create a Raw AES keyring. + + Usage: create_keyring() + """ + # We fix the static key in order to make the test deterministic + static_key = DEFAULT_AES_256_STATIC_KEY + + mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + config=MaterialProvidersConfig() + ) + + # The key namespace in the Raw keyrings is equivalent to Provider ID (or Provider) field + # in the Raw Master Key Providers + # The key name in the Raw keyrings is equivalent to the Key ID field + # in the Raw Master Key Providers + keyring_input: CreateRawAesKeyringInput = CreateRawAesKeyringInput( + key_namespace=DEFAULT_KEY_NAME_SPACE, + key_name=DEFAULT_KEY_NAME, + wrapping_key=static_key, + wrapping_alg=AesWrappingAlg.ALG_AES256_GCM_IV12_TAG16 + ) + + keyring: IKeyring = mat_prov.create_raw_aes_keyring( + input=keyring_input + ) + + return keyring + + +# This is a helper class necessary for the Raw AES master key provider +# In the StaticMasterKeyProvider, we fix the static key to +# DEFAULT_AES_256_STATIC_KEY in order to make the test deterministic. +# Thus, both the Raw AES keyring and Raw AES MKP have the same key +# and we are able to encrypt data using keyrings and decrypt using MKP and vice versa +# In practice, users should generate a new random key for each key id. +class StaticMasterKeyProvider(RawMasterKeyProvider): + """Generates 256-bit keys for each unique key ID.""" + + # The key namespace in the Raw keyrings is equivalent to Provider ID (or Provider) field + # in the Raw Master Key Providers + provider_id = DEFAULT_KEY_NAME_SPACE + + def __init__(self, **kwargs): # pylint: disable=unused-argument + """Initialize empty map of keys.""" + self._static_keys = {} + + def _get_raw_key(self, key_id): + """Returns a static, symmetric key for the specified key ID. + + :param str key_id: Key ID + :returns: Wrapping key that contains the specified static key + :rtype: :class:`aws_encryption_sdk.internal.crypto.WrappingKey` + """ + try: + static_key = self._static_keys[key_id] + except KeyError: + # We fix the static key in order to make the test deterministic + # In practice, you should get this key from a secure key management system such as an HSM. + static_key = DEFAULT_AES_256_STATIC_KEY + self._static_keys[key_id] = static_key + return WrappingKey( + wrapping_algorithm=WrappingAlgorithm.AES_256_GCM_IV12_TAG16_NO_PADDING, + wrapping_key=static_key, + wrapping_key_type=EncryptionKeyType.SYMMETRIC, + ) + + +def create_key_provider(): + """Demonstrate how to create a Raw AES master key provider. + + Usage: create_key_provider() + """ + # Create a Raw AES master key provider. + + # The key name in the Raw keyrings is equivalent to the Key ID field + # in the Raw Master Key Providers + key_id = DEFAULT_KEY_NAME + key_provider = StaticMasterKeyProvider() + key_provider.add_master_key(key_id) + + return key_provider + + +def migration_raw_aes_key(): + """Demonstrate a migration example for moving to a Raw AES keyring from Raw AES MKP. + + Usage: migration_raw_aes_key() + """ + client = aws_encryption_sdk.EncryptionSDKClient() + + # 1a. Create a Raw AES Keyring + raw_aes_keyring = create_keyring() + + # 1b. Create a Raw AES Master Key Provider + raw_aes_master_key_provider = create_key_provider() + + # 2a. Encrypt EXAMPLE_DATA using Raw AES Keyring + ciphertext_keyring, _ = client.encrypt( + source=EXAMPLE_DATA, + keyring=raw_aes_keyring, + encryption_context=DEFAULT_ENCRYPTION_CONTEXT + ) + + # 2b. Encrypt EXAMPLE_DATA using Raw AES Master Key Provider + ciphertext_mkp, _ = client.encrypt( + source=EXAMPLE_DATA, + key_provider=raw_aes_master_key_provider, + encryption_context=DEFAULT_ENCRYPTION_CONTEXT + ) + + # Note: The ciphertexts obtained by encrypting EXAMPLE_DATA using keyring and MKP + # (that is ciphertext_keyring and ciphertext_mkp) are not the same because the ESDK + # generates different data keys each time for encryption of the data. But both + # ciphertexts when decrypted using keyring and MKP will give the same plaintext result. + + # 3. Decrypt the ciphertext_keyring using both the keyring and MKP and ensure the + # resulting plaintext is the same and also equal to EXAMPLE_DATA + decrypted_ciphertext_keyring_using_keyring, _ = client.decrypt( + source=ciphertext_keyring, + keyring=raw_aes_keyring + ) + + decrypted_ciphertext_keyring_using_mkp, _ = client.decrypt( + source=ciphertext_keyring, + key_provider=raw_aes_master_key_provider + ) + + assert decrypted_ciphertext_keyring_using_keyring == decrypted_ciphertext_keyring_using_mkp \ + and decrypted_ciphertext_keyring_using_keyring == EXAMPLE_DATA, \ + "Decrypted outputs using keyring and master key provider are not the same" + + # 4. Decrypt the ciphertext_mkp using both the keyring and MKP and ensure the + # resulting plaintext is the same and also equal to EXAMPLE_DATA + decrypted_ciphertext_mkp_using_keyring, _ = client.decrypt( + source=ciphertext_mkp, + keyring=raw_aes_keyring + ) + + decrypted_ciphertext_mkp_using_mkp, _ = client.decrypt( + source=ciphertext_mkp, + key_provider=raw_aes_master_key_provider + ) + + assert decrypted_ciphertext_mkp_using_keyring == decrypted_ciphertext_mkp_using_mkp \ + and decrypted_ciphertext_mkp_using_keyring == EXAMPLE_DATA, \ + "Decrypted outputs using keyring and master key provider are not the same" diff --git a/examples/src/migration/migration_raw_rsa_key_example.py b/examples/src/migration/migration_raw_rsa_key_example.py new file mode 100644 index 000000000..7c6020a53 --- /dev/null +++ b/examples/src/migration/migration_raw_rsa_key_example.py @@ -0,0 +1,259 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +""" +This is a migration example for moving to the Raw RSA Keyring from Raw RSA master key provider (MKP) + +The Raw RSA keyring performs asymmetric encryption and decryption of data keys in local memory +with RSA public and private keys that you provide. In this example, we define the RSA keys to +encrypt and decrypt the data keys. + +You need to generate, store, and protect the private key, preferably in a +hardware security module (HSM) or key management system. +The encryption function encrypts the data key under the RSA public key. The decryption function +decrypts the data key using the private key. + +This example creates a Raw RSA Keyring and Raw RSA MKP and +then encrypts a custom input EXAMPLE_DATA with the same encryption context using both +the keyring and MKP. The example then decrypts the ciphertexts using both keyring and MKPs. +This example also includes some sanity checks for demonstration: +1. Decryption of these ciphertexts encrypted using keyring and MKP + is possible using both Raw RSA keyring and Raw RSA MKP +2. Both decrypted plaintexts are same and match EXAMPLE_DATA +These sanity checks are for demonstration in the example only. You do not need these in your code. + +Note: The ciphertexts obtained by encrypting EXAMPLE_DATA using keyring and MKP are not +the same because the ESDK generates different data keys each time for encryption of the data. +But both ciphertexts when decrypted using keyring and MKP will give the same plaintext result. + +For more information on how to use Raw RSA keyrings, see +https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-raw-rsa-keyring.html +""" +from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig +from aws_cryptographic_materialproviders.mpl.models import CreateRawRsaKeyringInput, PaddingScheme +from aws_cryptographic_materialproviders.mpl.references import IKeyring +from cryptography.hazmat.backends import default_backend as crypto_default_backend +from cryptography.hazmat.primitives import serialization as crypto_serialization +from cryptography.hazmat.primitives.asymmetric import rsa +from typing import Dict # noqa pylint: disable=wrong-import-order + +import aws_encryption_sdk +from aws_encryption_sdk.identifiers import EncryptionKeyType, WrappingAlgorithm +from aws_encryption_sdk.internal.crypto.wrapping_keys import WrappingKey +from aws_encryption_sdk.key_providers.raw import RawMasterKeyProvider + +EXAMPLE_DATA: bytes = b"Hello World" + +DEFAULT_ENCRYPTION_CONTEXT : Dict[str, str] = { + "encryption": "context", + "is not": "secret", + "but adds": "useful metadata", + "that can help you": "be confident that", + "the data you are handling": "is what you think it is", +} + +# The key namespace in the Raw keyrings is equivalent to Provider ID (or Provider) field +# in the Raw Master Key Providers +DEFAULT_KEY_NAME_SPACE = "Some managed raw keys" + +# The key name in the Raw keyrings is equivalent to the Key ID field +# in the Raw Master Key Providers +DEFAULT_KEY_NAME = "My 4096-bit RSA wrapping key" + + +def generate_rsa_keys_helper(): + """Generates a 4096-bit RSA public and private key pair + + Usage: generate_rsa_keys_helper() + """ + ssh_rsa_exponent = 65537 + bit_strength = 4096 + key = rsa.generate_private_key( + backend=crypto_default_backend(), + public_exponent=ssh_rsa_exponent, + key_size=bit_strength + ) + + # This example choses a particular type of encoding, format and encryption_algorithm + # Users can choose the PublicFormat, PrivateFormat and encryption_algorithm that align most + # with their use-cases + public_key = key.public_key().public_bytes( + encoding=crypto_serialization.Encoding.PEM, + format=crypto_serialization.PublicFormat.SubjectPublicKeyInfo + ) + private_key = key.private_bytes( + encoding=crypto_serialization.Encoding.PEM, + format=crypto_serialization.PrivateFormat.TraditionalOpenSSL, + encryption_algorithm=crypto_serialization.NoEncryption() + ) + + return public_key, private_key + + +DEFAULT_RSA_PUBLIC_KEY, DEFAULT_RSA_PRIVATE_KEY = generate_rsa_keys_helper() + + +def create_keyring(public_key, private_key): + """Demonstrate how to create a Raw RSA keyring using the key pair. + + Usage: create_keyring(public_key, private_key) + """ + mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + config=MaterialProvidersConfig() + ) + + # The key namespace in the Raw keyrings is equivalent to Provider ID (or Provider) field + # in the Raw Master Key Providers + # The key name in the Raw keyrings is equivalent to the Key ID field + # in the Raw Master Key Providers + keyring_input: CreateRawRsaKeyringInput = CreateRawRsaKeyringInput( + key_namespace=DEFAULT_KEY_NAME_SPACE, + key_name=DEFAULT_KEY_NAME, + padding_scheme=PaddingScheme.OAEP_SHA256_MGF1, + public_key=public_key, + private_key=private_key + ) + + keyring: IKeyring = mat_prov.create_raw_rsa_keyring( + input=keyring_input + ) + + return keyring + + +# This is a helper class necessary for the Raw RSA master key provider. +# In the StaticMasterKeyProvider, we fix the static key to +# DEFAULT_RSA_PRIVATE_KEY in order to make the test deterministic. +# Thus, both the Raw RSA keyring and Raw RSA MKP have the same private_key +# and we are able to encrypt data using keyrings and decrypt using MKP and vice versa +# In practice, users should generate a new random key pair for each key id. +class StaticMasterKeyProvider(RawMasterKeyProvider): + """Provides 4096-bit RSA keys consistently per unique key id.""" + + # The key namespace in the Raw keyrings is equivalent to Provider ID (or Provider) field + # in the Raw Master Key Providers + provider_id = DEFAULT_KEY_NAME_SPACE + + def __init__(self, **kwargs): # pylint: disable=unused-argument + """Initialize empty map of keys.""" + self._static_keys = {} + + def _get_raw_key(self, key_id): + """Retrieves a static, RSA key for the specified key id. + + :param str key_id: User-defined ID for the static key + :returns: Wrapping key that contains the specified static key + :rtype: :class:`aws_encryption_sdk.internal.crypto.WrappingKey` + """ + try: + static_key = self._static_keys[key_id] + except KeyError: + # We fix the static key in order to make the test deterministic + # In practice, you should get this key from a secure key management system such as an HSM. + # Also, in practice, users should generate a new key pair for each key id in + # the StaticMasterKeyProvider. + static_key = DEFAULT_RSA_PRIVATE_KEY + self._static_keys[key_id] = static_key + return WrappingKey( + wrapping_algorithm=WrappingAlgorithm.RSA_OAEP_SHA256_MGF1, + wrapping_key=static_key, + wrapping_key_type=EncryptionKeyType.PRIVATE, + ) + + +def create_key_provider(): + """Demonstrate how to create a Raw RSA master key provider. + + Usage: create_key_provider() + """ + # Create a Raw RSA master key provider. + + # The key name in the Raw keyrings is equivalent to the Key ID field + # in the Raw Master Key Providers + key_id = DEFAULT_KEY_NAME + + # In this example, we fix the static key to DEFAULT_RSA_PRIVATE_KEY in both the keyring + # and MKP (for MKP, we fix the static key in StaticMasterKeyProvider) in order to make + # the test deterministic. Thus, both the Raw RSA keyring and Raw RSA MKP have the same + # private_key and we are able to encrypt data using keyrings and decrypt using MKP + # and vice versa. In practice, users should generate a new key pair for each key id in + # the StaticMasterKeyProvider. + key_provider = StaticMasterKeyProvider() + key_provider.add_master_key(key_id) + + return key_provider + + +def migration_raw_rsa_key( + public_key=DEFAULT_RSA_PUBLIC_KEY, + private_key=DEFAULT_RSA_PRIVATE_KEY +): + """Demonstrate a migration example for moving to a Raw RSA keyring from Raw RSA MKP. + + Usage: migration_raw_rsa_key(public_key, private_key) + """ + client = aws_encryption_sdk.EncryptionSDKClient() + + # 1a. Create a Raw RSA Keyring + raw_rsa_keyring = create_keyring(public_key=public_key, private_key=private_key) + + # 1b. Create a Raw RSA Master Key Provider + + # In this example, we fix the static key to DEFAULT_RSA_PRIVATE_KEY in both the keyring + # and MKP (for MKP, we fix the static key in StaticMasterKeyProvider) in order to make + # the test deterministic. Thus, both the Raw RSA keyring and Raw RSA MKP have the same + # private_key and we are able to encrypt data using keyrings and decrypt using MKP + # and vice versa. In practice, users should generate a new key pair for each key id in + # the StaticMasterKeyProvider. + raw_rsa_master_key_provider = create_key_provider() + + # 2a. Encrypt EXAMPLE_DATA using Raw RSA Keyring + ciphertext_keyring, _ = client.encrypt( + source=EXAMPLE_DATA, + keyring=raw_rsa_keyring, + encryption_context=DEFAULT_ENCRYPTION_CONTEXT + ) + + # 2b. Encrypt EXAMPLE_DATA using Raw RSA Master Key Provider + ciphertext_mkp, _ = client.encrypt( + source=EXAMPLE_DATA, + key_provider=raw_rsa_master_key_provider, + encryption_context=DEFAULT_ENCRYPTION_CONTEXT + ) + + # Note: The ciphertexts obtained by encrypting EXAMPLE_DATA using keyring and MKP + # (that is ciphertext_keyring and ciphertext_mkp) are not the same because the ESDK + # generates different data keys each time for encryption of the data. But both + # ciphertexts when decrypted using keyring and MKP will give the same plaintext result. + + # 3. Decrypt the ciphertext_keyring using both the keyring and MKP and ensure the + # resulting plaintext is the same and also equal to EXAMPLE_DATA + decrypted_ciphertext_keyring_using_keyring, _ = client.decrypt( + source=ciphertext_keyring, + keyring=raw_rsa_keyring + ) + + decrypted_ciphertext_keyring_using_mkp, _ = client.decrypt( + source=ciphertext_keyring, + key_provider=raw_rsa_master_key_provider + ) + + assert decrypted_ciphertext_keyring_using_keyring == decrypted_ciphertext_keyring_using_mkp \ + and decrypted_ciphertext_keyring_using_keyring == EXAMPLE_DATA, \ + "Decrypted outputs using keyring and master key provider are not the same" + + # 4. Decrypt the ciphertext_mkp using both the keyring and MKP and ensure the + # resulting plaintext is the same and also equal to EXAMPLE_DATA + decrypted_ciphertext_mkp_using_keyring, _ = client.decrypt( + source=ciphertext_mkp, + keyring=raw_rsa_keyring + ) + + decrypted_ciphertext_mkp_using_mkp, _ = client.decrypt( + source=ciphertext_mkp, + key_provider=raw_rsa_master_key_provider + ) + + assert decrypted_ciphertext_mkp_using_keyring == decrypted_ciphertext_mkp_using_mkp \ + and decrypted_ciphertext_mkp_using_keyring == EXAMPLE_DATA, \ + "Decrypted outputs using keyring and master key provider are not the same" diff --git a/examples/src/migration_set_commitment_policy_example.py b/examples/src/migration/migration_set_commitment_policy_example.py similarity index 100% rename from examples/src/migration_set_commitment_policy_example.py rename to examples/src/migration/migration_set_commitment_policy_example.py diff --git a/examples/test/migration/__init__.py b/examples/test/migration/__init__.py new file mode 100644 index 000000000..120179eda --- /dev/null +++ b/examples/test/migration/__init__.py @@ -0,0 +1,3 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Stub module indicator to make linter configuration simpler.""" diff --git a/examples/test/migration/test_i_migration_aws_kms_key_example.py b/examples/test/migration/test_i_migration_aws_kms_key_example.py new file mode 100644 index 000000000..d4cf49ce9 --- /dev/null +++ b/examples/test/migration/test_i_migration_aws_kms_key_example.py @@ -0,0 +1,16 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Test suite for the migration_aws_kms_key_example.""" +import pytest + +from ...src.migration.migration_aws_kms_key_example import ( + migration_aws_kms_key, +) + +pytestmark = [pytest.mark.examples] + + +def test_migration_aws_kms_key(): + """Test function for migration of AWS KMS Keys.""" + kms_key_id = "arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f" + migration_aws_kms_key(kms_key_id) diff --git a/examples/test/migration/test_i_migration_raw_aes_key_example.py b/examples/test/migration/test_i_migration_raw_aes_key_example.py new file mode 100644 index 000000000..7601e7dc0 --- /dev/null +++ b/examples/test/migration/test_i_migration_raw_aes_key_example.py @@ -0,0 +1,15 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Test suite for the migration_raw_aes_key_example.""" +import pytest + +from ...src.migration.migration_raw_aes_key_example import ( + migration_raw_aes_key, +) + +pytestmark = [pytest.mark.examples] + + +def test_migration_raw_aes_key(): + """Test function for migration of Raw AES keys.""" + migration_raw_aes_key() diff --git a/examples/test/migration/test_i_migration_raw_rsa_key_example.py b/examples/test/migration/test_i_migration_raw_rsa_key_example.py new file mode 100644 index 000000000..9e111d25a --- /dev/null +++ b/examples/test/migration/test_i_migration_raw_rsa_key_example.py @@ -0,0 +1,15 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Test suite for the migration_raw_rsa_key_example.""" +import pytest + +from ...src.migration.migration_raw_rsa_key_example import ( + migration_raw_rsa_key, +) + +pytestmark = [pytest.mark.examples] + + +def test_migration_raw_rsa_key(): + """Test function for migration of Raw RSA keys.""" + migration_raw_rsa_key() diff --git a/examples/test/test_i_migration_set_commitment_policy_example.py b/examples/test/migration/test_i_migration_set_commitment_policy_example.py similarity index 83% rename from examples/test/test_i_migration_set_commitment_policy_example.py rename to examples/test/migration/test_i_migration_set_commitment_policy_example.py index afbc758bc..4620d64df 100644 --- a/examples/test/test_i_migration_set_commitment_policy_example.py +++ b/examples/test/migration/test_i_migration_set_commitment_policy_example.py @@ -3,7 +3,7 @@ """Test suite for the migration_set_commitment_policy_example.""" import pytest -from ..src.migration_set_commitment_policy_example import encrypt_and_decrypt_with_keyring +from ...src.migration.migration_set_commitment_policy_example import encrypt_and_decrypt_with_keyring pytestmark = [pytest.mark.examples] From fc8fd38ba1a6efa1ae2db109c890f7d6bccd225e Mon Sep 17 00:00:00 2001 From: Ritvik Kapila <61410899+RitvikKapila@users.noreply.github.com> Date: Wed, 26 Jun 2024 13:32:15 -0700 Subject: [PATCH 04/18] chore(custom_cmm_example.py): added test for custom_cmm_example.py (#690) --- examples/src/custom_mpl_cmm_example.py | 125 ++++++++++++++ ...cryptographic_materials_manager_example.py | 133 +++++++++++++++ examples/src/legacy/custom_cmm_example.py | 87 ++++++++++ examples/test/legacy/examples_test_utils.py | 2 +- .../test/legacy/test_i_custom_cmm_example.py | 51 ++++++ examples/test/legacy/v3_default_cmm.py | 159 ++++++++++++++++++ .../test_i_migration_aws_kms_key_example.py | 4 +- .../test_i_migration_raw_aes_key_example.py | 4 +- .../test_i_migration_raw_rsa_key_example.py | 4 +- .../test/test_i_custom_mpl_cmm_example.py | 39 +++++ ...cryptographic_materials_manager_example.py | 14 ++ tox.ini | 4 +- 12 files changed, 615 insertions(+), 11 deletions(-) create mode 100644 examples/src/custom_mpl_cmm_example.py create mode 100644 examples/src/default_cryptographic_materials_manager_example.py create mode 100644 examples/src/legacy/custom_cmm_example.py create mode 100644 examples/test/legacy/test_i_custom_cmm_example.py create mode 100644 examples/test/legacy/v3_default_cmm.py create mode 100644 examples/test/test_i_custom_mpl_cmm_example.py create mode 100644 examples/test/test_i_default_cryptographic_materials_manager_example.py diff --git a/examples/src/custom_mpl_cmm_example.py b/examples/src/custom_mpl_cmm_example.py new file mode 100644 index 000000000..544ca5f00 --- /dev/null +++ b/examples/src/custom_mpl_cmm_example.py @@ -0,0 +1,125 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +""" +Example to create a custom implementation of the MPL's ICryptographicMaterialsManager class and use it with the ESDK. + +The cryptographic materials manager (CMM) assembles the cryptographic materials that are used +to encrypt and decrypt data. The cryptographic materials include plaintext and encrypted data keys, +and an optional message signing key. + +Cryptographic Materials Managers (CMMs) are composable; if you just want to extend the behavior of +the default CMM, you can do this as demonstrated in this example. This is the easiest approach if +you are just adding a small check to the CMM methods, as in this example. + +If your use case calls for fundamentally changing aspects of the default CMM, you can also write +your own implementation without extending an existing CMM. The default CMM's implementation is a +good reference to use if you need to write a custom CMM implementation from scratch. +Custom implementations of CMMs must implement get_encryption_materials and decrypt_materials. + +For more information on a default implementation of a CMM, +please look at the default_cryptographic_materials_manager_example.py example. + +For more information on Cryptographic Material Managers, see +https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#crypt-materials-manager +""" + +from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig +from aws_cryptographic_materialproviders.mpl.models import ( + CreateDefaultCryptographicMaterialsManagerInput, + SignatureAlgorithmNone, +) +from aws_cryptographic_materialproviders.mpl.references import ICryptographicMaterialsManager, IKeyring + +import aws_encryption_sdk +from aws_encryption_sdk import CommitmentPolicy + + +# Custom CMM implementation using the MPL. +# This CMM only allows encryption/decryption using signing algorithms. +# It wraps an underlying CMM implementation and checks its materials +# to ensure that it is only using signed encryption algorithms. +class MPLCustomSigningSuiteOnlyCMM(ICryptographicMaterialsManager): + """Example custom crypto materials manager class.""" + + def __init__(self, keyring: IKeyring, cmm: ICryptographicMaterialsManager = None) -> None: + """Constructor for MPLCustomSigningSuiteOnlyCMM class.""" + if cmm is not None: + self.underlying_cmm = cmm + else: + mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + config=MaterialProvidersConfig() + ) + + # Create a CryptographicMaterialsManager for encryption and decryption + cmm_input: CreateDefaultCryptographicMaterialsManagerInput = \ + CreateDefaultCryptographicMaterialsManagerInput( + keyring=keyring + ) + + self.underlying_cmm: ICryptographicMaterialsManager = \ + mat_prov.create_default_cryptographic_materials_manager( + input=cmm_input + ) + + def get_encryption_materials(self, param): + """Provides encryption materials appropriate for the request for the custom CMM. + + :param aws_cryptographic_materialproviders.mpl.models.GetEncryptionMaterialsInput param: Input object to + provide to a crypto material manager's `get_encryption_materials` method. + :returns: Encryption materials output + :rtype: aws_cryptographic_materialproviders.mpl.models.GetEncryptionMaterialsOutput + """ + materials = self.underlying_cmm.get_encryption_materials(param) + if isinstance(materials.encryption_materials.algorithm_suite.signature, SignatureAlgorithmNone): + raise ValueError( + "Algorithm provided to MPLCustomSigningSuiteOnlyCMM" + + " is not a supported signing algorithm: " + str(materials.encryption_materials.algorithm_suite) + ) + return materials + + def decrypt_materials(self, param): + """Provides decryption materials appropriate for the request for the custom CMM. + + :param aws_cryptographic_materialproviders.mpl.models.DecryptMaterialsInput param: Input object to provide + to a crypto material manager's `decrypt_materials` method. + :returns: Decryption materials output + :rtype: aws_cryptographic_materialproviders.mpl.models.GetDecryptionMaterialsOutput + """ + materials = self.underlying_cmm.decrypt_materials(param) + if isinstance(materials.decryption_materials.algorithm_suite.signature, SignatureAlgorithmNone): + raise ValueError( + "Algorithm provided to MPLCustomSigningSuiteOnlyCMM" + + " is not a supported signing algorithm: " + str(materials.decryption_materials.algorithm_suite) + ) + return materials + + +EXAMPLE_DATA: bytes = b"Hello World" + + +def encrypt_decrypt_with_cmm( + cmm: ICryptographicMaterialsManager +): + """Encrypts and decrypts a string using a custom CMM. + + :param ICryptographicMaterialsManager cmm: CMM to use for encryption and decryption + """ + # Set up an encryption client with an explicit commitment policy. Note that if you do not explicitly choose a + # commitment policy, REQUIRE_ENCRYPT_REQUIRE_DECRYPT is used by default. + client = aws_encryption_sdk.EncryptionSDKClient(commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT) + + # Encrypt the plaintext source data + ciphertext, _ = client.encrypt( + source=EXAMPLE_DATA, + materials_manager=cmm + ) + + # Decrypt the ciphertext + cycled_plaintext, _ = client.decrypt( + source=ciphertext, + materials_manager=cmm + ) + + # Verify that the "cycled" (encrypted, then decrypted) plaintext is identical to the source plaintext + assert cycled_plaintext == EXAMPLE_DATA diff --git a/examples/src/default_cryptographic_materials_manager_example.py b/examples/src/default_cryptographic_materials_manager_example.py new file mode 100644 index 000000000..bfffc36d9 --- /dev/null +++ b/examples/src/default_cryptographic_materials_manager_example.py @@ -0,0 +1,133 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +""" +This example sets up the default Cryptographic Material Managers (CMM). + +The default cryptographic materials manager (CMM) assembles the cryptographic materials +that are used to encrypt and decrypt data. The cryptographic materials include +plaintext and encrypted data keys, and an optional message signing key. +This example creates a CMM and then encrypts a custom input EXAMPLE_DATA +with an encryption context. Creating a CMM involves taking a keyring as input, +and we use an AWS KMS Keyring for this example. +This example also includes some sanity checks for demonstration: +1. Ciphertext and plaintext data are not the same +2. Encryption context is correct in the decrypted message header +3. Decrypted plaintext value matches EXAMPLE_DATA +These sanity checks are for demonstration in the example only. You do not need these in your code. + +For more information on Cryptographic Material Managers, see +https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#crypt-materials-manager +""" +import sys + +import boto3 +from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig +from aws_cryptographic_materialproviders.mpl.models import ( + CreateAwsKmsKeyringInput, + CreateDefaultCryptographicMaterialsManagerInput, +) +from aws_cryptographic_materialproviders.mpl.references import ICryptographicMaterialsManager, IKeyring +from typing import Dict # noqa pylint: disable=wrong-import-order + +import aws_encryption_sdk +from aws_encryption_sdk import CommitmentPolicy + +# TODO-MPL: Remove this as part of removing PYTHONPATH hacks. +MODULE_ROOT_DIR = '/'.join(__file__.split("/")[:-1]) + +sys.path.append(MODULE_ROOT_DIR) + +EXAMPLE_DATA: bytes = b"Hello World" + + +def encrypt_and_decrypt_with_default_cmm( + kms_key_id: str +): + """Demonstrate an encrypt/decrypt cycle using default Cryptographic Material Managers. + + Usage: encrypt_and_decrypt_with_default_cmm(kms_key_id) + :param kms_key_id: KMS Key identifier for the KMS key you want to use for encryption and + decryption of your data keys. + :type kms_key_id: string + + For more information on KMS Key identifiers, see + https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id + """ + # 1. Instantiate the encryption SDK client. + # This builds the client with the REQUIRE_ENCRYPT_REQUIRE_DECRYPT commitment policy, + # which enforces that this client only encrypts using committing algorithm suites and enforces + # that this client will only decrypt encrypted messages that were created with a committing + # algorithm suite. + # This is the default commitment policy if you were to build the client as + # `client = aws_encryption_sdk.EncryptionSDKClient()`. + client = aws_encryption_sdk.EncryptionSDKClient( + commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT + ) + + # 2. Create encryption context. + # Remember that your encryption context is NOT SECRET. + # For more information, see + # https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#encryption-context + encryption_context: Dict[str, str] = { + "encryption": "context", + "is not": "secret", + "but adds": "useful metadata", + "that can help you": "be confident that", + "the data you are handling": "is what you think it is", + } + + # 3. Create a KMS keyring to use with the CryptographicMaterialsManager + kms_client = boto3.client('kms', region_name="us-west-2") + + mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + config=MaterialProvidersConfig() + ) + + keyring_input: CreateAwsKmsKeyringInput = CreateAwsKmsKeyringInput( + kms_key_id=kms_key_id, + kms_client=kms_client + ) + + kms_keyring: IKeyring = mat_prov.create_aws_kms_keyring( + input=keyring_input + ) + + # 4. Create a CryptographicMaterialsManager for encryption and decryption + cmm_input: CreateDefaultCryptographicMaterialsManagerInput = \ + CreateDefaultCryptographicMaterialsManagerInput( + keyring=kms_keyring + ) + + cmm: ICryptographicMaterialsManager = mat_prov.create_default_cryptographic_materials_manager( + input=cmm_input + ) + + # 5. Encrypt the data with the encryptionContext. + ciphertext, _ = client.encrypt( + source=EXAMPLE_DATA, + materials_manager=cmm, + encryption_context=encryption_context + ) + + # 6. Demonstrate that the ciphertext and plaintext are different. + # (This is an example for demonstration; you do not need to do this in your own code.) + assert ciphertext != EXAMPLE_DATA, \ + "Ciphertext and plaintext data are the same. Invalid encryption" + + # 7. Decrypt your encrypted data using the same cmm you used on encrypt. + plaintext_bytes, dec_header = client.decrypt( + source=ciphertext, + materials_manager=cmm + ) + + # 8. Demonstrate that the encryption context is correct in the decrypted message header + # (This is an example for demonstration; you do not need to do this in your own code.) + for k, v in encryption_context.items(): + assert v == dec_header.encryption_context[k], \ + "Encryption context does not match expected values" + + # 9. Demonstrate that the decrypted plaintext is identical to the original plaintext. + # (This is an example for demonstration; you do not need to do this in your own code.) + assert plaintext_bytes == EXAMPLE_DATA, \ + "Decrypted plaintext should be identical to the original plaintext. Invalid decryption" diff --git a/examples/src/legacy/custom_cmm_example.py b/examples/src/legacy/custom_cmm_example.py new file mode 100644 index 000000000..07e8ca50b --- /dev/null +++ b/examples/src/legacy/custom_cmm_example.py @@ -0,0 +1,87 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Example to create a custom implementation of the native ESDK CryptoMaterialsManager class.""" + +import aws_encryption_sdk +from aws_encryption_sdk import CommitmentPolicy, StrictAwsKmsMasterKeyProvider +from aws_encryption_sdk.materials_managers.base import CryptoMaterialsManager +from aws_encryption_sdk.materials_managers.default import DefaultCryptoMaterialsManager + + +# Custom CMM implementation. +# This CMM only allows encryption/decryption using signing algorithms. +# It wraps an underlying CMM implementation and checks its materials +# to ensure that it is only using signed encryption algorithms. +class CustomSigningSuiteOnlyCMM(CryptoMaterialsManager): + """Example custom crypto materials manager class.""" + + def __init__(self, master_key_provider: StrictAwsKmsMasterKeyProvider) -> None: + """Constructor for CustomSigningSuiteOnlyCMM class.""" + self.underlying_cmm = DefaultCryptoMaterialsManager(master_key_provider) + + def get_encryption_materials(self, request): + """Provides encryption materials appropriate for the request for the custom CMM. + + :param EncryptionMaterialsRequest request: Request object to provide to a + crypto material manager's `get_encryption_materials` method. + :returns: Encryption materials + :rtype: EncryptionMaterials + """ + materials = self.underlying_cmm.get_encryption_materials(request) + if not materials.algorithm.is_signing(): + raise ValueError( + "Algorithm provided to CustomSigningSuiteOnlyCMM" + + " is not a supported signing algorithm: " + materials.algorithm + ) + return materials + + def decrypt_materials(self, request): + """Provides decryption materials appropriate for the request for the custom CMM. + + :param DecryptionMaterialsRequest request: Request object to provide to a + crypto material manager's `decrypt_materials` method. + """ + if not request.algorithm.is_signing(): + raise ValueError( + "Algorithm provided to CustomSigningSuiteOnlyCMM" + + " is not a supported signing algorithm: " + request.algorithm + ) + return self.underlying_cmm.decrypt_materials(request) + + +def encrypt_decrypt_with_cmm( + cmm: CryptoMaterialsManager, + source_plaintext: str +): + """Encrypts and decrypts a string using a custom CMM. + + :param CryptoMaterialsManager cmm: CMM to use for encryption and decryption + :param bytes source_plaintext: Data to encrypt + """ + # Set up an encryption client with an explicit commitment policy. Note that if you do not explicitly choose a + # commitment policy, REQUIRE_ENCRYPT_REQUIRE_DECRYPT is used by default. + client = aws_encryption_sdk.EncryptionSDKClient(commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT) + + # Encrypt the plaintext source data + ciphertext, encryptor_header = client.encrypt( + source=source_plaintext, + materials_manager=cmm + ) + + # Decrypt the ciphertext + cycled_plaintext, decrypted_header = client.decrypt( + source=ciphertext, + materials_manager=cmm + ) + + # Verify that the "cycled" (encrypted, then decrypted) plaintext is identical to the source plaintext + assert cycled_plaintext == source_plaintext + + # Verify that the encryption context used in the decrypt operation includes all key pairs from + # the encrypt operation. (The SDK can add pairs, so don't require an exact match.) + # + # In production, always use a meaningful encryption context. In this sample, we omit the + # encryption context (no key pairs). + assert all( + pair in decrypted_header.encryption_context.items() for pair in encryptor_header.encryption_context.items() + ) diff --git a/examples/test/legacy/examples_test_utils.py b/examples/test/legacy/examples_test_utils.py index 3f877e301..8787e0f38 100644 --- a/examples/test/legacy/examples_test_utils.py +++ b/examples/test/legacy/examples_test_utils.py @@ -39,7 +39,7 @@ from integration_test_utils import ( # noqa pylint: disable=unused-import,import-error get_cmk_arn, - get_second_cmk_arn, get_mrk_arn, + get_second_cmk_arn, get_second_mrk_arn, ) diff --git a/examples/test/legacy/test_i_custom_cmm_example.py b/examples/test/legacy/test_i_custom_cmm_example.py new file mode 100644 index 000000000..397230090 --- /dev/null +++ b/examples/test/legacy/test_i_custom_cmm_example.py @@ -0,0 +1,51 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Test suite for encryption and decryption using custom CMM.""" +import botocore.session +import pytest + +import aws_encryption_sdk + +from ...src.legacy.custom_cmm_example import CustomSigningSuiteOnlyCMM, encrypt_decrypt_with_cmm +from .examples_test_utils import get_cmk_arn, static_plaintext +from .v3_default_cmm import V3DefaultCryptoMaterialsManager + +pytestmark = [pytest.mark.examples] + + +def test_custom_cmm_example(): + """Test method for encryption and decryption using V3 default CMM.""" + plaintext = static_plaintext + cmk_arn = get_cmk_arn() + botocore_session = botocore.session.Session() + + # Create a KMS master key provider. + kms_kwargs = dict(key_ids=[cmk_arn]) + if botocore_session is not None: + kms_kwargs["botocore_session"] = botocore_session + master_key_provider = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider(**kms_kwargs) + + # Create the custom signing CMM using the master_key_provider + cmm = CustomSigningSuiteOnlyCMM(master_key_provider=master_key_provider) + + encrypt_decrypt_with_cmm(cmm=cmm, + source_plaintext=plaintext) + + +def test_v3_default_cmm(): + """Test method for encryption and decryption using V3 default CMM.""" + plaintext = static_plaintext + cmk_arn = get_cmk_arn() + botocore_session = botocore.session.Session() + + # Create a KMS master key provider. + kms_kwargs = dict(key_ids=[cmk_arn]) + if botocore_session is not None: + kms_kwargs["botocore_session"] = botocore_session + master_key_provider = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider(**kms_kwargs) + + # Create the V3 default CMM (V3DefaultCryptoMaterialsManager) using the master_key_provider + cmm = V3DefaultCryptoMaterialsManager(master_key_provider=master_key_provider) + + encrypt_decrypt_with_cmm(cmm=cmm, + source_plaintext=plaintext) diff --git a/examples/test/legacy/v3_default_cmm.py b/examples/test/legacy/v3_default_cmm.py new file mode 100644 index 000000000..f077e26c9 --- /dev/null +++ b/examples/test/legacy/v3_default_cmm.py @@ -0,0 +1,159 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Copy-paste of the V3 default CMM with small changes to pass linters.""" +import logging + +import attr + +from aws_encryption_sdk.exceptions import MasterKeyProviderError, SerializationError +from aws_encryption_sdk.identifiers import CommitmentPolicy +from aws_encryption_sdk.internal.crypto.authentication import Signer, Verifier +from aws_encryption_sdk.internal.crypto.elliptic_curve import generate_ecc_signing_key +from aws_encryption_sdk.internal.defaults import ALGORITHM, ALGORITHM_COMMIT_KEY, ENCODED_SIGNER_KEY +from aws_encryption_sdk.internal.str_ops import to_str +from aws_encryption_sdk.internal.utils import prepare_data_keys +from aws_encryption_sdk.internal.utils.commitment import ( + validate_commitment_policy_on_decrypt, + validate_commitment_policy_on_encrypt, +) +from aws_encryption_sdk.key_providers.base import MasterKeyProvider +from aws_encryption_sdk.materials_managers import DecryptionMaterials, EncryptionMaterials +from aws_encryption_sdk.materials_managers.base import CryptoMaterialsManager + +_LOGGER = logging.getLogger(__name__) + + +@attr.s(hash=False) +class V3DefaultCryptoMaterialsManager(CryptoMaterialsManager): + """Copy of the default crypto material manager for ESDK V3. + + This is a copy-paste of the DefaultCryptoMaterialsManager implementation + from the V3 ESDK commit: 98b5eb7c2bd7d1b2a3380aacfa508e8721c4d8a9 + This CMM is used to explicitly assert that the V3 implementation of + the DefaultCMM is compatible with future version's logic, + which implicitly asserts that custom implementations of V3-compatible CMMs + are also compatible with future version's logic. + + :param master_key_provider: Master key provider to use + :type master_key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider + """ + + master_key_provider = attr.ib(validator=attr.validators.instance_of(MasterKeyProvider)) + +# pylint: disable=no-self-use + def _generate_signing_key_and_update_encryption_context(self, algorithm, encryption_context): + """Generates a signing key based on the provided algorithm. + + :param algorithm: Algorithm for which to generate signing key + :type algorithm: aws_encryption_sdk.identifiers.Algorithm + :param dict encryption_context: Encryption context from request + :returns: Signing key bytes + :rtype: bytes or None + """ + _LOGGER.debug("Generating signing key") + if algorithm.signing_algorithm_info is None: + return None + + signer = Signer(algorithm=algorithm, key=generate_ecc_signing_key(algorithm=algorithm)) + encryption_context[ENCODED_SIGNER_KEY] = to_str(signer.encoded_public_key()) + return signer.key_bytes() + + def get_encryption_materials(self, request): + """Creates encryption materials using underlying master key provider. + + :param request: encryption materials request + :type request: aws_encryption_sdk.materials_managers.EncryptionMaterialsRequest + :returns: encryption materials + :rtype: aws_encryption_sdk.materials_managers.EncryptionMaterials + :raises MasterKeyProviderError: if no master keys are available from the underlying master key provider + :raises MasterKeyProviderError: if the primary master key provided by the underlying master key provider + is not included in the full set of master keys provided by that provider + :raises ActionNotAllowedError: if the commitment policy in the request is violated by the algorithm being + used + """ + default_algorithm = ALGORITHM + if request.commitment_policy in ( + CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT, + CommitmentPolicy.REQUIRE_ENCRYPT_ALLOW_DECRYPT, + ): + default_algorithm = ALGORITHM_COMMIT_KEY + algorithm = request.algorithm if request.algorithm is not None else default_algorithm + + validate_commitment_policy_on_encrypt(request.commitment_policy, request.algorithm) + + encryption_context = request.encryption_context.copy() + + signing_key = self._generate_signing_key_and_update_encryption_context(algorithm, encryption_context) + + primary_master_key, master_keys = self.master_key_provider.master_keys_for_encryption( + encryption_context=encryption_context, + plaintext_rostream=request.plaintext_rostream, + plaintext_length=request.plaintext_length, + ) + if not master_keys: + raise MasterKeyProviderError("No Master Keys available from Master Key Provider") + if primary_master_key not in master_keys: + raise MasterKeyProviderError("Primary Master Key not in provided Master Keys") + + data_encryption_key, encrypted_data_keys = prepare_data_keys( + primary_master_key=primary_master_key, + master_keys=master_keys, + algorithm=algorithm, + encryption_context=encryption_context, + ) + + _LOGGER.debug("Post-encrypt encryption context: %s", encryption_context) + + return EncryptionMaterials( + algorithm=algorithm, + data_encryption_key=data_encryption_key, + encrypted_data_keys=encrypted_data_keys, + encryption_context=encryption_context, + signing_key=signing_key, + ) + +# pylint: disable=no-self-use + def _load_verification_key_from_encryption_context(self, algorithm, encryption_context): + """Loads the verification key from the encryption context if used by algorithm suite. + + :param algorithm: Algorithm for which to generate signing key + :type algorithm: aws_encryption_sdk.identifiers.Algorithm + :param dict encryption_context: Encryption context from request + :returns: Raw verification key + :rtype: bytes + :raises SerializationError: if algorithm suite requires message signing and no verification key is found + """ + encoded_verification_key = encryption_context.get(ENCODED_SIGNER_KEY, None) + + if algorithm.signing_algorithm_info is not None and encoded_verification_key is None: + raise SerializationError("No signature verification key found in header for signed algorithm.") + + if algorithm.signing_algorithm_info is None: + if encoded_verification_key is not None: + raise SerializationError("Signature verification key found in header for non-signed algorithm.") + return None + + verifier = Verifier.from_encoded_point(algorithm=algorithm, encoded_point=encoded_verification_key) + return verifier.key_bytes() + + def decrypt_materials(self, request): + """Obtains a plaintext data key from one or more encrypted data keys + using underlying master key provider. + + :param request: decrypt materials request + :type request: aws_encryption_sdk.materials_managers.DecryptionMaterialsRequest + :returns: decryption materials + :rtype: aws_encryption_sdk.materials_managers.DecryptionMaterials + """ + validate_commitment_policy_on_decrypt(request.commitment_policy, request.algorithm) + + data_key = self.master_key_provider.decrypt_data_key_from_list( + encrypted_data_keys=request.encrypted_data_keys, + algorithm=request.algorithm, + encryption_context=request.encryption_context, + ) + verification_key = self._load_verification_key_from_encryption_context( + algorithm=request.algorithm, encryption_context=request.encryption_context + ) + + return DecryptionMaterials(data_key=data_key, verification_key=verification_key) diff --git a/examples/test/migration/test_i_migration_aws_kms_key_example.py b/examples/test/migration/test_i_migration_aws_kms_key_example.py index d4cf49ce9..612a896ba 100644 --- a/examples/test/migration/test_i_migration_aws_kms_key_example.py +++ b/examples/test/migration/test_i_migration_aws_kms_key_example.py @@ -3,9 +3,7 @@ """Test suite for the migration_aws_kms_key_example.""" import pytest -from ...src.migration.migration_aws_kms_key_example import ( - migration_aws_kms_key, -) +from ...src.migration.migration_aws_kms_key_example import migration_aws_kms_key pytestmark = [pytest.mark.examples] diff --git a/examples/test/migration/test_i_migration_raw_aes_key_example.py b/examples/test/migration/test_i_migration_raw_aes_key_example.py index 7601e7dc0..d5e4f7789 100644 --- a/examples/test/migration/test_i_migration_raw_aes_key_example.py +++ b/examples/test/migration/test_i_migration_raw_aes_key_example.py @@ -3,9 +3,7 @@ """Test suite for the migration_raw_aes_key_example.""" import pytest -from ...src.migration.migration_raw_aes_key_example import ( - migration_raw_aes_key, -) +from ...src.migration.migration_raw_aes_key_example import migration_raw_aes_key pytestmark = [pytest.mark.examples] diff --git a/examples/test/migration/test_i_migration_raw_rsa_key_example.py b/examples/test/migration/test_i_migration_raw_rsa_key_example.py index 9e111d25a..238dcbaab 100644 --- a/examples/test/migration/test_i_migration_raw_rsa_key_example.py +++ b/examples/test/migration/test_i_migration_raw_rsa_key_example.py @@ -3,9 +3,7 @@ """Test suite for the migration_raw_rsa_key_example.""" import pytest -from ...src.migration.migration_raw_rsa_key_example import ( - migration_raw_rsa_key, -) +from ...src.migration.migration_raw_rsa_key_example import migration_raw_rsa_key pytestmark = [pytest.mark.examples] diff --git a/examples/test/test_i_custom_mpl_cmm_example.py b/examples/test/test_i_custom_mpl_cmm_example.py new file mode 100644 index 000000000..d98b6b6b9 --- /dev/null +++ b/examples/test/test_i_custom_mpl_cmm_example.py @@ -0,0 +1,39 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Test suite for encryption and decryption using custom CMM.""" +import boto3 +import pytest +from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig +from aws_cryptographic_materialproviders.mpl.models import CreateAwsKmsKeyringInput +from aws_cryptographic_materialproviders.mpl.references import IKeyring + +from ..src.custom_mpl_cmm_example import MPLCustomSigningSuiteOnlyCMM, encrypt_decrypt_with_cmm + +pytestmark = [pytest.mark.examples] + + +def test_custom_cmm_example(): + """Test method for encryption and decryption using V3 default CMM.""" + kms_key_id = "arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f" + + # Create KMS keyring to use with the CMM + kms_client = boto3.client('kms', region_name="us-west-2") + + mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + config=MaterialProvidersConfig() + ) + + keyring_input: CreateAwsKmsKeyringInput = CreateAwsKmsKeyringInput( + kms_key_id=kms_key_id, + kms_client=kms_client + ) + + kms_keyring: IKeyring = mat_prov.create_aws_kms_keyring( + input=keyring_input + ) + + # Create the custom MPL signing CMM using the keyring + cmm = MPLCustomSigningSuiteOnlyCMM(keyring=kms_keyring) + + encrypt_decrypt_with_cmm(cmm=cmm) diff --git a/examples/test/test_i_default_cryptographic_materials_manager_example.py b/examples/test/test_i_default_cryptographic_materials_manager_example.py new file mode 100644 index 000000000..8a18f655d --- /dev/null +++ b/examples/test/test_i_default_cryptographic_materials_manager_example.py @@ -0,0 +1,14 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Test suite for the default Cryptographic Materials Manager example.""" +import pytest + +from ..src.default_cryptographic_materials_manager_example import encrypt_and_decrypt_with_default_cmm + +pytestmark = [pytest.mark.examples] + + +def test_encrypt_and_decrypt_with_default_cmm(): + """Test function for encrypt and decrypt using the default Cryptographic Materials Manager example.""" + kms_key_id = "arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f" + encrypt_and_decrypt_with_default_cmm(kms_key_id) diff --git a/tox.ini b/tox.ini index 9152f51a6..28be94a63 100644 --- a/tox.ini +++ b/tox.ini @@ -169,10 +169,12 @@ deps = {[testenv:flake8]deps} commands = flake8 examples/src/ flake8 \ - # Ingore D103 missing docstring errors in tests (test names should be self-documenting) + # Ignore D103 missing docstring errors in tests (test names should be self-documenting) # E203 is not PEP8 compliant https://github.com/ambv/black#slices # W503 is not PEP8 compliant https://github.com/ambv/black#line-breaks--binary-operators --ignore D103,E203,W503 \ + # copy-paste test for v3_default_cmm; intentionally not changing code + --per-file-ignores 'examples/test/legacy/v3_default_cmm.py: D205,D400,D401' \ examples/test/ [testenv:pylint] From fe6af09fd71cfde92e8189949c371d1b0c98bb4c Mon Sep 17 00:00:00 2001 From: Ritvik Kapila Date: Wed, 26 Jun 2024 14:59:30 -0700 Subject: [PATCH 05/18] chore(multi-threaded examples: Added keyring examples --- examples/test/multithreaded/__init__.py | 3 +++ ...i_raw_aes_keyring_multithreaded_example.py | 23 +++++++++++++++++++ ...i_raw_rsa_keyring_multithreaded_example.py | 23 +++++++++++++++++++ 3 files changed, 49 insertions(+) create mode 100644 examples/test/multithreaded/__init__.py create mode 100644 examples/test/multithreaded/test_i_raw_aes_keyring_multithreaded_example.py create mode 100644 examples/test/multithreaded/test_i_raw_rsa_keyring_multithreaded_example.py diff --git a/examples/test/multithreaded/__init__.py b/examples/test/multithreaded/__init__.py new file mode 100644 index 000000000..120179eda --- /dev/null +++ b/examples/test/multithreaded/__init__.py @@ -0,0 +1,3 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Stub module indicator to make linter configuration simpler.""" diff --git a/examples/test/multithreaded/test_i_raw_aes_keyring_multithreaded_example.py b/examples/test/multithreaded/test_i_raw_aes_keyring_multithreaded_example.py new file mode 100644 index 000000000..b88f55d97 --- /dev/null +++ b/examples/test/multithreaded/test_i_raw_aes_keyring_multithreaded_example.py @@ -0,0 +1,23 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Test suite for the Raw AES keyring example with multi-threading.""" +from concurrent.futures import ThreadPoolExecutor, as_completed +import pytest + +from ...src.raw_aes_keyring_example import encrypt_and_decrypt_with_keyring + +pytestmark = [pytest.mark.examples] + + +def test_encrypt_and_decrypt_with_keyring(n_threads=10): + """Test function for multi-threaded encrypt and decrypt using the Raw AES Keyring example.""" + with ThreadPoolExecutor(max_workers=n_threads) as executor: + thread_futures = {executor.submit(encrypt_and_decrypt_with_keyring): i for i in range(n_threads)} + + for future in as_completed(thread_futures): + thread_id = thread_futures[future] + try: + result = future.result() + print(f"Thread {thread_id} passed with result: {result}") + except Exception as e: + raise e diff --git a/examples/test/multithreaded/test_i_raw_rsa_keyring_multithreaded_example.py b/examples/test/multithreaded/test_i_raw_rsa_keyring_multithreaded_example.py new file mode 100644 index 000000000..cb3368d86 --- /dev/null +++ b/examples/test/multithreaded/test_i_raw_rsa_keyring_multithreaded_example.py @@ -0,0 +1,23 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Test suite for the Raw RSA keyring example with multi-threading.""" +from concurrent.futures import ThreadPoolExecutor, as_completed +import pytest + +from ...src.raw_rsa_keyring_example import encrypt_and_decrypt_with_keyring + +pytestmark = [pytest.mark.examples] + + +def test_encrypt_and_decrypt_with_keyring(n_threads=10): + """Test function for multi-threaded encrypt and decrypt using the Raw RSA Keyring example.""" + with ThreadPoolExecutor(max_workers=n_threads) as executor: + thread_futures = {executor.submit(encrypt_and_decrypt_with_keyring): i for i in range(n_threads)} + + for future in as_completed(thread_futures): + thread_id = thread_futures[future] + try: + result = future.result() + print(f"Thread {thread_id} passed with result: {result}") + except Exception as e: + raise e From ebb7c2cfe509b605bf6ab8d9403ff13225dfdbc7 Mon Sep 17 00:00:00 2001 From: Ritvik Kapila Date: Wed, 26 Jun 2024 15:14:51 -0700 Subject: [PATCH 06/18] remove print statements --- .../test_i_raw_aes_keyring_multithreaded_example.py | 8 ++------ .../test_i_raw_rsa_keyring_multithreaded_example.py | 8 ++------ 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/examples/test/multithreaded/test_i_raw_aes_keyring_multithreaded_example.py b/examples/test/multithreaded/test_i_raw_aes_keyring_multithreaded_example.py index b88f55d97..0760028f2 100644 --- a/examples/test/multithreaded/test_i_raw_aes_keyring_multithreaded_example.py +++ b/examples/test/multithreaded/test_i_raw_aes_keyring_multithreaded_example.py @@ -2,6 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 """Test suite for the Raw AES keyring example with multi-threading.""" from concurrent.futures import ThreadPoolExecutor, as_completed + import pytest from ...src.raw_aes_keyring_example import encrypt_and_decrypt_with_keyring @@ -15,9 +16,4 @@ def test_encrypt_and_decrypt_with_keyring(n_threads=10): thread_futures = {executor.submit(encrypt_and_decrypt_with_keyring): i for i in range(n_threads)} for future in as_completed(thread_futures): - thread_id = thread_futures[future] - try: - result = future.result() - print(f"Thread {thread_id} passed with result: {result}") - except Exception as e: - raise e + future.result() diff --git a/examples/test/multithreaded/test_i_raw_rsa_keyring_multithreaded_example.py b/examples/test/multithreaded/test_i_raw_rsa_keyring_multithreaded_example.py index cb3368d86..0eb247d7b 100644 --- a/examples/test/multithreaded/test_i_raw_rsa_keyring_multithreaded_example.py +++ b/examples/test/multithreaded/test_i_raw_rsa_keyring_multithreaded_example.py @@ -2,6 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 """Test suite for the Raw RSA keyring example with multi-threading.""" from concurrent.futures import ThreadPoolExecutor, as_completed + import pytest from ...src.raw_rsa_keyring_example import encrypt_and_decrypt_with_keyring @@ -15,9 +16,4 @@ def test_encrypt_and_decrypt_with_keyring(n_threads=10): thread_futures = {executor.submit(encrypt_and_decrypt_with_keyring): i for i in range(n_threads)} for future in as_completed(thread_futures): - thread_id = thread_futures[future] - try: - result = future.result() - print(f"Thread {thread_id} passed with result: {result}") - except Exception as e: - raise e + future.result() From d1a650070dd037686861ab1965857154366100f4 Mon Sep 17 00:00:00 2001 From: Ritvik Kapila Date: Wed, 26 Jun 2024 16:41:04 -0700 Subject: [PATCH 07/18] refactoring --- examples/src/multithreading/__init__.py | 45 ++++++++++++ .../src/multithreading/raw_aes_keyring.py | 37 ++++++++++ .../src/multithreading/raw_rsa_keyring.py | 73 +++++++++++++++++++ ...i_raw_aes_keyring_multithreaded_example.py | 19 ----- ...i_raw_rsa_keyring_multithreaded_example.py | 19 ----- .../__init__.py | 0 ...i_raw_aes_keyring_multithreaded_example.py | 33 +++++++++ ...i_raw_rsa_keyring_multithreaded_example.py | 33 +++++++++ 8 files changed, 221 insertions(+), 38 deletions(-) create mode 100644 examples/src/multithreading/__init__.py create mode 100644 examples/src/multithreading/raw_aes_keyring.py create mode 100644 examples/src/multithreading/raw_rsa_keyring.py delete mode 100644 examples/test/multithreaded/test_i_raw_aes_keyring_multithreaded_example.py delete mode 100644 examples/test/multithreaded/test_i_raw_rsa_keyring_multithreaded_example.py rename examples/test/{multithreaded => multithreading}/__init__.py (100%) create mode 100644 examples/test/multithreading/test_i_raw_aes_keyring_multithreaded_example.py create mode 100644 examples/test/multithreading/test_i_raw_rsa_keyring_multithreaded_example.py diff --git a/examples/src/multithreading/__init__.py b/examples/src/multithreading/__init__.py new file mode 100644 index 000000000..cb53f5c10 --- /dev/null +++ b/examples/src/multithreading/__init__.py @@ -0,0 +1,45 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""init file for multi-threading examples.""" +import aws_encryption_sdk +from aws_cryptographic_materialproviders.mpl.references import IKeyring +from typing import Dict # noqa pylint: disable=wrong-import-order + + +def encrypt_and_decrypt_with_keyring( + plaintext_data: bytes, + keyring: IKeyring, + esdk_client: aws_encryption_sdk.EncryptionSDKClient +): + """encrypt_and_decrypt_with_keyring how to encrypt plaintext data using a Raw AES keyring. + + Usage: encrypt_and_decrypt_with_keyring(plaintext_data, keyring, esdk_client) + :param plaintext_data: plaintext data you want to encrypt + :type: bytes + :param keyring: Keyring to use for encryption. + :type keyring: IKeyring + :param esdk_client: The Encryption SDK client to use for encryption. + :type esdk_client: aws_encryption_sdk.EncryptionSDKClient + :return: encrypted and decrypted (cycled) plaintext data + :rtype: bytes + """ + encryption_context: Dict[str, str] = { + "encryption": "context", + "is not": "secret", + "but adds": "useful metadata", + "that can help you": "be confident that", + "the data you are handling": "is what you think it is", + } + + ciphertext_data, _ = esdk_client.encrypt( + source=plaintext_data, + keyring=keyring, + encryption_context=encryption_context + ) + + decrypted_plaintext_data, _ = esdk_client.decrypt( + source=ciphertext_data, + keyring=keyring + ) + + return decrypted_plaintext_data diff --git a/examples/src/multithreading/raw_aes_keyring.py b/examples/src/multithreading/raw_aes_keyring.py new file mode 100644 index 000000000..8abacdc85 --- /dev/null +++ b/examples/src/multithreading/raw_aes_keyring.py @@ -0,0 +1,37 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""This file contains methdos to use for the multi-threaded Raw AES keyring.""" + +from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig +from aws_cryptographic_materialproviders.mpl.models import AesWrappingAlg, CreateRawAesKeyringInput +from aws_cryptographic_materialproviders.mpl.references import IKeyring +import secrets + + +def create_keyring(): + """Demonstrate how to create a Raw AES keyring. + + Usage: create_keyring() + """ + key_name_space = "Some managed raw keys" + key_name = "My 256-bit AES wrapping key" + + static_key = secrets.token_bytes(32) + + mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + config=MaterialProvidersConfig() + ) + + keyring_input: CreateRawAesKeyringInput = CreateRawAesKeyringInput( + key_namespace=key_name_space, + key_name=key_name, + wrapping_key=static_key, + wrapping_alg=AesWrappingAlg.ALG_AES256_GCM_IV12_TAG16 + ) + + keyring: IKeyring = mat_prov.create_raw_aes_keyring( + input=keyring_input + ) + + return keyring diff --git a/examples/src/multithreading/raw_rsa_keyring.py b/examples/src/multithreading/raw_rsa_keyring.py new file mode 100644 index 000000000..de56e2da1 --- /dev/null +++ b/examples/src/multithreading/raw_rsa_keyring.py @@ -0,0 +1,73 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""This file contains methdos to use for the multi-threaded Raw RSA keyring.""" +from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig +from aws_cryptographic_materialproviders.mpl.models import CreateRawRsaKeyringInput, PaddingScheme +from aws_cryptographic_materialproviders.mpl.references import IKeyring + + +from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig +from aws_cryptographic_materialproviders.mpl.models import CreateRawRsaKeyringInput, PaddingScheme +from aws_cryptographic_materialproviders.mpl.references import IKeyring +from cryptography.hazmat.backends import default_backend as crypto_default_backend +from cryptography.hazmat.primitives import serialization as crypto_serialization +from cryptography.hazmat.primitives.asymmetric import rsa +from typing import Dict # noqa pylint: disable=wrong-import-order + + +def generate_rsa_keys(): + """Generates a 4096-bit RSA public and private key pair + + Usage: generate_rsa_keys() + """ + ssh_rsa_exponent = 65537 + bit_strength = 4096 + key = rsa.generate_private_key( + backend=crypto_default_backend(), + public_exponent=ssh_rsa_exponent, + key_size=bit_strength + ) + + # This example choses a particular type of encoding, format and encryption_algorithm + # Users can choose the PublicFormat, PrivateFormat and encryption_algorithm that align most + # with their use-cases + public_key = key.public_key().public_bytes( + encoding=crypto_serialization.Encoding.PEM, + format=crypto_serialization.PublicFormat.SubjectPublicKeyInfo + ) + private_key = key.private_bytes( + encoding=crypto_serialization.Encoding.PEM, + format=crypto_serialization.PrivateFormat.TraditionalOpenSSL, + encryption_algorithm=crypto_serialization.NoEncryption() + ) + + return public_key, private_key + + +def create_keyring(public_key, private_key): + """Demonstrate how to create a Raw RSA keyring using the key pair. + + Usage: create_keyring(public_key, private_key) + """ + key_name_space = "Some managed raw keys" + key_name = "My 4096-bit RSA wrapping key" + + mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + config=MaterialProvidersConfig() + ) + + keyring_input: CreateRawRsaKeyringInput = CreateRawRsaKeyringInput( + key_namespace=key_name_space, + key_name=key_name, + padding_scheme=PaddingScheme.OAEP_SHA256_MGF1, + public_key=public_key, + private_key=private_key + ) + + keyring: IKeyring = mat_prov.create_raw_rsa_keyring( + input=keyring_input + ) + + return keyring diff --git a/examples/test/multithreaded/test_i_raw_aes_keyring_multithreaded_example.py b/examples/test/multithreaded/test_i_raw_aes_keyring_multithreaded_example.py deleted file mode 100644 index 0760028f2..000000000 --- a/examples/test/multithreaded/test_i_raw_aes_keyring_multithreaded_example.py +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. -# SPDX-License-Identifier: Apache-2.0 -"""Test suite for the Raw AES keyring example with multi-threading.""" -from concurrent.futures import ThreadPoolExecutor, as_completed - -import pytest - -from ...src.raw_aes_keyring_example import encrypt_and_decrypt_with_keyring - -pytestmark = [pytest.mark.examples] - - -def test_encrypt_and_decrypt_with_keyring(n_threads=10): - """Test function for multi-threaded encrypt and decrypt using the Raw AES Keyring example.""" - with ThreadPoolExecutor(max_workers=n_threads) as executor: - thread_futures = {executor.submit(encrypt_and_decrypt_with_keyring): i for i in range(n_threads)} - - for future in as_completed(thread_futures): - future.result() diff --git a/examples/test/multithreaded/test_i_raw_rsa_keyring_multithreaded_example.py b/examples/test/multithreaded/test_i_raw_rsa_keyring_multithreaded_example.py deleted file mode 100644 index 0eb247d7b..000000000 --- a/examples/test/multithreaded/test_i_raw_rsa_keyring_multithreaded_example.py +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. -# SPDX-License-Identifier: Apache-2.0 -"""Test suite for the Raw RSA keyring example with multi-threading.""" -from concurrent.futures import ThreadPoolExecutor, as_completed - -import pytest - -from ...src.raw_rsa_keyring_example import encrypt_and_decrypt_with_keyring - -pytestmark = [pytest.mark.examples] - - -def test_encrypt_and_decrypt_with_keyring(n_threads=10): - """Test function for multi-threaded encrypt and decrypt using the Raw RSA Keyring example.""" - with ThreadPoolExecutor(max_workers=n_threads) as executor: - thread_futures = {executor.submit(encrypt_and_decrypt_with_keyring): i for i in range(n_threads)} - - for future in as_completed(thread_futures): - future.result() diff --git a/examples/test/multithreaded/__init__.py b/examples/test/multithreading/__init__.py similarity index 100% rename from examples/test/multithreaded/__init__.py rename to examples/test/multithreading/__init__.py diff --git a/examples/test/multithreading/test_i_raw_aes_keyring_multithreaded_example.py b/examples/test/multithreading/test_i_raw_aes_keyring_multithreaded_example.py new file mode 100644 index 000000000..49dcb1058 --- /dev/null +++ b/examples/test/multithreading/test_i_raw_aes_keyring_multithreaded_example.py @@ -0,0 +1,33 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Test suite for the Raw AES keyring example with multi-threading.""" +from concurrent.futures import ThreadPoolExecutor, as_completed + +import pytest + +from ...src.multithreading.raw_aes_keyring import create_keyring +from ...src.multithreading import encrypt_and_decrypt_with_keyring + +import aws_encryption_sdk +from aws_encryption_sdk import CommitmentPolicy +pytestmark = [pytest.mark.examples] + + +def test_encrypt_and_decrypt_with_keyring(n_threads=10): + """Test function for multi-threaded encrypt and decrypt using the Raw AES Keyring example.""" + keyring = create_keyring() + plaintext_data = b"Hello World" + esdk_client = aws_encryption_sdk.EncryptionSDKClient( + commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT + ) + + with ThreadPoolExecutor(max_workers=n_threads) as executor: + thread_futures = {executor.submit(encrypt_and_decrypt_with_keyring, + plaintext_data=plaintext_data, + keyring=keyring, + esdk_client=esdk_client): i for i in range(n_threads)} + + for future in as_completed(thread_futures): + decrypted_plaintext_data = future.result() + assert decrypted_plaintext_data == plaintext_data, \ + "Decrypted plaintext should be identical to the original plaintext. Invalid decryption" diff --git a/examples/test/multithreading/test_i_raw_rsa_keyring_multithreaded_example.py b/examples/test/multithreading/test_i_raw_rsa_keyring_multithreaded_example.py new file mode 100644 index 000000000..cd49e569b --- /dev/null +++ b/examples/test/multithreading/test_i_raw_rsa_keyring_multithreaded_example.py @@ -0,0 +1,33 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Test suite for the Raw RSA keyring example with multi-threading.""" +from concurrent.futures import ThreadPoolExecutor, as_completed + +import pytest +from ...src.multithreading.raw_rsa_keyring import generate_rsa_keys, create_keyring +from ...src.multithreading import encrypt_and_decrypt_with_keyring +import aws_encryption_sdk +from aws_encryption_sdk import CommitmentPolicy + +pytestmark = [pytest.mark.examples] + + +def test_encrypt_and_decrypt_with_keyring(n_threads=10): + """Test function for multi-threaded encrypt and decrypt using the Raw RSA Keyring example.""" + public_key, private_key = generate_rsa_keys() + keyring = create_keyring(public_key=public_key, private_key=private_key) + plaintext_data = b"Hello World" + esdk_client = aws_encryption_sdk.EncryptionSDKClient( + commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT + ) + + with ThreadPoolExecutor(max_workers=n_threads) as executor: + thread_futures = {executor.submit(encrypt_and_decrypt_with_keyring, + plaintext_data=plaintext_data, + keyring=keyring, + esdk_client=esdk_client): i for i in range(n_threads)} + + for future in as_completed(thread_futures): + decrypted_plaintext_data = future.result() + assert decrypted_plaintext_data == plaintext_data, \ + "Decrypted plaintext should be identical to the original plaintext. Invalid decryption" From f14eaa08d1f237dd56a858373a514835f4c2aae8 Mon Sep 17 00:00:00 2001 From: Ritvik Kapila Date: Wed, 26 Jun 2024 16:42:03 -0700 Subject: [PATCH 08/18] fix --- examples/src/multithreading/__init__.py | 3 ++- examples/src/multithreading/raw_aes_keyring.py | 3 ++- examples/src/multithreading/raw_rsa_keyring.py | 6 ------ .../test_i_raw_aes_keyring_multithreaded_example.py | 7 ++++--- .../test_i_raw_rsa_keyring_multithreaded_example.py | 6 ++++-- 5 files changed, 12 insertions(+), 13 deletions(-) diff --git a/examples/src/multithreading/__init__.py b/examples/src/multithreading/__init__.py index cb53f5c10..34e837b8b 100644 --- a/examples/src/multithreading/__init__.py +++ b/examples/src/multithreading/__init__.py @@ -1,10 +1,11 @@ # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0 """init file for multi-threading examples.""" -import aws_encryption_sdk from aws_cryptographic_materialproviders.mpl.references import IKeyring from typing import Dict # noqa pylint: disable=wrong-import-order +import aws_encryption_sdk + def encrypt_and_decrypt_with_keyring( plaintext_data: bytes, diff --git a/examples/src/multithreading/raw_aes_keyring.py b/examples/src/multithreading/raw_aes_keyring.py index 8abacdc85..4216bb875 100644 --- a/examples/src/multithreading/raw_aes_keyring.py +++ b/examples/src/multithreading/raw_aes_keyring.py @@ -2,11 +2,12 @@ # SPDX-License-Identifier: Apache-2.0 """This file contains methdos to use for the multi-threaded Raw AES keyring.""" +import secrets + from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig from aws_cryptographic_materialproviders.mpl.models import AesWrappingAlg, CreateRawAesKeyringInput from aws_cryptographic_materialproviders.mpl.references import IKeyring -import secrets def create_keyring(): diff --git a/examples/src/multithreading/raw_rsa_keyring.py b/examples/src/multithreading/raw_rsa_keyring.py index de56e2da1..184519c11 100644 --- a/examples/src/multithreading/raw_rsa_keyring.py +++ b/examples/src/multithreading/raw_rsa_keyring.py @@ -1,12 +1,6 @@ # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0 """This file contains methdos to use for the multi-threaded Raw RSA keyring.""" -from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders -from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig -from aws_cryptographic_materialproviders.mpl.models import CreateRawRsaKeyringInput, PaddingScheme -from aws_cryptographic_materialproviders.mpl.references import IKeyring - - from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig from aws_cryptographic_materialproviders.mpl.models import CreateRawRsaKeyringInput, PaddingScheme diff --git a/examples/test/multithreading/test_i_raw_aes_keyring_multithreaded_example.py b/examples/test/multithreading/test_i_raw_aes_keyring_multithreaded_example.py index 49dcb1058..2f496d18c 100644 --- a/examples/test/multithreading/test_i_raw_aes_keyring_multithreaded_example.py +++ b/examples/test/multithreading/test_i_raw_aes_keyring_multithreaded_example.py @@ -5,11 +5,12 @@ import pytest -from ...src.multithreading.raw_aes_keyring import create_keyring -from ...src.multithreading import encrypt_and_decrypt_with_keyring - import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy + +from ...src.multithreading import encrypt_and_decrypt_with_keyring +from ...src.multithreading.raw_aes_keyring import create_keyring + pytestmark = [pytest.mark.examples] diff --git a/examples/test/multithreading/test_i_raw_rsa_keyring_multithreaded_example.py b/examples/test/multithreading/test_i_raw_rsa_keyring_multithreaded_example.py index cd49e569b..b999129c5 100644 --- a/examples/test/multithreading/test_i_raw_rsa_keyring_multithreaded_example.py +++ b/examples/test/multithreading/test_i_raw_rsa_keyring_multithreaded_example.py @@ -4,11 +4,13 @@ from concurrent.futures import ThreadPoolExecutor, as_completed import pytest -from ...src.multithreading.raw_rsa_keyring import generate_rsa_keys, create_keyring -from ...src.multithreading import encrypt_and_decrypt_with_keyring + import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy +from ...src.multithreading import encrypt_and_decrypt_with_keyring +from ...src.multithreading.raw_rsa_keyring import create_keyring, generate_rsa_keys + pytestmark = [pytest.mark.examples] From 01551829bb97cce76ceeb05ea2cf080492b6916b Mon Sep 17 00:00:00 2001 From: Ritvik Kapila Date: Wed, 26 Jun 2024 16:47:02 -0700 Subject: [PATCH 09/18] minor fix --- examples/src/multithreading/__init__.py | 14 +++++++------- examples/src/multithreading/raw_aes_keyring.py | 2 +- examples/src/multithreading/raw_rsa_keyring.py | 2 +- ...test_i_raw_aes_keyring_multithreaded_example.py | 4 ++-- ...test_i_raw_rsa_keyring_multithreaded_example.py | 4 ++-- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/examples/src/multithreading/__init__.py b/examples/src/multithreading/__init__.py index 34e837b8b..3afc55898 100644 --- a/examples/src/multithreading/__init__.py +++ b/examples/src/multithreading/__init__.py @@ -10,17 +10,17 @@ def encrypt_and_decrypt_with_keyring( plaintext_data: bytes, keyring: IKeyring, - esdk_client: aws_encryption_sdk.EncryptionSDKClient + client: aws_encryption_sdk.EncryptionSDKClient ): - """encrypt_and_decrypt_with_keyring how to encrypt plaintext data using a Raw AES keyring. + """Demonstrate how to encrypt and decrypt plaintext data using a keyring. - Usage: encrypt_and_decrypt_with_keyring(plaintext_data, keyring, esdk_client) + Usage: encrypt_and_decrypt_with_keyring(plaintext_data, keyring, client) :param plaintext_data: plaintext data you want to encrypt :type: bytes :param keyring: Keyring to use for encryption. :type keyring: IKeyring - :param esdk_client: The Encryption SDK client to use for encryption. - :type esdk_client: aws_encryption_sdk.EncryptionSDKClient + :param client: The Encryption SDK client to use for encryption. + :type client: aws_encryption_sdk.EncryptionSDKClient :return: encrypted and decrypted (cycled) plaintext data :rtype: bytes """ @@ -32,13 +32,13 @@ def encrypt_and_decrypt_with_keyring( "the data you are handling": "is what you think it is", } - ciphertext_data, _ = esdk_client.encrypt( + ciphertext_data, _ = client.encrypt( source=plaintext_data, keyring=keyring, encryption_context=encryption_context ) - decrypted_plaintext_data, _ = esdk_client.decrypt( + decrypted_plaintext_data, _ = client.decrypt( source=ciphertext_data, keyring=keyring ) diff --git a/examples/src/multithreading/raw_aes_keyring.py b/examples/src/multithreading/raw_aes_keyring.py index 4216bb875..42a391344 100644 --- a/examples/src/multithreading/raw_aes_keyring.py +++ b/examples/src/multithreading/raw_aes_keyring.py @@ -1,6 +1,6 @@ # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0 -"""This file contains methdos to use for the multi-threaded Raw AES keyring.""" +"""This file contains methods to use for testing multi-threading for Raw AES keyring.""" import secrets diff --git a/examples/src/multithreading/raw_rsa_keyring.py b/examples/src/multithreading/raw_rsa_keyring.py index 184519c11..1d63c1f9c 100644 --- a/examples/src/multithreading/raw_rsa_keyring.py +++ b/examples/src/multithreading/raw_rsa_keyring.py @@ -1,6 +1,6 @@ # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0 -"""This file contains methdos to use for the multi-threaded Raw RSA keyring.""" +"""This file contains methods to use for testing multi-threading for Raw RSA keyring.""" from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig from aws_cryptographic_materialproviders.mpl.models import CreateRawRsaKeyringInput, PaddingScheme diff --git a/examples/test/multithreading/test_i_raw_aes_keyring_multithreaded_example.py b/examples/test/multithreading/test_i_raw_aes_keyring_multithreaded_example.py index 2f496d18c..a3bb6ae1e 100644 --- a/examples/test/multithreading/test_i_raw_aes_keyring_multithreaded_example.py +++ b/examples/test/multithreading/test_i_raw_aes_keyring_multithreaded_example.py @@ -18,7 +18,7 @@ def test_encrypt_and_decrypt_with_keyring(n_threads=10): """Test function for multi-threaded encrypt and decrypt using the Raw AES Keyring example.""" keyring = create_keyring() plaintext_data = b"Hello World" - esdk_client = aws_encryption_sdk.EncryptionSDKClient( + client = aws_encryption_sdk.EncryptionSDKClient( commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT ) @@ -26,7 +26,7 @@ def test_encrypt_and_decrypt_with_keyring(n_threads=10): thread_futures = {executor.submit(encrypt_and_decrypt_with_keyring, plaintext_data=plaintext_data, keyring=keyring, - esdk_client=esdk_client): i for i in range(n_threads)} + client=client): i for i in range(n_threads)} for future in as_completed(thread_futures): decrypted_plaintext_data = future.result() diff --git a/examples/test/multithreading/test_i_raw_rsa_keyring_multithreaded_example.py b/examples/test/multithreading/test_i_raw_rsa_keyring_multithreaded_example.py index b999129c5..dee5f72ac 100644 --- a/examples/test/multithreading/test_i_raw_rsa_keyring_multithreaded_example.py +++ b/examples/test/multithreading/test_i_raw_rsa_keyring_multithreaded_example.py @@ -19,7 +19,7 @@ def test_encrypt_and_decrypt_with_keyring(n_threads=10): public_key, private_key = generate_rsa_keys() keyring = create_keyring(public_key=public_key, private_key=private_key) plaintext_data = b"Hello World" - esdk_client = aws_encryption_sdk.EncryptionSDKClient( + client = aws_encryption_sdk.EncryptionSDKClient( commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT ) @@ -27,7 +27,7 @@ def test_encrypt_and_decrypt_with_keyring(n_threads=10): thread_futures = {executor.submit(encrypt_and_decrypt_with_keyring, plaintext_data=plaintext_data, keyring=keyring, - esdk_client=esdk_client): i for i in range(n_threads)} + client=client): i for i in range(n_threads)} for future in as_completed(thread_futures): decrypted_plaintext_data = future.result() From ae766931bda747b35f4d20124f345845005a599e Mon Sep 17 00:00:00 2001 From: Ritvik Kapila Date: Wed, 26 Jun 2024 16:51:17 -0700 Subject: [PATCH 10/18] fix imports --- examples/src/multithreading/raw_rsa_keyring.py | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/src/multithreading/raw_rsa_keyring.py b/examples/src/multithreading/raw_rsa_keyring.py index 1d63c1f9c..77d26f2fc 100644 --- a/examples/src/multithreading/raw_rsa_keyring.py +++ b/examples/src/multithreading/raw_rsa_keyring.py @@ -8,7 +8,6 @@ from cryptography.hazmat.backends import default_backend as crypto_default_backend from cryptography.hazmat.primitives import serialization as crypto_serialization from cryptography.hazmat.primitives.asymmetric import rsa -from typing import Dict # noqa pylint: disable=wrong-import-order def generate_rsa_keys(): From c8b27bba4145407ec8e0d2a1806e926c6673e764 Mon Sep 17 00:00:00 2001 From: Ritvik Kapila Date: Thu, 27 Jun 2024 14:13:38 -0700 Subject: [PATCH 11/18] fix --- examples/src/multithreading/__init__.py | 16 ++++++++++ ...i_raw_aes_keyring_multithreaded_example.py | 32 ++++++++++++++----- 2 files changed, 40 insertions(+), 8 deletions(-) diff --git a/examples/src/multithreading/__init__.py b/examples/src/multithreading/__init__.py index 3afc55898..491d92080 100644 --- a/examples/src/multithreading/__init__.py +++ b/examples/src/multithreading/__init__.py @@ -5,6 +5,7 @@ from typing import Dict # noqa pylint: disable=wrong-import-order import aws_encryption_sdk +import time def encrypt_and_decrypt_with_keyring( @@ -44,3 +45,18 @@ def encrypt_and_decrypt_with_keyring( ) return decrypted_plaintext_data + + +def run_encrypt_and_decrypt_with_keyring_for_duration_seconds( + plaintext_data: bytes, + keyring: IKeyring, + client: aws_encryption_sdk.EncryptionSDKClient, + duration: int = 2 +): + """Helper function to repeatedly run an encrypt and decrypt cycle for 'duration' seconds.""" + time_end = time.time() + duration + + while time.time() < time_end: + decrypted_plaintext_data = encrypt_and_decrypt_with_keyring(plaintext_data, keyring, client) + assert decrypted_plaintext_data == plaintext_data, \ + "Decrypted plaintext should be identical to the original plaintext. Invalid decryption" diff --git a/examples/test/multithreading/test_i_raw_aes_keyring_multithreaded_example.py b/examples/test/multithreading/test_i_raw_aes_keyring_multithreaded_example.py index a3bb6ae1e..1856d68c7 100644 --- a/examples/test/multithreading/test_i_raw_aes_keyring_multithreaded_example.py +++ b/examples/test/multithreading/test_i_raw_aes_keyring_multithreaded_example.py @@ -8,14 +8,19 @@ import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy -from ...src.multithreading import encrypt_and_decrypt_with_keyring +from ...src.multithreading import run_encrypt_and_decrypt_with_keyring_for_duration_seconds from ...src.multithreading.raw_aes_keyring import create_keyring +import time + pytestmark = [pytest.mark.examples] -def test_encrypt_and_decrypt_with_keyring(n_threads=10): - """Test function for multi-threaded encrypt and decrypt using the Raw AES Keyring example.""" +def test_encrypt_and_decrypt_with_keyring_multithreaded_helper(n_threads=16, duration=60): + """Helper function for multi-threaded encrypt and decrypt using a keyring for fixed n_threads and duration.""" + print(n_threads, duration) + start_time = time.time() + print('start_time', start_time) keyring = create_keyring() plaintext_data = b"Hello World" client = aws_encryption_sdk.EncryptionSDKClient( @@ -23,12 +28,23 @@ def test_encrypt_and_decrypt_with_keyring(n_threads=10): ) with ThreadPoolExecutor(max_workers=n_threads) as executor: - thread_futures = {executor.submit(encrypt_and_decrypt_with_keyring, + thread_futures = {executor.submit(run_encrypt_and_decrypt_with_keyring_for_duration_seconds, plaintext_data=plaintext_data, keyring=keyring, - client=client): i for i in range(n_threads)} + client=client, + duration=duration): i for i in range(n_threads)} for future in as_completed(thread_futures): - decrypted_plaintext_data = future.result() - assert decrypted_plaintext_data == plaintext_data, \ - "Decrypted plaintext should be identical to the original plaintext. Invalid decryption" + future.result() + end_time = time.time() + print('end_time', end_time) + print('duration', end_time - start_time) + + +# def test_encrypt_and_decrypt_with_keyring_multithreaded(n_threads_list: list = [4, 16, 64], duration_list: list = [2, 10, 60]): +# """Test function for multi-threaded encrypt and decrypt using a keyring for different n_threads and duration.""" +# print('hello', n_threads_list, duration_list) +# for n in n_threads_list: +# for d in duration_list: +# print(n, d, time.time()) +# encrypt_and_decrypt_with_keyring_helper(n_threads=n, duration=d) From 5b35e28f5370b50f9d83580be6d501f94e583213 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Mon, 20 May 2024 11:30:05 -0700 Subject: [PATCH 12/18] mplv2 --- examples/src/aws_kms_discovery_keyring_example.py | 4 ---- examples/src/aws_kms_discovery_multi_keyring_example.py | 4 ---- examples/src/aws_kms_keyring_example.py | 4 ---- examples/src/aws_kms_mrk_discovery_keyring_example.py | 4 ---- examples/src/aws_kms_mrk_discovery_multi_keyring_example.py | 4 ---- examples/src/aws_kms_mrk_keyring_example.py | 4 ---- examples/src/aws_kms_mrk_multi_keyring_example.py | 4 ---- examples/src/aws_kms_multi_keyring_example.py | 4 ---- examples/src/aws_kms_rsa_keyring_example.py | 4 ---- examples/src/file_streaming_example.py | 4 ---- examples/src/hierarchical_keyring_example.py | 4 ---- examples/src/legacy/module_.py | 1 - .../src/migration/migration_set_commitment_policy_example.py | 4 ---- examples/src/module_.py | 1 - examples/src/multi_keyring_example.py | 4 ---- examples/src/raw_aes_keyring_example.py | 4 ---- examples/src/raw_rsa_keyring_example.py | 4 ---- examples/src/required_encryption_context_cmm.py | 5 ----- examples/src/set_encryption_algorithm_suite_example.py | 4 ---- setup.py | 2 +- 20 files changed, 1 insertion(+), 72 deletions(-) delete mode 100644 examples/src/legacy/module_.py delete mode 100644 examples/src/module_.py diff --git a/examples/src/aws_kms_discovery_keyring_example.py b/examples/src/aws_kms_discovery_keyring_example.py index 4695e8783..2a9e40ea6 100644 --- a/examples/src/aws_kms_discovery_keyring_example.py +++ b/examples/src/aws_kms_discovery_keyring_example.py @@ -49,10 +49,6 @@ from aws_encryption_sdk import CommitmentPolicy from aws_encryption_sdk.exceptions import AWSEncryptionSDKClientError -# TODO-MPL: Remove this as part of removing PYTHONPATH hacks. -MODULE_ROOT_DIR = '/'.join(__file__.split("/")[:-1]) - -sys.path.append(MODULE_ROOT_DIR) EXAMPLE_DATA: bytes = b"Hello World" diff --git a/examples/src/aws_kms_discovery_multi_keyring_example.py b/examples/src/aws_kms_discovery_multi_keyring_example.py index 60d74ff31..452327da1 100644 --- a/examples/src/aws_kms_discovery_multi_keyring_example.py +++ b/examples/src/aws_kms_discovery_multi_keyring_example.py @@ -45,10 +45,6 @@ import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy -# TODO-MPL: Remove this as part of removing PYTHONPATH hacks. -MODULE_ROOT_DIR = '/'.join(__file__.split("/")[:-1]) - -sys.path.append(MODULE_ROOT_DIR) EXAMPLE_DATA: bytes = b"Hello World" diff --git a/examples/src/aws_kms_keyring_example.py b/examples/src/aws_kms_keyring_example.py index b166aab99..4cbab444a 100644 --- a/examples/src/aws_kms_keyring_example.py +++ b/examples/src/aws_kms_keyring_example.py @@ -29,10 +29,6 @@ import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy -# TODO-MPL: Remove this as part of removing PYTHONPATH hacks. -MODULE_ROOT_DIR = '/'.join(__file__.split("/")[:-1]) - -sys.path.append(MODULE_ROOT_DIR) EXAMPLE_DATA: bytes = b"Hello World" diff --git a/examples/src/aws_kms_mrk_discovery_keyring_example.py b/examples/src/aws_kms_mrk_discovery_keyring_example.py index 8ba80b621..bf7c47e4b 100644 --- a/examples/src/aws_kms_mrk_discovery_keyring_example.py +++ b/examples/src/aws_kms_mrk_discovery_keyring_example.py @@ -50,10 +50,6 @@ import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy -# TODO-MPL: Remove this as part of removing PYTHONPATH hacks. -MODULE_ROOT_DIR = '/'.join(__file__.split("/")[:-1]) - -sys.path.append(MODULE_ROOT_DIR) EXAMPLE_DATA: bytes = b"Hello World" diff --git a/examples/src/aws_kms_mrk_discovery_multi_keyring_example.py b/examples/src/aws_kms_mrk_discovery_multi_keyring_example.py index 47cb80f1d..6154bdb16 100644 --- a/examples/src/aws_kms_mrk_discovery_multi_keyring_example.py +++ b/examples/src/aws_kms_mrk_discovery_multi_keyring_example.py @@ -52,10 +52,6 @@ import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy -# TODO-MPL: Remove this as part of removing PYTHONPATH hacks. -MODULE_ROOT_DIR = '/'.join(__file__.split("/")[:-1]) - -sys.path.append(MODULE_ROOT_DIR) EXAMPLE_DATA: bytes = b"Hello World" diff --git a/examples/src/aws_kms_mrk_keyring_example.py b/examples/src/aws_kms_mrk_keyring_example.py index 65d8be71b..f09a2482b 100644 --- a/examples/src/aws_kms_mrk_keyring_example.py +++ b/examples/src/aws_kms_mrk_keyring_example.py @@ -33,10 +33,6 @@ import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy -# TODO-MPL: Remove this as part of removing PYTHONPATH hacks. -MODULE_ROOT_DIR = '/'.join(__file__.split("/")[:-1]) - -sys.path.append(MODULE_ROOT_DIR) EXAMPLE_DATA: bytes = b"Hello World" diff --git a/examples/src/aws_kms_mrk_multi_keyring_example.py b/examples/src/aws_kms_mrk_multi_keyring_example.py index 9c87008fe..50b39b6b0 100644 --- a/examples/src/aws_kms_mrk_multi_keyring_example.py +++ b/examples/src/aws_kms_mrk_multi_keyring_example.py @@ -39,10 +39,6 @@ import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy -# TODO-MPL: Remove this as part of removing PYTHONPATH hacks. -MODULE_ROOT_DIR = '/'.join(__file__.split("/")[:-1]) - -sys.path.append(MODULE_ROOT_DIR) EXAMPLE_DATA: bytes = b"Hello World" diff --git a/examples/src/aws_kms_multi_keyring_example.py b/examples/src/aws_kms_multi_keyring_example.py index 715181646..b98cb32ad 100644 --- a/examples/src/aws_kms_multi_keyring_example.py +++ b/examples/src/aws_kms_multi_keyring_example.py @@ -48,10 +48,6 @@ import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy -# TODO-MPL: Remove this as part of removing PYTHONPATH hacks. -MODULE_ROOT_DIR = '/'.join(__file__.split("/")[:-1]) - -sys.path.append(MODULE_ROOT_DIR) EXAMPLE_DATA: bytes = b"Hello World" diff --git a/examples/src/aws_kms_rsa_keyring_example.py b/examples/src/aws_kms_rsa_keyring_example.py index 337dd14b6..09a51be98 100644 --- a/examples/src/aws_kms_rsa_keyring_example.py +++ b/examples/src/aws_kms_rsa_keyring_example.py @@ -27,10 +27,6 @@ from aws_encryption_sdk import CommitmentPolicy from aws_encryption_sdk.identifiers import AlgorithmSuite -# TODO-MPL: Remove this as part of removing PYTHONPATH hacks. -MODULE_ROOT_DIR = '/'.join(__file__.split("/")[:-1]) - -sys.path.append(MODULE_ROOT_DIR) EXAMPLE_DATA: bytes = b"Hello World" diff --git a/examples/src/file_streaming_example.py b/examples/src/file_streaming_example.py index 72decde60..344f2c4bc 100644 --- a/examples/src/file_streaming_example.py +++ b/examples/src/file_streaming_example.py @@ -36,10 +36,6 @@ import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy -# TODO-MPL: Remove this as part of removing PYTHONPATH hacks. -MODULE_ROOT_DIR = '/'.join(__file__.split("/")[:-1]) - -sys.path.append(MODULE_ROOT_DIR) def encrypt_and_decrypt_with_keyring( diff --git a/examples/src/hierarchical_keyring_example.py b/examples/src/hierarchical_keyring_example.py index c781f4f40..3091ea4c9 100644 --- a/examples/src/hierarchical_keyring_example.py +++ b/examples/src/hierarchical_keyring_example.py @@ -55,10 +55,6 @@ from .branch_key_id_supplier_example import ExampleBranchKeyIdSupplier -# TODO-MPL: Remove this as part of removing PYTHONPATH hacks. -module_root_dir = '/'.join(__file__.split("/")[:-1]) - -sys.path.append(module_root_dir) EXAMPLE_DATA: bytes = b"Hello World" diff --git a/examples/src/legacy/module_.py b/examples/src/legacy/module_.py deleted file mode 100644 index 3e8d3062a..000000000 --- a/examples/src/legacy/module_.py +++ /dev/null @@ -1 +0,0 @@ -"""Should remove this once PYTHONPATH issues are resolved by adding doo files.""" diff --git a/examples/src/migration/migration_set_commitment_policy_example.py b/examples/src/migration/migration_set_commitment_policy_example.py index 4bd0bc372..87de2129b 100644 --- a/examples/src/migration/migration_set_commitment_policy_example.py +++ b/examples/src/migration/migration_set_commitment_policy_example.py @@ -32,10 +32,6 @@ import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy -# TODO-MPL: Remove this as part of removing PYTHONPATH hacks. -MODULE_ROOT_DIR = '/'.join(__file__.split("/")[:-1]) - -sys.path.append(MODULE_ROOT_DIR) EXAMPLE_DATA: bytes = b"Hello World" diff --git a/examples/src/module_.py b/examples/src/module_.py deleted file mode 100644 index 3e8d3062a..000000000 --- a/examples/src/module_.py +++ /dev/null @@ -1 +0,0 @@ -"""Should remove this once PYTHONPATH issues are resolved by adding doo files.""" diff --git a/examples/src/multi_keyring_example.py b/examples/src/multi_keyring_example.py index b12ab61a3..73ae9e1e6 100644 --- a/examples/src/multi_keyring_example.py +++ b/examples/src/multi_keyring_example.py @@ -54,10 +54,6 @@ import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy -# TODO-MPL: Remove this as part of removing PYTHONPATH hacks. -MODULE_ROOT_DIR = '/'.join(__file__.split("/")[:-1]) - -sys.path.append(MODULE_ROOT_DIR) EXAMPLE_DATA: bytes = b"Hello World" diff --git a/examples/src/raw_aes_keyring_example.py b/examples/src/raw_aes_keyring_example.py index d8634f774..5dcf64147 100644 --- a/examples/src/raw_aes_keyring_example.py +++ b/examples/src/raw_aes_keyring_example.py @@ -34,10 +34,6 @@ import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy -# TODO-MPL: Remove this as part of removing PYTHONPATH hacks. -MODULE_ROOT_DIR = '/'.join(__file__.split("/")[:-1]) - -sys.path.append(MODULE_ROOT_DIR) EXAMPLE_DATA: bytes = b"Hello World" diff --git a/examples/src/raw_rsa_keyring_example.py b/examples/src/raw_rsa_keyring_example.py index 4a38fd166..4adbb911e 100644 --- a/examples/src/raw_rsa_keyring_example.py +++ b/examples/src/raw_rsa_keyring_example.py @@ -48,10 +48,6 @@ from aws_encryption_sdk import CommitmentPolicy from aws_encryption_sdk.exceptions import AWSEncryptionSDKClientError -# TODO-MPL: Remove this as part of removing PYTHONPATH hacks. -MODULE_ROOT_DIR = '/'.join(__file__.split("/")[:-1]) - -sys.path.append(MODULE_ROOT_DIR) EXAMPLE_DATA: bytes = b"Hello World" diff --git a/examples/src/required_encryption_context_cmm.py b/examples/src/required_encryption_context_cmm.py index 1d5140e6d..a1083be95 100644 --- a/examples/src/required_encryption_context_cmm.py +++ b/examples/src/required_encryption_context_cmm.py @@ -25,11 +25,6 @@ from aws_encryption_sdk import CommitmentPolicy from aws_encryption_sdk.exceptions import AWSEncryptionSDKClientError -# TODO-MPL: Remove this as part of removing PYTHONPATH hacks -module_root_dir = '/'.join(__file__.split("/")[:-1]) - -sys.path.append(module_root_dir) - EXAMPLE_DATA: bytes = b"Hello World" diff --git a/examples/src/set_encryption_algorithm_suite_example.py b/examples/src/set_encryption_algorithm_suite_example.py index 200570083..ea3950561 100644 --- a/examples/src/set_encryption_algorithm_suite_example.py +++ b/examples/src/set_encryption_algorithm_suite_example.py @@ -51,10 +51,6 @@ from aws_encryption_sdk import CommitmentPolicy from aws_encryption_sdk.identifiers import AlgorithmSuite -# TODO-MPL: Remove this as part of removing PYTHONPATH hacks. -MODULE_ROOT_DIR = '/'.join(__file__.split("/")[:-1]) - -sys.path.append(MODULE_ROOT_DIR) EXAMPLE_DATA: bytes = b"Hello World" diff --git a/setup.py b/setup.py index 8ed2fe4e0..c069bade1 100644 --- a/setup.py +++ b/setup.py @@ -45,7 +45,7 @@ def get_requirements(): extras_require={ "MPL": ["aws-cryptographic-material-providers @" \ "git+https://github.com/aws/aws-cryptographic-material-providers-library.git@" \ - "lucmcdon/python-mpl#subdirectory=AwsCryptographicMaterialProviders/runtimes/python"], + "lucmcdon/python-mpl-v2#subdirectory=AwsCryptographicMaterialProviders/runtimes/python"], }, classifiers=[ "Development Status :: 5 - Production/Stable", From cdf3f93b506e7d031a1801c689bbd3a44643f1a8 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Mon, 20 May 2024 15:49:53 -0700 Subject: [PATCH 13/18] cleanup --- examples/src/aws_kms_discovery_keyring_example.py | 1 - examples/src/aws_kms_discovery_multi_keyring_example.py | 1 - examples/src/aws_kms_keyring_example.py | 1 - examples/src/aws_kms_mrk_discovery_keyring_example.py | 1 - examples/src/aws_kms_mrk_discovery_multi_keyring_example.py | 1 - examples/src/aws_kms_mrk_keyring_example.py | 1 - examples/src/aws_kms_mrk_multi_keyring_example.py | 1 - examples/src/aws_kms_multi_keyring_example.py | 1 - examples/src/aws_kms_rsa_keyring_example.py | 1 - examples/src/file_streaming_example.py | 1 - examples/src/hierarchical_keyring_example.py | 1 - .../src/migration/migration_set_commitment_policy_example.py | 1 - examples/src/multi_keyring_example.py | 1 - examples/src/raw_aes_keyring_example.py | 1 - examples/src/raw_rsa_keyring_example.py | 1 - examples/src/required_encryption_context_cmm.py | 1 - examples/src/set_encryption_algorithm_suite_example.py | 1 - 17 files changed, 17 deletions(-) diff --git a/examples/src/aws_kms_discovery_keyring_example.py b/examples/src/aws_kms_discovery_keyring_example.py index 2a9e40ea6..a6a1e1a26 100644 --- a/examples/src/aws_kms_discovery_keyring_example.py +++ b/examples/src/aws_kms_discovery_keyring_example.py @@ -32,7 +32,6 @@ For more information on how to use KMS Discovery keyrings, see https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-kms-keyring.html#kms-keyring-discovery """ -import sys import boto3 from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders diff --git a/examples/src/aws_kms_discovery_multi_keyring_example.py b/examples/src/aws_kms_discovery_multi_keyring_example.py index 452327da1..159647cbc 100644 --- a/examples/src/aws_kms_discovery_multi_keyring_example.py +++ b/examples/src/aws_kms_discovery_multi_keyring_example.py @@ -29,7 +29,6 @@ For more information on how to use KMS Discovery keyrings, see https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-kms-keyring.html#kms-keyring-discovery """ -import sys import boto3 from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders diff --git a/examples/src/aws_kms_keyring_example.py b/examples/src/aws_kms_keyring_example.py index 4cbab444a..4a927bb37 100644 --- a/examples/src/aws_kms_keyring_example.py +++ b/examples/src/aws_kms_keyring_example.py @@ -17,7 +17,6 @@ For more information on how to use KMS keyrings, see https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-kms-keyring.html """ -import sys import boto3 from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders diff --git a/examples/src/aws_kms_mrk_discovery_keyring_example.py b/examples/src/aws_kms_mrk_discovery_keyring_example.py index bf7c47e4b..8f13be3c8 100644 --- a/examples/src/aws_kms_mrk_discovery_keyring_example.py +++ b/examples/src/aws_kms_mrk_discovery_keyring_example.py @@ -34,7 +34,6 @@ For more information on how to use KMS Discovery keyrings, see https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-kms-keyring.html#kms-keyring-discovery """ -import sys import boto3 from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders diff --git a/examples/src/aws_kms_mrk_discovery_multi_keyring_example.py b/examples/src/aws_kms_mrk_discovery_multi_keyring_example.py index 6154bdb16..fd172c4a5 100644 --- a/examples/src/aws_kms_mrk_discovery_multi_keyring_example.py +++ b/examples/src/aws_kms_mrk_discovery_multi_keyring_example.py @@ -36,7 +36,6 @@ For more information on how to use KMS Discovery keyrings, see https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-kms-keyring.html#kms-keyring-discovery """ -import sys import boto3 from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders diff --git a/examples/src/aws_kms_mrk_keyring_example.py b/examples/src/aws_kms_mrk_keyring_example.py index f09a2482b..d7a594fdf 100644 --- a/examples/src/aws_kms_mrk_keyring_example.py +++ b/examples/src/aws_kms_mrk_keyring_example.py @@ -21,7 +21,6 @@ For more info on KMS MRK (multi-region keys), see the KMS documentation: https://docs.aws.amazon.com/kms/latest/developerguide/multi-region-keys-overview.html """ -import sys import boto3 from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders diff --git a/examples/src/aws_kms_mrk_multi_keyring_example.py b/examples/src/aws_kms_mrk_multi_keyring_example.py index 50b39b6b0..eed755bcd 100644 --- a/examples/src/aws_kms_mrk_multi_keyring_example.py +++ b/examples/src/aws_kms_mrk_multi_keyring_example.py @@ -27,7 +27,6 @@ For more info on KMS MRK (multi-region keys), see the KMS documentation: https://docs.aws.amazon.com/kms/latest/developerguide/multi-region-keys-overview.html """ -import sys import boto3 from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders diff --git a/examples/src/aws_kms_multi_keyring_example.py b/examples/src/aws_kms_multi_keyring_example.py index b98cb32ad..b639d4283 100644 --- a/examples/src/aws_kms_multi_keyring_example.py +++ b/examples/src/aws_kms_multi_keyring_example.py @@ -36,7 +36,6 @@ For more information on how to use Multi keyrings, see https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-multi-keyring.html """ -import sys import boto3 from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders diff --git a/examples/src/aws_kms_rsa_keyring_example.py b/examples/src/aws_kms_rsa_keyring_example.py index 09a51be98..f0319e957 100644 --- a/examples/src/aws_kms_rsa_keyring_example.py +++ b/examples/src/aws_kms_rsa_keyring_example.py @@ -14,7 +14,6 @@ # For more information on how to use KMS keyrings, see # https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-kms-keyring.html """ -import sys import boto3 from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders diff --git a/examples/src/file_streaming_example.py b/examples/src/file_streaming_example.py index 344f2c4bc..bbc117490 100644 --- a/examples/src/file_streaming_example.py +++ b/examples/src/file_streaming_example.py @@ -25,7 +25,6 @@ """ import filecmp import secrets -import sys from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig diff --git a/examples/src/hierarchical_keyring_example.py b/examples/src/hierarchical_keyring_example.py index 3091ea4c9..84b05d3b8 100644 --- a/examples/src/hierarchical_keyring_example.py +++ b/examples/src/hierarchical_keyring_example.py @@ -31,7 +31,6 @@ This example also requires using a KMS Key. You need the following access on this key: - GenerateDataKeyWithoutPlaintext - Decrypt """ -import sys import boto3 # Ignore missing MPL for pylint, but the MPL is required for this example diff --git a/examples/src/migration/migration_set_commitment_policy_example.py b/examples/src/migration/migration_set_commitment_policy_example.py index 87de2129b..d34a1ef59 100644 --- a/examples/src/migration/migration_set_commitment_policy_example.py +++ b/examples/src/migration/migration_set_commitment_policy_example.py @@ -20,7 +20,6 @@ For more information on setting your commitment policy, see https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#commitment-policy """ -import sys import boto3 from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders diff --git a/examples/src/multi_keyring_example.py b/examples/src/multi_keyring_example.py index 73ae9e1e6..98b6228bb 100644 --- a/examples/src/multi_keyring_example.py +++ b/examples/src/multi_keyring_example.py @@ -37,7 +37,6 @@ https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-multi-keyring.html """ import secrets -import sys import boto3 from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders diff --git a/examples/src/raw_aes_keyring_example.py b/examples/src/raw_aes_keyring_example.py index 5dcf64147..f1d971b62 100644 --- a/examples/src/raw_aes_keyring_example.py +++ b/examples/src/raw_aes_keyring_example.py @@ -23,7 +23,6 @@ https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-raw-aes-keyring.html """ import secrets -import sys from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig diff --git a/examples/src/raw_rsa_keyring_example.py b/examples/src/raw_rsa_keyring_example.py index 4adbb911e..ca488b474 100644 --- a/examples/src/raw_rsa_keyring_example.py +++ b/examples/src/raw_rsa_keyring_example.py @@ -33,7 +33,6 @@ For more information on how to use Raw RSA keyrings, see https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-raw-rsa-keyring.html """ -import sys from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig diff --git a/examples/src/required_encryption_context_cmm.py b/examples/src/required_encryption_context_cmm.py index a1083be95..edbb3f414 100644 --- a/examples/src/required_encryption_context_cmm.py +++ b/examples/src/required_encryption_context_cmm.py @@ -6,7 +6,6 @@ on encrypt such that they will not be stored on the message, but WILL be included in the header signature. On decrypt, the client MUST supply the key/value pair(s) that were not stored to successfully decrypt the message. """ -import sys import boto3 # Ignore missing MPL for pylint, but the MPL is required for this example diff --git a/examples/src/set_encryption_algorithm_suite_example.py b/examples/src/set_encryption_algorithm_suite_example.py index ea3950561..ffa453a30 100644 --- a/examples/src/set_encryption_algorithm_suite_example.py +++ b/examples/src/set_encryption_algorithm_suite_example.py @@ -39,7 +39,6 @@ https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-raw-aes-keyring.html """ import secrets -import sys from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig From f0c27f43d3b2cbb275684960c1d28780823c9940 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Mon, 20 May 2024 15:51:41 -0700 Subject: [PATCH 14/18] isort --- examples/src/aws_kms_discovery_keyring_example.py | 1 - examples/src/aws_kms_discovery_multi_keyring_example.py | 1 - examples/src/aws_kms_keyring_example.py | 1 - examples/src/aws_kms_mrk_discovery_keyring_example.py | 1 - examples/src/aws_kms_mrk_discovery_multi_keyring_example.py | 1 - examples/src/aws_kms_mrk_keyring_example.py | 1 - examples/src/aws_kms_mrk_multi_keyring_example.py | 1 - examples/src/aws_kms_multi_keyring_example.py | 1 - examples/src/aws_kms_rsa_keyring_example.py | 1 - examples/src/file_streaming_example.py | 1 - examples/src/hierarchical_keyring_example.py | 1 - .../src/migration/migration_set_commitment_policy_example.py | 1 - examples/src/multi_keyring_example.py | 1 - examples/src/raw_aes_keyring_example.py | 1 - examples/src/raw_rsa_keyring_example.py | 1 - examples/src/set_encryption_algorithm_suite_example.py | 1 - 16 files changed, 16 deletions(-) diff --git a/examples/src/aws_kms_discovery_keyring_example.py b/examples/src/aws_kms_discovery_keyring_example.py index a6a1e1a26..d78121bc3 100644 --- a/examples/src/aws_kms_discovery_keyring_example.py +++ b/examples/src/aws_kms_discovery_keyring_example.py @@ -48,7 +48,6 @@ from aws_encryption_sdk import CommitmentPolicy from aws_encryption_sdk.exceptions import AWSEncryptionSDKClientError - EXAMPLE_DATA: bytes = b"Hello World" diff --git a/examples/src/aws_kms_discovery_multi_keyring_example.py b/examples/src/aws_kms_discovery_multi_keyring_example.py index 159647cbc..9381a740b 100644 --- a/examples/src/aws_kms_discovery_multi_keyring_example.py +++ b/examples/src/aws_kms_discovery_multi_keyring_example.py @@ -44,7 +44,6 @@ import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy - EXAMPLE_DATA: bytes = b"Hello World" diff --git a/examples/src/aws_kms_keyring_example.py b/examples/src/aws_kms_keyring_example.py index 4a927bb37..8977e3750 100644 --- a/examples/src/aws_kms_keyring_example.py +++ b/examples/src/aws_kms_keyring_example.py @@ -28,7 +28,6 @@ import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy - EXAMPLE_DATA: bytes = b"Hello World" diff --git a/examples/src/aws_kms_mrk_discovery_keyring_example.py b/examples/src/aws_kms_mrk_discovery_keyring_example.py index 8f13be3c8..23d6cb322 100644 --- a/examples/src/aws_kms_mrk_discovery_keyring_example.py +++ b/examples/src/aws_kms_mrk_discovery_keyring_example.py @@ -49,7 +49,6 @@ import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy - EXAMPLE_DATA: bytes = b"Hello World" diff --git a/examples/src/aws_kms_mrk_discovery_multi_keyring_example.py b/examples/src/aws_kms_mrk_discovery_multi_keyring_example.py index fd172c4a5..adb249e2a 100644 --- a/examples/src/aws_kms_mrk_discovery_multi_keyring_example.py +++ b/examples/src/aws_kms_mrk_discovery_multi_keyring_example.py @@ -51,7 +51,6 @@ import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy - EXAMPLE_DATA: bytes = b"Hello World" diff --git a/examples/src/aws_kms_mrk_keyring_example.py b/examples/src/aws_kms_mrk_keyring_example.py index d7a594fdf..edb3cc410 100644 --- a/examples/src/aws_kms_mrk_keyring_example.py +++ b/examples/src/aws_kms_mrk_keyring_example.py @@ -32,7 +32,6 @@ import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy - EXAMPLE_DATA: bytes = b"Hello World" diff --git a/examples/src/aws_kms_mrk_multi_keyring_example.py b/examples/src/aws_kms_mrk_multi_keyring_example.py index eed755bcd..6b1e64eec 100644 --- a/examples/src/aws_kms_mrk_multi_keyring_example.py +++ b/examples/src/aws_kms_mrk_multi_keyring_example.py @@ -38,7 +38,6 @@ import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy - EXAMPLE_DATA: bytes = b"Hello World" diff --git a/examples/src/aws_kms_multi_keyring_example.py b/examples/src/aws_kms_multi_keyring_example.py index b639d4283..7cba36167 100644 --- a/examples/src/aws_kms_multi_keyring_example.py +++ b/examples/src/aws_kms_multi_keyring_example.py @@ -47,7 +47,6 @@ import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy - EXAMPLE_DATA: bytes = b"Hello World" diff --git a/examples/src/aws_kms_rsa_keyring_example.py b/examples/src/aws_kms_rsa_keyring_example.py index f0319e957..fd05fc20b 100644 --- a/examples/src/aws_kms_rsa_keyring_example.py +++ b/examples/src/aws_kms_rsa_keyring_example.py @@ -26,7 +26,6 @@ from aws_encryption_sdk import CommitmentPolicy from aws_encryption_sdk.identifiers import AlgorithmSuite - EXAMPLE_DATA: bytes = b"Hello World" diff --git a/examples/src/file_streaming_example.py b/examples/src/file_streaming_example.py index bbc117490..3f547d220 100644 --- a/examples/src/file_streaming_example.py +++ b/examples/src/file_streaming_example.py @@ -36,7 +36,6 @@ from aws_encryption_sdk import CommitmentPolicy - def encrypt_and_decrypt_with_keyring( plaintext_filename: str, ciphertext_filename: str, diff --git a/examples/src/hierarchical_keyring_example.py b/examples/src/hierarchical_keyring_example.py index 84b05d3b8..00dadf9d8 100644 --- a/examples/src/hierarchical_keyring_example.py +++ b/examples/src/hierarchical_keyring_example.py @@ -54,7 +54,6 @@ from .branch_key_id_supplier_example import ExampleBranchKeyIdSupplier - EXAMPLE_DATA: bytes = b"Hello World" diff --git a/examples/src/migration/migration_set_commitment_policy_example.py b/examples/src/migration/migration_set_commitment_policy_example.py index d34a1ef59..3851df0e2 100644 --- a/examples/src/migration/migration_set_commitment_policy_example.py +++ b/examples/src/migration/migration_set_commitment_policy_example.py @@ -31,7 +31,6 @@ import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy - EXAMPLE_DATA: bytes = b"Hello World" diff --git a/examples/src/multi_keyring_example.py b/examples/src/multi_keyring_example.py index 98b6228bb..20af7ba81 100644 --- a/examples/src/multi_keyring_example.py +++ b/examples/src/multi_keyring_example.py @@ -53,7 +53,6 @@ import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy - EXAMPLE_DATA: bytes = b"Hello World" diff --git a/examples/src/raw_aes_keyring_example.py b/examples/src/raw_aes_keyring_example.py index f1d971b62..ab9603af6 100644 --- a/examples/src/raw_aes_keyring_example.py +++ b/examples/src/raw_aes_keyring_example.py @@ -33,7 +33,6 @@ import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy - EXAMPLE_DATA: bytes = b"Hello World" diff --git a/examples/src/raw_rsa_keyring_example.py b/examples/src/raw_rsa_keyring_example.py index ca488b474..1200a7c72 100644 --- a/examples/src/raw_rsa_keyring_example.py +++ b/examples/src/raw_rsa_keyring_example.py @@ -47,7 +47,6 @@ from aws_encryption_sdk import CommitmentPolicy from aws_encryption_sdk.exceptions import AWSEncryptionSDKClientError - EXAMPLE_DATA: bytes = b"Hello World" diff --git a/examples/src/set_encryption_algorithm_suite_example.py b/examples/src/set_encryption_algorithm_suite_example.py index ffa453a30..75eaee85a 100644 --- a/examples/src/set_encryption_algorithm_suite_example.py +++ b/examples/src/set_encryption_algorithm_suite_example.py @@ -50,7 +50,6 @@ from aws_encryption_sdk import CommitmentPolicy from aws_encryption_sdk.identifiers import AlgorithmSuite - EXAMPLE_DATA: bytes = b"Hello World" From c8f15d184096c3f63a992a0b9110385f0453c822 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Wed, 22 May 2024 12:26:23 -0700 Subject: [PATCH 15/18] win --- .github/workflows/ci_tests.yaml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/workflows/ci_tests.yaml b/.github/workflows/ci_tests.yaml index 7ec273ba2..1a3229683 100644 --- a/.github/workflows/ci_tests.yaml +++ b/.github/workflows/ci_tests.yaml @@ -25,11 +25,7 @@ jobs: matrix: os: - ubuntu-latest - # Windows fails due to "No module named 'Wrappers'" - # This SHOULD be fixed once Dafny generates fully-qualified import statements - # (i.e. doo files, per-package module names) - # Disable for now - # - windows-latest + - windows-latest - macos-12 python: - 3.8 From acc33d1eaaca4820f5cb027ade3e48d745e5c62c Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Wed, 22 May 2024 12:36:51 -0700 Subject: [PATCH 16/18] debug win import --- src/aws_encryption_sdk/streaming_client.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/aws_encryption_sdk/streaming_client.py b/src/aws_encryption_sdk/streaming_client.py index 64d77b91a..62801eb6c 100644 --- a/src/aws_encryption_sdk/streaming_client.py +++ b/src/aws_encryption_sdk/streaming_client.py @@ -76,7 +76,8 @@ # Import internal ESDK modules that depend on the MPL from aws_encryption_sdk.materials_managers.mpl.cmm import CryptoMaterialsManagerFromMPL -except ImportError: +except ImportError as e: + print("streamingerror" + e) _HAS_MPL = False _LOGGER = logging.getLogger(__name__) From 09c3bdef849bbe5123d2a97b484bde2e983aae86 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Wed, 22 May 2024 12:39:16 -0700 Subject: [PATCH 17/18] debug win import --- src/aws_encryption_sdk/streaming_client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/aws_encryption_sdk/streaming_client.py b/src/aws_encryption_sdk/streaming_client.py index 62801eb6c..5b87abba0 100644 --- a/src/aws_encryption_sdk/streaming_client.py +++ b/src/aws_encryption_sdk/streaming_client.py @@ -77,7 +77,7 @@ from aws_encryption_sdk.materials_managers.mpl.cmm import CryptoMaterialsManagerFromMPL except ImportError as e: - print("streamingerror" + e) + print("streamingerror " + str(e)) _HAS_MPL = False _LOGGER = logging.getLogger(__name__) From 07542aaad54dbd17c00d63d2c83702d4e908d816 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Wed, 22 May 2024 12:43:20 -0700 Subject: [PATCH 18/18] actual v2 --- requirements_mpl.txt | 2 +- test_vector_handlers/requirements_mpl.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements_mpl.txt b/requirements_mpl.txt index 209e10f2c..28d7dc356 100644 --- a/requirements_mpl.txt +++ b/requirements_mpl.txt @@ -1 +1 @@ -aws-cryptographic-material-providers @ git+https://github.com/aws/aws-cryptographic-material-providers-library.git@lucmcdon/python-mpl#subdirectory=AwsCryptographicMaterialProviders/runtimes/python \ No newline at end of file +aws-cryptographic-material-providers @ git+https://github.com/aws/aws-cryptographic-material-providers-library.git@lucmcdon/python-mpl-v2#subdirectory=AwsCryptographicMaterialProviders/runtimes/python \ No newline at end of file diff --git a/test_vector_handlers/requirements_mpl.txt b/test_vector_handlers/requirements_mpl.txt index c7927a851..1aab5f534 100644 --- a/test_vector_handlers/requirements_mpl.txt +++ b/test_vector_handlers/requirements_mpl.txt @@ -1 +1 @@ -amazon-cryptographic-material-providers-test-vectors @ git+https://github.com/aws/aws-cryptographic-material-providers-library.git@lucmcdon/python-mpl#subdirectory=TestVectorsAwsCryptographicMaterialProviders/runtimes/python \ No newline at end of file +amazon-cryptographic-material-providers-test-vectors @ git+https://github.com/aws/aws-cryptographic-material-providers-library.git@lucmcdon/python-mpl-v2#subdirectory=TestVectorsAwsCryptographicMaterialProviders/runtimes/python \ No newline at end of file