main/set_encryption_algorithm_suite_example.rs
1// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4/*
5This example demonstrates how to set an algorithm suite while using the Raw AES Keyring
6in the AWS Encryption SDK.
7
8The algorithm suite used in the encrypt() method is the algorithm used to protect your
9data using the data key. By setting this algorithm, you can configure the algorithm used
10to encrypt and decrypt your data.
11
12Algorithm suites can be set in a similar manner in other keyrings as well. However,
13please make sure that you're using a logical algorithm suite that is compatible with your
14keyring. For more information on algorithm suites supported by the AWS Encryption SDK, see
15https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/supported-algorithms.html
16
17The AES wrapping algorithm (AesWrappingAlg::AlgAes256GcmIv12Tag16) protects your data key using
18the user-provided wrapping key. In contrast, the algorithm suite used in the encrypt() method
19is the algorithm used to protect your data using the data key. This example demonstrates setting the
20latter, which is the algorithm suite for protecting your data. When the commitment policy is
21RequireEncryptRequireDecrypt, the default algorithm used in the encrypt method is
22AlgAes256GcmHkdfSha512CommitKeyEcdsaP384, which is a committing and signing algorithm.
23Signature verification ensures the integrity of a digital message as it goes across trust
24boundaries. However, signature verification adds a significant performance cost to encryption
25and decryption. If encryptors and decryptors are equally trusted, we can consider using an algorithm
26suite that does not include signing. This example sets the algorithm suite as
27AlgAes256GcmHkdfSha512CommitKey, which is a committing but non-signing algorithm.
28For more information on digital signatures, see
29https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#digital-sigs
30
31This example creates a Raw AES Keyring and then encrypts a custom input EXAMPLE_DATA
32with an encryption context and the algorithm suite AlgAes256GcmHkdfSha512CommitKey.
33This example also includes some sanity checks for demonstration:
341. Ciphertext and plaintext data are not the same
352. Decrypted plaintext value matches EXAMPLE_DATA
36These sanity checks are for demonstration in the example only. You do not need these in your code.
37
38For more information on how to use Raw AES keyrings, see
39https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-raw-aes-keyring.html
40*/
41
42use aws_esdk::client as esdk_client;
43use aws_esdk::material_providers::client as mpl_client;
44use aws_esdk::material_providers::types::material_providers_config::MaterialProvidersConfig;
45use aws_esdk::material_providers::types::AesWrappingAlg;
46use aws_esdk::material_providers::types::EsdkAlgorithmSuiteId::AlgAes256GcmHkdfSha512CommitKey;
47use aws_esdk::types::aws_encryption_sdk_config::AwsEncryptionSdkConfig;
48use rand::TryRngCore;
49use std::collections::HashMap;
50
51pub async fn encrypt_and_decrypt_with_keyring(example_data: &str) -> Result<(), crate::BoxError> {
52 // 1. Instantiate the encryption SDK client.
53 // This builds the default client with the RequireEncryptRequireDecrypt commitment policy,
54 // which enforces that this client only encrypts using committing algorithm suites and enforces
55 // that this client will only decrypt encrypted messages that were created with a committing
56 // algorithm suite.
57 let esdk_config = AwsEncryptionSdkConfig::builder().build()?;
58 let esdk_client = esdk_client::Client::from_conf(esdk_config)?;
59
60 // 2. The key namespace and key name are defined by you.
61 // and are used by the Raw AES keyring to determine
62 // whether it should attempt to decrypt an encrypted data key.
63 // For more information, see
64 // https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-raw-aes-keyring.html
65 let key_namespace: &str = "my-key-namespace";
66 let key_name: &str = "my-aes-key-name";
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 let encryption_context = HashMap::from([
73 ("encryption".to_string(), "context".to_string()),
74 ("is not".to_string(), "secret".to_string()),
75 ("but adds".to_string(), "useful metadata".to_string()),
76 (
77 "that can help you".to_string(),
78 "be confident that".to_string(),
79 ),
80 (
81 "the data you are handling".to_string(),
82 "is what you think it is".to_string(),
83 ),
84 ]);
85
86 // 4. Generate a 256-bit AES key to use with your keyring.
87 // In practice, you should get this key from a secure key management system such as an HSM.
88 let aes_key_bytes = generate_aes_key_bytes();
89
90 // 5. Create a Raw AES Keyring
91 let mpl_config = MaterialProvidersConfig::builder().build()?;
92 let mpl = mpl_client::Client::from_conf(mpl_config)?;
93
94 // The wrapping algorithm here is NOT the algorithm suite we set in this example.
95 let raw_aes_keyring = mpl
96 .create_raw_aes_keyring()
97 .key_name(key_name)
98 .key_namespace(key_namespace)
99 .wrapping_key(aes_key_bytes)
100 .wrapping_alg(AesWrappingAlg::AlgAes256GcmIv12Tag16)
101 .send()
102 .await?;
103
104 // 6. Encrypt the data with the encryption_context
105 let plaintext = example_data.as_bytes();
106
107 // This is the important step in this example where we specify the algorithm suite
108 // you want to use for encrypting your data
109 let encryption_response = esdk_client
110 .encrypt()
111 .plaintext(plaintext)
112 .keyring(raw_aes_keyring.clone())
113 .encryption_context(encryption_context.clone())
114 .algorithm_suite_id(AlgAes256GcmHkdfSha512CommitKey)
115 .send()
116 .await?;
117
118 let ciphertext = encryption_response
119 .ciphertext
120 .expect("Unable to unwrap ciphertext from encryption response");
121
122 // 7. Demonstrate that the ciphertext and plaintext are different.
123 // (This is an example for demonstration; you do not need to do this in your own code.)
124 assert_ne!(
125 ciphertext,
126 aws_smithy_types::Blob::new(plaintext),
127 "Ciphertext and plaintext data are the same. Invalid encryption"
128 );
129
130 // 8. Decrypt your encrypted data using the same keyring you used on encrypt.
131 let decryption_response = esdk_client
132 .decrypt()
133 .ciphertext(ciphertext)
134 .keyring(raw_aes_keyring)
135 // Provide the encryption context that was supplied to the encrypt method
136 .encryption_context(encryption_context)
137 .send()
138 .await?;
139
140 let decrypted_plaintext = decryption_response
141 .plaintext
142 .expect("Unable to unwrap plaintext from decryption response");
143
144 // 9. Demonstrate that the decrypted plaintext is identical to the original plaintext.
145 // (This is an example for demonstration; you do not need to do this in your own code.)
146 assert_eq!(
147 decrypted_plaintext,
148 aws_smithy_types::Blob::new(plaintext),
149 "Decrypted plaintext should be identical to the original plaintext. Invalid decryption"
150 );
151
152 println!("Set Encryption Algorithm Suite Example Completed Successfully");
153
154 Ok(())
155}
156
157fn generate_aes_key_bytes() -> Vec<u8> {
158 // This example returns a random AES key.
159 // In practice, you should not generate this key in your code, and should instead
160 // retrieve this key from a secure key management system (e.g. HSM).
161 // This key is created here for example purposes only and should not be used for any other purpose.
162 let mut random_bytes = [0u8; 32];
163 rand::rngs::OsRng.try_fill_bytes(&mut random_bytes).unwrap();
164
165 random_bytes.to_vec()
166}
167
168#[tokio::test(flavor = "multi_thread")]
169pub async fn test_encrypt_and_decrypt_with_keyring() -> Result<(), crate::BoxError2> {
170 // Test function for encrypt and decrypt using the Set Encryption Algorithm Suite example
171 use crate::example_utils::utils;
172
173 encrypt_and_decrypt_with_keyring(utils::TEST_EXAMPLE_DATA).await?;
174
175 Ok(())
176}