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.
Files changed (49) hide show
  1. {CryptoParser-0.11.2 → CryptoParser-0.12.1}/CHANGELOG.rst +32 -0
  2. {CryptoParser-0.11.2 → CryptoParser-0.12.1/CryptoParser.egg-info}/PKG-INFO +2 -2
  3. {CryptoParser-0.11.2 → CryptoParser-0.12.1}/CryptoParser.egg-info/requires.txt +1 -1
  4. {CryptoParser-0.11.2/CryptoParser.egg-info → CryptoParser-0.12.1}/PKG-INFO +2 -2
  5. {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/__setup__.py +1 -1
  6. {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/common/base.py +41 -10
  7. {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/common/field.py +85 -0
  8. {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/common/parse.py +13 -10
  9. {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/httpx/header.py +930 -51
  10. {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/ssh/key.py +59 -82
  11. {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/tls/version.py +3 -1
  12. {CryptoParser-0.11.2 → CryptoParser-0.12.1}/requirements.txt +1 -1
  13. {CryptoParser-0.11.2 → CryptoParser-0.12.1}/CONTRIBUTING.rst +0 -0
  14. {CryptoParser-0.11.2 → CryptoParser-0.12.1}/CryptoParser.egg-info/SOURCES.txt +0 -0
  15. {CryptoParser-0.11.2 → CryptoParser-0.12.1}/CryptoParser.egg-info/dependency_links.txt +0 -0
  16. {CryptoParser-0.11.2 → CryptoParser-0.12.1}/CryptoParser.egg-info/top_level.txt +0 -0
  17. {CryptoParser-0.11.2 → CryptoParser-0.12.1}/LICENSE.txt +0 -0
  18. {CryptoParser-0.11.2 → CryptoParser-0.12.1}/MANIFEST.in +0 -0
  19. {CryptoParser-0.11.2 → CryptoParser-0.12.1}/README.rst +0 -0
  20. {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/__init__.py +0 -0
  21. {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/common/__init__.py +0 -0
  22. {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/common/classes.py +0 -0
  23. {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/common/exception.py +0 -0
  24. {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/common/utils.py +0 -0
  25. {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/common/x509.py +0 -0
  26. {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/dnsrec/__init__.py +0 -0
  27. {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/dnsrec/record.py +0 -0
  28. {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/dnsrec/txt.py +0 -0
  29. {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/httpx/__init__.py +0 -0
  30. {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/httpx/parse.py +0 -0
  31. {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/httpx/version.py +0 -0
  32. {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/ssh/__init__.py +0 -0
  33. {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/ssh/record.py +0 -0
  34. {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/ssh/subprotocol.py +0 -0
  35. {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/ssh/version.py +0 -0
  36. {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/tls/__init__.py +0 -0
  37. {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/tls/algorithm.py +0 -0
  38. {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/tls/ciphersuite.py +0 -0
  39. {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/tls/extension.py +0 -0
  40. {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/tls/grease.py +0 -0
  41. {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/tls/ldap.py +0 -0
  42. {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/tls/mysql.py +0 -0
  43. {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/tls/openvpn.py +0 -0
  44. {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/tls/postgresql.py +0 -0
  45. {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/tls/rdp.py +0 -0
  46. {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/tls/record.py +0 -0
  47. {CryptoParser-0.11.2 → CryptoParser-0.12.1}/cryptoparser/tls/subprotocol.py +0 -0
  48. {CryptoParser-0.11.2 → CryptoParser-0.12.1}/setup.cfg +0 -0
  49. {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.11.2
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.11.2
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
  asn1crypto
2
2
  attrs<22.0.1,>=20.3.0
3
- cryptodatahub==0.11.2
3
+ cryptodatahub==0.12.1
4
4
  python-dateutil
5
5
  python-dateutil
6
6
  urllib3
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: CryptoParser
3
- Version: 0.11.2
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.11.2
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.11.2'
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 VariantParsable(ParsableBase):
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
- def compose(self):
339
- return self.variant.compose()
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=1):
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
- parsed_value = self._apply_item_class(
409
- name,
410
- item_offset,
411
- item_offset + parsed_length,
412
- separator,
413
- item_class,
414
- fallback_class,
415
- True
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: