25
25
USER_AGENT_SUFFIX = 'AwsEncryptionSdkPython-KMSMasterKey/{}' .format (__version__ )
26
26
27
27
28
- def _kdf_input_len_check (data_key_len , kdf_type , kdf_input_len ):
29
- """Validates that data_key_len and kdf_input_len have the correct relationship.
28
+ class EncryptionSuite (Enum ):
29
+ """Static definition of encryption algorithm details.
30
+
31
+ .. warning:: These members must only be used as part of an AlgorithmSuite.
32
+
33
+ :param algorithm: Encryption algorithm to use
34
+ :type algorithm: cryptography.io ciphers algorithm object
35
+ :param mode: Encryption mode in which to operate
36
+ :type mode: cryptography.io ciphers modes object
37
+ :param int data_key_length: Number of bytes in envelope encryption data key
38
+ :param int iv_length: Number of bytes in IV
39
+ :param int auth_length: Number of bytes in auth data (tag)
40
+ :param int auth_key_length: Number of bytes in auth key (not currently supported by any algorithms)
41
+ """
42
+
43
+ AES_128_GCM_IV12_TAG16 = (algorithms .AES , modes .GCM , 16 , 12 , 16 )
44
+ AES_192_GCM_IV12_TAG16 = (algorithms .AES , modes .GCM , 24 , 12 , 16 )
45
+ AES_256_GCM_IV12_TAG16 = (algorithms .AES , modes .GCM , 32 , 12 , 16 )
46
+
47
+ def __init__ (self , algorithm , mode , data_key_length , iv_length , auth_length , auth_key_length = 0 ):
48
+ """Prepare a new EncryptionSuite."""
49
+ self .algorithm = algorithm
50
+ self .mode = mode
51
+ self .data_key_length = data_key_length
52
+ self .iv_length = iv_length
53
+ self .auth_length = self .tag_len = auth_length
54
+ # Auth keys are not currently supported
55
+ self .auth_key_length = auth_key_length
56
+
57
+ def valid_kdf (self , kdf ):
58
+ """Determine whether a KDFSuite can be used with this EncryptionSuite.
59
+
60
+ :param kdf: KDFSuite to evaluate
61
+ :type kdf: aws_encryption_sdk.identifiers.KDFSuite
62
+ :rtype: bool
63
+ """
64
+ if kdf .input_length is None :
65
+ return True
66
+
67
+ if self .data_key_length > kdf .input_length (self ):
68
+ raise InvalidAlgorithmError (
69
+ 'Invalid Algorithm definition: data_key_len must not be greater than kdf_input_len'
70
+ )
71
+
72
+ return True
30
73
31
- :param int data_key_len: Number of bytes in key
32
- :param kdf_type: KDF algorithm to use
33
- :param kdf_type: cryptography.io KDF object
34
- :param int kdf_input_len: Length of input data to feed into KDF function
74
+
75
+ class KDFSuite (Enum ):
76
+ """Static definition of key derivation algorithm details.
77
+
78
+ .. warning:: These members must only be used as part of an AlgorithmSuite.
79
+
80
+ :param algorithm: KDF algorithm to use
81
+ :type algorithm: cryptography.io KDF object
82
+ :param int input_length: Number of bytes of input data to feed into KDF function
83
+ :param hash_algorithm: Hash algorithm to use in KDF
84
+ :type hash_algorithm: cryptography.io hashes object
35
85
"""
36
- if kdf_type is None and data_key_len != kdf_input_len :
37
- raise InvalidAlgorithmError (
38
- 'Invalid Algorithm definition: data_key_len must equal kdf_input_len for non-KDF algorithms'
39
- )
40
- elif data_key_len > kdf_input_len :
41
- raise InvalidAlgorithmError (
42
- 'Invalid Algorithm definition: data_key_len must not be greater than kdf_input_len'
43
- )
44
86
87
+ NONE = (None , None , None )
88
+ HKDF_SHA256 = (hkdf .HKDF , None , hashes .SHA256 )
89
+ HKDF_SHA384 = (hkdf .HKDF , None , hashes .SHA384 )
90
+
91
+ def __init__ (self , algorithm , input_length , hash_algorithm ):
92
+ """Prepare a new KDFSuite."""
93
+ self .algorithm = algorithm
94
+ self ._input_length = input_length
95
+ self .hash_algorithm = hash_algorithm
96
+
97
+ def input_length (self , encryption ):
98
+ """Determine the correct KDF input value length for this KDFSuite when used with
99
+ a specific EncryptionSuite.
100
+
101
+ :param encryption: EncryptionSuite to use
102
+ :type encryption: aws_encryption_sdk.identifiers.EncryptionSuite
103
+ :rtype: int
104
+ """
105
+ # type: (EncryptionSuite) -> bool
106
+ if self ._input_length is None :
107
+ return encryption .data_key_length
108
+
109
+ return self ._input_length
45
110
46
- class Algorithm (Enum ): # pylint: disable=too-many-instance-attributes
47
- """IDs of cryptographic algorithms this library knows about.
111
+
112
+ class AuthenticationSuite (Enum ):
113
+ """Static definition of authentication algorithm details.
114
+
115
+ .. warning:: These members must only be used as part of an AlgorithmSuite.
116
+
117
+ :param algorithm: Information needed by signing algorithm to define behavior
118
+ :type algorithm: may vary (currently only ECC curve object)
119
+ :param hash_algorithm: Hash algorithm to use in signature
120
+ :type hash_algorithm: cryptography.io hashes object
121
+ :param int signature_lenth: Number of bytes in signature
122
+ """
123
+
124
+ NONE = (None , None , 0 )
125
+ SHA256_ECDSA_P256 = (ec .SECP256R1 , hashes .SHA256 , 71 )
126
+ SHA256_ECDSA_P384 = (ec .SECP384R1 , hashes .SHA384 , 103 )
127
+
128
+ def __init__ (self , algorithm , hash_algorithm , signature_length ):
129
+ """Prepare a new AuthenticationSuite."""
130
+ self .algorithm = algorithm
131
+ self .hash_algorithm = hash_algorithm
132
+ self .signature_length = signature_length
133
+
134
+
135
+ class AlgorithmSuite (Enum ): # pylint: disable=too-many-instance-attributes
136
+ """Static combinations of encryption, KDF, and authentication algorithms.
137
+
138
+ .. warning:: No AlgorithmSuites except those defined here are supported.
48
139
49
140
:param int algorithm_id: KMS Encryption Algorithm ID
50
- :param encryption_algorithm: Encryption algorithm to use
51
- :type encryption_algorithm: cryptography.io ciphers algorithm object
52
- :param encryption_mode: Encryption mode in which to operate
53
- :type encryption_mode: cryptography.io ciphers modes object
54
- :param int iv_len: Number of bytes in IV
55
- :param int auth_len: Number of bytes in auth data (tag)
56
- :param int auth_key_len: Number of bytes in auth key (not currently supported by any algorithms)
57
- :param int data_key_len: Number of bytes in envelope encryption data key
58
- :param kdf_type: KDF algorithm to use
59
- :type kdf_type: cryptography.io KDF object
60
- :param int kdf_input_len: Number of bytes of input data to feed into KDF function
61
- :param kdf_hash_type: Hash algorithm to use in KDF
62
- :type kdf_hash_type: cryptography.io hashes object
63
- :param signing_algorithm_info: Information needed by signing algorithm to define behavior
64
- :type signing_algorithm_info: may vary (currently only ECC curve object)
65
- :param signature_hash_type: Hash algorithm to use in signature
66
- :type signature_hash_type: cryptography.io hashes object
67
- :param int signature_len: Number of bytes in signature
141
+ :param encryption_suite: EncryptionSuite to use with this AlgorithmSuite
142
+ :type encryption_suite: aws_encryption_sdk.identifiers.EncryptionSuite
143
+ :param kdf_suite: KDFSuite to use with this AlgorithmSuite
144
+ :type kdf_suite: aws_encryption_sdk.identifiers.KDFSuite
145
+ :param authentication_suite: AuthenticationSuite to use with this AlgorithmSuite
146
+ :type authentication_suite: aws_encryption_sdk.identifiers.AuthenticationSuite
68
147
"""
69
148
70
- __rlookup__ = {} # algorithm_id -> Algorithm
149
+ __rlookup__ = {} # algorithm_id -> AlgorithmSuite
71
150
72
- AES_128_GCM_IV12_TAG16 = (0x0014 , algorithms .AES , modes .GCM , 12 , 16 , 0 , 16 , None , 16 , None , None , None , 0 )
73
- AES_192_GCM_IV12_TAG16 = (0x0046 , algorithms .AES , modes .GCM , 12 , 16 , 0 , 24 , None , 24 , None , None , None , 0 )
74
- AES_256_GCM_IV12_TAG16 = (0x0078 , algorithms .AES , modes .GCM , 12 , 16 , 0 , 32 , None , 32 , None , None , None , 0 )
75
- AES_128_GCM_IV12_TAG16_HKDF_SHA256 = (
76
- 0x0114 , algorithms .AES , modes .GCM , 12 , 16 , 0 , 16 , hkdf .HKDF , 16 , hashes .SHA256 , None , None , 0
77
- )
78
- AES_192_GCM_IV12_TAG16_HKDF_SHA256 = (
79
- 0x0146 , algorithms .AES , modes .GCM , 12 , 16 , 0 , 24 , hkdf .HKDF , 24 , hashes .SHA256 , None , None , 0
80
- )
81
- AES_256_GCM_IV12_TAG16_HKDF_SHA256 = (
82
- 0x0178 , algorithms .AES , modes .GCM , 12 , 16 , 0 , 32 , hkdf .HKDF , 32 , hashes .SHA256 , None , None , 0
83
- )
151
+ AES_128_GCM_IV12_TAG16 = (0x0014 , EncryptionSuite .AES_128_GCM_IV12_TAG16 )
152
+ AES_192_GCM_IV12_TAG16 = (0x0046 , EncryptionSuite .AES_192_GCM_IV12_TAG16 )
153
+ AES_256_GCM_IV12_TAG16 = (0x0078 , EncryptionSuite .AES_256_GCM_IV12_TAG16 )
154
+ AES_128_GCM_IV12_TAG16_HKDF_SHA256 = (0x0114 , EncryptionSuite .AES_128_GCM_IV12_TAG16 , KDFSuite .HKDF_SHA256 )
155
+ AES_192_GCM_IV12_TAG16_HKDF_SHA256 = (0x0146 , EncryptionSuite .AES_192_GCM_IV12_TAG16 , KDFSuite .HKDF_SHA256 )
156
+ AES_256_GCM_IV12_TAG16_HKDF_SHA256 = (0x0178 , EncryptionSuite .AES_256_GCM_IV12_TAG16 , KDFSuite .HKDF_SHA256 )
84
157
AES_128_GCM_IV12_TAG16_HKDF_SHA256_ECDSA_P256 = (
85
- 0x0214 , algorithms . AES , modes . GCM , 12 , 16 , 0 , 16 , hkdf . HKDF , 16 , hashes . SHA256 , ec . SECP256R1 , hashes . SHA256 , 71
158
+ 0x0214 , EncryptionSuite . AES_128_GCM_IV12_TAG16 , KDFSuite . HKDF_SHA256 , AuthenticationSuite . SHA256_ECDSA_P256
86
159
)
87
160
AES_192_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384 = (
88
- 0x0346 , algorithms . AES , modes . GCM , 12 , 16 , 0 , 24 , hkdf . HKDF , 24 , hashes . SHA384 , ec . SECP384R1 , hashes . SHA384 , 103
161
+ 0x0346 , EncryptionSuite . AES_192_GCM_IV12_TAG16 , KDFSuite . HKDF_SHA384 , AuthenticationSuite . SHA256_ECDSA_P384
89
162
)
90
163
AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384 = (
91
- 0x0378 , algorithms . AES , modes . GCM , 12 , 16 , 0 , 32 , hkdf . HKDF , 32 , hashes . SHA384 , ec . SECP384R1 , hashes . SHA384 , 103
164
+ 0x0378 , EncryptionSuite . AES_256_GCM_IV12_TAG16 , KDFSuite . HKDF_SHA384 , AuthenticationSuite . SHA256_ECDSA_P384
92
165
)
93
166
94
- def __init__ ( # pylint: disable=too-many-arguments
167
+ def __init__ (
95
168
self ,
96
- algorithm_id ,
97
- encryption_algorithm ,
98
- encryption_mode ,
99
- iv_len ,
100
- auth_len ,
101
- auth_key_len ,
102
- data_key_len ,
103
- kdf_type ,
104
- kdf_input_len ,
105
- kdf_hash_type ,
106
- signing_algorithm_info ,
107
- signing_hash_type ,
108
- signature_len
169
+ algorithm_id , # type: int
170
+ encryption , # type: EncryptionSuite
171
+ kdf = KDFSuite .NONE , # type: Optional[KDFSuite]
172
+ authentication = AuthenticationSuite .NONE , # type: Optional[AuthenticationSuite]
173
+ allowed = True # type: bool
109
174
):
110
- """Prepares new Algorithm."""
111
- _kdf_input_len_check (
112
- data_key_len = data_key_len ,
113
- kdf_type = kdf_type ,
114
- kdf_input_len = kdf_input_len
115
- )
175
+ # type: (...) -> None
176
+ """Prepare a new AlgorithmSuite."""
116
177
self .algorithm_id = algorithm_id
117
- self .encryption_algorithm = encryption_algorithm
118
- self .encryption_mode = encryption_mode
119
- self .iv_len = iv_len
120
- # Auth keys are not currently supported
121
- self .auth_key_len = auth_key_len
122
- self .auth_len = self .tag_len = auth_len
123
- self .data_key_len = data_key_len
124
- self .kdf_type = kdf_type
125
- self .kdf_input_len = kdf_input_len
126
- self .kdf_hash_type = kdf_hash_type
127
- self .signing_algorithm_info = signing_algorithm_info
128
- self .signing_hash_type = signing_hash_type
129
- self .signature_len = signature_len
130
- # All algorithms in this enum are allowed for now.
131
- # This might change in the future.
132
- self .allowed = True
178
+ self .encryption = encryption
179
+ self .encryption .valid_kdf (kdf )
180
+ self .kdf = kdf
181
+ self .authentication = authentication
182
+ self .allowed = allowed
183
+
184
+ # Encryption Values
185
+ self .encryption_algorithm = self .encryption .algorithm
186
+ self .encryption_mode = self .encryption .mode
187
+ self .data_key_len = self .encryption .data_key_length
188
+ self .iv_len = self .encryption .iv_length
189
+ self .auth_key_len = self .encryption .auth_key_length
190
+ self .auth_len = self .tag_len = self .encryption .auth_length
191
+
192
+ # KDF Values
193
+ self .kdf_type = self .kdf .algorithm
194
+ self .kdf_hash_type = self .kdf .hash_algorithm
195
+
196
+ # Authentication Values
197
+ self .signing_algorithm_info = self .authentication .algorithm
198
+ self .signing_hash_type = self .authentication .hash_algorithm
199
+ self .signature_len = self .authentication .signature_length
200
+
133
201
self .__rlookup__ [algorithm_id ] = self
134
202
203
+ @property
204
+ def kdf_input_len (self ):
205
+ """Determine the correct KDF input value length for this algorithm suite."""
206
+ return self .kdf .input_length (self .encryption )
207
+
135
208
@classmethod
136
209
def get_by_id (cls , algorithm_id ):
137
- """Returns the correct member based on the algorithm_id value.
210
+ """Return the correct member based on the algorithm_id value.
138
211
139
212
:param algorithm_id: Value of algorithm_id field with which to retrieve Algorithm
140
213
:type algorithm_id: int
@@ -144,12 +217,15 @@ def get_by_id(cls, algorithm_id):
144
217
return cls .__rlookup__ [algorithm_id ]
145
218
146
219
def id_as_bytes (self ):
147
- """Returns the algorithm suite ID as a 2-byte array"""
220
+ """Return the algorithm suite ID as a 2-byte array"""
148
221
return struct .pack ('>H' , self .algorithm_id )
149
222
150
223
def safe_to_cache (self ):
151
- """Determines whether encryption materials for this algorithm suite should be cached."""
152
- return self .kdf_type is not None
224
+ """Determine whether encryption materials for this algorithm suite should be cached."""
225
+ return self .kdf is not KDFSuite .NONE
226
+
227
+
228
+ Algorithm = AlgorithmSuite
153
229
154
230
155
231
class EncryptionType (Enum ):
0 commit comments