cryptoparser 0.11.2__tar.gz → 0.12.1__tar.gz
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.
- {CryptoParser-0.11.2 → CryptoParser-0.12.1}/CHANGELOG.rst +32 -0
- {CryptoParser-0.11.2 → CryptoParser-0.12.1/CryptoParser.egg-info}/PKG-INFO +2 -2
- {CryptoParser-0.11.2 → CryptoParser-0.12.1}/CryptoParser.egg-info/requires.txt +1 -1
- {CryptoParser-0.11.2/CryptoParser.egg-info → CryptoParser-0.12.1}/PKG-INFO +2 -2
- {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/__setup__.py +1 -1
- {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/common/base.py +41 -10
- {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/common/field.py +85 -0
- {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/common/parse.py +13 -10
- {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/httpx/header.py +930 -51
- {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/ssh/key.py +59 -82
- {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/tls/version.py +3 -1
- {CryptoParser-0.11.2 → CryptoParser-0.12.1}/requirements.txt +1 -1
- {CryptoParser-0.11.2 → CryptoParser-0.12.1}/CONTRIBUTING.rst +0 -0
- {CryptoParser-0.11.2 → CryptoParser-0.12.1}/CryptoParser.egg-info/SOURCES.txt +0 -0
- {CryptoParser-0.11.2 → CryptoParser-0.12.1}/CryptoParser.egg-info/dependency_links.txt +0 -0
- {CryptoParser-0.11.2 → CryptoParser-0.12.1}/CryptoParser.egg-info/top_level.txt +0 -0
- {CryptoParser-0.11.2 → CryptoParser-0.12.1}/LICENSE.txt +0 -0
- {CryptoParser-0.11.2 → CryptoParser-0.12.1}/MANIFEST.in +0 -0
- {CryptoParser-0.11.2 → CryptoParser-0.12.1}/README.rst +0 -0
- {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/__init__.py +0 -0
- {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/common/__init__.py +0 -0
- {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/common/classes.py +0 -0
- {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/common/exception.py +0 -0
- {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/common/utils.py +0 -0
- {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/common/x509.py +0 -0
- {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/dnsrec/__init__.py +0 -0
- {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/dnsrec/record.py +0 -0
- {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/dnsrec/txt.py +0 -0
- {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/httpx/__init__.py +0 -0
- {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/httpx/parse.py +0 -0
- {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/httpx/version.py +0 -0
- {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/ssh/__init__.py +0 -0
- {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/ssh/record.py +0 -0
- {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/ssh/subprotocol.py +0 -0
- {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/ssh/version.py +0 -0
- {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/tls/__init__.py +0 -0
- {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/tls/algorithm.py +0 -0
- {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/tls/ciphersuite.py +0 -0
- {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/tls/extension.py +0 -0
- {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/tls/grease.py +0 -0
- {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/tls/ldap.py +0 -0
- {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/tls/mysql.py +0 -0
- {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/tls/openvpn.py +0 -0
- {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/tls/postgresql.py +0 -0
- {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/tls/rdp.py +0 -0
- {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/tls/record.py +0 -0
- {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/tls/subprotocol.py +0 -0
- {CryptoParser-0.11.2 → CryptoParser-0.12.1}/setup.cfg +0 -0
- {CryptoParser-0.11.2 → CryptoParser-0.12.1}/setup.py +0 -0
|
@@ -2,6 +2,38 @@
|
|
|
2
2
|
Changelog
|
|
3
3
|
=========
|
|
4
4
|
|
|
5
|
+
-------------------
|
|
6
|
+
0.12.1 - 2023-12-13
|
|
7
|
+
-------------------
|
|
8
|
+
|
|
9
|
+
Notable fixes
|
|
10
|
+
=============
|
|
11
|
+
|
|
12
|
+
- SSH
|
|
13
|
+
|
|
14
|
+
- add missing host key algorithms to key parser classes (#79)
|
|
15
|
+
|
|
16
|
+
- Generic
|
|
17
|
+
|
|
18
|
+
- fix markdown generation in the case of TLS client versions (#80)
|
|
19
|
+
|
|
20
|
+
-------------------
|
|
21
|
+
0.12.0 - 2023-11-23
|
|
22
|
+
-------------------
|
|
23
|
+
|
|
24
|
+
Features
|
|
25
|
+
========
|
|
26
|
+
|
|
27
|
+
- HTTP(S) (``http``)
|
|
28
|
+
|
|
29
|
+
- Headers (``headers``)
|
|
30
|
+
|
|
31
|
+
- add parsers for security related headers
|
|
32
|
+
(`Content Security Policy <https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP>`__ (CSP),
|
|
33
|
+
`Content-Security-Policy-Report-Only <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only>`__)
|
|
34
|
+
(#59)
|
|
35
|
+
|
|
36
|
+
|
|
5
37
|
-------------------
|
|
6
38
|
0.11.2 - 2023-11-13
|
|
7
39
|
-------------------
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: CryptoParser
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.12.1
|
|
4
4
|
Summary: Fast and flexible security protocol parser and generator
|
|
5
5
|
Author: Szilárd Pfeiffer
|
|
6
6
|
Author-email: coroner@pfeifferszilard.hu
|
|
@@ -48,7 +48,7 @@ Description-Content-Type: text/x-rst
|
|
|
48
48
|
License-File: LICENSE.txt
|
|
49
49
|
Requires-Dist: asn1crypto
|
|
50
50
|
Requires-Dist: attrs<22.0.1,>=20.3.0
|
|
51
|
-
Requires-Dist: cryptodatahub==0.
|
|
51
|
+
Requires-Dist: cryptodatahub==0.12.1
|
|
52
52
|
Requires-Dist: python-dateutil
|
|
53
53
|
Requires-Dist: py2-ipaddress; python_version < "3.4"
|
|
54
54
|
Requires-Dist: typing; python_version < "3.5"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: CryptoParser
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.12.1
|
|
4
4
|
Summary: Fast and flexible security protocol parser and generator
|
|
5
5
|
Author: Szilárd Pfeiffer
|
|
6
6
|
Author-email: coroner@pfeifferszilard.hu
|
|
@@ -48,7 +48,7 @@ Description-Content-Type: text/x-rst
|
|
|
48
48
|
License-File: LICENSE.txt
|
|
49
49
|
Requires-Dist: asn1crypto
|
|
50
50
|
Requires-Dist: attrs<22.0.1,>=20.3.0
|
|
51
|
-
Requires-Dist: cryptodatahub==0.
|
|
51
|
+
Requires-Dist: cryptodatahub==0.12.1
|
|
52
52
|
Requires-Dist: python-dateutil
|
|
53
53
|
Requires-Dist: py2-ipaddress; python_version < "3.4"
|
|
54
54
|
Requires-Dist: typing; python_version < "3.5"
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
__title__ = 'CryptoParser'
|
|
4
4
|
__technical_name__ = __title__.lower()
|
|
5
|
-
__version__ = '0.
|
|
5
|
+
__version__ = '0.12.1'
|
|
6
6
|
__description__ = 'Fast and flexible security protocol parser and generator'
|
|
7
7
|
__author__ = 'Szilárd Pfeiffer'
|
|
8
8
|
__author_email__ = 'coroner@pfeifferszilard.hu'
|
|
@@ -61,7 +61,6 @@ class SerializableTextEncoder(object):
|
|
|
61
61
|
|
|
62
62
|
class Serializable(object): # pylint: disable=too-few-public-methods
|
|
63
63
|
_MARKDOWN_RESULT_STRING_CLASSES = (
|
|
64
|
-
CryptoDataParamsBase,
|
|
65
64
|
ipaddress.IPv4Network,
|
|
66
65
|
ipaddress.IPv6Network,
|
|
67
66
|
urllib3.util.url.Url,
|
|
@@ -143,7 +142,7 @@ class Serializable(object): # pylint: disable=too-few-public-methods
|
|
|
143
142
|
])
|
|
144
143
|
elif hasattr(obj, '__dict__'):
|
|
145
144
|
result = Serializable._json_traverse(obj.__dict__, result_func)
|
|
146
|
-
elif isinstance(obj, (list, tuple)):
|
|
145
|
+
elif isinstance(obj, (list, tuple, frozenset, set)):
|
|
147
146
|
result = [Serializable._json_traverse(item, result_func) for item in obj]
|
|
148
147
|
else:
|
|
149
148
|
result = result_func(obj)
|
|
@@ -227,7 +226,7 @@ class Serializable(object): # pylint: disable=too-few-public-methods
|
|
|
227
226
|
return not isinstance(obj, enum.Enum) and isinstance(obj, six.string_types + six.integer_types + (float, ))
|
|
228
227
|
|
|
229
228
|
@classmethod
|
|
230
|
-
def _markdown_result(cls, obj, level=0): # pylint: disable=too-many-branches
|
|
229
|
+
def _markdown_result(cls, obj, level=0): # pylint: disable=too-many-branches,too-many-return-statements
|
|
231
230
|
if obj is None:
|
|
232
231
|
result = cls.post_text_encoder('n/a', level)
|
|
233
232
|
elif isinstance(obj, bool):
|
|
@@ -245,17 +244,19 @@ class Serializable(object): # pylint: disable=too-few-public-methods
|
|
|
245
244
|
return cls.post_text_encoder(obj.value, level)
|
|
246
245
|
|
|
247
246
|
return cls.post_text_encoder(obj.name, level)
|
|
248
|
-
elif attr.has(type(obj)):
|
|
249
|
-
result = cls._markdown_result_complex(obj, level)
|
|
250
247
|
elif isinstance(obj, cls._MARKDOWN_RESULT_STRING_CLASSES):
|
|
251
248
|
return False, str(obj)
|
|
252
249
|
elif isinstance(obj, datetime.timedelta):
|
|
253
250
|
return False, str(obj.seconds)
|
|
251
|
+
elif isinstance(obj, CryptoDataParamsBase) and hasattr(obj, '__str__'):
|
|
252
|
+
return False, str(obj)
|
|
253
|
+
elif attr.has(type(obj)):
|
|
254
|
+
result = cls._markdown_result_complex(obj, level)
|
|
254
255
|
elif hasattr(obj, '_asdict'):
|
|
255
256
|
result = cls._markdown_result(obj._asdict(), level)
|
|
256
257
|
elif hasattr(obj, '__dict__') or isinstance(obj, dict):
|
|
257
258
|
result = cls._markdown_result_complex(obj, level)
|
|
258
|
-
elif isinstance(obj, (list, tuple, set, ArrayBase)):
|
|
259
|
+
elif isinstance(obj, (list, tuple, frozenset, set, ArrayBase)):
|
|
259
260
|
result = cls._markdown_result_list(obj, level)
|
|
260
261
|
elif isinstance(obj, (bytes, bytearray)):
|
|
261
262
|
result = cls.post_text_encoder(bytes_to_hex_string(obj, separator=':', lowercase=False), level)
|
|
@@ -279,7 +280,7 @@ class Serializable(object): # pylint: disable=too-few-public-methods
|
|
|
279
280
|
|
|
280
281
|
|
|
281
282
|
@attr.s
|
|
282
|
-
class
|
|
283
|
+
class VariantParsableBase(ParsableBase):
|
|
283
284
|
variant = attr.ib()
|
|
284
285
|
|
|
285
286
|
_REGISTERED_VARIANTS = OrderedDict()
|
|
@@ -324,6 +325,21 @@ class VariantParsable(ParsableBase):
|
|
|
324
325
|
|
|
325
326
|
registered_variants[variant_tag].append(parsable_class)
|
|
326
327
|
|
|
328
|
+
@classmethod
|
|
329
|
+
@abc.abstractmethod
|
|
330
|
+
def _parse(cls, parsable):
|
|
331
|
+
raise NotImplementedError()
|
|
332
|
+
|
|
333
|
+
def compose(self):
|
|
334
|
+
return self.variant.compose()
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
class VariantParsable(VariantParsableBase):
|
|
338
|
+
@classmethod
|
|
339
|
+
@abc.abstractmethod
|
|
340
|
+
def _get_variants(cls):
|
|
341
|
+
raise NotImplementedError()
|
|
342
|
+
|
|
327
343
|
@classmethod
|
|
328
344
|
def _parse(cls, parsable):
|
|
329
345
|
for variant_parser in cls._get_variant_types():
|
|
@@ -335,8 +351,23 @@ class VariantParsable(ParsableBase):
|
|
|
335
351
|
|
|
336
352
|
raise InvalidValue(parsable, cls)
|
|
337
353
|
|
|
338
|
-
|
|
339
|
-
|
|
354
|
+
|
|
355
|
+
class VariantParsableExact(VariantParsableBase):
|
|
356
|
+
@classmethod
|
|
357
|
+
@abc.abstractmethod
|
|
358
|
+
def _get_variants(cls):
|
|
359
|
+
raise NotImplementedError()
|
|
360
|
+
|
|
361
|
+
@classmethod
|
|
362
|
+
def _parse(cls, parsable):
|
|
363
|
+
for variant_parser in cls._get_variant_types():
|
|
364
|
+
try:
|
|
365
|
+
parsed_object = variant_parser.parse_exact_size(parsable)
|
|
366
|
+
return parsed_object, len(parsable)
|
|
367
|
+
except (InvalidType, InvalidValue, TooMuchData):
|
|
368
|
+
pass
|
|
369
|
+
|
|
370
|
+
raise InvalidValue(parsable, cls)
|
|
340
371
|
|
|
341
372
|
|
|
342
373
|
@attr.s
|
|
@@ -825,7 +856,7 @@ class StringEnumParsableBase(ParsableBaseNoABC):
|
|
|
825
856
|
enum_items.sort(key=lambda color: len(color.value.code), reverse=True)
|
|
826
857
|
|
|
827
858
|
try:
|
|
828
|
-
code = six.ensure_text(parsable, 'ascii')
|
|
859
|
+
code = six.ensure_text(bytes(parsable), 'ascii')
|
|
829
860
|
except UnicodeDecodeError as e:
|
|
830
861
|
six.raise_from(InvalidValue(parsable, cls), e)
|
|
831
862
|
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
|
+
# pylint: disable=too-many-lines
|
|
2
3
|
|
|
3
4
|
import abc
|
|
4
5
|
import collections
|
|
5
6
|
import datetime
|
|
7
|
+
import enum
|
|
6
8
|
import json
|
|
7
9
|
|
|
8
10
|
import attr
|
|
@@ -791,6 +793,63 @@ class FieldsSemicolonSeparated(FieldValueMultiple):
|
|
|
791
793
|
return NameValuePairListSemicolonSeparated
|
|
792
794
|
|
|
793
795
|
|
|
796
|
+
class MimeTypeRegistry(enum.Enum):
|
|
797
|
+
APPLICATION = 'application'
|
|
798
|
+
AUDIO = 'audio'
|
|
799
|
+
FONT = 'font'
|
|
800
|
+
EXAMPLE = 'example'
|
|
801
|
+
IMAGE = 'image'
|
|
802
|
+
MESSAGE = 'message'
|
|
803
|
+
MODEL = 'model'
|
|
804
|
+
MULTIPART = 'multipart'
|
|
805
|
+
TEXT = 'text'
|
|
806
|
+
VIDEO = 'video'
|
|
807
|
+
|
|
808
|
+
|
|
809
|
+
@attr.s
|
|
810
|
+
class FieldValueMimeType(FieldValueComponentBase):
|
|
811
|
+
type = attr.ib(
|
|
812
|
+
validator=attr.validators.instance_of(six.string_types),
|
|
813
|
+
default=None,
|
|
814
|
+
)
|
|
815
|
+
registry = attr.ib(
|
|
816
|
+
validator=attr.validators.optional(attr.validators.instance_of(MimeTypeRegistry)),
|
|
817
|
+
default=None,
|
|
818
|
+
)
|
|
819
|
+
|
|
820
|
+
def __str__(self):
|
|
821
|
+
return '{}/{}'.format(self.registry.value, self.type)
|
|
822
|
+
|
|
823
|
+
@property
|
|
824
|
+
def value(self):
|
|
825
|
+
return self
|
|
826
|
+
|
|
827
|
+
@classmethod
|
|
828
|
+
def get_canonical_name(cls):
|
|
829
|
+
return ''
|
|
830
|
+
|
|
831
|
+
@classmethod
|
|
832
|
+
def _parse(cls, parsable):
|
|
833
|
+
parser = ParserText(parsable)
|
|
834
|
+
|
|
835
|
+
parser.parse_string_until_separator('registry', '/', item_class=MimeTypeRegistry)
|
|
836
|
+
parser.parse_separator('/')
|
|
837
|
+
parser.parse_string_by_length('type', parser.unparsed_length)
|
|
838
|
+
|
|
839
|
+
return FieldValueMimeType(**parser), parser.parsed_length
|
|
840
|
+
|
|
841
|
+
def compose(self):
|
|
842
|
+
composer = ComposerText()
|
|
843
|
+
|
|
844
|
+
composer.compose_string(str(self))
|
|
845
|
+
|
|
846
|
+
return composer.composed
|
|
847
|
+
|
|
848
|
+
@classmethod
|
|
849
|
+
def _check_name(cls, name):
|
|
850
|
+
pass
|
|
851
|
+
|
|
852
|
+
|
|
794
853
|
@attr.s
|
|
795
854
|
class FieldValueSingleBase(FieldValueBase, Serializable):
|
|
796
855
|
value = attr.ib()
|
|
@@ -916,6 +975,32 @@ class FieldValueDateTime(FieldValueSingleComplexBase):
|
|
|
916
975
|
return self._markdown_result(self.value, level)
|
|
917
976
|
|
|
918
977
|
|
|
978
|
+
class FieldValueStringBySeparatorBase(FieldValueSingleComplexBase):
|
|
979
|
+
@classmethod
|
|
980
|
+
@abc.abstractmethod
|
|
981
|
+
def _get_separators(cls):
|
|
982
|
+
raise NotImplementedError()
|
|
983
|
+
|
|
984
|
+
@classmethod
|
|
985
|
+
def _get_value_type(cls):
|
|
986
|
+
return six.string_types
|
|
987
|
+
|
|
988
|
+
@classmethod
|
|
989
|
+
def _parse(cls, parsable):
|
|
990
|
+
parser = ParserText(parsable)
|
|
991
|
+
|
|
992
|
+
parser.parse_string_until_separator_or_end('value', cls._get_separators())
|
|
993
|
+
|
|
994
|
+
return cls(parser['value']), parser.parsed_length
|
|
995
|
+
|
|
996
|
+
def compose(self):
|
|
997
|
+
composer = ComposerText()
|
|
998
|
+
|
|
999
|
+
composer.compose_string(self.value)
|
|
1000
|
+
|
|
1001
|
+
return composer.composed
|
|
1002
|
+
|
|
1003
|
+
|
|
919
1004
|
class FieldValueStringEnum(FieldValueSingleComplexBase):
|
|
920
1005
|
@classmethod
|
|
921
1006
|
@abc.abstractmethod
|
|
@@ -201,7 +201,7 @@ class ParserText(ParserBase):
|
|
|
201
201
|
|
|
202
202
|
return actual_offset - count_offset
|
|
203
203
|
|
|
204
|
-
def parse_separator(self, separator, min_length=1, max_length=
|
|
204
|
+
def parse_separator(self, separator, min_length=1, max_length=None):
|
|
205
205
|
self._parsed_length += self._check_separators(
|
|
206
206
|
'separator', self._parsed_length, separator, min_length, max_length
|
|
207
207
|
)
|
|
@@ -405,15 +405,18 @@ class ParserText(ParserBase):
|
|
|
405
405
|
name, item_offset, separator, str, None, True, separator_spaces
|
|
406
406
|
)
|
|
407
407
|
if parsed_length:
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
408
|
+
if isinstance(item_class, type) and issubclass(item_class, ParsableBase):
|
|
409
|
+
parsed_value = item_class.parse_exact_size(parsed_value.encode(self._encoding))
|
|
410
|
+
else:
|
|
411
|
+
parsed_value = self._apply_item_class(
|
|
412
|
+
name,
|
|
413
|
+
item_offset,
|
|
414
|
+
item_offset + parsed_length,
|
|
415
|
+
separator,
|
|
416
|
+
item_class,
|
|
417
|
+
fallback_class,
|
|
418
|
+
True
|
|
419
|
+
)
|
|
417
420
|
value.append(parsed_value)
|
|
418
421
|
item_offset += parsed_length
|
|
419
422
|
elif not skip_empty:
|