Skip to content

Commit 3b5157d

Browse files
add
1 parent a83ab6d commit 3b5157d

File tree

6 files changed

+254
-0
lines changed

6 files changed

+254
-0
lines changed
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
"""init file for multi-threading examples."""
4+
from aws_cryptographic_materialproviders.mpl.references import IKeyring
5+
from typing import Dict # noqa pylint: disable=wrong-import-order
6+
7+
import aws_encryption_sdk
8+
import time
9+
10+
11+
def encrypt_and_decrypt_with_keyring(
12+
plaintext_data: bytes,
13+
keyring: IKeyring,
14+
client: aws_encryption_sdk.EncryptionSDKClient
15+
):
16+
"""Demonstrate how to encrypt and decrypt plaintext data using a keyring.
17+
18+
Usage: encrypt_and_decrypt_with_keyring(plaintext_data, keyring, client)
19+
:param plaintext_data: plaintext data you want to encrypt
20+
:type: bytes
21+
:param keyring: Keyring to use for encryption.
22+
:type keyring: IKeyring
23+
:param client: The Encryption SDK client to use for encryption.
24+
:type client: aws_encryption_sdk.EncryptionSDKClient
25+
:return: encrypted and decrypted (cycled) plaintext data
26+
:rtype: bytes
27+
"""
28+
encryption_context: Dict[str, str] = {
29+
"encryption": "context",
30+
"is not": "secret",
31+
"but adds": "useful metadata",
32+
"that can help you": "be confident that",
33+
"the data you are handling": "is what you think it is",
34+
}
35+
36+
ciphertext_data, _ = client.encrypt(
37+
source=plaintext_data,
38+
keyring=keyring,
39+
encryption_context=encryption_context
40+
)
41+
42+
decrypted_plaintext_data, _ = client.decrypt(
43+
source=ciphertext_data,
44+
keyring=keyring
45+
)
46+
47+
return decrypted_plaintext_data
48+
49+
50+
def run_encrypt_and_decrypt_with_keyring_for_duration_seconds(
51+
plaintext_data: bytes,
52+
keyring: IKeyring,
53+
client: aws_encryption_sdk.EncryptionSDKClient,
54+
duration: int = 2
55+
):
56+
"""Helper function to repeatedly run an encrypt and decrypt cycle for 'duration' seconds."""
57+
time_end = time.time() + duration
58+
59+
while time.time() < time_end:
60+
decrypted_plaintext_data = encrypt_and_decrypt_with_keyring(plaintext_data, keyring, client)
61+
assert decrypted_plaintext_data == plaintext_data, \
62+
"Decrypted plaintext should be identical to the original plaintext. Invalid decryption"
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
"""This file contains methods to use for testing multi-threading for Raw AES keyring."""
4+
5+
import secrets
6+
7+
from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders
8+
from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig
9+
from aws_cryptographic_materialproviders.mpl.models import AesWrappingAlg, CreateRawAesKeyringInput
10+
from aws_cryptographic_materialproviders.mpl.references import IKeyring
11+
12+
13+
def create_keyring():
14+
"""Demonstrate how to create a Raw AES keyring.
15+
16+
Usage: create_keyring()
17+
"""
18+
key_name_space = "Some managed raw keys"
19+
key_name = "My 256-bit AES wrapping key"
20+
21+
static_key = secrets.token_bytes(32)
22+
23+
mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders(
24+
config=MaterialProvidersConfig()
25+
)
26+
27+
keyring_input: CreateRawAesKeyringInput = CreateRawAesKeyringInput(
28+
key_namespace=key_name_space,
29+
key_name=key_name,
30+
wrapping_key=static_key,
31+
wrapping_alg=AesWrappingAlg.ALG_AES256_GCM_IV12_TAG16
32+
)
33+
34+
keyring: IKeyring = mat_prov.create_raw_aes_keyring(
35+
input=keyring_input
36+
)
37+
38+
return keyring
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
"""This file contains methods to use for testing multi-threading for Raw RSA keyring."""
4+
from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders
5+
from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig
6+
from aws_cryptographic_materialproviders.mpl.models import CreateRawRsaKeyringInput, PaddingScheme
7+
from aws_cryptographic_materialproviders.mpl.references import IKeyring
8+
from cryptography.hazmat.backends import default_backend as crypto_default_backend
9+
from cryptography.hazmat.primitives import serialization as crypto_serialization
10+
from cryptography.hazmat.primitives.asymmetric import rsa
11+
12+
13+
def generate_rsa_keys():
14+
"""Generates a 4096-bit RSA public and private key pair
15+
16+
Usage: generate_rsa_keys()
17+
"""
18+
ssh_rsa_exponent = 65537
19+
bit_strength = 4096
20+
key = rsa.generate_private_key(
21+
backend=crypto_default_backend(),
22+
public_exponent=ssh_rsa_exponent,
23+
key_size=bit_strength
24+
)
25+
26+
# This example choses a particular type of encoding, format and encryption_algorithm
27+
# Users can choose the PublicFormat, PrivateFormat and encryption_algorithm that align most
28+
# with their use-cases
29+
public_key = key.public_key().public_bytes(
30+
encoding=crypto_serialization.Encoding.PEM,
31+
format=crypto_serialization.PublicFormat.SubjectPublicKeyInfo
32+
)
33+
private_key = key.private_bytes(
34+
encoding=crypto_serialization.Encoding.PEM,
35+
format=crypto_serialization.PrivateFormat.TraditionalOpenSSL,
36+
encryption_algorithm=crypto_serialization.NoEncryption()
37+
)
38+
39+
return public_key, private_key
40+
41+
42+
def create_keyring(public_key, private_key):
43+
"""Demonstrate how to create a Raw RSA keyring using the key pair.
44+
45+
Usage: create_keyring(public_key, private_key)
46+
"""
47+
key_name_space = "Some managed raw keys"
48+
key_name = "My 4096-bit RSA wrapping key"
49+
50+
mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders(
51+
config=MaterialProvidersConfig()
52+
)
53+
54+
keyring_input: CreateRawRsaKeyringInput = CreateRawRsaKeyringInput(
55+
key_namespace=key_name_space,
56+
key_name=key_name,
57+
padding_scheme=PaddingScheme.OAEP_SHA256_MGF1,
58+
public_key=public_key,
59+
private_key=private_key
60+
)
61+
62+
keyring: IKeyring = mat_prov.create_raw_rsa_keyring(
63+
input=keyring_input
64+
)
65+
66+
return keyring
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
"""Stub module indicator to make linter configuration simpler."""
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
"""Test suite for the Raw AES keyring example with multi-threading."""
4+
from concurrent.futures import ThreadPoolExecutor, as_completed
5+
6+
import pytest
7+
8+
import aws_encryption_sdk
9+
from aws_encryption_sdk import CommitmentPolicy
10+
11+
from ...src.multithreading import run_encrypt_and_decrypt_with_keyring_for_duration_seconds
12+
from ...src.multithreading.raw_aes_keyring import create_keyring
13+
14+
import time
15+
16+
pytestmark = [pytest.mark.examples]
17+
18+
19+
def test_encrypt_and_decrypt_with_keyring_multithreaded_helper(n_threads=16, duration=60):
20+
"""Helper function for multi-threaded encrypt and decrypt using a keyring for fixed n_threads and duration."""
21+
print(n_threads, duration)
22+
start_time = time.time()
23+
print('start_time', start_time)
24+
keyring = create_keyring()
25+
plaintext_data = b"Hello World"
26+
client = aws_encryption_sdk.EncryptionSDKClient(
27+
commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT
28+
)
29+
30+
with ThreadPoolExecutor(max_workers=n_threads) as executor:
31+
thread_futures = {executor.submit(run_encrypt_and_decrypt_with_keyring_for_duration_seconds,
32+
plaintext_data=plaintext_data,
33+
keyring=keyring,
34+
client=client,
35+
duration=duration): i for i in range(n_threads)}
36+
37+
for future in as_completed(thread_futures):
38+
future.result()
39+
end_time = time.time()
40+
print('end_time', end_time)
41+
print('duration', end_time - start_time)
42+
43+
44+
# def test_encrypt_and_decrypt_with_keyring_multithreaded(n_threads_list: list = [4, 16, 64], duration_list: list = [2, 10, 60]):
45+
# """Test function for multi-threaded encrypt and decrypt using a keyring for different n_threads and duration."""
46+
# print('hello', n_threads_list, duration_list)
47+
# for n in n_threads_list:
48+
# for d in duration_list:
49+
# print(n, d, time.time())
50+
# encrypt_and_decrypt_with_keyring_helper(n_threads=n, duration=d)
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
"""Test suite for the Raw RSA keyring example with multi-threading."""
4+
from concurrent.futures import ThreadPoolExecutor, as_completed
5+
6+
import pytest
7+
8+
import aws_encryption_sdk
9+
from aws_encryption_sdk import CommitmentPolicy
10+
11+
from ...src.multithreading import encrypt_and_decrypt_with_keyring
12+
from ...src.multithreading.raw_rsa_keyring import create_keyring, generate_rsa_keys
13+
14+
pytestmark = [pytest.mark.examples]
15+
16+
17+
def test_encrypt_and_decrypt_with_keyring(n_threads=10):
18+
"""Test function for multi-threaded encrypt and decrypt using the Raw RSA Keyring example."""
19+
public_key, private_key = generate_rsa_keys()
20+
keyring = create_keyring(public_key=public_key, private_key=private_key)
21+
plaintext_data = b"Hello World"
22+
client = aws_encryption_sdk.EncryptionSDKClient(
23+
commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT
24+
)
25+
26+
with ThreadPoolExecutor(max_workers=n_threads) as executor:
27+
thread_futures = {executor.submit(encrypt_and_decrypt_with_keyring,
28+
plaintext_data=plaintext_data,
29+
keyring=keyring,
30+
client=client): i for i in range(n_threads)}
31+
32+
for future in as_completed(thread_futures):
33+
decrypted_plaintext_data = future.result()
34+
assert decrypted_plaintext_data == plaintext_data, \
35+
"Decrypted plaintext should be identical to the original plaintext. Invalid decryption"

0 commit comments

Comments
 (0)