Skip to content

Commit 13acd28

Browse files
committed
refactoring
1 parent b69c418 commit 13acd28

9 files changed

+301
-295
lines changed

examples/src/migration/README.rst

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,16 @@ Migration Examples
33
##################
44

55
The native Python ESDK now uses the `AWS Cryptographic Material Providers Library`_,
6-
which introduces keyrings in place of the Master Key Provider. The MPL abstracts lower
6+
which introduces keyrings in place of Master Key Providers. The MPL abstracts lower
77
level cryptographic materials management of encryption and decryption materials.
88

9-
This directory contains some examples to migrate from the legacy Master Key Providers
10-
to keyrings. Here is the list of examples:
11-
1. Migration to AWS KMS Keyring from AWS KMS Master Key Provider
12-
2. Migration to Raw AES Keyring from Raw AES Master Key Provider
13-
3. Migration to Raw RSA Keyring from Raw RSA Master Key Provider
9+
This directory contains some examples to migrate from the old version of the ESDK.
10+
If you have messages encrypted in the older versions using Master Key Providers,
11+
these examples can guide you on how to decrypt those messages using the new version
12+
of the ESDK. Here is the list of examples:
13+
1. Migration example for AWS KMS keys
14+
2. Migration example for Raw AES keys
15+
3. Migration example for Raw RSA keys
1416
4. Setting a 'CommitmentPolicy' during migration
1517

1618
.. _AWS Cryptographic Material Providers Library: https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/introduction.html
Lines changed: 276 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,276 @@
1+
# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
"""
4+
This is a migration example for moving to the AWS KMS Keyring from AWS KMS master key provider (MKP)
5+
6+
The AWS KMS keyring uses symmetric encryption KMS keys to generate, encrypt and
7+
decrypt data keys. This example creates the KMS Keyring and KMS MKP and
8+
then encrypts a custom input EXAMPLE_DATA with an encryption context using both
9+
the keyring and MKP. The example then decrypts the ciphertext using both keyring and MKPs.
10+
This example also includes some sanity checks for demonstration:
11+
1. Decryption of these ciphertexts encrypted using keyring and MKP
12+
is possible using both KMS keyring and KMS MKP
13+
2. Both decrypted plaintexts are same and match EXAMPLE_DATA
14+
These sanity checks are for demonstration in the example only. You do not need these in your code.
15+
16+
Note: The ciphertexts obtained by encrypting EXAMPLE_DATA using keyring and MKP are not
17+
the same because the ESDK generates different data keys each time for encryption of the data.
18+
But both ciphertexts when decrypted using keyring and MKP should give the same plaintext result.
19+
20+
For more information on how to use KMS keyrings, see
21+
https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-kms-keyring.html
22+
"""
23+
import boto3
24+
from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders
25+
from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig
26+
from aws_cryptographic_materialproviders.mpl.models import CreateAwsKmsKeyringInput
27+
from aws_cryptographic_materialproviders.mpl.references import IKeyring
28+
from typing import Dict # noqa pylint: disable=wrong-import-order
29+
30+
import aws_encryption_sdk
31+
32+
EXAMPLE_DATA: bytes = b"Hello World"
33+
34+
DEFAULT_ENCRYPTION_CONTEXT : Dict[str, str] = {
35+
"encryption": "context",
36+
"is not": "secret",
37+
"but adds": "useful metadata",
38+
"that can help you": "be confident that",
39+
"the data you are handling": "is what you think it is",
40+
}
41+
42+
43+
def create_kms_client(aws_region="us-west-2"):
44+
"""Create an AWS KMS client.
45+
46+
Usage: create_kms_client(aws_region)
47+
:param aws_region: AWS region to use for KMS client.
48+
:type aws_region: string
49+
"""
50+
# Create a boto3 client for KMS.
51+
kms_client = boto3.client('kms', region_name=aws_region)
52+
53+
return kms_client
54+
55+
56+
def create_keyring(
57+
kms_key_id: str
58+
):
59+
"""Demonstrate how to create an AWS KMS keyring.
60+
61+
Usage: create_keyring(kms_key_id)
62+
:param kms_key_id: KMS Key identifier for the KMS key you want to use.
63+
:type kms_key_id: string
64+
65+
For more information on KMS Key identifiers, see
66+
https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id
67+
"""
68+
# Create a boto3 client for KMS.
69+
kms_client = create_kms_client()
70+
71+
# Create a KMS keyring
72+
mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders(
73+
config=MaterialProvidersConfig()
74+
)
75+
76+
keyring_input: CreateAwsKmsKeyringInput = CreateAwsKmsKeyringInput(
77+
kms_key_id=kms_key_id,
78+
kms_client=kms_client
79+
)
80+
81+
keyring: IKeyring = mat_prov.create_aws_kms_keyring(
82+
input=keyring_input
83+
)
84+
85+
return keyring
86+
87+
88+
def encrypt_using_keyring(
89+
plaintext_data: bytes,
90+
keyring: IKeyring,
91+
client: aws_encryption_sdk.EncryptionSDKClient
92+
):
93+
"""Demonstrate how to encrypt plaintext data using an AWS KMS keyring.
94+
95+
Usage: encrypt_using_keyring(plaintext_data, keyring)
96+
:param plaintext_data: plaintext data you want to encrypt
97+
:type: bytes
98+
:param keyring: Keyring to use for encryption.
99+
:type keyring: IKeyring
100+
:param client: AWS Encryption SDK client.
101+
:type client: aws_encryption_sdk.EncryptionSDKClient
102+
"""
103+
ciphertext_data, _ = client.encrypt(
104+
source=plaintext_data,
105+
keyring=keyring,
106+
encryption_context=DEFAULT_ENCRYPTION_CONTEXT
107+
)
108+
109+
return ciphertext_data
110+
111+
112+
def decrypt_using_keyring(
113+
ciphertext_data: bytes,
114+
keyring: IKeyring,
115+
client: aws_encryption_sdk.EncryptionSDKClient
116+
):
117+
"""Demonstrate how to decrypt ciphertext data using an AWS KMS keyring.
118+
119+
Usage: decrypt_using_keyring(ciphertext_data, keyring)
120+
:param ciphertext_data: ciphertext data you want to decrypt
121+
:type: bytes
122+
:param keyring: Keyring to use for decryption.
123+
:type keyring: IKeyring
124+
:param client: AWS Encryption SDK client.
125+
:type client: aws_encryption_sdk.EncryptionSDKClient
126+
"""
127+
decrypted_plaintext_data, _ = client.decrypt(
128+
source=ciphertext_data,
129+
keyring=keyring
130+
)
131+
132+
return decrypted_plaintext_data
133+
134+
135+
def create_key_provider(
136+
kms_key_id: str
137+
):
138+
"""Demonstrate how to create an AWS KMS master key provider.
139+
140+
Usage: create_key_provider(kms_key_id)
141+
:param kms_key_id: KMS Key identifier for the KMS key you want to use.
142+
:type kms_key_id: string
143+
144+
For more information on KMS Key identifiers, see
145+
https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id
146+
"""
147+
# Create a KMS master key provider.
148+
key_provider = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider(key_ids=[
149+
kms_key_id,
150+
])
151+
152+
return key_provider
153+
154+
155+
def encrypt_using_key_provider(
156+
plaintext_data: bytes,
157+
key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider,
158+
client: aws_encryption_sdk.EncryptionSDKClient
159+
):
160+
"""Demonstrate how to encrypt plaintext data using an AWS KMS master key provider.
161+
162+
Usage: encrypt_using_key_provider(plaintext_data, key_provider)
163+
:param plaintext_data: plaintext data you want to encrypt
164+
:type: bytes
165+
:param key_provider: Master key provider to use for encryption.
166+
:type key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider
167+
:param client: AWS Encryption SDK client.
168+
:type client: aws_encryption_sdk.EncryptionSDKClient
169+
"""
170+
ciphertext_data, _ = client.encrypt(
171+
source=plaintext_data,
172+
key_provider=key_provider,
173+
encryption_context=DEFAULT_ENCRYPTION_CONTEXT
174+
)
175+
176+
return ciphertext_data
177+
178+
179+
def decrypt_using_key_provider(
180+
ciphertext_data: bytes,
181+
key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider,
182+
client: aws_encryption_sdk.EncryptionSDKClient
183+
):
184+
"""Demonstrate how to decrypt ciphertext data using an AWS KMS master key provider.
185+
186+
Usage: decrypt_using_key_provider(ciphertext_data, key_provider)
187+
:param ciphertext_data: ciphertext data you want to decrypt
188+
:type: bytes
189+
:param key_provider: Master key provider to use for decryption.
190+
:type key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider
191+
:param client: AWS Encryption SDK client.
192+
:type client: aws_encryption_sdk.EncryptionSDKClient
193+
"""
194+
decrypted_plaintext_data, _ = client.decrypt(
195+
source=ciphertext_data,
196+
key_provider=key_provider
197+
)
198+
199+
return decrypted_plaintext_data
200+
201+
202+
def migration_aws_kms_key(
203+
kms_key_id: str
204+
):
205+
"""Demonstrate a migration example for moving from an AWS KMS keyring to AWS KMS MKP.
206+
207+
Usage: migration_to_aws_kms_keyring_from_aws_kms_master_key_provider(kms_key_id)
208+
:param kms_key_id: KMS Key identifier for the KMS key you want to use for encryption and
209+
decryption of your data keys.
210+
:type kms_key_id: string
211+
212+
For more information on KMS Key identifiers, see
213+
https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id
214+
"""
215+
client = aws_encryption_sdk.EncryptionSDKClient()
216+
217+
# 1a. Create a AWS KMS Keyring
218+
aws_kms_keyring = create_keyring(kms_key_id=kms_key_id)
219+
220+
# 1b. Create a AWS KMS Master Key Provider
221+
aws_kms_master_key_provider = create_key_provider(kms_key_id=kms_key_id)
222+
223+
# 2a. Encrypt EXAMPLE_DATA using AWS KMS Keyring
224+
ciphertext_keyring = encrypt_using_keyring(
225+
plaintext_data=EXAMPLE_DATA,
226+
keyring=aws_kms_keyring,
227+
client=client
228+
)
229+
230+
# 2b. Encrypt EXAMPLE_DATA using AWS KMS Master Key Provider
231+
ciphertext_mkp = encrypt_using_key_provider(
232+
plaintext_data=EXAMPLE_DATA,
233+
key_provider=aws_kms_master_key_provider,
234+
client=client
235+
)
236+
237+
# Note: The ciphertexts obtained by encrypting EXAMPLE_DATA using keyring and MKP
238+
# (that is ciphertext_keyring and ciphertext_mkp) are not the same because the ESDK
239+
# generates different data keys each time for encryption of the data. But both
240+
# ciphertexts when decrypted using keyring and MKP should give the same plaintext result.
241+
242+
# 3. Decrypt the ciphertext_keyring using both the keyring and MKP and ensure the
243+
# resulting plaintext is the same and also equal to EXAMPLE_DATA
244+
decrypted_ciphertext_keyring_using_keyring = decrypt_using_keyring(
245+
ciphertext_data=ciphertext_keyring,
246+
keyring=aws_kms_keyring,
247+
client=client
248+
)
249+
250+
decrypted_ciphertext_keyring_using_mkp = decrypt_using_key_provider(
251+
ciphertext_data=ciphertext_keyring,
252+
key_provider=aws_kms_master_key_provider,
253+
client=client
254+
)
255+
256+
assert decrypted_ciphertext_keyring_using_keyring == decrypted_ciphertext_keyring_using_mkp \
257+
and decrypted_ciphertext_keyring_using_keyring == EXAMPLE_DATA, \
258+
"Decrypted outputs using keyring and master key provider are not the same"
259+
260+
# 4. Decrypt the ciphertext_mkp using both the keyring and MKP and ensure the
261+
# resulting plaintext is the same and also equal to EXAMPLE_DATA
262+
decrypted_ciphertext_mkp_using_keyring = decrypt_using_keyring(
263+
ciphertext_data=ciphertext_mkp,
264+
keyring=aws_kms_keyring,
265+
client=client
266+
)
267+
268+
decrypted_ciphertext_mkp_using_mkp = decrypt_using_key_provider(
269+
ciphertext_data=ciphertext_mkp,
270+
key_provider=aws_kms_master_key_provider,
271+
client=client
272+
)
273+
274+
assert decrypted_ciphertext_mkp_using_keyring == decrypted_ciphertext_mkp_using_mkp \
275+
and decrypted_ciphertext_mkp_using_keyring == EXAMPLE_DATA, \
276+
"Decrypted outputs using keyring and master key provider are not the same"

0 commit comments

Comments
 (0)