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