Skip to content

docs: add AES example and rules for example templates #177

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

Merged
merged 4 commits into from
Jul 20, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 52 additions & 1 deletion examples/examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,14 @@

## Version

0.1.0
0.2.0

### Changelog

- 0.2.0

- Add [Example Templates](#example-templates) section

- 0.1.0

- [Require examples](../changes/2020-06-16_required-examples/change.md)
Expand Down Expand Up @@ -50,3 +54,50 @@ in this document are to be interpreted as described in
- ex: Raw keyring examples generate wrapping keys as part of the example.
These examples MUST contain guidance that
in production those keys SHOULD be managed by an HSM.

### Example Templates

Each example is defined by a [template](./templates).
Templates MUST include sufficient code to clearly demonstrate
how to implement an example.
This code MAY be in any language.

Each template MUST contain the following sections:

1. Header :
This is a detailed description
that independently describes the purpose of the example
and what it describes.
It includes any links to supporting documentation.

- Implementations MUST include this text verbatim
at the top of the file,
adjusted appropriately for language comment syntax.

1. Summary :
One-sentence summary of the header.

- Implementations MUST include this text verbatim
in the documentation for the example entry point
function/method/etc,
adjusted appropriately for language comment syntax.

1. Inputs :
List of inputs that the example entry point MUST accept,
with an accompanying description.

- Implementations MUST provide all of these inputs in CI
as part of their testing framework.
- Implementations MUST name their inputs to match the naming of
the input in the template.
- Implementations MUST use the description text verbatim,
adjusted appropriately for language comment syntax.

1. Steps :
List of steps that define the example.

- Implementations MUST include every step.
- Implementations MUST include any comments verbatim,
adjusted appropriately for language comment syntax.
- Implementations MAY alter the order of steps
if another order is more appropriate for that language.
132 changes: 132 additions & 0 deletions examples/templates/configuration/raw-keyrings/raw-aes-keyring.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
[//]: # "Copyright Amazon.com Inc. or its affiliates. All Rights Reserved."
[//]: # "SPDX-License-Identifier: CC-BY-SA-4.0"

# Raw AES keyring example

Implementations of this example MUST follow the rules defined in
[Example Templates](../../../examples.md#example-templates).

## Implementations

- [Python (DEV)](https://github.com/aws/aws-encryption-sdk-python/blob/keyring/examples/src/keyring/raw_aes/raw_aes.py)
- [Python Master Key Provider (DEV)](https://github.com/aws/aws-encryption-sdk-python/blob/keyring/examples/src/master_key_provider/raw_aes/raw_aes.py)
- [Java (DEV)](https://github.com/aws/aws-encryption-sdk-java/blob/keyring/src/examples/java/com/amazonaws/crypto/examples/keyring/rawaes/RawAes.java)
- [Java Master Key Provider (DEV)](https://github.com/aws/aws-encryption-sdk-java/blob/keyring/src/examples/java/com/amazonaws/crypto/examples/masterkeyprovider/rawaes/RawAes.java)
Comment on lines +11 to +14
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

np: Should this be a table instead?

Also, what about JavaScript and C?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Neither JS nor C have these examples yet. We use a simple list for similar things elsewhere; IMO if we only have one column it's not worth a table.


## Definitions

### Conventions used in this document

The key words
"MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL"
in this document are to be interpreted as described in
[RFC 2119](https://tools.ietf.org/html/rfc2119).

## Header

```python
# This examples shows how to configure and use a raw AES keyring.
#
# https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/choose-keyring.html#use-raw-aes-keyring
#
# In this example, we use the one-step encrypt and decrypt APIs.
```

## Summary

```python
# Demonstrate an encrypt/decrypt cycle using a raw AES keyring.
```

## Inputs

- **source plaintext** :
Plaintext to encrypt

## Steps

1. Define encryption context.

```python
# Prepare your encryption context.
# Remember that your encryption context is NOT SECRET.
# 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",
}
```

1. Generate the wrapping key.

```python
# Generate a 256-bit (32 byte) AES key to use with your keyring.
#
# In practice, you should get this key from a secure key management system such as an HSM.
key = os.urandom(32)
```

1. Create keyring.

```python
# Create the keyring that determines how your data keys are protected.
keyring = RawAESKeyring(
# The key namespace and key name are defined by you
# and are used by the raw AES keyring
# to determine whether it should attempt to decrypt
# an encrypted data key.
#
# https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/choose-keyring.html#use-raw-aes-keyring
key_namespace="some managed raw keys",
key_name="my AES wrapping key",
wrapping_key=key,
)
```

1. Encrypt plaintext data.

```python
# Encrypt your plaintext data.
ciphertext, _encrypt_header = aws_encryption_sdk.encrypt(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
ciphertext, _encrypt_header = aws_encryption_sdk.encrypt(
ciphertext, encrypt_header = aws_encryption_sdk.encrypt(

I wasn't sure if the _ was supposed to be there.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is, yes. In Python in this use, that denotes "I need to collect this variable and I want to give it a name for clarity, but I do not intend to ever use it."

source=source_plaintext, encryption_context=encryption_context, keyring=keyring
)
```

1. Compare ciphertext to plaintext.

```python
# Demonstrate that the ciphertext and plaintext are different.
assert ciphertext != source_plaintext
```

1. Decrypt encrypted data.

```python
# Decrypt your encrypted data using the same keyring you used on encrypt.
#
# You do not need to specify the encryption context on decrypt
# because the header of the encrypted message includes the encryption context.
decrypted, decrypt_header = aws_encryption_sdk.decrypt(source=ciphertext, keyring=keyring)
```

1. Compare the decrypted plaintext and original plaintext.

```python
# Demonstrate that the decrypted plaintext is identical to the original plaintext.
assert decrypted == source_plaintext
```

1. Verify the encryption context.

```python
# 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(decrypt_header.encryption_context.items())
```