-
Notifications
You must be signed in to change notification settings - Fork 86
/
Copy pathaws_cryptographic_materials_manager_example.py
133 lines (110 loc) · 5.6 KB
/
aws_cryptographic_materials_manager_example.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
"""
This example sets up the AWS Cryptographic Material Managers (CMM).
The AWS 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 AWS 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_cmm(
kms_key_id: str
):
"""Demonstrate an encrypt/decrypt cycle using an AWS Cryptographic Material Managers.
Usage: encrypt_and_decrypt_with_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",
}
# 4. 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
)
# 5. 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
)
# 6. Encrypt the data with the encryptionContext.
ciphertext, _ = client.encrypt(
source=EXAMPLE_DATA,
materials_manager=cmm,
encryption_context=encryption_context
)
# 7. 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"
# 8. Decrypt your encrypted data using the same cmm you used on encrypt.
plaintext_bytes, dec_header = client.decrypt(
source=ciphertext,
materials_manager=cmm
)
# 9. 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"
# 10. 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"