Skip to content

Commit 8e0a317

Browse files
committed
added custom mpl cmm example
1 parent 7512802 commit 8e0a317

File tree

4 files changed

+155
-5
lines changed

4 files changed

+155
-5
lines changed
+112
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
"""Example to create a custom implementation of the ESDK-MPL ICryptographicMaterialsManager class."""
4+
5+
from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders
6+
from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig
7+
from aws_cryptographic_materialproviders.mpl.models import CreateDefaultCryptographicMaterialsManagerInput, SignatureAlgorithmNone
8+
from aws_cryptographic_materialproviders.mpl.references import ICryptographicMaterialsManager, IKeyring
9+
10+
import aws_encryption_sdk
11+
from aws_encryption_sdk import CommitmentPolicy
12+
13+
14+
# Custom CMM implementation using the MPL.
15+
# This CMM only allows encryption/decryption using signing algorithms.
16+
# It wraps an underlying CMM implementation and checks its materials
17+
# to ensure that it is only using signed encryption algorithms.
18+
class MPLCustomSigningSuiteOnlyCMM(ICryptographicMaterialsManager):
19+
"""Example custom crypto materials manager class."""
20+
21+
def __init__(self, keyring: IKeyring) -> None:
22+
"""Constructor for MPLCustomSigningSuiteOnlyCMM class."""
23+
mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders(
24+
config=MaterialProvidersConfig()
25+
)
26+
27+
# Create a CryptographicMaterialsManager for encryption and decryption
28+
cmm_input: CreateDefaultCryptographicMaterialsManagerInput = \
29+
CreateDefaultCryptographicMaterialsManagerInput(
30+
keyring=keyring
31+
)
32+
33+
self.underlying_cmm: ICryptographicMaterialsManager = mat_prov.create_default_cryptographic_materials_manager(
34+
input=cmm_input
35+
)
36+
37+
def get_encryption_materials(self, param):
38+
"""Provides encryption materials appropriate for the request for the custom CMM.
39+
40+
:param aws_cryptographic_materialproviders.mpl.models.GetEncryptionMaterialsInput param: Input object to
41+
provide to a crypto material manager's `get_encryption_materials` method.
42+
:returns: Encryption materials output
43+
:rtype: aws_cryptographic_materialproviders.mpl.models.GetEncryptionMaterialsOutput
44+
"""
45+
materials = self.underlying_cmm.get_encryption_materials(param)
46+
if isinstance(materials.encryption_materials.algorithm_suite.signature, SignatureAlgorithmNone):
47+
raise ValueError(
48+
"Algorithm provided to MPLCustomSigningSuiteOnlyCMM"
49+
+ " is not a supported signing algorithm: " + str(materials.encryption_materials.algorithm_suite)
50+
)
51+
return materials
52+
53+
def decrypt_materials(self, param):
54+
"""Provides decryption materials appropriate for the request for the custom CMM.
55+
56+
:param aws_cryptographic_materialproviders.mpl.models.DecryptMaterialsInput param: Input object to provide
57+
to a crypto material manager's `decrypt_materials` method.
58+
:returns: Decryption materials output
59+
:rtype: aws_cryptographic_materialproviders.mpl.models.GetDecryptionMaterialsOutput
60+
"""
61+
materials = self.underlying_cmm.decrypt_materials(param)
62+
if isinstance(materials.decryption_materials.algorithm_suite.signature, SignatureAlgorithmNone):
63+
raise ValueError(
64+
"Algorithm provided to MPLCustomSigningSuiteOnlyCMM"
65+
+ " is not a supported signing algorithm: " + str(materials.decryption_materials.algorithm_suite)
66+
)
67+
return materials
68+
69+
70+
EXAMPLE_DATA: bytes = b"Hello World"
71+
72+
73+
def encrypt_decrypt_with_cmm(
74+
cmm: ICryptographicMaterialsManager
75+
):
76+
"""Encrypts and decrypts a string using a custom CMM.
77+
78+
:param ICryptographicMaterialsManager cmm: CMM to use for encryption and decryption
79+
:param bytes source_plaintext: Data to encrypt
80+
"""
81+
# Set up an encryption client with an explicit commitment policy. Note that if you do not explicitly choose a
82+
# commitment policy, REQUIRE_ENCRYPT_REQUIRE_DECRYPT is used by default.
83+
client = aws_encryption_sdk.EncryptionSDKClient(commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT)
84+
85+
# Encrypt the plaintext source data
86+
ciphertext, encryptor_header = client.encrypt(
87+
source=EXAMPLE_DATA,
88+
materials_manager=cmm
89+
)
90+
91+
# Decrypt the ciphertext
92+
cycled_plaintext, decrypted_header = client.decrypt(
93+
source=ciphertext,
94+
materials_manager=cmm
95+
)
96+
97+
# Verify that the "cycled" (encrypted, then decrypted) plaintext is identical to the source plaintext
98+
assert cycled_plaintext == EXAMPLE_DATA
99+
100+
# Verify that the encryption context used in the decrypt operation includes all key pairs from
101+
# the encrypt operation. (The SDK can add pairs, so don't require an exact match.)
102+
#
103+
# In production, always use a meaningful encryption context. In this sample, we omit the
104+
# encryption context (no key pairs).
105+
# The encryptor_header.encryption_context has items of the form
106+
# b'key': b'value'
107+
# We convert these to strings for easier comparison with the decrypted header below.
108+
for k, v in encryptor_header.encryption_context.items():
109+
k = str(k.decode("utf-8"))
110+
v = str(v.decode("utf-8"))
111+
assert v == decrypted_header.encryption_context[k], \
112+
"Encryption context does not match expected values"

examples/src/legacy/custom_cmm_example.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -29,20 +29,20 @@ def get_encryption_materials(self, request):
2929
"""
3030
materials = self.underlying_cmm.get_encryption_materials(request)
3131
if not materials.algorithm.is_signing():
32-
raise AssertionError(
32+
raise ValueError(
3333
"Algorithm provided to CustomSigningSuiteOnlyCMM"
3434
+ " is not a supported signing algorithm: " + materials.algorithm
3535
)
3636
return materials
3737

3838
def decrypt_materials(self, request):
39-
"""Provider decryption materials appropriate for the request.
39+
"""Provides decryption materials appropriate for the request for the custom CMM.
4040
4141
:param DecryptionMaterialsRequest request: Request object to provide to a
4242
crypto material manager's `decrypt_materials` method.
4343
"""
4444
if not request.algorithm.is_signing():
45-
raise AssertionError(
45+
raise ValueError(
4646
"Algorithm provided to CustomSigningSuiteOnlyCMM"
4747
+ " is not a supported signing algorithm: " + request.algorithm
4848
)
@@ -53,7 +53,7 @@ def encrypt_decrypt_with_cmm(
5353
cmm: CryptoMaterialsManager,
5454
source_plaintext: str
5555
):
56-
"""Encrypts and decrypts a string using a CMM.
56+
"""Encrypts and decrypts a string using a custom CMM.
5757
5858
:param CryptoMaterialsManager cmm: CMM to use for encryption and decryption
5959
:param bytes source_plaintext: Data to encrypt

examples/test/legacy/test_i_custom_cmm_example.py

-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
22
# SPDX-License-Identifier: Apache-2.0
33
"""Test suite for encryption and decryption using custom CMM."""
4-
54
import botocore.session
65
import pytest
76

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
"""Test suite for encryption and decryption using custom CMM."""
4+
import boto3
5+
import pytest
6+
from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders
7+
from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig
8+
from aws_cryptographic_materialproviders.mpl.models import CreateAwsKmsKeyringInput
9+
from aws_cryptographic_materialproviders.mpl.references import IKeyring
10+
11+
from ..src.custom_mpl_cmm_example import MPLCustomSigningSuiteOnlyCMM, encrypt_decrypt_with_cmm
12+
13+
pytestmark = [pytest.mark.examples]
14+
15+
16+
def test_custom_cmm_example():
17+
"""Test method for encryption and decryption using V3 default CMM."""
18+
kms_key_id = "arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f"
19+
20+
# Create KMS keyring to use with the CMM
21+
kms_client = boto3.client('kms', region_name="us-west-2")
22+
23+
mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders(
24+
config=MaterialProvidersConfig()
25+
)
26+
27+
keyring_input: CreateAwsKmsKeyringInput = CreateAwsKmsKeyringInput(
28+
kms_key_id=kms_key_id,
29+
kms_client=kms_client
30+
)
31+
32+
kms_keyring: IKeyring = mat_prov.create_aws_kms_keyring(
33+
input=keyring_input
34+
)
35+
36+
# Create the custom MPL signing CMM using the keyring
37+
cmm = MPLCustomSigningSuiteOnlyCMM(keyring=kms_keyring)
38+
39+
encrypt_decrypt_with_cmm(cmm=cmm)

0 commit comments

Comments
 (0)