Skip to content

Commit fcc05ba

Browse files
MeghaShettymattsb42-aws
authored andcommitted
Raw keyrings (#165)
* Adding Keyring API * Delete __init__.py * Delete raw_keyring.py * Added docstring to public class * Edited docstring * Edited docstring again * Changes in docstring statements * Docstring changes * Changes in docstring * Raw keyring initial * Raw keyring encrypt commit * Encrypt functions for Raw RSA and AES * Raw RSA and AES initial * Changes in raw keyrings according to new keyring materials * Updated with autoformat * Modified base * Corrected tox and flake errors * Docstring error correction * Added docstrings and corrected errors * Some more changes in docstrings * Updating base API * Made all suggested changes * Corrected tox and flake8 errors * Minor change in raw-keyrings * Adding Keyring API * Delete __init__.py * Delete raw_keyring.py * Added docstring to public class * Edited docstring * Edited docstring again * Changes in docstring statements * Docstring changes * Changes in docstring * Raw keyring initial * Raw keyring encrypt commit * Encrypt functions for Raw RSA and AES * Raw RSA and AES initial * bump attrs to 19.1.0 * add keyring trace and integrate into updated encrytion/decryption materials * s/KeyRing/Keyring/g * align cryptographic materials and add write-only interface * encrypted_data_keys must only contain EncryptedDataKey * fix test to be Python 2 compatible * Changes in raw keyrings according to new keyring materials * Updated with autoformat * Modified base * data encryption key must be set before encrypted data keys can be added to EncryptionMaterials * Corrected tox and flake errors * Docstring error correction * Added docstrings and corrected errors * Some more changes in docstrings * Updating base API * add signing/verification key checks to Encryption/DecryptionMaterials * DecryptionMaterials.algorithm must be set before DecryptionMaterials.add_data_encryption_key can be called * update materials docs and typehints * Made all suggested changes * EncryptionMaterials must not be initialized with encrypted_data_keys but no data_encryption_key * add is_complete properties to EncryptionMaterials and DecryptionMaterials * Corrected tox and flake8 errors * Minor change in raw-keyrings * change KeyringTraceFlag values to bitshifted ints to match other implementations * normalize EncryptionMaterials._encrypted_data_keys to list and encrypted_data_keys to tuple * temporarily pin pydocstyle at <4.0.0 to avoid issue breaking flake8-docstrings * temporarily cap pydocstyle at <4.0.0 for decrypt oracle * Changes to keyring trace in raw keyrings * Adding test files * Adding tests * Changed data encryption key type to RawDataKey * Added keyring trace to pytest encryption materials * Changed value of keyring_trace.wrapping_key * Few changes to match new API * Tox errors * Functional tests pass * Formatting errors corrected and functional tests pass * Corrected too broad exception error and deleted empty return statement from tests * Changed Exeception to BaseException to solve broad exception error * Added suppress broad exception * Added pylint disable broad exception * Changed wrapping keys for RSA keyrings from WrappingKey to cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey/RSAPublicKey * Fixed tox errors * More tox errors * Moved code for generation of plaintext to be before the check for key being private or public * Tox errors * Added metaclass to base API and unit tests for base API * Changed metaclass to six.add_metaclass in base API * Fixed pylint errors * Fixed more pylint errors * Removed RawAESKeyring instance * Changed on_encrypt_helper to generate_data_key and removed on_decrypt_helper. Renamed base API unit test file * Changed docstring for generate_data_key * Changed decryption_materials.data_key to decryption_materials.data_encryption_key and fixed pylint errors * Fixed pylint errors * Changed raw keyrings to have class methods for PEM and DER encoded keys * Unit tests for raw keyrings * Changes for PEM encoding * Made suggested changes to raw keyrings * partial commit for raw keyrings * Made suggested changes * Changed wrapping_key_id in deserialize_wrapped_key() back to self.key_name * Decryption and PEM input now works * Adding sample * Removed test comments * Unit tests for raw aes and rsa * All unit tests working * All unit tests done. Functional tests - key_info_prefix_vectors for AES and compatibility with MKP for RSA remaining * Delete sample_aes.py * Corrected tox and pylint errors * Removed print statements used while debugging * Partial commit for changes to tests * Partial commit for tests for raw keyrings * All tests except compatibility of raw rsa with mkp and key info prefix in raw aes * Pulled from keyring branch * Updated base API * Added test for key info prefix * Changed unittest.mock to mock * Raw keyrings test partial commit * All tests for raw keyrings work * Removed unused imports * Removed unused imports
1 parent 004ea5d commit fcc05ba

File tree

7 files changed

+1611
-1
lines changed

7 files changed

+1611
-1
lines changed

src/aws_encryption_sdk/keyring/raw_keyring.py

+436
Large diffs are not rendered by default.
+202
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
# Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License"). You
4+
# may not use this file except in compliance with the License. A copy of
5+
# the License is located at
6+
#
7+
# http://aws.amazon.com/apache2.0/
8+
#
9+
# or in the "license" file accompanying this file. This file is
10+
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
11+
# ANY KIND, either express or implied. See the License for the specific
12+
# language governing permissions and limitations under the License.
13+
"""Functional tests for Raw AES keyring encryption decryption path."""
14+
15+
import pytest
16+
17+
from aws_encryption_sdk.identifiers import (
18+
Algorithm,
19+
EncryptionKeyType,
20+
EncryptionType,
21+
KeyringTraceFlag,
22+
WrappingAlgorithm,
23+
)
24+
from aws_encryption_sdk.internal.crypto import WrappingKey
25+
from aws_encryption_sdk.internal.formatting.serialize import serialize_raw_master_key_prefix
26+
from aws_encryption_sdk.key_providers.raw import RawMasterKey
27+
from aws_encryption_sdk.keyring.raw_keyring import RawAESKeyring
28+
from aws_encryption_sdk.materials_managers import DecryptionMaterials, EncryptionMaterials
29+
from aws_encryption_sdk.structures import KeyringTrace, MasterKeyInfo, RawDataKey
30+
31+
pytestmark = [pytest.mark.functional, pytest.mark.local]
32+
33+
_ENCRYPTION_CONTEXT = {"encryption": "context", "values": "here"}
34+
_PROVIDER_ID = "Random Raw Keys"
35+
_KEY_ID = b"5325b043-5843-4629-869c-64794af77ada"
36+
_WRAPPING_KEY = b"12345678901234567890123456789012"
37+
_SIGNING_KEY = b"aws-crypto-public-key"
38+
39+
_WRAPPING_ALGORITHM = [alg for alg in WrappingAlgorithm if alg.encryption_type is EncryptionType.SYMMETRIC]
40+
41+
42+
def sample_encryption_materials():
43+
return [
44+
EncryptionMaterials(
45+
algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384,
46+
encryption_context=_ENCRYPTION_CONTEXT,
47+
signing_key=_SIGNING_KEY,
48+
),
49+
EncryptionMaterials(
50+
algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384,
51+
data_encryption_key=RawDataKey(
52+
key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID),
53+
data_key=b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(',
54+
),
55+
encryption_context=_ENCRYPTION_CONTEXT,
56+
signing_key=_SIGNING_KEY,
57+
keyring_trace=[
58+
KeyringTrace(
59+
wrapping_key=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID),
60+
flags={KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY},
61+
)
62+
],
63+
),
64+
]
65+
66+
67+
@pytest.mark.parametrize("encryption_materials_samples", sample_encryption_materials())
68+
@pytest.mark.parametrize("wrapping_algorithm_samples", _WRAPPING_ALGORITHM)
69+
def test_raw_aes_encryption_decryption(encryption_materials_samples, wrapping_algorithm_samples):
70+
71+
# Initializing attributes
72+
key_namespace = _PROVIDER_ID
73+
key_name = _KEY_ID
74+
_wrapping_algorithm = wrapping_algorithm_samples
75+
76+
# Creating an instance of a raw AES keyring
77+
test_raw_aes_keyring = RawAESKeyring(
78+
key_namespace=key_namespace,
79+
key_name=key_name,
80+
wrapping_key=_WRAPPING_KEY,
81+
wrapping_algorithm=_wrapping_algorithm,
82+
)
83+
84+
# Call on_encrypt function for the keyring
85+
encryption_materials = test_raw_aes_keyring.on_encrypt(encryption_materials=encryption_materials_samples)
86+
87+
# Generate decryption materials
88+
decryption_materials = DecryptionMaterials(
89+
algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384,
90+
verification_key=b"ex_verification_key",
91+
encryption_context=_ENCRYPTION_CONTEXT,
92+
)
93+
94+
# Call on_decrypt function for the keyring
95+
decryption_materials = test_raw_aes_keyring.on_decrypt(
96+
decryption_materials=decryption_materials, encrypted_data_keys=encryption_materials.encrypted_data_keys
97+
)
98+
99+
# Check if the data keys match
100+
assert encryption_materials.data_encryption_key.data_key == decryption_materials.data_encryption_key.data_key
101+
102+
103+
@pytest.mark.parametrize("encryption_materials_samples", sample_encryption_materials())
104+
@pytest.mark.parametrize("wrapping_algorithm_samples", _WRAPPING_ALGORITHM)
105+
def test_raw_master_key_decrypts_what_raw_keyring_encrypts(encryption_materials_samples, wrapping_algorithm_samples):
106+
107+
# Initializing attributes
108+
key_namespace = _PROVIDER_ID
109+
key_name = _KEY_ID
110+
_wrapping_algorithm = wrapping_algorithm_samples
111+
112+
# Creating an instance of a raw AES keyring
113+
test_raw_aes_keyring = RawAESKeyring(
114+
key_namespace=key_namespace,
115+
key_name=key_name,
116+
wrapping_key=_WRAPPING_KEY,
117+
wrapping_algorithm=_wrapping_algorithm,
118+
)
119+
120+
# Creating an instance of a raw master key
121+
test_raw_master_key = RawMasterKey(
122+
key_id=test_raw_aes_keyring.key_name,
123+
provider_id=test_raw_aes_keyring.key_namespace,
124+
wrapping_key=test_raw_aes_keyring._wrapping_key_structure,
125+
)
126+
127+
# Encrypt using raw AES keyring
128+
encryption_materials = test_raw_aes_keyring.on_encrypt(encryption_materials=encryption_materials_samples)
129+
130+
# Check if plaintext data key encrypted by raw keyring is decrypted by raw master key
131+
132+
raw_mkp_decrypted_data_key = test_raw_master_key.decrypt_data_key_from_list(
133+
encrypted_data_keys=encryption_materials._encrypted_data_keys,
134+
algorithm=encryption_materials.algorithm,
135+
encryption_context=encryption_materials.encryption_context,
136+
).data_key
137+
138+
assert encryption_materials.data_encryption_key.data_key == raw_mkp_decrypted_data_key
139+
140+
141+
@pytest.mark.parametrize("encryption_materials_samples", sample_encryption_materials())
142+
@pytest.mark.parametrize("wrapping_algorithm_samples", _WRAPPING_ALGORITHM)
143+
def test_raw_keyring_decrypts_what_raw_master_key_encrypts(encryption_materials_samples, wrapping_algorithm_samples):
144+
145+
# Initializing attributes
146+
key_namespace = _PROVIDER_ID
147+
key_name = _KEY_ID
148+
_wrapping_algorithm = wrapping_algorithm_samples
149+
150+
# Creating an instance of a raw AES keyring
151+
test_raw_aes_keyring = RawAESKeyring(
152+
key_namespace=key_namespace,
153+
key_name=key_name,
154+
wrapping_key=_WRAPPING_KEY,
155+
wrapping_algorithm=_wrapping_algorithm,
156+
)
157+
158+
# Creating an instance of a raw master key
159+
test_raw_master_key = RawMasterKey(
160+
key_id=test_raw_aes_keyring.key_name,
161+
provider_id=test_raw_aes_keyring.key_namespace,
162+
wrapping_key=test_raw_aes_keyring._wrapping_key_structure,
163+
)
164+
165+
if encryption_materials_samples.data_encryption_key is None:
166+
return
167+
raw_master_key_encrypted_data_key = test_raw_master_key.encrypt_data_key(
168+
data_key=encryption_materials_samples.data_encryption_key,
169+
algorithm=encryption_materials_samples.algorithm,
170+
encryption_context=encryption_materials_samples.encryption_context,
171+
)
172+
173+
# Check if plaintext data key encrypted by raw master key is decrypted by raw keyring
174+
175+
raw_aes_keyring_decrypted_data_key = test_raw_aes_keyring.on_decrypt(
176+
decryption_materials=DecryptionMaterials(
177+
algorithm=encryption_materials_samples.algorithm,
178+
encryption_context=encryption_materials_samples.encryption_context,
179+
verification_key=b"ex_verification_key",
180+
),
181+
encrypted_data_keys=[raw_master_key_encrypted_data_key],
182+
).data_encryption_key.data_key
183+
184+
assert encryption_materials_samples.data_encryption_key.data_key == raw_aes_keyring_decrypted_data_key
185+
186+
187+
@pytest.mark.parametrize("wrapping_algorithm", _WRAPPING_ALGORITHM)
188+
def test_key_info_prefix_vectors(wrapping_algorithm):
189+
assert (
190+
serialize_raw_master_key_prefix(
191+
raw_master_key=RawMasterKey(
192+
provider_id=_PROVIDER_ID,
193+
key_id=_KEY_ID,
194+
wrapping_key=WrappingKey(
195+
wrapping_algorithm=wrapping_algorithm,
196+
wrapping_key=_WRAPPING_KEY,
197+
wrapping_key_type=EncryptionKeyType.SYMMETRIC,
198+
),
199+
)
200+
)
201+
== _KEY_ID + b"\x00\x00\x00\x80\x00\x00\x00\x0c"
202+
)

0 commit comments

Comments
 (0)