Skip to content

Commit 6f16233

Browse files
committed
chore: added examples for raw rsa and raw aes keyrings
1 parent 1c43dd9 commit 6f16233

File tree

4 files changed

+319
-0
lines changed

4 files changed

+319
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
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 Raw AES Keyring
5+
6+
The Raw AES keyring lets you use an AES symmetric key that you provide as a wrapping key that
7+
protects your data key. You need to generate, store, and protect the key material,
8+
preferably in a hardware security module (HSM) or key management system. Use a Raw AES keyring
9+
when you need to provide the wrapping key and encrypt the data keys locally or offline.
10+
11+
This example creates a Raw AES Keyring and then encrypts a custom input EXAMPLE_DATA
12+
with an encryption context. This example also includes some sanity checks for demonstration:
13+
1. Ciphertext and plaintext data are not the same
14+
2. Encryption context is correct in the decrypted message header
15+
3. Decrypted plaintext value matches EXAMPLE_DATA
16+
These sanity checks are for demonstration in the example only. You do not need these in your code.
17+
18+
The Raw AES keyring encrypts data by using the AES-GCM algorithm and a wrapping key that
19+
you specify as a byte array. You can specify only one wrapping key in each Raw AES keyring,
20+
but you can include multiple Raw AES keyrings, alone or with other keyrings, in a multi-keyring.
21+
22+
For more information on how to use Raw AES keyrings, see
23+
https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-raw-aes-keyring.html
24+
"""
25+
import secrets
26+
import sys
27+
28+
from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders
29+
from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig
30+
from aws_cryptographic_materialproviders.mpl.models import CreateRawAesKeyringInput
31+
from aws_cryptographic_materialproviders.mpl.references import IKeyring
32+
from typing import Dict
33+
34+
import aws_encryption_sdk
35+
from aws_encryption_sdk import CommitmentPolicy
36+
37+
# TODO-MPL: Remove this as part of removing PYTHONPATH hacks.
38+
MODULE_ROOT_DIR = '/'.join(__file__.split("/")[:-1])
39+
40+
sys.path.append(MODULE_ROOT_DIR)
41+
42+
EXAMPLE_DATA: bytes = b"Hello World"
43+
44+
45+
def encrypt_and_decrypt_with_keyring():
46+
"""Demonstrate an encrypt/decrypt cycle using a Raw AES keyring.
47+
48+
Usage: encrypt_and_decrypt_with_keyring()
49+
"""
50+
# 1. Instantiate the encryption SDK client.
51+
# This builds the client with the REQUIRE_ENCRYPT_REQUIRE_DECRYPT commitment policy,
52+
# which enforces that this client only encrypts using committing algorithm suites and enforces
53+
# that this client will only decrypt encrypted messages that were created with a committing
54+
# algorithm suite.
55+
# This is the default commitment policy if you were to build the client as
56+
# `client = aws_encryption_sdk.EncryptionSDKClient()`.
57+
client = aws_encryption_sdk.EncryptionSDKClient(
58+
commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT
59+
)
60+
61+
# 2. The key namespace and key name are defined by you.
62+
# and are used by the Raw AES keyring to determine
63+
# whether it should attempt to decrypt an encrypted data key.
64+
# For more information, see
65+
# https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-raw-aes-keyring.html
66+
key_name_space = "Some managed raw keys"
67+
key_name = "My 256-bit AES wrapping key"
68+
69+
# 3. Create encryption context.
70+
# Remember that your encryption context is NOT SECRET.
71+
# For more information, see
72+
# https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#encryption-context
73+
encryption_context: Dict[str, str] = {
74+
"encryption": "context",
75+
"is not": "secret",
76+
"but adds": "useful metadata",
77+
"that can help you": "be confident that",
78+
"the data you are handling": "is what you think it is",
79+
}
80+
81+
# 4. Generate a 256-bit AES key to use with your keyring.
82+
# Here, the input to secrets.token_bytes() = 32 bytes = 256 bits
83+
static_key = secrets.token_bytes(32)
84+
85+
# 5. Create a Raw AES keyring
86+
mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders(
87+
config=MaterialProvidersConfig()
88+
)
89+
90+
keyring_input: CreateRawAesKeyringInput = CreateRawAesKeyringInput(
91+
key_namespace=key_name_space,
92+
key_name=key_name,
93+
wrapping_key=static_key,
94+
wrapping_alg="ALG_AES256_GCM_IV12_TAG16"
95+
)
96+
97+
raw_aes_keyring: IKeyring = mat_prov.create_raw_aes_keyring(
98+
input=keyring_input
99+
)
100+
101+
# 6. Encrypt the data for the encryptionContext
102+
ciphertext, _ = client.encrypt(
103+
source=EXAMPLE_DATA,
104+
keyring=raw_aes_keyring,
105+
encryption_context=encryption_context
106+
)
107+
108+
# 7. Demonstrate that the ciphertext and plaintext are different.
109+
# (This is an example for demonstration; you do not need to do this in your own code.)
110+
assert ciphertext != EXAMPLE_DATA, \
111+
"Ciphertext and plaintext data are the same. Invalid encryption"
112+
113+
# 8. Decrypt your encrypted data using the same keyring you used on encrypt.
114+
plaintext_bytes, dec_header = client.decrypt(
115+
source=ciphertext,
116+
keyring=raw_aes_keyring
117+
)
118+
119+
# 9. Demonstrate that the encryption context is correct in the decrypted message header
120+
# (This is an example for demonstration; you do not need to do this in your own code.)
121+
for k, v in encryption_context.items():
122+
assert v == dec_header.encryption_context[k], \
123+
"Encryption context does not match expected values"
124+
125+
# 10. Demonstrate that the decrypted plaintext is identical to the original plaintext.
126+
# (This is an example for demonstration; you do not need to do this in your own code.)
127+
assert plaintext_bytes == EXAMPLE_DATA
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
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 Raw RSA Keyring
5+
6+
The Raw RSA keyring performs asymmetric encryption and decryption of data keys in local memory
7+
with RSA public and private keys that you provide. In this example, we define the RSA keys to
8+
encrypt and decrypt the data keys.
9+
10+
You need to generate, store, and protect the private key, preferably in a
11+
hardware security module (HSM) or key management system.
12+
The encryption function encrypts the data key under the RSA public key. The decryption function
13+
decrypts the data key using the private key.
14+
15+
This example creates a Raw RSA Keyring and then encrypts a custom input EXAMPLE_DATA
16+
with an encryption context. This example also includes some sanity checks for demonstration:
17+
1. Ciphertext and plaintext data are not the same
18+
2. Encryption context is correct in the decrypted message header
19+
3. Decrypted plaintext value matches EXAMPLE_DATA
20+
These sanity checks are for demonstration in the example only. You do not need these in your code.
21+
22+
A Raw RSA keyring that encrypts and decrypts must include an asymmetric public key and private
23+
key pair. However, you can encrypt data with a Raw RSA keyring that has only a public key,
24+
and you can decrypt data with a Raw RSA keyring that has only a private key. You can include
25+
any Raw RSA keyring in a multi-keyring. If you configure a Raw RSA keyring with a public and
26+
private key, be sure that they are part of the same key pair. Some language implementations
27+
of the AWS Encryption SDK will not construct a Raw RSA keyring with keys from different pairs.
28+
Others rely on you to verify that your keys are from the same key pair.
29+
30+
For more information on how to use Raw RSA keyrings, see
31+
https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-raw-rsa-keyring.html
32+
"""
33+
import sys
34+
35+
from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders
36+
from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig
37+
from aws_cryptographic_materialproviders.mpl.models import CreateRawRsaKeyringInput
38+
from aws_cryptographic_materialproviders.mpl.references import IKeyring
39+
from cryptography.hazmat.backends import default_backend as crypto_default_backend
40+
from cryptography.hazmat.primitives import serialization as crypto_serialization
41+
from cryptography.hazmat.primitives.asymmetric import rsa
42+
from typing import Dict
43+
44+
import aws_encryption_sdk
45+
from aws_encryption_sdk import CommitmentPolicy
46+
47+
# TODO-MPL: Remove this as part of removing PYTHONPATH hacks.
48+
MODULE_ROOT_DIR = '/'.join(__file__.split("/")[:-1])
49+
50+
sys.path.append(MODULE_ROOT_DIR)
51+
52+
EXAMPLE_DATA: bytes = b"Hello World"
53+
54+
55+
def generate_rsa_keyring():
56+
"""Creates a new RSA keyring along with generating new keys
57+
58+
Usage: generate_rsa_keyring()
59+
"""
60+
# 1. The key namespace and key name are defined by you.
61+
# and are used by the Raw RSA keyring
62+
# For more information, see
63+
# https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-raw-rsa-keyring.html
64+
key_name_space = "Some managed raw keys"
65+
key_name = "My 4096-bit RSA wrapping key"
66+
67+
# 2. Generate a 4096-bit RSA key to use with your keyring.
68+
ssh_rsa_exponent = 65537
69+
bit_strength = 4096
70+
key = rsa.generate_private_key(
71+
backend=crypto_default_backend(),
72+
public_exponent=ssh_rsa_exponent,
73+
key_size=bit_strength
74+
)
75+
76+
# This example choses a particular type of encoding, format and encryption_algorithm
77+
# Users can choose the PrivateFormat, PublicFormat and encryption_algorithm that align most
78+
# with their use-cases
79+
private_key = key.private_bytes(
80+
encoding=crypto_serialization.Encoding.PEM,
81+
format=crypto_serialization.PrivateFormat.TraditionalOpenSSL,
82+
encryption_algorithm=crypto_serialization.NoEncryption()
83+
)
84+
public_key = key.public_key().public_bytes(
85+
encoding=crypto_serialization.Encoding.PEM,
86+
format=crypto_serialization.PublicFormat.SubjectPublicKeyInfo
87+
)
88+
89+
# 3. Create a Raw RSA keyring
90+
mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders(
91+
config=MaterialProvidersConfig()
92+
)
93+
94+
keyring_input: CreateRawRsaKeyringInput = CreateRawRsaKeyringInput(
95+
key_namespace=key_name_space,
96+
key_name=key_name,
97+
padding_scheme="OAEP_SHA256_MGF1",
98+
public_key=public_key,
99+
private_key=private_key
100+
)
101+
102+
raw_rsa_keyring: IKeyring = mat_prov.create_raw_rsa_keyring(
103+
input=keyring_input
104+
)
105+
106+
return raw_rsa_keyring
107+
108+
109+
def encrypt_and_decrypt_with_keyring():
110+
"""Demonstrate an encrypt/decrypt cycle using a Raw RSA keyring.
111+
112+
Usage: encrypt_and_decrypt_with_keyring()
113+
"""
114+
# 1. Instantiate the encryption SDK client.
115+
# This builds the client with the REQUIRE_ENCRYPT_REQUIRE_DECRYPT commitment policy,
116+
# which enforces that this client only encrypts using committing algorithm suites and enforces
117+
# that this client will only decrypt encrypted messages that were created with a committing
118+
# algorithm suite.
119+
# This is the default commitment policy if you were to build the client as
120+
# `client = aws_encryption_sdk.EncryptionSDKClient()`.
121+
client = aws_encryption_sdk.EncryptionSDKClient(
122+
commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT
123+
)
124+
125+
# 2. Create encryption context.
126+
# Remember that your encryption context is NOT SECRET.
127+
# For more information, see
128+
# https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#encryption-context
129+
encryption_context: Dict[str, str] = {
130+
"encryption": "context",
131+
"is not": "secret",
132+
"but adds": "useful metadata",
133+
"that can help you": "be confident that",
134+
"the data you are handling": "is what you think it is",
135+
}
136+
137+
# 3. Create a Raw RSA keyring
138+
raw_rsa_keyring = generate_rsa_keyring()
139+
140+
# 4. Encrypt the data for the encryptionContext
141+
ciphertext, _ = client.encrypt(
142+
source=EXAMPLE_DATA,
143+
keyring=raw_rsa_keyring,
144+
encryption_context=encryption_context
145+
)
146+
147+
# 5. Demonstrate that the ciphertext and plaintext are different.
148+
# (This is an example for demonstration; you do not need to do this in your own code.)
149+
assert ciphertext != EXAMPLE_DATA, \
150+
"Ciphertext and plaintext data are the same. Invalid encryption"
151+
152+
# 6. Decrypt your encrypted data using the same keyring you used on encrypt.
153+
plaintext_bytes, dec_header = client.decrypt(
154+
source=ciphertext,
155+
keyring=raw_rsa_keyring
156+
)
157+
158+
# 7. Demonstrate that the encryption context is correct in the decrypted message header
159+
# (This is an example for demonstration; you do not need to do this in your own code.)
160+
for k, v in encryption_context.items():
161+
assert v == dec_header.encryption_context[k], \
162+
"Encryption context does not match expected values"
163+
164+
# 8. Demonstrate that the decrypted plaintext is identical to the original plaintext.
165+
# (This is an example for demonstration; you do not need to do this in your own code.)
166+
assert plaintext_bytes == EXAMPLE_DATA
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
"""Test suite for the Raw AES keyring example."""
4+
import pytest
5+
6+
from ...src.keyrings.raw_aes_keyring_example import encrypt_and_decrypt_with_keyring
7+
8+
pytestmark = [pytest.mark.examples]
9+
10+
11+
def test_encrypt_and_decrypt_with_keyring():
12+
"""Test function for encrypt and decrypt using the Raw AES Keyring example."""
13+
encrypt_and_decrypt_with_keyring()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
"""Test suite for the Raw AES keyring example."""
4+
import pytest
5+
6+
from ...src.keyrings.raw_rsa_keyring_example import encrypt_and_decrypt_with_keyring
7+
8+
pytestmark = [pytest.mark.examples]
9+
10+
11+
def test_encrypt_and_decrypt_with_keyring():
12+
"""Test function for encrypt and decrypt using the Raw AES Keyring example."""
13+
encrypt_and_decrypt_with_keyring()

0 commit comments

Comments
 (0)