CryptoDataHub 0.12.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- CryptoDataHub-0.12.6.dist-info/LICENSE.txt +373 -0
- CryptoDataHub-0.12.6.dist-info/METADATA +119 -0
- CryptoDataHub-0.12.6.dist-info/RECORD +70 -0
- CryptoDataHub-0.12.6.dist-info/WHEEL +5 -0
- CryptoDataHub-0.12.6.dist-info/top_level.txt +1 -0
- cryptodatahub/__init__.py +0 -0
- cryptodatahub/__setup__.py +10 -0
- cryptodatahub/common/__init__.py +0 -0
- cryptodatahub/common/algorithm.py +164 -0
- cryptodatahub/common/attack-named.json +74 -0
- cryptodatahub/common/attack-type.json +58 -0
- cryptodatahub/common/authentication.json +113 -0
- cryptodatahub/common/block-cipher-mode.json +75 -0
- cryptodatahub/common/block-cipher.json +474 -0
- cryptodatahub/common/certificate-transparency-log.json +2394 -0
- cryptodatahub/common/client.json +20 -0
- cryptodatahub/common/dhparam-well-known.json +1975 -0
- cryptodatahub/common/ecparam-well-known.json +1868 -0
- cryptodatahub/common/entity.json +269 -0
- cryptodatahub/common/entity.py +110 -0
- cryptodatahub/common/exception.py +28 -0
- cryptodatahub/common/grade.py +200 -0
- cryptodatahub/common/hash.json +273 -0
- cryptodatahub/common/key-exchange.json +140 -0
- cryptodatahub/common/key.py +571 -0
- cryptodatahub/common/mac.json +404 -0
- cryptodatahub/common/named-group.json +902 -0
- cryptodatahub/common/parameter.py +149 -0
- cryptodatahub/common/root-certificate.json +19240 -0
- cryptodatahub/common/server.json +56 -0
- cryptodatahub/common/signature.json +233 -0
- cryptodatahub/common/standard.json +57 -0
- cryptodatahub/common/stores.py +323 -0
- cryptodatahub/common/types.py +524 -0
- cryptodatahub/common/utils.py +112 -0
- cryptodatahub/common/vulnerability.json +2 -0
- cryptodatahub/dnsrec/__init__.py +0 -0
- cryptodatahub/dnsrec/algorithm.json +114 -0
- cryptodatahub/dnsrec/algorithm.py +87 -0
- cryptodatahub/dnsrec/digest-type.json +26 -0
- cryptodatahub/dnsrec/rr-type.json +805 -0
- cryptodatahub/ssh/__init__.py +0 -0
- cryptodatahub/ssh/algorithm.py +194 -0
- cryptodatahub/ssh/compression-algorithm.json +24 -0
- cryptodatahub/ssh/elliptic-curve-identifier.json +50 -0
- cryptodatahub/ssh/encryption-algorithm.json +587 -0
- cryptodatahub/ssh/host-key-algorithm.json +482 -0
- cryptodatahub/ssh/kex-algorithm.json +709 -0
- cryptodatahub/ssh/mac-algorithm.json +566 -0
- cryptodatahub/tls/__init__.py +0 -0
- cryptodatahub/tls/algorithm.py +324 -0
- cryptodatahub/tls/certificate-compression-algorithm.json +14 -0
- cryptodatahub/tls/cipher-kind.json +171 -0
- cryptodatahub/tls/cipher-suite-extension.json +10 -0
- cryptodatahub/tls/cipher-suite.json +5098 -0
- cryptodatahub/tls/client.json +4757 -0
- cryptodatahub/tls/client.py +220 -0
- cryptodatahub/tls/compression-method.json +20 -0
- cryptodatahub/tls/ec-point-format.json +20 -0
- cryptodatahub/tls/extension-type.json +282 -0
- cryptodatahub/tls/grease-one-byte.json +34 -0
- cryptodatahub/tls/grease-two-byte.json +66 -0
- cryptodatahub/tls/hash-and-signature-algorithm.json +266 -0
- cryptodatahub/tls/named-curve.json +292 -0
- cryptodatahub/tls/next-protocol-name.json +20 -0
- cryptodatahub/tls/protocol-name.json +71 -0
- cryptodatahub/tls/psk-key-exchange-mode.json +10 -0
- cryptodatahub/tls/token-binding-paramater.json +14 -0
- cryptodatahub/tls/version.json +154 -0
- cryptodatahub/tls/version.py +17 -0
|
@@ -0,0 +1,524 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
import abc
|
|
4
|
+
import base64
|
|
5
|
+
import codecs
|
|
6
|
+
import collections
|
|
7
|
+
import datetime
|
|
8
|
+
import enum
|
|
9
|
+
import json
|
|
10
|
+
import inspect
|
|
11
|
+
import os
|
|
12
|
+
import re
|
|
13
|
+
import unicodedata
|
|
14
|
+
|
|
15
|
+
import dateutil.parser
|
|
16
|
+
import six
|
|
17
|
+
from six.moves import collections_abc
|
|
18
|
+
|
|
19
|
+
try:
|
|
20
|
+
import pathlib
|
|
21
|
+
except ImportError: # pragma: no cover
|
|
22
|
+
import pathlib2 as pathlib # pragma: no cover
|
|
23
|
+
|
|
24
|
+
import attr
|
|
25
|
+
import urllib3
|
|
26
|
+
|
|
27
|
+
from cryptodatahub.common.exception import InvalidValue
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class _ConverterBase(object):
|
|
31
|
+
@abc.abstractmethod
|
|
32
|
+
def __call__(self, value):
|
|
33
|
+
raise NotImplementedError()
|
|
34
|
+
|
|
35
|
+
@abc.abstractmethod
|
|
36
|
+
def __repr__(self):
|
|
37
|
+
raise NotImplementedError()
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@attr.s(repr=False, slots=True, hash=True)
|
|
41
|
+
class _DictObjectConverter(_ConverterBase):
|
|
42
|
+
object_type = attr.ib(validator=attr.validators.instance_of(type))
|
|
43
|
+
|
|
44
|
+
def __call__(self, value):
|
|
45
|
+
if value is None:
|
|
46
|
+
return None
|
|
47
|
+
|
|
48
|
+
try:
|
|
49
|
+
return self.object_type(**value)
|
|
50
|
+
except TypeError:
|
|
51
|
+
pass
|
|
52
|
+
|
|
53
|
+
return value
|
|
54
|
+
|
|
55
|
+
def __repr__(self):
|
|
56
|
+
return '<dict to object converter>'
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def convert_dict_to_object(object_type):
|
|
60
|
+
return _DictObjectConverter(object_type)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
@attr.s(repr=False, slots=True, hash=True)
|
|
64
|
+
class _ValueToObjectConverter(_ConverterBase):
|
|
65
|
+
object_type = attr.ib(validator=attr.validators.instance_of(type))
|
|
66
|
+
value_converter = attr.ib(validator=attr.validators.optional(attr.validators.instance_of(_ConverterBase)))
|
|
67
|
+
|
|
68
|
+
def __call__(self, value):
|
|
69
|
+
if value is None:
|
|
70
|
+
return None
|
|
71
|
+
|
|
72
|
+
if isinstance(value, self.object_type):
|
|
73
|
+
return value
|
|
74
|
+
|
|
75
|
+
if self.value_converter is not None:
|
|
76
|
+
value = self.value_converter(value)
|
|
77
|
+
|
|
78
|
+
return self.object_type(value)
|
|
79
|
+
|
|
80
|
+
def __repr__(self):
|
|
81
|
+
return '<value to object converter>'
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def convert_value_to_object(object_type, value_converter=None):
|
|
85
|
+
return _ValueToObjectConverter(object_type, value_converter)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
@attr.s(repr=False, slots=True, hash=True)
|
|
89
|
+
class _EnumConverter(_ConverterBase):
|
|
90
|
+
enum_type = attr.ib(validator=attr.validators.instance_of(type))
|
|
91
|
+
|
|
92
|
+
def __call__(self, value):
|
|
93
|
+
if value is None:
|
|
94
|
+
return None
|
|
95
|
+
|
|
96
|
+
if not isinstance(value, six.string_types):
|
|
97
|
+
return value
|
|
98
|
+
|
|
99
|
+
try:
|
|
100
|
+
value = getattr(self.enum_type, value.upper())
|
|
101
|
+
except AttributeError:
|
|
102
|
+
pass
|
|
103
|
+
|
|
104
|
+
return value
|
|
105
|
+
|
|
106
|
+
def __repr__(self):
|
|
107
|
+
return '<enum converter>'
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def convert_enum(enum_type):
|
|
111
|
+
return _EnumConverter(enum_type)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
@attr.s(frozen=True)
|
|
115
|
+
class Base64Data(object):
|
|
116
|
+
value = attr.ib(validator=attr.validators.instance_of((bytes, bytearray)))
|
|
117
|
+
|
|
118
|
+
def _asdict(self):
|
|
119
|
+
return str(self)
|
|
120
|
+
|
|
121
|
+
def __str__(self):
|
|
122
|
+
return base64.b64encode(self.value).decode('ascii')
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
@attr.s(repr=False, slots=True, hash=True)
|
|
126
|
+
class _DateTimeConverter(_ConverterBase):
|
|
127
|
+
strptime_format = attr.ib(validator=attr.validators.optional(attr.validators.instance_of(str)))
|
|
128
|
+
|
|
129
|
+
def __call__(self, date_time):
|
|
130
|
+
if date_time is None:
|
|
131
|
+
return None
|
|
132
|
+
|
|
133
|
+
if isinstance(date_time, datetime.datetime):
|
|
134
|
+
return date_time
|
|
135
|
+
|
|
136
|
+
try:
|
|
137
|
+
if self.strptime_format is None:
|
|
138
|
+
date_time = dateutil.parser.isoparse(date_time)
|
|
139
|
+
else:
|
|
140
|
+
date_time = datetime.datetime.strptime(date_time, self.strptime_format)
|
|
141
|
+
except (TypeError, ValueError):
|
|
142
|
+
pass
|
|
143
|
+
|
|
144
|
+
return date_time
|
|
145
|
+
|
|
146
|
+
def __repr__(self):
|
|
147
|
+
return '<datetime converter>'
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def convert_datetime(strptime_format=None):
|
|
151
|
+
return _DateTimeConverter(strptime_format)
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
@attr.s(repr=False, slots=True, hash=True)
|
|
155
|
+
class _Base64DataConverter(_ConverterBase):
|
|
156
|
+
def __call__(self, value):
|
|
157
|
+
if value is None:
|
|
158
|
+
return None
|
|
159
|
+
|
|
160
|
+
if isinstance(value, bytearray) or (six.PY3 and isinstance(value, bytes)):
|
|
161
|
+
return Base64Data(value)
|
|
162
|
+
|
|
163
|
+
if not isinstance(value, six.string_types):
|
|
164
|
+
return value
|
|
165
|
+
|
|
166
|
+
try:
|
|
167
|
+
value = Base64Data(base64.b64decode(value))
|
|
168
|
+
except (ValueError, TypeError):
|
|
169
|
+
pass
|
|
170
|
+
|
|
171
|
+
return value
|
|
172
|
+
|
|
173
|
+
def __repr__(self):
|
|
174
|
+
return '<base64 data converter>'
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def convert_base64_data():
|
|
178
|
+
return _Base64DataConverter()
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
@attr.s(repr=False, slots=True, hash=True)
|
|
182
|
+
class _BigNumberConverter(_ConverterBase):
|
|
183
|
+
def __call__(self, value):
|
|
184
|
+
if value is None:
|
|
185
|
+
return None
|
|
186
|
+
|
|
187
|
+
if not isinstance(value, collections_abc.Iterable):
|
|
188
|
+
return value
|
|
189
|
+
|
|
190
|
+
if not all(map(lambda big_number_part: isinstance(big_number_part, six.string_types), value)):
|
|
191
|
+
return value
|
|
192
|
+
|
|
193
|
+
try:
|
|
194
|
+
value = int(''.join(value).replace('0x', '').replace(' ', '').replace(',', ''), 16)
|
|
195
|
+
except ValueError:
|
|
196
|
+
pass
|
|
197
|
+
|
|
198
|
+
return value
|
|
199
|
+
|
|
200
|
+
def __repr__(self):
|
|
201
|
+
return '<big number converter>'
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def convert_big_enum():
|
|
205
|
+
return _BigNumberConverter()
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
@attr.s(repr=False, slots=True, hash=True)
|
|
209
|
+
class _IterableConverter(_ConverterBase):
|
|
210
|
+
member_converter = attr.ib(validator=attr.validators.instance_of(collections_abc.Callable))
|
|
211
|
+
|
|
212
|
+
def __call__(self, iterable):
|
|
213
|
+
if iterable is None:
|
|
214
|
+
return None
|
|
215
|
+
|
|
216
|
+
try:
|
|
217
|
+
for idx, member in enumerate(iterable):
|
|
218
|
+
iterable[idx] = self.member_converter(member)
|
|
219
|
+
except (TypeError, ValueError):
|
|
220
|
+
pass
|
|
221
|
+
|
|
222
|
+
return iterable
|
|
223
|
+
|
|
224
|
+
def __repr__(self):
|
|
225
|
+
return '<iterable converter>'
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
def convert_iterable(member_converter):
|
|
229
|
+
return _IterableConverter(member_converter)
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
@attr.s(repr=False, slots=True, hash=True)
|
|
233
|
+
class _MappingConverter(_ConverterBase):
|
|
234
|
+
key_converter = attr.ib(validator=attr.validators.optional(attr.validators.instance_of(collections_abc.Callable)))
|
|
235
|
+
value_converter = attr.ib(validator=attr.validators.optional(attr.validators.instance_of(collections_abc.Callable)))
|
|
236
|
+
|
|
237
|
+
def __call__(self, mapping):
|
|
238
|
+
if mapping is None:
|
|
239
|
+
return None
|
|
240
|
+
|
|
241
|
+
if not isinstance(mapping, collections_abc.Mapping):
|
|
242
|
+
return mapping
|
|
243
|
+
|
|
244
|
+
try:
|
|
245
|
+
key_value_pairs = [[key, value] for key, value in mapping.items()]
|
|
246
|
+
if self.key_converter is not None:
|
|
247
|
+
for pair in key_value_pairs:
|
|
248
|
+
pair[0] = self.key_converter(pair[0])
|
|
249
|
+
if self.value_converter is not None:
|
|
250
|
+
for pair in key_value_pairs:
|
|
251
|
+
pair[1] = self.value_converter(pair[1])
|
|
252
|
+
mapping = type(mapping)(key_value_pairs)
|
|
253
|
+
except (TypeError, ValueError):
|
|
254
|
+
pass
|
|
255
|
+
|
|
256
|
+
return mapping
|
|
257
|
+
|
|
258
|
+
def __repr__(self):
|
|
259
|
+
return '<mapping converter>'
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
def convert_mapping(key_converter=None, value_converter=None):
|
|
263
|
+
return _MappingConverter(key_converter, value_converter)
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
@attr.s(frozen=True)
|
|
267
|
+
class ClientVersion(object):
|
|
268
|
+
parts = attr.ib(validator=attr.validators.deep_iterable(attr.validators.instance_of(int)))
|
|
269
|
+
|
|
270
|
+
@classmethod
|
|
271
|
+
def from_str(cls, version_str):
|
|
272
|
+
try:
|
|
273
|
+
return cls((int(version_str), ))
|
|
274
|
+
except ValueError:
|
|
275
|
+
pass
|
|
276
|
+
|
|
277
|
+
return cls(tuple(map(int, version_str.split('.'))))
|
|
278
|
+
|
|
279
|
+
def __str__(self):
|
|
280
|
+
return '.'.join(map(str, self.parts))
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
@attr.s(repr=False, slots=True, hash=True)
|
|
284
|
+
class _ClientVersionConverter(_ConverterBase):
|
|
285
|
+
def __call__(self, version):
|
|
286
|
+
if version is None:
|
|
287
|
+
return None
|
|
288
|
+
|
|
289
|
+
if not isinstance(version, six.string_types):
|
|
290
|
+
return version
|
|
291
|
+
|
|
292
|
+
try:
|
|
293
|
+
version = ClientVersion.from_str(version)
|
|
294
|
+
except (TypeError, ValueError):
|
|
295
|
+
pass
|
|
296
|
+
|
|
297
|
+
return version
|
|
298
|
+
|
|
299
|
+
def __repr__(self):
|
|
300
|
+
return '<client version converter>'
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
def convert_client_version():
|
|
304
|
+
return _ClientVersionConverter()
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
@attr.s(repr=False, slots=True, hash=True)
|
|
308
|
+
class _UrlConverter(_ConverterBase):
|
|
309
|
+
def __call__(self, value):
|
|
310
|
+
if value is None:
|
|
311
|
+
return None
|
|
312
|
+
|
|
313
|
+
if not isinstance(value, six.string_types):
|
|
314
|
+
return value
|
|
315
|
+
|
|
316
|
+
try:
|
|
317
|
+
value = urllib3.util.parse_url(value)
|
|
318
|
+
except urllib3.exceptions.LocationParseError:
|
|
319
|
+
pass
|
|
320
|
+
|
|
321
|
+
return value
|
|
322
|
+
|
|
323
|
+
def __repr__(self):
|
|
324
|
+
return '<url converter>'
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
def convert_url():
|
|
328
|
+
return _UrlConverter()
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
@attr.s(repr=False, slots=True, hash=True)
|
|
332
|
+
class _VariadicConverter(_ConverterBase):
|
|
333
|
+
converters = attr.ib(
|
|
334
|
+
validator=attr.validators.deep_iterable(attr.validators.instance_of(_ConverterBase))
|
|
335
|
+
)
|
|
336
|
+
|
|
337
|
+
def __call__(self, convertable):
|
|
338
|
+
if convertable is None:
|
|
339
|
+
return None
|
|
340
|
+
|
|
341
|
+
for converter in self.converters:
|
|
342
|
+
converted = converter(convertable)
|
|
343
|
+
if id(converted) != id(convertable):
|
|
344
|
+
return converted
|
|
345
|
+
|
|
346
|
+
return convertable
|
|
347
|
+
|
|
348
|
+
def __repr__(self):
|
|
349
|
+
return '<variadic converter>'
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
def convert_variadic(converters):
|
|
353
|
+
return _VariadicConverter(converters)
|
|
354
|
+
|
|
355
|
+
|
|
356
|
+
class CryptoDataParamsBase(object):
|
|
357
|
+
@classmethod
|
|
358
|
+
def get_init_attribute_names(cls):
|
|
359
|
+
return [
|
|
360
|
+
six.ensure_text(name)
|
|
361
|
+
for name, attribute in attr.fields_dict(cls).items()
|
|
362
|
+
if attribute.init
|
|
363
|
+
]
|
|
364
|
+
|
|
365
|
+
def _asdict_filter(self, attribute, value):
|
|
366
|
+
if attribute.name.startswith('_'):
|
|
367
|
+
return False
|
|
368
|
+
|
|
369
|
+
if attribute.default != attr.NOTHING and value == attribute.default:
|
|
370
|
+
return False
|
|
371
|
+
|
|
372
|
+
return True
|
|
373
|
+
|
|
374
|
+
def _asdict_serializer(self, _, __, value):
|
|
375
|
+
if hasattr(value, '_asdict'):
|
|
376
|
+
return getattr(value, '_asdict')()
|
|
377
|
+
if isinstance(value, enum.Enum):
|
|
378
|
+
return value.name
|
|
379
|
+
|
|
380
|
+
return value
|
|
381
|
+
|
|
382
|
+
def _asdict(self):
|
|
383
|
+
return attr.asdict(
|
|
384
|
+
self,
|
|
385
|
+
filter=self._asdict_filter,
|
|
386
|
+
dict_factory=collections.OrderedDict,
|
|
387
|
+
value_serializer=self._asdict_serializer
|
|
388
|
+
)
|
|
389
|
+
|
|
390
|
+
|
|
391
|
+
@attr.s(frozen=True)
|
|
392
|
+
class CryptoDataParamsFetchedBase(CryptoDataParamsBase):
|
|
393
|
+
@property
|
|
394
|
+
@abc.abstractmethod
|
|
395
|
+
def identifier(self):
|
|
396
|
+
raise NotImplementedError()
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
@attr.s(frozen=True)
|
|
400
|
+
class CryptoDataParamsNamed(CryptoDataParamsBase):
|
|
401
|
+
name = attr.ib(validator=attr.validators.instance_of(six.string_types))
|
|
402
|
+
long_name = attr.ib(validator=attr.validators.optional(attr.validators.instance_of(six.string_types)))
|
|
403
|
+
|
|
404
|
+
def __str__(self):
|
|
405
|
+
return self.name
|
|
406
|
+
|
|
407
|
+
|
|
408
|
+
@attr.s(frozen=True)
|
|
409
|
+
class CryptoDataParamsEnumNumeric(CryptoDataParamsBase):
|
|
410
|
+
code = attr.ib()
|
|
411
|
+
|
|
412
|
+
@code.validator
|
|
413
|
+
def _validator_code(self, _, value):
|
|
414
|
+
if not isinstance(value, int):
|
|
415
|
+
raise ValueError(value)
|
|
416
|
+
if value < 0:
|
|
417
|
+
raise ValueError(value)
|
|
418
|
+
if value >= 2 ** (self.get_code_size() * 8):
|
|
419
|
+
raise ValueError(value)
|
|
420
|
+
|
|
421
|
+
@classmethod
|
|
422
|
+
def get_code_size(cls):
|
|
423
|
+
raise NotImplementedError()
|
|
424
|
+
|
|
425
|
+
|
|
426
|
+
@attr.s(frozen=True)
|
|
427
|
+
class CryptoDataParamsEnumString(CryptoDataParamsBase):
|
|
428
|
+
code = attr.ib(validator=attr.validators.instance_of(six.string_types))
|
|
429
|
+
|
|
430
|
+
def __str__(self):
|
|
431
|
+
return self.code
|
|
432
|
+
|
|
433
|
+
def _asdict(self):
|
|
434
|
+
return str(self)
|
|
435
|
+
|
|
436
|
+
def get_code_size(self):
|
|
437
|
+
return len(self.code)
|
|
438
|
+
|
|
439
|
+
|
|
440
|
+
@attr.s(frozen=True)
|
|
441
|
+
class CryptoDataParamsOIDOptional(CryptoDataParamsNamed):
|
|
442
|
+
oid = attr.ib(validator=attr.validators.optional(attr.validators.instance_of(six.string_types)))
|
|
443
|
+
|
|
444
|
+
|
|
445
|
+
class CryptoDataEnumBase(enum.Enum):
|
|
446
|
+
@classmethod
|
|
447
|
+
def get_json_records(cls, param_class):
|
|
448
|
+
return collections.OrderedDict([
|
|
449
|
+
(six.ensure_str(unicodedata.normalize('NFD', name).encode('ascii', 'ignore')), param_class(**{
|
|
450
|
+
init_param_name.replace('-', '_'): value
|
|
451
|
+
for init_param_name, value in params.items()
|
|
452
|
+
if not init_param_name.startswith('_')
|
|
453
|
+
}))
|
|
454
|
+
for name, params in cls.get_json_object(param_class).items()
|
|
455
|
+
])
|
|
456
|
+
|
|
457
|
+
@staticmethod
|
|
458
|
+
def get_file_name_from_param_class(param_class):
|
|
459
|
+
if not param_class.__name__.endswith('Params'):
|
|
460
|
+
raise TypeError(param_class)
|
|
461
|
+
|
|
462
|
+
enum_class_name = param_class.__name__[:-6]
|
|
463
|
+
enum_class_name_parts = [
|
|
464
|
+
name_part.lower()
|
|
465
|
+
for name_part in re.split("([A-Z]+[^A-Z]*)", enum_class_name)
|
|
466
|
+
if name_part
|
|
467
|
+
]
|
|
468
|
+
|
|
469
|
+
return '-'.join(enum_class_name_parts) + '.json'
|
|
470
|
+
|
|
471
|
+
@classmethod
|
|
472
|
+
def get_json_path(cls, param_class):
|
|
473
|
+
return (
|
|
474
|
+
pathlib.Path(inspect.getfile(param_class)).parent /
|
|
475
|
+
cls.get_file_name_from_param_class(param_class)
|
|
476
|
+
)
|
|
477
|
+
|
|
478
|
+
@classmethod
|
|
479
|
+
def get_json_encoding(cls):
|
|
480
|
+
return 'ascii'
|
|
481
|
+
|
|
482
|
+
@classmethod
|
|
483
|
+
def is_json_encoding_ascii(cls):
|
|
484
|
+
return cls.get_json_encoding() == 'ascii'
|
|
485
|
+
|
|
486
|
+
@classmethod
|
|
487
|
+
def get_json_object(cls, param_class):
|
|
488
|
+
json_path = cls.get_json_path(param_class)
|
|
489
|
+
with codecs.open(str(json_path), 'r', encoding=cls.get_json_encoding()) as json_file:
|
|
490
|
+
return json.load(json_file, object_pairs_hook=collections.OrderedDict)
|
|
491
|
+
|
|
492
|
+
@classmethod
|
|
493
|
+
def dump_json(cls, json_object):
|
|
494
|
+
return json.dumps(json_object, ensure_ascii=cls.is_json_encoding_ascii(), indent=4) + os.linesep
|
|
495
|
+
|
|
496
|
+
@classmethod
|
|
497
|
+
def set_json(cls, param_class, json_object):
|
|
498
|
+
json_path = cls.get_json_path(param_class)
|
|
499
|
+
with codecs.open(str(json_path), 'w+', encoding=cls.get_json_encoding()) as json_file:
|
|
500
|
+
json_file.write(cls.dump_json(json_object))
|
|
501
|
+
|
|
502
|
+
@classmethod
|
|
503
|
+
def get_json(cls, param_class):
|
|
504
|
+
return cls.get_json_object(param_class)
|
|
505
|
+
|
|
506
|
+
@classmethod
|
|
507
|
+
def _from_attr(cls, attr_name, value):
|
|
508
|
+
for item in cls:
|
|
509
|
+
if value == getattr(item.value, attr_name):
|
|
510
|
+
return item
|
|
511
|
+
|
|
512
|
+
raise InvalidValue(value, cls, attr_name)
|
|
513
|
+
|
|
514
|
+
|
|
515
|
+
class CryptoDataEnumCodedBase(CryptoDataEnumBase):
|
|
516
|
+
@classmethod
|
|
517
|
+
def from_code(cls, code):
|
|
518
|
+
return cls._from_attr('code', code)
|
|
519
|
+
|
|
520
|
+
|
|
521
|
+
class CryptoDataEnumOIDBase(CryptoDataEnumCodedBase):
|
|
522
|
+
@classmethod
|
|
523
|
+
def from_oid(cls, oid):
|
|
524
|
+
return cls._from_attr('oid', oid)
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
import binascii
|
|
4
|
+
import hashlib
|
|
5
|
+
|
|
6
|
+
import attr
|
|
7
|
+
import six
|
|
8
|
+
import urllib3
|
|
9
|
+
|
|
10
|
+
from cryptodatahub.common.algorithm import Hash
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def bytes_to_hex_string(byte_array, separator='', lowercase=False):
|
|
14
|
+
if lowercase:
|
|
15
|
+
format_str = '{:02x}'
|
|
16
|
+
else:
|
|
17
|
+
format_str = '{:02X}'
|
|
18
|
+
|
|
19
|
+
return separator.join([format_str.format(x) for x in six.iterbytes(bytes(byte_array))])
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def bytes_from_hex_string(hex_string, separator=''):
|
|
23
|
+
if separator:
|
|
24
|
+
hex_string = ''.join(hex_string.split(separator))
|
|
25
|
+
|
|
26
|
+
try:
|
|
27
|
+
binary_data = binascii.a2b_hex(hex_string)
|
|
28
|
+
except (TypeError, ValueError) as e:
|
|
29
|
+
six.raise_from(ValueError(*e.args), e)
|
|
30
|
+
|
|
31
|
+
return binary_data
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def name_to_enum_item_name(name):
|
|
35
|
+
converted_name = ''
|
|
36
|
+
for char in name:
|
|
37
|
+
if char.isalnum():
|
|
38
|
+
converted_name += char
|
|
39
|
+
elif char == '\'':
|
|
40
|
+
pass
|
|
41
|
+
elif converted_name and converted_name[-1] != '_':
|
|
42
|
+
converted_name += '_'
|
|
43
|
+
|
|
44
|
+
return converted_name.rstrip('_').upper()
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
_HASHLIB_FUNCS = {
|
|
48
|
+
Hash.MD5: hashlib.md5,
|
|
49
|
+
Hash.SHA1: hashlib.sha1,
|
|
50
|
+
Hash.SHA2_224: hashlib.sha224,
|
|
51
|
+
Hash.SHA2_256: hashlib.sha256,
|
|
52
|
+
Hash.SHA2_384: hashlib.sha384,
|
|
53
|
+
Hash.SHA2_512: hashlib.sha512,
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def hash_bytes(hash_algorithm, hashable_value):
|
|
58
|
+
try:
|
|
59
|
+
hashlib_funcs = _HASHLIB_FUNCS[hash_algorithm]
|
|
60
|
+
except KeyError as e:
|
|
61
|
+
six.raise_from(NotImplementedError(hash_algorithm), e)
|
|
62
|
+
|
|
63
|
+
return hashlib_funcs(hashable_value).digest()
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
@attr.s
|
|
67
|
+
class HttpFetcher(object):
|
|
68
|
+
connect_timeout = attr.ib(default=2, validator=attr.validators.instance_of((int, float)))
|
|
69
|
+
read_timeout = attr.ib(default=1, validator=attr.validators.instance_of((int, float)))
|
|
70
|
+
retry = attr.ib(default=1, validator=attr.validators.instance_of(int))
|
|
71
|
+
_request_params = attr.ib(default=None, init=False)
|
|
72
|
+
_response = attr.ib(default=None, init=False)
|
|
73
|
+
|
|
74
|
+
def __attrs_post_init__(self):
|
|
75
|
+
request_params = {
|
|
76
|
+
'preload_content': False,
|
|
77
|
+
'timeout': urllib3.Timeout(connect=self.connect_timeout, read=self.read_timeout),
|
|
78
|
+
'retries': urllib3.Retry(
|
|
79
|
+
self.retry, status_forcelist=urllib3.Retry.RETRY_AFTER_STATUS_CODES | frozenset([502])
|
|
80
|
+
),
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
object.__setattr__(self, '_request_params', request_params)
|
|
84
|
+
|
|
85
|
+
def get_response_header(self, header_name):
|
|
86
|
+
if self._response is None:
|
|
87
|
+
raise AttributeError()
|
|
88
|
+
|
|
89
|
+
return self._response.headers.get(header_name, None)
|
|
90
|
+
|
|
91
|
+
@property
|
|
92
|
+
def response_data(self):
|
|
93
|
+
if self._response is None:
|
|
94
|
+
raise AttributeError()
|
|
95
|
+
|
|
96
|
+
return self._response.data
|
|
97
|
+
|
|
98
|
+
def fetch(self, url):
|
|
99
|
+
pool_manager = urllib3.PoolManager()
|
|
100
|
+
|
|
101
|
+
try:
|
|
102
|
+
self._response = pool_manager.request('GET', str(url), **self._request_params)
|
|
103
|
+
except BaseException as e: # pylint: disable=broad-except
|
|
104
|
+
if e.__class__.__name__ != 'TimeoutError' and not isinstance(e, urllib3.exceptions.HTTPError):
|
|
105
|
+
raise e
|
|
106
|
+
|
|
107
|
+
pool_manager.clear()
|
|
108
|
+
|
|
109
|
+
def __call__(self, url):
|
|
110
|
+
self.fetch(url)
|
|
111
|
+
|
|
112
|
+
return self.response_data
|
|
File without changes
|