Skip to content

Commit b262fe5

Browse files
committed
updated readme and __init__.py
1 parent 44d1746 commit b262fe5

File tree

2 files changed

+104
-113
lines changed

2 files changed

+104
-113
lines changed

README.rst

Lines changed: 98 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -147,99 +147,80 @@ version of the AWS Encryption SDK, we recommend using the default value.
147147
148148
You must then create an instance of either a keyring (with the MPL installed) or a CMM.
149149
(You may also provide an instance of a legacy master key provider, but this is not recommended.)
150-
The examples in this README use the ``AwsKmsKeyring`` class.
150+
The examples in this README use the ``AwsKmsMultiKeyring`` class.
151151
Note: You must also install the `AWS Cryptographic Material Providers Library (MPL)`_ to use this class.
152152

153153

154-
AwsKmsKeyring
155-
=============================
156-
An ``AwsKmsKeyring`` is configured with an AWS KMS key ARN whose AWS KMS key
157-
will be used to generate, encrypt, and decrypt data keys.
158-
On encryption, it encrypts the plaintext with the data key.
159-
On decryption, it decrypts an encrypted version of the data key,
160-
then uses the decrypted data key to decrypt the ciphertext.
154+
AwsKmsMultiKeyring
155+
==================
161156

162-
To create an ``AwsKmsKeyring`` you must provide a AWS KMS key ARN.
157+
An ``AwsKmsMultiKeyring`` is configured with a generator keyring and a list of
158+
child keyrings of type ``AwsKmsKeyring``. The effect is like using several keyrings
159+
in a series. When you use a multi-keyring to encrypt data, any of the wrapping keys
160+
in any of its keyrings can decrypt that data.
161+
162+
On encryption, the generator keyring generates and encrypts the plaintext data key.
163+
Then, all of the wrapping keys in all of the child keyrings encrypt the same plaintext data key.
164+
On decryption, the AWS Encryption SDK uses the keyrings to try to decrypt one of the encrypted data keys.
165+
The keyrings are called in the order that they are specified in the multi-keyring.
166+
Processing stops as soon as any key in any keyring can decrypt an encrypted data key.
167+
168+
An individual ``AwsKmsKeyring`` in an ``AwsKmsMultiKeyring`` is configured with an
169+
AWS KMS key ARN.
163170
For keyrings that will only be used for encryption,
164171
you can use any valid `KMS key identifier`_.
165172
For providers that will be used for decryption,
166173
you must use the key ARN.
167174
Key ids, alias names, and alias ARNs are not supported for decryption.
168175

169-
Because the ``AwsKmsKeyring`` uses the `boto3 SDK`_ to interact with `AWS KMS`_,
176+
Because the ``AwsKmsMultiKeyring`` uses the `boto3 SDK`_ to interact with `AWS KMS`_,
170177
it requires AWS Credentials.
171178
To provide these credentials, use the `standard means by which boto3 locates credentials`_ or provide a
172-
pre-existing instance of a ``botocore session`` to the ``AwsKmsKeyring``.
179+
pre-existing instance of a ``botocore session`` to the ``AwsKmsMultiKeyring``.
173180
This latter option can be useful if you have an alternate way to store your AWS credentials or
174181
you want to reuse an existing instance of a botocore session in order to decrease startup costs.
175182

176183
.. code:: python
177184
178-
import boto3
179185
from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders
180186
from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig
181-
from aws_cryptographic_materialproviders.mpl.models import CreateAwsKmsKeyringInput
187+
from aws_cryptographic_materialproviders.mpl.models import CreateAwsKmsMultiKeyringInput
182188
from aws_cryptographic_materialproviders.mpl.references import IKeyring
183189
184-
import aws_encryption_sdk
185-
from aws_encryption_sdk import CommitmentPolicy
186-
187-
# Instantiate the encryption SDK client.
188-
client = aws_encryption_sdk.EncryptionSDKClient(
189-
commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT
190-
)
191-
192-
# Create a KMS keyring.
190+
# Create an AwsKmsMultiKeyring that protects your data under two different KMS Keys.
191+
# Either KMS Key individually is capable of decrypting data encrypted under this Multi Keyring.
193192
mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders(
194193
config=MaterialProvidersConfig()
195194
)
196195
197-
keyring_input: CreateAwsKmsKeyringInput = CreateAwsKmsKeyringInput(
198-
kms_key_id='arn:aws:kms:us-east-1:2222222222222:key/22222222-2222-2222-2222-222222222222',
199-
kms_client=boto3.client('kms', region_name="us-east-1")
196+
kms_multi_keyring_input: CreateAwsKmsMultiKeyringInput = CreateAwsKmsMultiKeyringInput(
197+
generator='arn:aws:kms:us-east-1:2222222222222:key/22222222-2222-2222-2222-222222222222',
198+
kms_key_ids=['arn:aws:kms:us-east-1:3333333333333:key/33333333-3333-3333-3333-333333333333']
200199
)
201200
202-
kms_keyring: IKeyring = mat_prov.create_aws_kms_keyring(
203-
input=keyring_input
201+
kms_multi_keyring: IKeyring = mat_prov.create_aws_kms_multi_keyring(
202+
input=kms_multi_keyring_input
204203
)
205204
206-
207-
If you want to configure a keyring with multiple AWS KMS keys, see the multi-keyring.
208-
209-
MultiKeyring
210-
============
211-
212-
A ``MultiKeyring`` is configured with an optional generator keyring and a list of
213-
child keyrings of the same or a different type.
214-
215-
The effect is like using several keyrings in a series. When you use a multi-keyring to
216-
encrypt data, any of the wrapping keys in any of its keyrings can decrypt that data.
205+
You can add KMS keys from multiple regions to the ``AwsKmsMultiKeyring``.
217206

218207
.. code:: python
219208
220-
import boto3
221209
from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders
222210
from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig
223211
from aws_cryptographic_materialproviders.mpl.models import CreateAwsKmsMultiKeyringInput
224212
from aws_cryptographic_materialproviders.mpl.references import IKeyring
225213
226-
import aws_encryption_sdk
227-
from aws_encryption_sdk import CommitmentPolicy
228-
229-
# Instantiate the encryption SDK client.
230-
client = aws_encryption_sdk.EncryptionSDKClient(
231-
commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT
232-
)
233-
234-
# Create an AwsKmsMultiKeyring that protects your data under two different KMS Keys.
214+
# Create an AwsKmsMultiKeyring that protects your data under three different KMS Keys.
235215
# Either KMS Key individually is capable of decrypting data encrypted under this Multi Keyring.
236216
mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders(
237217
config=MaterialProvidersConfig()
238218
)
239219
240220
kms_multi_keyring_input: CreateAwsKmsMultiKeyringInput = CreateAwsKmsMultiKeyringInput(
241221
generator='arn:aws:kms:us-east-1:2222222222222:key/22222222-2222-2222-2222-222222222222',
242-
kms_key_ids=['arn:aws:kms:us-east-1:3333333333333:key/33333333-3333-3333-3333-333333333333']
222+
kms_key_ids=['arn:aws:kms:us-west-2:3333333333333:key/33333333-3333-3333-3333-333333333333',
223+
'arn:aws:kms:ap-northeast-1:4444444444444:key/44444444-4444-4444-4444-444444444444']
243224
)
244225
245226
kms_multi_keyring: IKeyring = mat_prov.create_aws_kms_multi_keyring(
@@ -249,9 +230,8 @@ encrypt data, any of the wrapping keys in any of its keyrings can decrypt that d
249230
250231
AwsKmsDiscoveryKeyring
251232
======================
252-
We recommend using an ``AwsKmsKeyring`` in order to ensure that you can only
253-
encrypt and decrypt data using the AWS KMS key ARN you expect,
254-
or a ``MultiKeyring`` if you are using multiple keys. However, if you are unable to
233+
We recommend using an ``AwsKmsMultiKeyring`` in order to ensure that you can only
234+
encrypt and decrypt data using the AWS KMS key ARN you expect. However, if you are unable to
255235
explicitly identify the AWS KMS key ARNs that should be used for decryption, you can instead
256236
use an ``AwsKmsDiscoveryKeyring`` for decryption operations. This provider
257237
attempts decryption of any ciphertexts as long as they match a ``DiscoveryFilter`` that
@@ -263,20 +243,12 @@ partition.
263243
import boto3
264244
from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders
265245
from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig
266-
ffrom aws_cryptographic_materialproviders.mpl.models import (
246+
from aws_cryptographic_materialproviders.mpl.models import (
267247
CreateAwsKmsDiscoveryKeyringInput,
268248
DiscoveryFilter,
269249
)
270250
from aws_cryptographic_materialproviders.mpl.references import IKeyring
271251
272-
import aws_encryption_sdk
273-
from aws_encryption_sdk import CommitmentPolicy
274-
275-
# Instantiate the encryption SDK client.
276-
client = aws_encryption_sdk.EncryptionSDKClient(
277-
commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT
278-
)
279-
280252
# Create a Discovery keyring to use for decryption
281253
mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders(
282254
config=MaterialProvidersConfig()
@@ -304,78 +276,94 @@ Encryption and Decryption
304276
After you create an instance of an ``EncryptionSDKClient`` and a ``Keyring``, you can use either of
305277
the client's two ``encrypt``/``decrypt`` functions to encrypt and decrypt your data.
306278

307-
Here's an example for using a KMS keyring for encryption and decryption:
308-
309279
.. code:: python
310280
311-
# Encrypt the data.
312-
my_ciphertext, enc_header = client.encrypt(
281+
from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders
282+
from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig
283+
from aws_cryptographic_materialproviders.mpl.models import CreateAwsKmsMultiKeyringInput
284+
from aws_cryptographic_materialproviders.mpl.references import IKeyring
285+
286+
import aws_encryption_sdk
287+
from aws_encryption_sdk.identifiers import CommitmentPolicy
288+
289+
client = aws_encryption_sdk.EncryptionSDKClient(
290+
commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_ALLOW_DECRYPT
291+
)
292+
293+
mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders(
294+
config=MaterialProvidersConfig()
295+
)
296+
297+
kms_multi_keyring_input: CreateAwsKmsMultiKeyringInput = CreateAwsKmsMultiKeyringInput(
298+
generator='arn:aws:kms:us-east-1:2222222222222:key/22222222-2222-2222-2222-222222222222',
299+
kms_key_ids=['arn:aws:kms:us-east-1:3333333333333:key/33333333-3333-3333-3333-333333333333']
300+
)
301+
302+
kms_multi_keyring: IKeyring = mat_prov.create_aws_kms_multi_keyring(
303+
input=kms_multi_keyring_input
304+
)
305+
306+
my_plaintext = b'This is some super secret data! Yup, sure is!'
307+
308+
my_ciphertext, encryptor_header = client.encrypt(
313309
source=my_plaintext,
314-
keyring=kms_keyring
310+
keyring=kms_multi_keyring
315311
)
316312
317-
# Decrypt your encrypted data.
318-
my_decrypted_plaintext, dec_header = client.decrypt(
313+
decrypted_plaintext, decryptor_header = client.decrypt(
319314
source=my_ciphertext,
320-
keyring=kms_keyring
315+
keyring=kms_multi_keyring
321316
)
322317
323-
You can provide an `encryption context`_: a form of additional authenticating information.
318+
assert my_plaintext == decrypted_plaintext
324319
325-
Here's an example for using KMS keyring with an encryption context:
320+
You can provide an `encryption context`_: a form of additional authenticating information.
326321

327322
.. code:: python
328323
329-
import boto3
330324
from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders
331325
from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig
332-
from aws_cryptographic_materialproviders.mpl.models import CreateAwsKmsKeyringInput
326+
from aws_cryptographic_materialproviders.mpl.models import CreateAwsKmsMultiKeyringInput
333327
from aws_cryptographic_materialproviders.mpl.references import IKeyring
334328
335329
import aws_encryption_sdk
336-
from aws_encryption_sdk import CommitmentPolicy
330+
from aws_encryption_sdk.identifiers import CommitmentPolicy
337331
338-
# Instantiate the encryption SDK client.
339332
client = aws_encryption_sdk.EncryptionSDKClient(
340-
commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT
333+
commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_ALLOW_DECRYPT
341334
)
342335
343-
# Create an encryption context
344-
encryption_context: Dict[str, str] = {
345-
"encryption": "context",
346-
"is not": "secret",
347-
"but adds": "useful metadata",
348-
"that can help you": "be confident that",
349-
"the data you are handling": "is what you think it is",
350-
}
351-
352-
# Create a KMS keyring.
353336
mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders(
354337
config=MaterialProvidersConfig()
355338
)
356339
357-
keyring_input: CreateAwsKmsKeyringInput = CreateAwsKmsKeyringInput(
358-
kms_key_id='arn:aws:kms:us-east-1:2222222222222:key/22222222-2222-2222-2222-222222222222',
359-
kms_client=boto3.client('kms', region_name="us-east-1")
340+
kms_multi_keyring_input: CreateAwsKmsMultiKeyringInput = CreateAwsKmsMultiKeyringInput(
341+
generator='arn:aws:kms:us-east-1:2222222222222:key/22222222-2222-2222-2222-222222222222',
342+
kms_key_ids=['arn:aws:kms:us-east-1:3333333333333:key/33333333-3333-3333-3333-333333333333']
360343
)
361344
362-
kms_keyring: IKeyring = mat_prov.create_aws_kms_keyring(
363-
input=keyring_input
345+
kms_multi_keyring: IKeyring = mat_prov.create_aws_kms_multi_keyring(
346+
input=kms_multi_keyring_input
364347
)
348+
349+
my_plaintext = b'This is some super secret data! Yup, sure is!'
365350
366-
# Encrypt the data with the encryptionContext.
367-
my_ciphertext, enc_header = client.encrypt(
351+
my_ciphertext, encryptor_header = client.encrypt(
368352
source=my_plaintext,
369-
keyring=kms_keyring,
370-
encryption_context=encryption_context
353+
keyring=kms_multi_keyring,
354+
encryption_context={
355+
'not really': 'a secret',
356+
'but adds': 'some authentication'
357+
}
371358
)
372359
373-
# Decrypt your encrypted data.
374-
my_decrypted_plaintext, dec_header = client.decrypt(
360+
decrypted_plaintext, decryptor_header = client.decrypt(
375361
source=my_ciphertext,
376-
keyring=kms_keyring
362+
keyring=kms_multi_keyring
377363
)
378364
365+
assert my_plaintext == decrypted_plaintext
366+
379367
380368
Streaming
381369
=========
@@ -386,59 +374,56 @@ offering context manager and iteration support.
386374

387375
.. code:: python
388376
389-
import boto3
390377
from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders
391378
from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig
392-
from aws_cryptographic_materialproviders.mpl.models import CreateAwsKmsKeyringInput
379+
from aws_cryptographic_materialproviders.mpl.models import CreateAwsKmsMultiKeyringInput
393380
from aws_cryptographic_materialproviders.mpl.references import IKeyring
394381
395382
import aws_encryption_sdk
396-
from aws_encryption_sdk import CommitmentPolicy
383+
from aws_encryption_sdk.identifiers import CommitmentPolicy
397384
398-
# Instantiate the encryption SDK client.
399385
client = aws_encryption_sdk.EncryptionSDKClient(
400386
commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_ALLOW_DECRYPT
401387
)
402388
403-
# Create a keyring.
404389
mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders(
405390
config=MaterialProvidersConfig()
406391
)
407392
408-
keyring_input: CreateAwsKmsKeyringInput = CreateAwsKmsKeyringInput(
409-
kms_key_id='arn:aws:kms:us-east-1:2222222222222:key/22222222-2222-2222-2222-222222222222',
410-
kms_client=boto3.client('kms', region_name="us-east-1")
393+
kms_multi_keyring_input: CreateAwsKmsMultiKeyringInput = CreateAwsKmsMultiKeyringInput(
394+
generator='arn:aws:kms:us-east-1:2222222222222:key/22222222-2222-2222-2222-222222222222',
395+
kms_key_ids=['arn:aws:kms:us-east-1:3333333333333:key/33333333-3333-3333-3333-333333333333']
411396
)
412397
413-
kms_keyring: IKeyring = mat_prov.create_aws_kms_keyring(
414-
input=keyring_input
398+
kms_multi_keyring: IKeyring = mat_prov.create_aws_kms_multi_keyring(
399+
input=kms_multi_keyring_input
415400
)
416401
417402
plaintext_filename = 'my-secret-data.dat'
418403
ciphertext_filename = 'my-encrypted-data.ct'
419404
420-
# Encrypt the data stream.
421405
with open(plaintext_filename, 'rb') as pt_file, open(ciphertext_filename, 'wb') as ct_file:
422406
with client.stream(
423407
mode='e',
424408
source=pt_file,
425-
keyring=kms_keyring
409+
keyring=kms_multi_keyring
426410
) as encryptor:
427411
for chunk in encryptor:
428412
ct_file.write(chunk)
429413
430414
decrypted_filename = 'my-decrypted-data.dat'
431415
432-
# Decrypt your encrypted data stream.
433416
with open(ciphertext_filename, 'rb') as ct_file, open(decrypted_filename, 'wb') as pt_file:
434417
with client.stream(
435418
mode='d',
436419
source=ct_file,
437-
keyring=kms_keyring
420+
keyring=kms_multi_keyring
438421
) as decryptor:
439422
for chunk in decryptor:
440423
pt_file.write(chunk)
441424
425+
assert filecmp.cmp(plaintext_filename, decrypted_filename)
426+
442427
443428
Performance Considerations
444429
==========================
@@ -456,7 +441,7 @@ raw keyrings need testing, but may be launched as not thread safe.
456441

457442
The ``EncryptionSDKClient`` class is thread safe.
458443
But instances of key material providers (i.e. keyrings or legacy master key providers) that call AWS KMS
459-
(ex. ``AwsKmsKeyring`` or other KMS keyrings; ``BaseKmsMasterKeyProvider`` or children of this class)
444+
(ex. ``AwsKmsMultiKeyring`` or other KMS keyrings; ``BaseKmsMasterKeyProvider`` or children of this class)
460445
MUST not be shared between threads
461446
for the reasons outlined in `the boto3 docs <https://boto3.amazonaws.com/v1/documentation/api/latest/guide/resources.html#multithreading-or-multiprocessing-with-resources>`_.
462447

src/aws_encryption_sdk/__init__.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,9 @@ def encrypt(self, **kwargs):
134134
:param materials_manager: `CryptoMaterialsManager` that returns cryptographic materials
135135
(requires either `materials_manager` or `keyring`)
136136
:type materials_manager: aws_encryption_sdk.materials_managers.base.CryptoMaterialsManager
137+
:param key_provider: `MasterKeyProvider` that returns data keys for encryption
138+
(requires either `materials_manager` or `key_provider`)
139+
:type key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider
137140
:param keyring: `IKeyring` that returns keyring for encryption
138141
(requires either `materials_manager` or `keyring`)
139142
:type keyring: aws_cryptographic_materialproviders.mpl.references.IKeyring
@@ -199,6 +202,9 @@ def decrypt(self, **kwargs):
199202
:param materials_manager: `CryptoMaterialsManager` that returns cryptographic materials
200203
(requires either `materials_manager` or `keyring`)
201204
:type materials_manager: aws_encryption_sdk.materials_managers.base.CryptoMaterialsManager
205+
:param key_provider: `MasterKeyProvider` that returns data keys for decryption
206+
(requires either `materials_manager` or `key_provider`)
207+
:type key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider
202208
:param keyring: `IKeyring` that returns keyring for encryption
203209
(requires either `materials_manager` or `keyring`)
204210
:type keyring: aws_cryptographic_materialproviders.mpl.references.IKeyring

0 commit comments

Comments
 (0)