main/keyring/
aws_kms_rsa_keyring_example.rs

1// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4/*
5This example sets up the AWS KMS RSA Keyring
6
7This example creates a KMS RSA Keyring and then encrypts a custom input
8example_data with an encryption context. This example also includes some sanity checks for
9demonstration:
101. Ciphertext and plaintext data are not the same
112. Decrypted plaintext value matches EXAMPLE_DATA
12These sanity checks are for demonstration in the example only. You do not need these in your code.
13
14# For more information on how to use KMS keyrings, see
15# https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-kms-keyring.html
16
17For more information on KMS Key identifiers, see
18https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id
19*/
20
21use aws_esdk::client as esdk_client;
22use aws_esdk::material_providers::client as mpl_client;
23use aws_esdk::material_providers::types::material_providers_config::MaterialProvidersConfig;
24use aws_esdk::material_providers::types::EsdkAlgorithmSuiteId;
25use aws_esdk::types::aws_encryption_sdk_config::AwsEncryptionSdkConfig;
26use std::collections::HashMap;
27
28pub async fn encrypt_and_decrypt_with_keyring(
29    example_data: &str,
30    kms_rsa_key_id: &str,
31    kms_rsa_public_key: &str,
32) -> Result<(), crate::BoxError> {
33    // 1. Instantiate the encryption SDK client.
34    // This builds the default client with the RequireEncryptRequireDecrypt commitment policy,
35    // which enforces that this client only encrypts using committing algorithm suites and enforces
36    // that this client will only decrypt encrypted messages that were created with a committing
37    // algorithm suite.
38    let esdk_config = AwsEncryptionSdkConfig::builder().build()?;
39    let esdk_client = esdk_client::Client::from_conf(esdk_config)?;
40
41    // 2. Create a KMS client.
42    let sdk_config = aws_config::load_defaults(aws_config::BehaviorVersion::latest()).await;
43    let kms_client = aws_sdk_kms::Client::new(&sdk_config);
44
45    // 3. Create encryption context.
46    // Remember that your encryption context is NOT SECRET.
47    // For more information, see
48    // https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#encryption-context
49    let encryption_context = HashMap::from([
50        ("encryption".to_string(), "context".to_string()),
51        ("is not".to_string(), "secret".to_string()),
52        ("but adds".to_string(), "useful metadata".to_string()),
53        (
54            "that can help you".to_string(),
55            "be confident that".to_string(),
56        ),
57        (
58            "the data you are handling".to_string(),
59            "is what you think it is".to_string(),
60        ),
61    ]);
62
63    // 4. Create a KMS RSA keyring
64    let mpl_config = MaterialProvidersConfig::builder().build()?;
65    let mpl = mpl_client::Client::from_conf(mpl_config)?;
66
67    // For more information on the allowed encryption algorithms, please see
68    // https://docs.aws.amazon.com/kms/latest/developerguide/asymmetric-key-specs.html#key-spec-rsa
69    let kms_rsa_keyring = mpl
70        .create_aws_kms_rsa_keyring()
71        .kms_key_id(kms_rsa_key_id)
72        .public_key(aws_smithy_types::Blob::new(kms_rsa_public_key))
73        .encryption_algorithm(aws_sdk_kms::types::EncryptionAlgorithmSpec::RsaesOaepSha256)
74        .kms_client(kms_client)
75        .send()
76        .await?;
77
78    // 5. Encrypt the data with the encryption_context
79    let plaintext = example_data.as_bytes();
80
81    let encryption_response = esdk_client
82        .encrypt()
83        .plaintext(plaintext)
84        .keyring(kms_rsa_keyring.clone())
85        .encryption_context(encryption_context.clone())
86        .algorithm_suite_id(EsdkAlgorithmSuiteId::AlgAes256GcmHkdfSha512CommitKey)
87        .send()
88        .await?;
89
90    let ciphertext = encryption_response
91        .ciphertext
92        .expect("Unable to unwrap ciphertext from encryption response");
93
94    // 6. Demonstrate that the ciphertext and plaintext are different.
95    // (This is an example for demonstration; you do not need to do this in your own code.)
96    assert_ne!(
97        ciphertext,
98        aws_smithy_types::Blob::new(plaintext),
99        "Ciphertext and plaintext data are the same. Invalid encryption"
100    );
101
102    // 7. Decrypt your encrypted data using the same keyring you used on encrypt.
103    let decryption_response = esdk_client
104        .decrypt()
105        .ciphertext(ciphertext)
106        .keyring(kms_rsa_keyring)
107        // Provide the encryption context that was supplied to the encrypt method
108        .encryption_context(encryption_context)
109        .send()
110        .await?;
111
112    let decrypted_plaintext = decryption_response
113        .plaintext
114        .expect("Unable to unwrap plaintext from decryption response");
115
116    // 8. Demonstrate that the decrypted plaintext is identical to the original plaintext.
117    // (This is an example for demonstration; you do not need to do this in your own code.)
118    assert_eq!(
119        decrypted_plaintext,
120        aws_smithy_types::Blob::new(plaintext),
121        "Decrypted plaintext should be identical to the original plaintext. Invalid decryption"
122    );
123
124    println!("KMS RSA Keyring Example Completed Successfully");
125
126    Ok(())
127}
128
129#[tokio::test(flavor = "multi_thread")]
130pub async fn test_encrypt_and_decrypt_with_keyring() -> Result<(), crate::BoxError2> {
131    // Test function for encrypt and decrypt using the AWS KMS RSA Keyring example
132    use crate::example_utils::utils;
133
134    encrypt_and_decrypt_with_keyring(
135        utils::TEST_EXAMPLE_DATA,
136        utils::TEST_KMS_RSA_KEY_ID,
137        utils::TEST_KMS_RSA_PUBLIC_KEY,
138    )
139    .await?;
140
141    Ok(())
142}