Skip to content

Commit 7df11d4

Browse files
committed
Merge branch 'keyring' into multi-keyrings
2 parents 324b8e7 + fcc05ba commit 7df11d4

File tree

7 files changed

+1211
-80
lines changed

7 files changed

+1211
-80
lines changed

src/aws_encryption_sdk/keyring/raw_keyring.py

+63-77
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
_LOGGER = logging.getLogger(__name__)
4242

4343

44-
def generate_data_key(
44+
def _generate_data_key(
4545
encryption_materials, # type: EncryptionMaterials
4646
key_provider, # type: MasterKeyInfo
4747
):
@@ -80,20 +80,39 @@ def generate_data_key(
8080

8181
@attr.s
8282
class RawAESKeyring(Keyring):
83-
"""Public class for Raw AES Keyring.
83+
"""Generate an instance of Raw AES Keyring which encrypts using AES-GCM algorithm using wrapping key provided as a
84+
byte array
8485
8586
:param str key_namespace: String defining the keyring.
8687
:param bytes key_name: Key ID
8788
:param bytes wrapping_key: Encryption key with which to wrap plaintext data key.
8889
:param wrapping_algorithm: Wrapping Algorithm with which to wrap plaintext data key.
8990
:type wrapping_algorithm: WrappingAlgorithm
91+
92+
.. note::
93+
Only one wrapping key can be specified in a Raw AES Keyring
9094
"""
9195

9296
key_namespace = attr.ib(validator=instance_of(six.string_types))
9397
key_name = attr.ib(validator=instance_of(six.binary_type))
9498
_wrapping_key = attr.ib(repr=False, validator=instance_of(six.binary_type))
9599
_wrapping_algorithm = attr.ib(repr=False, validator=instance_of(WrappingAlgorithm))
96100

101+
def __attrs_post_init__(self):
102+
# type: () -> None
103+
"""Prepares initial values not handled by attrs."""
104+
self._key_provider = MasterKeyInfo(provider_id=self.key_namespace, key_info=self.key_name)
105+
106+
self._wrapping_key_structure = WrappingKey(
107+
wrapping_algorithm=self._wrapping_algorithm,
108+
wrapping_key=self._wrapping_key,
109+
wrapping_key_type=EncryptionKeyType.SYMMETRIC,
110+
)
111+
112+
self._key_info_prefix = self._get_key_info_prefix(
113+
key_namespace=self.key_namespace, key_name=self.key_name, wrapping_key=self._wrapping_key_structure
114+
)
115+
97116
@staticmethod
98117
def _get_key_info_prefix(key_namespace, key_name, wrapping_key):
99118
# type: (str, bytes, WrappingKey) -> six.binary_type
@@ -111,21 +130,6 @@ def _get_key_info_prefix(key_namespace, key_name, wrapping_key):
111130
)
112131
return key_info_prefix
113132

114-
def __attrs_post_init__(self):
115-
# type: () -> None
116-
"""Prepares initial values not handled by attrs."""
117-
self._key_provider = MasterKeyInfo(provider_id=self.key_namespace, key_info=self.key_name)
118-
119-
self._wrapping_key_structure = WrappingKey(
120-
wrapping_algorithm=self._wrapping_algorithm,
121-
wrapping_key=self._wrapping_key,
122-
wrapping_key_type=EncryptionKeyType.SYMMETRIC,
123-
)
124-
125-
self._key_info_prefix = self._get_key_info_prefix(
126-
key_namespace=self.key_namespace, key_name=self.key_name, wrapping_key=self._wrapping_key_structure
127-
)
128-
129133
def on_encrypt(self, encryption_materials):
130134
# type: (EncryptionMaterials) -> EncryptionMaterials
131135
"""Generate a data key if not present and encrypt it using any available wrapping key
@@ -136,26 +140,16 @@ def on_encrypt(self, encryption_materials):
136140
:rtype: aws_encryption_sdk.materials_managers.EncryptionMaterials
137141
"""
138142
if encryption_materials.data_encryption_key is None:
139-
plaintext_generated = generate_data_key(
140-
encryption_materials=encryption_materials, key_provider=self._key_provider
141-
)
142-
143-
# Check if data key exists
144-
if not plaintext_generated or plaintext_generated is None:
145-
raise GenerateKeyError("Unable to generate data encryption key.")
146-
147-
# Encrypt data key
148-
encrypted_wrapped_key = self._wrapping_key_structure.encrypt(
149-
plaintext_data_key=encryption_materials.data_encryption_key.data_key,
150-
encryption_context=encryption_materials.encryption_context,
151-
)
152-
153-
# Check if encryption is successful
154-
if encrypted_wrapped_key is None:
155-
return encryption_materials
143+
_generate_data_key(encryption_materials=encryption_materials, key_provider=self._key_provider)
156144

157-
# EncryptedData to EncryptedDataKey
158145
try:
146+
# Encrypt data key
147+
encrypted_wrapped_key = self._wrapping_key_structure.encrypt(
148+
plaintext_data_key=encryption_materials.data_encryption_key.data_key,
149+
encryption_context=encryption_materials.encryption_context,
150+
)
151+
152+
# EncryptedData to EncryptedDataKey
159153
encrypted_data_key = serialize_wrapped_key(
160154
key_provider=self._key_provider,
161155
wrapping_algorithm=self._wrapping_algorithm,
@@ -227,29 +221,30 @@ def on_decrypt(self, decryption_materials, encrypted_data_keys):
227221
)
228222

229223
# Update decryption materials
230-
data_encryption_key = RawDataKey(
231-
key_provider=MasterKeyInfo(provider_id=self._key_provider.provider_id, key_info=self.key_name),
232-
data_key=plaintext_data_key,
233-
)
224+
data_encryption_key = RawDataKey(key_provider=self._key_provider, data_key=plaintext_data_key)
234225
decryption_materials.add_data_encryption_key(data_encryption_key, keyring_trace)
235226

236227
return decryption_materials
237228

238229

239230
@attr.s
240231
class RawRSAKeyring(Keyring):
241-
"""Public class for Raw RSA Keyring.
232+
"""Generate an instance of Raw RSA Keyring which performs asymmetric encryption and decryption using public
233+
and private keys provided
242234
243235
:param str key_namespace: String defining the keyring ID
244236
:param bytes key_name: Key ID
245-
:param _private_wrapping_key: Private encryption key with which to wrap plaintext data key (optional)
246-
:type _private_wrapping_key: RSAPrivateKey
247-
:param _public_wrapping_key: Public encryption key with which to wrap plaintext data key (optional)
248-
:type _public_wrapping_key: RSAPublicKey
237+
:param private_wrapping_key: Private encryption key with which to wrap plaintext data key (optional)
238+
:type private_wrapping_key: RSAPrivateKey
239+
:param public_wrapping_key: Public encryption key with which to wrap plaintext data key (optional)
240+
:type public_wrapping_key: RSAPublicKey
249241
:param wrapping_algorithm: Wrapping Algorithm with which to wrap plaintext data key
250242
:type wrapping_algorithm: WrappingAlgorithm
251243
:param key_provider: Complete information about the key in the keyring
252244
:type key_provider: MasterKeyInfo
245+
246+
.. note::
247+
At least one of public wrapping key or private wrapping key must be provided.
253248
"""
254249

255250
key_namespace = attr.ib(validator=instance_of(six.string_types))
@@ -258,6 +253,17 @@ class RawRSAKeyring(Keyring):
258253
_private_wrapping_key = attr.ib(default=None, repr=False, validator=optional(instance_of(rsa.RSAPrivateKey)))
259254
_public_wrapping_key = attr.ib(default=None, repr=False, validator=optional(instance_of(rsa.RSAPublicKey)))
260255

256+
def __attrs_post_init__(self):
257+
# type: () -> None
258+
"""Prepares initial values not handled by attrs."""
259+
self._key_provider = MasterKeyInfo(provider_id=self.key_namespace, key_info=self.key_name)
260+
261+
if self._public_wrapping_key is None and self._private_wrapping_key is None:
262+
raise TypeError("At least one of public key or private key must be provided.")
263+
264+
if self._private_wrapping_key is not None and self._public_wrapping_key is None:
265+
self._public_wrapping_key = self._private_wrapping_key.public_key()
266+
261267
@classmethod
262268
def from_pem_encoding(
263269
cls,
@@ -269,7 +275,7 @@ def from_pem_encoding(
269275
password=None, # type: bytes
270276
):
271277
# type: (...) -> RawRSAKeyring
272-
"""Generate a raw RSA keyring using a key with PEM Encoding
278+
"""Generate a Raw RSA keyring using PEM Encoded public and private keys
273279
274280
:param str key_namespace: String defining the keyring ID
275281
:param bytes key_name: Key ID
@@ -308,7 +314,7 @@ def from_der_encoding(
308314
private_encoded_key=None, # type: bytes
309315
password=None, # type: bytes
310316
):
311-
"""Generate a raw RSA keyring using a key with DER Encoding
317+
"""Generate a raw RSA keyring using DER Encoded public and private keys
312318
313319
:param str key_namespace: String defining the keyring ID
314320
:param bytes key_name: Key ID
@@ -337,17 +343,6 @@ def from_der_encoding(
337343
public_wrapping_key=loaded_public_wrapping_key,
338344
)
339345

340-
def __attrs_post_init__(self):
341-
# type: () -> None
342-
"""Prepares initial values not handled by attrs."""
343-
self._key_provider = MasterKeyInfo(provider_id=self.key_namespace, key_info=self.key_name)
344-
345-
if self._public_wrapping_key is None and self._private_wrapping_key is None:
346-
raise TypeError("At least one of public key or private key must be provided.")
347-
348-
if self._private_wrapping_key is not None:
349-
self._public_wrapping_key = self._private_wrapping_key.public_key()
350-
351346
def on_encrypt(self, encryption_materials):
352347
# type: (EncryptionMaterials) -> EncryptionMaterials
353348
"""Generate a data key if not present and encrypt it using any available wrapping key.
@@ -358,19 +353,13 @@ def on_encrypt(self, encryption_materials):
358353
:rtype: aws_encryption_sdk.materials_managers.EncryptionMaterials
359354
"""
360355
if encryption_materials.data_encryption_key is None:
361-
plaintext_generated = generate_data_key(
362-
encryption_materials=encryption_materials, key_provider=self._key_provider
363-
)
364-
365-
# Check if data key exists
366-
if not plaintext_generated or plaintext_generated is None:
367-
raise GenerateKeyError("Unable to generate data encryption key.")
356+
_generate_data_key(encryption_materials=encryption_materials, key_provider=self._key_provider)
368357

369358
if self._public_wrapping_key is None:
370359
return encryption_materials
371360

372-
# Encrypt data key
373361
try:
362+
# Encrypt data key
374363
encrypted_wrapped_key = EncryptedData(
375364
iv=None,
376365
ciphertext=self._public_wrapping_key.encrypt(
@@ -379,19 +368,19 @@ def on_encrypt(self, encryption_materials):
379368
),
380369
tag=None,
381370
)
371+
372+
# EncryptedData to EncryptedDataKey
373+
encrypted_data_key = serialize_wrapped_key(
374+
key_provider=self._key_provider,
375+
wrapping_algorithm=self._wrapping_algorithm,
376+
wrapping_key_id=self.key_name,
377+
encrypted_wrapped_key=encrypted_wrapped_key,
378+
)
382379
except Exception: # pylint: disable=broad-except
383380
error_message = "Raw RSA Keyring unable to encrypt data key"
384381
_LOGGER.exception(error_message)
385382
return encryption_materials
386383

387-
# EncryptedData to EncryptedDataKey
388-
encrypted_data_key = serialize_wrapped_key(
389-
key_provider=self._key_provider,
390-
wrapping_algorithm=self._wrapping_algorithm,
391-
wrapping_key_id=self.key_name,
392-
encrypted_wrapped_key=encrypted_wrapped_key,
393-
)
394-
395384
# Update Keyring Trace
396385
keyring_trace = KeyringTrace(
397386
wrapping_key=encrypted_data_key.key_provider, flags={KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY}
@@ -441,10 +430,7 @@ def on_decrypt(self, decryption_materials, encrypted_data_keys):
441430
)
442431

443432
# Update decryption materials
444-
data_encryption_key = RawDataKey(
445-
key_provider=MasterKeyInfo(provider_id=self._key_provider.provider_id, key_info=self.key_name),
446-
data_key=plaintext_data_key,
447-
)
433+
data_encryption_key = RawDataKey(key_provider=self._key_provider, data_key=plaintext_data_key)
448434
decryption_materials.add_data_encryption_key(data_encryption_key, keyring_trace)
449435

450436
return decryption_materials

0 commit comments

Comments
 (0)