-
Notifications
You must be signed in to change notification settings - Fork 86
Examples refresh, take 1 #219
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
0938325
ee1b4cc
9351933
3b62bc3
626d5ba
83f4ff8
d3383c6
534e225
42e86ab
6b84d3a
2dfe2d0
fabc5e3
67f0ddc
30eab33
453b82d
2208890
d724335
306d1a9
bde7a56
b7e9dd1
4d8c7a0
1fdbb32
d3240eb
4eb5fde
bb6c650
1de8d5c
baf1164
d89e6dc
3af7795
a833f52
9e5fcd4
38e2757
a7fcb4a
862734a
850d8c9
4def8ba
f00fdd2
c232607
81d79d3
8026e31
9d07fde
421e121
4c53891
675c4dd
ef475d7
371daaf
886341c
460e6e1
7a81af4
78484eb
a818ea5
52906eb
7d7ddcc
36df978
95047f1
1815399
b0c7c80
c54f21a
727ebab
0af1cf9
68b35c3
f054b12
d31b40d
57077b1
f1469f1
586f88e
bf2e6c9
3c19f1f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
# AWS Encryption SDK Examples | ||
|
||
This section features examples that show you | ||
how to use the AWS Encryption SDK. | ||
We demonstrate how to use the encryption and decryption APIs | ||
and how to set up some common configuration patterns. | ||
|
||
## APIs | ||
|
||
The AWS Encryption SDK provides two high-level APIs: | ||
one-step APIs that process the entire operation in memory | ||
and streaming APIs. | ||
|
||
You can find examples that demonstrate these APIs | ||
in the [`examples/src/`](./src) directory. | ||
|
||
## Configuration | ||
|
||
To use the library APIs, | ||
you need to describe how you want the library to protect your data keys. | ||
You can do this using | ||
[keyrings][#keyrings] or [cryptographic materials managers][#cryptographic-materials-managers], | ||
or using [master key providers][#master-key-providers]. | ||
These examples will show you how. | ||
|
||
### Keyrings | ||
|
||
Keyrings are the most common way for you to configure the AWS Encryption SDK. | ||
They determine how the AWS Encryption SDK protects your data. | ||
You can find these examples in [`examples/src/keyring`](./src/keyring). | ||
|
||
### Cryptographic Materials Managers | ||
|
||
Keyrings define how your data keys are protected, | ||
but there is more going on here than just protecting data keys. | ||
|
||
Cryptographic materials managers give you higher-level controls | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. higher-level or lower-level? I think of the CMM as lower-level. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Higher-level than keyrings. |
||
over how the AWS Encryption SDK protects your data. | ||
This can include things like | ||
enforcing the use of certain algorithm suites or encryption context settings, | ||
reusing data keys across messages, | ||
or changing how you interact with keyrings. | ||
You can find these examples in | ||
[`examples/src/crypto_materials_manager`](./src/crypto_materials_manager). | ||
|
||
### Master Key Providers | ||
|
||
Before there were keyrings, there were master key providers. | ||
Master key providers were the original configuration structure | ||
that we provided for defining how you want to protect your data keys. | ||
Keyrings provide a simpler experience and often more powerful configuration options, | ||
but if you need to use master key providers, | ||
need help migrating from master key providers to keyrings, | ||
or simply want to see the difference between these configuration experiences, | ||
you can find these examples in [`examples/src/master_key_provider`](./src/master_key_provider). | ||
mattsb42-aws marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
## Legacy | ||
|
||
This section includes older examples, including examples of using master keys and master key providers in Java and Python. | ||
You can use them as a reference, | ||
but we recommend looking at the newer examples, which explain the preferred ways of using this library. | ||
You can find these examples in [`examples/src/legacy`](./src/legacy). | ||
|
||
# Writing Examples | ||
|
||
If you want to contribute a new example, that's awesome! | ||
To make sure that your example is tested in our CI, | ||
please make sure that it meets the following requirements: | ||
|
||
1. The example MUST be a distinct module in the [`examples/src/`](./src) directory. | ||
1. The example MAY be nested arbitrarily deeply, | ||
but every intermediate directory MUST contain a `__init__.py` file | ||
so that CPython 2.7 will recognize it as a module. | ||
1. Every example MUST be CPython 2.7 compatible. | ||
1. Each example file MUST contain exactly one example. | ||
1. Each example file MUST contain a function called `run` that runs the example. | ||
1. If your `run` function needs any of the following inputs, | ||
the parameters MUST have the following names: | ||
* `aws_kms_cmk` (`str`) : A single AWS KMS CMK ARN. | ||
* NOTE: You can assume that automatically discovered credentials have | ||
`kms:GenerateDataKey`, `kms:Encrypt`, and `kms:Decrypt` permissions on this CMK. | ||
* `aws_kms_generator_cmk` (`str`) : A single AWS KMS CMK ARN to use as a generator key. | ||
* NOTE: You can assume that automatically discovered credentials have | ||
`kms:GenerateDataKey`, `kms:Encrypt`, and `kms:Decrypt` permissions on this CMK. | ||
* `aws_kms_additional_cmks` (`List[str]`) : | ||
A list of AWS KMS CMK ARNs to use for encrypting and decrypting data keys. | ||
* NOTE: You can assume that automatically discovered credentials have | ||
`kms:Encrypt` and `kms:Decrypt` permissions on these CMKs. | ||
* `source_plaintext` (`bytes`) : Plaintext data to encrypt. | ||
* `source_plaintext_filename` (`str`) : A path to a file containing plaintext to encrypt. | ||
* NOTE: You can assume that you have write access to the parent directory | ||
and that anything you do in that directory will be cleaned up | ||
by our test runners. | ||
1. Any additional parameters MUST be optional. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. | ||
# SPDX-License-Identifier: Apache-2.0 | ||
""" | ||
This example shows how to use the streaming encrypt and decrypt APIs when working with files. | ||
|
||
One benefit of using the streaming API is that | ||
we can check the encryption context in the header before we start decrypting. | ||
|
||
In this example, we use an AWS KMS customer master key (CMK), | ||
but you can use other key management options with the AWS Encryption SDK. | ||
For examples that demonstrate how to use other key management configurations, | ||
see the ``keyring`` and ``master_key_provider`` directories. | ||
""" | ||
import filecmp | ||
|
||
import aws_encryption_sdk | ||
from aws_encryption_sdk.keyrings.aws_kms import KmsKeyring | ||
|
||
|
||
def run(aws_kms_cmk, source_plaintext_filename): | ||
# type: (str, str) -> None | ||
"""Demonstrate an encrypt/decrypt cycle using the streaming encrypt/decrypt APIs with files. | ||
|
||
:param str aws_kms_cmk: The ARN of an AWS KMS CMK that protects data keys | ||
:param str source_plaintext_filename: Path to plaintext file to encrypt | ||
""" | ||
# We assume that you can also write to the directory containing the plaintext file, | ||
# so that is where we will put all of the results. | ||
ciphertext_filename = source_plaintext_filename + ".encrypted" | ||
decrypted_filename = ciphertext_filename + ".decrypted" | ||
|
||
# Prepare your encryption context. | ||
mattsb42-aws marked this conversation as resolved.
Show resolved
Hide resolved
|
||
# https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#encryption-context | ||
encryption_context = { | ||
"encryption": "context", | ||
"is not": "secret", | ||
"but adds": "useful metadata", | ||
"that can help you": "be confident that", | ||
"the data you are handling": "is what you think it is", | ||
juneb marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
# Create the keyring that determines how your data keys are protected. | ||
keyring = KmsKeyring(generator_key_id=aws_kms_cmk) | ||
|
||
# Open the files you want to work with. | ||
with open(source_plaintext_filename, "rb") as plaintext, open(ciphertext_filename, "wb") as ciphertext: | ||
# The streaming API provides a context manager. | ||
# You can read from it just as you read from a file. | ||
with aws_encryption_sdk.stream( | ||
mode="encrypt", source=plaintext, encryption_context=encryption_context, keyring=keyring | ||
) as encryptor: | ||
# Iterate through the segments in the context manager | ||
# and write the results to the ciphertext. | ||
for segment in encryptor: | ||
ciphertext.write(segment) | ||
|
||
# Verify that the ciphertext and plaintext are different. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Kind of a low bar ... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is, but I'm not sure what else we can really make a concrete statement about to demonstrate that "yes, this is encrypted" without getting really complicated. |
||
assert not filecmp.cmp(source_plaintext_filename, ciphertext_filename) | ||
|
||
# Open the files you want to work with. | ||
with open(ciphertext_filename, "rb") as ciphertext, open(decrypted_filename, "wb") as decrypted: | ||
# Decrypt your encrypted data using the same keyring you used on encrypt. | ||
# | ||
# We do not need to specify the encryption context on decrypt | ||
# because the message header includes the encryption context. | ||
with aws_encryption_sdk.stream(mode="decrypt", source=ciphertext, keyring=keyring) as decryptor: | ||
# Check the encryption context in the header before we start decrypting. | ||
# | ||
# Verify that the encryption context used in the decrypt operation includes | ||
# the encryption context that you specified when encrypting. | ||
# The AWS Encryption SDK can add pairs, so don't require an exact match. | ||
# | ||
# In production, always use a meaningful encryption context. | ||
assert set(encryption_context.items()) <= set(decryptor.header.encryption_context.items()) | ||
|
||
# Now that we are more confident that we will decrypt the right message, | ||
# we can start decrypting. | ||
for segment in decryptor: | ||
decrypted.write(segment) | ||
|
||
# Verify that the decrypted plaintext is identical to the original plaintext. | ||
assert filecmp.cmp(source_plaintext_filename, decrypted_filename) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. | ||
# SPDX-License-Identifier: Apache-2.0 | ||
""" | ||
This example shows how to use the streaming encrypt and decrypt APIs on data in memory. | ||
|
||
One benefit of using the streaming API is that | ||
we can check the encryption context in the header before we start decrypting. | ||
|
||
In this example, we use an AWS KMS customer master key (CMK), | ||
but you can use other key management options with the AWS Encryption SDK. | ||
For examples that demonstrate how to use other key management configurations, | ||
see the ``keyring`` and ``mater_key_provider`` directories. | ||
""" | ||
import io | ||
|
||
import aws_encryption_sdk | ||
from aws_encryption_sdk.keyrings.aws_kms import KmsKeyring | ||
|
||
|
||
def run(aws_kms_cmk, source_plaintext): | ||
# type: (str, bytes) -> None | ||
"""Demonstrate an encrypt/decrypt cycle using the streaming encrypt/decrypt APIs in-memory. | ||
|
||
:param str aws_kms_cmk: The ARN of an AWS KMS CMK that protects data keys | ||
:param bytes source_plaintext: Plaintext to encrypt | ||
""" | ||
# Prepare your encryption context. | ||
# https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#encryption-context | ||
encryption_context = { | ||
"encryption": "context", | ||
"is not": "secret", | ||
"but adds": "useful metadata", | ||
"that can help you": "be confident that", | ||
"the data you are handling": "is what you think it is", | ||
} | ||
|
||
# Create the keyring that determines how your data keys are protected. | ||
mattsb42-aws marked this conversation as resolved.
Show resolved
Hide resolved
|
||
keyring = KmsKeyring(generator_key_id=aws_kms_cmk) | ||
|
||
ciphertext = io.BytesIO() | ||
|
||
# The streaming API provides a context manager. | ||
# You can read from it just as you read from a file. | ||
with aws_encryption_sdk.stream( | ||
mode="encrypt", source=source_plaintext, encryption_context=encryption_context, keyring=keyring | ||
) as encryptor: | ||
# Iterate through the segments in the context manager | ||
# and write the results to the ciphertext. | ||
for segment in encryptor: | ||
ciphertext.write(segment) | ||
|
||
# Verify that the ciphertext and plaintext are different. | ||
assert ciphertext.getvalue() != source_plaintext | ||
|
||
# Reset the ciphertext stream position so that we can read from the beginning. | ||
ciphertext.seek(0) | ||
|
||
# Decrypt your encrypted data using the same keyring you used on encrypt. | ||
# | ||
# We do not need to specify the encryption context on decrypt | ||
# because the header message includes the encryption context. | ||
decrypted = io.BytesIO() | ||
with aws_encryption_sdk.stream(mode="decrypt", source=ciphertext, keyring=keyring) as decryptor: | ||
mattsb42-aws marked this conversation as resolved.
Show resolved
Hide resolved
|
||
# Check the encryption context in the header before we start decrypting. | ||
# | ||
# Verify that the encryption context used in the decrypt operation includes | ||
# the encryption context that you specified when encrypting. | ||
# The AWS Encryption SDK can add pairs, so don't require an exact match. | ||
# | ||
# In production, always use a meaningful encryption context. | ||
assert set(encryption_context.items()) <= set(decryptor.header.encryption_context.items()) | ||
|
||
# Now that we are more confident that we will decrypt the right message, | ||
# we can start decrypting. | ||
for segment in decryptor: | ||
decrypted.write(segment) | ||
|
||
# Verify that the decrypted plaintext is identical to the original plaintext. | ||
assert decrypted.getvalue() == source_plaintext |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. | ||
# SPDX-License-Identifier: Apache-2.0 | ||
""" | ||
Legacy examples. | ||
|
||
We keep these older examples as reference material, | ||
but we recommend that you use the new examples. | ||
The new examples reflect our current guidance for using the library. | ||
""" |
Uh oh!
There was an error while loading. Please reload this page.