main/cryptographic_materials_manager/required_encryption_context/
required_encryption_context_example.rs1use aws_esdk::client as esdk_client;
12use aws_esdk::material_providers::client as mpl_client;
13use aws_esdk::material_providers::types::material_providers_config::MaterialProvidersConfig;
14use aws_esdk::types::aws_encryption_sdk_config::AwsEncryptionSdkConfig;
15use aws_esdk::types::error::Error::AwsCryptographicMaterialProvidersError;
16use std::collections::HashMap;
17use std::vec::Vec;
18
19pub async fn encrypt_and_decrypt_with_cmm(
20 example_data: &str,
21 kms_key_id: &str,
22) -> Result<(), crate::BoxError> {
23 let esdk_config = AwsEncryptionSdkConfig::builder().build()?;
29 let esdk_client = esdk_client::Client::from_conf(esdk_config)?;
30
31 let sdk_config = aws_config::load_defaults(aws_config::BehaviorVersion::latest()).await;
33 let kms_client = aws_sdk_kms::Client::new(&sdk_config);
34
35 let encryption_context = HashMap::from([
40 ("encryption".to_string(), "context".to_string()),
41 ("is not".to_string(), "secret".to_string()),
42 ("but adds".to_string(), "useful metadata".to_string()),
43 (
44 "that can help you".to_string(),
45 "be confident that".to_string(),
46 ),
47 (
48 "the data you are handling".to_string(),
49 "is what you think it is".to_string(),
50 ),
51 ("requiredKey1".to_string(), "requiredValue1".to_string()),
52 ("requiredKey2".to_string(), "requiredValue2".to_string()),
53 ]);
54
55 let required_encryption_context_keys: Vec<String> =
60 vec!["requiredKey1".to_string(), "requiredKey2".to_string()];
61
62 let mpl_config = MaterialProvidersConfig::builder().build()?;
64 let mpl = mpl_client::Client::from_conf(mpl_config)?;
65
66 let kms_keyring = mpl
67 .create_aws_kms_keyring()
68 .kms_key_id(kms_key_id)
69 .kms_client(kms_client)
70 .send()
71 .await?;
72
73 let underlying_cmm = mpl
75 .create_default_cryptographic_materials_manager()
76 .keyring(kms_keyring)
77 .send()
78 .await?;
79
80 let required_ec_cmm = mpl
81 .create_required_encryption_context_cmm()
82 .underlying_cmm(underlying_cmm.clone())
83 .required_encryption_context_keys(required_encryption_context_keys)
84 .send()
85 .await?;
86
87 let plaintext = example_data.as_bytes();
92
93 let encryption_response = esdk_client
94 .encrypt()
95 .plaintext(plaintext)
96 .materials_manager(required_ec_cmm.clone())
97 .encryption_context(encryption_context.clone())
98 .send()
99 .await?;
100
101 let ciphertext = encryption_response
102 .ciphertext
103 .expect("Unable to unwrap ciphertext from encryption response");
104
105 assert_ne!(
108 ciphertext,
109 aws_smithy_types::Blob::new(plaintext),
110 "Ciphertext and plaintext data are the same. Invalid encryption"
111 );
112
113 let decryption_response = esdk_client
115 .decrypt()
116 .ciphertext(ciphertext.clone())
117 .materials_manager(required_ec_cmm.clone())
118 .encryption_context(encryption_context.clone())
120 .send()
121 .await?;
122
123 let decrypted_plaintext = decryption_response
124 .plaintext
125 .expect("Unable to unwrap plaintext from decryption response");
126
127 assert_eq!(
130 decrypted_plaintext,
131 aws_smithy_types::Blob::new(plaintext),
132 "Decrypted plaintext should be identical to the original plaintext. Invalid decryption"
133 );
134
135 let decryption_response_without_ec = esdk_client
139 .decrypt()
140 .ciphertext(ciphertext.clone())
141 .materials_manager(required_ec_cmm.clone())
142 .send()
143 .await;
144
145 match decryption_response_without_ec {
146 Ok(_) => panic!(
147 "Decrypt without encryption context MUST \
148 raise AwsCryptographicMaterialProvidersError"
149 ),
150 Err(AwsCryptographicMaterialProvidersError { error: _e }) => (),
151 _ => panic!("Unexpected error type"),
152 }
153
154 let reproduced_encryption_context = HashMap::from([
158 ("requiredKey1".to_string(), "requiredValue1".to_string()),
159 ("requiredKey2".to_string(), "requiredValue2".to_string()),
160 ]);
161
162 let decryption_response_with_reproduced_ec = esdk_client
163 .decrypt()
164 .ciphertext(ciphertext.clone())
165 .materials_manager(required_ec_cmm)
166 .encryption_context(reproduced_encryption_context)
168 .send()
169 .await?;
170
171 let decrypted_plaintext_with_reproduced_ec = decryption_response_with_reproduced_ec
172 .plaintext
173 .expect("Unable to unwrap plaintext from decryption response");
174
175 assert_eq!(
178 decrypted_plaintext_with_reproduced_ec,
179 aws_smithy_types::Blob::new(plaintext),
180 "Decrypted plaintext should be identical to the original plaintext. Invalid decryption"
181 );
182
183 let decryption_response_with_ec_underlying_cmm = esdk_client
188 .decrypt()
189 .ciphertext(ciphertext.clone())
190 .materials_manager(underlying_cmm.clone())
191 .encryption_context(encryption_context)
193 .send()
194 .await?;
195
196 let decrypted_plaintext_with_ec_underlying_cmm = decryption_response_with_ec_underlying_cmm
197 .plaintext
198 .expect("Unable to unwrap plaintext from decryption response");
199
200 assert_eq!(
203 decrypted_plaintext_with_ec_underlying_cmm,
204 aws_smithy_types::Blob::new(plaintext),
205 "Decrypted plaintext should be identical to the original plaintext. Invalid decryption"
206 );
207
208 let decryption_response_without_ec_underlying_cmm = esdk_client
210 .decrypt()
211 .ciphertext(ciphertext)
212 .materials_manager(underlying_cmm)
213 .send()
214 .await;
215
216 match decryption_response_without_ec_underlying_cmm {
217 Ok(_) => panic!(
218 "Decrypt without encryption context MUST \
219 raise AwsCryptographicMaterialProvidersError"
220 ),
221 Err(AwsCryptographicMaterialProvidersError { error: _e }) => (),
222 _ => panic!("Unexpected error type"),
223 }
224
225 println!("Required Encryption Context CMM Example Completed Successfully");
226
227 Ok(())
228}
229
230#[tokio::test(flavor = "multi_thread")]
231pub async fn test_encrypt_and_decrypt_with_cmm() -> Result<(), crate::BoxError2> {
232 use crate::example_utils::utils;
234
235 encrypt_and_decrypt_with_cmm(utils::TEST_EXAMPLE_DATA, utils::TEST_DEFAULT_KMS_KEY_ID).await?;
236
237 Ok(())
238}