1
+ # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
2
+ # SPDX-License-Identifier: Apache-2.0
3
+ """
4
+ This example sets up the AWS KMS RSA Keyring
5
+
6
+ The AWS KMS RSA keyring uses asymmetric encryption KMS RSA keys to generate, encrypt and
7
+ decrypt data keys. This example creates a KMS RSA Keyring and then encrypts a custom input
8
+ EXAMPLE_DATA with an encryption context. This example also includes some sanity checks for
9
+ demonstration:
10
+ 1. Ciphertext and plaintext data are not the same
11
+ 2. Encryption context is correct in the decrypted message header
12
+ 3. Decrypted plaintext value matches EXAMPLE_DATA
13
+ These sanity checks are for demonstration in the example only. You do not need these in your code.
14
+
15
+ AWS KMS RSA keyrings can be used independently or in a multi-keyring with other keyrings
16
+ of the same or a different type.
17
+
18
+ For more information on how to use KMS keyrings, see
19
+ https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-kms-keyring.html
20
+ """
21
+ import sys
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
29
+
30
+ import aws_encryption_sdk
31
+ from aws_encryption_sdk import CommitmentPolicy
32
+
33
+ # TODO-MPL: Remove this as part of removing PYTHONPATH hacks.
34
+ MODULE_ROOT_DIR = '/' .join (__file__ .split ("/" )[:- 1 ])
35
+
36
+ sys .path .append (MODULE_ROOT_DIR )
37
+
38
+ EXAMPLE_DATA : bytes = b"Hello World"
39
+
40
+
41
+ def encrypt_and_decrypt_with_keyring (
42
+ kms_rsa_key_id : str
43
+ ):
44
+ """Demonstrate an encrypt/decrypt cycle using an AWS KMS keyring.
45
+
46
+ Usage: encrypt_and_decrypt_with_keyring(kms_rsa_key_id)
47
+ :param kms_rsa_key_id: KMS RSA Key identifier for the KMS key you want to use for encryption and
48
+ decryption of your data keys.
49
+ :type kms_rsa_key_id: string
50
+
51
+ For more information on KMS Key identifiers, see
52
+ https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id
53
+ """
54
+ # 1. Instantiate the encryption SDK client.
55
+ # This builds the client with the REQUIRE_ENCRYPT_REQUIRE_DECRYPT commitment policy,
56
+ # which enforces that this client only encrypts using committing algorithm suites and enforces
57
+ # that this client will only decrypt encrypted messages that were created with a committing
58
+ # algorithm suite.
59
+ # This is the default commitment policy if you were to build the client as
60
+ # `client = aws_encryption_sdk.EncryptionSDKClient()`.
61
+ client = aws_encryption_sdk .EncryptionSDKClient (
62
+ commitment_policy = CommitmentPolicy .REQUIRE_ENCRYPT_REQUIRE_DECRYPT
63
+ )
64
+
65
+ # 2. Create a boto3 client for KMS.
66
+ kms_client = boto3 .client ('kms' , region_name = "us-west-2" )
67
+
68
+ # 3. Create encryption context.
69
+ # Remember that your encryption context is NOT SECRET.
70
+ # For more information, see
71
+ # https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#encryption-context
72
+ encryption_context : Dict [str , str ] = {
73
+ "encryption" : "context" ,
74
+ "is not" : "secret" ,
75
+ "but adds" : "useful metadata" ,
76
+ "that can help you" : "be confident that" ,
77
+ "the data you are handling" : "is what you think it is" ,
78
+ }
79
+
80
+ # 4. Create a KMS keyring
81
+ mat_prov : AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders (
82
+ config = MaterialProvidersConfig ()
83
+ )
84
+
85
+ keyring_input : CreateAwsKmsKeyringInput = CreateAwsKmsKeyringInput (
86
+ kms_rsa_key_id = kms_rsa_key_id ,
87
+ kms_client = kms_client
88
+ )
89
+
90
+ kms_keyring : IKeyring = mat_prov .create_aws_kms_keyring (
91
+ input = keyring_input
92
+ )
93
+
94
+ # 5. Encrypt the data for the encryptionContext
95
+ ciphertext , _ = client .encrypt (
96
+ source = EXAMPLE_DATA ,
97
+ keyring = kms_keyring ,
98
+ encryption_context = encryption_context
99
+ )
100
+
101
+ # 6. Demonstrate that the ciphertext and plaintext are different.
102
+ # (This is an example for demonstration; you do not need to do this in your own code.)
103
+ assert ciphertext != EXAMPLE_DATA , \
104
+ "Ciphertext and plaintext data are the same. Invalid encryption"
105
+
106
+ # 7. Decrypt your encrypted data using the same keyring you used on encrypt.
107
+ plaintext_bytes , dec_header = client .decrypt (
108
+ source = ciphertext ,
109
+ keyring = kms_keyring
110
+ )
111
+
112
+ # 8. Demonstrate that the encryption context is correct in the decrypted message header
113
+ # (This is an example for demonstration; you do not need to do this in your own code.)
114
+ for k , v in encryption_context .items ():
115
+ assert v == dec_header .encryption_context [k ], \
116
+ "Encryption context does not match expected values"
117
+
118
+ # 9. Demonstrate that the decrypted plaintext is identical to the original plaintext.
119
+ # (This is an example for demonstration; you do not need to do this in your own code.)
120
+ assert plaintext_bytes == EXAMPLE_DATA
0 commit comments