CryptoParser 1.0.2__tar.gz → 1.1.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 (122) hide show
  1. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/CHANGELOG.rst +25 -1
  2. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/CryptoParser.egg-info/PKG-INFO +3 -3
  3. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/CryptoParser.egg-info/SOURCES.txt +15 -0
  4. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/CryptoParser.egg-info/requires.txt +1 -1
  5. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/CryptoParser.egg-info/top_level.txt +1 -0
  6. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/PKG-INFO +3 -3
  7. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/cryptoparser/common/exception.py +6 -1
  8. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/cryptoparser/common/parse.py +18 -5
  9. cryptoparser-1.1.1/cryptoparser/ike/common.py +235 -0
  10. cryptoparser-1.1.1/cryptoparser/ike/ikev1.py +755 -0
  11. cryptoparser-1.1.1/cryptoparser/ike/ikev2.py +1185 -0
  12. cryptoparser-1.1.1/cryptoparser/ike/isakmp.py +200 -0
  13. cryptoparser-1.1.1/cryptoparser/ike/version.py +85 -0
  14. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/cryptoparser/ssh/key.py +5 -0
  15. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/docs/features.rst +14 -2
  16. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/docs/index.rst +3 -3
  17. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/pyproject.toml +4 -3
  18. cryptoparser-1.1.1/test/ike/classes.py +231 -0
  19. cryptoparser-1.1.1/test/ike/test_ikev1_payload.py +1143 -0
  20. cryptoparser-1.1.1/test/ike/test_ikev1_sa.py +416 -0
  21. cryptoparser-1.1.1/test/ike/test_ikev2_notify.py +375 -0
  22. cryptoparser-1.1.1/test/ike/test_ikev2_payload.py +723 -0
  23. cryptoparser-1.1.1/test/ike/test_ikev2_sa.py +596 -0
  24. cryptoparser-1.1.1/test/ike/test_isakmp.py +311 -0
  25. cryptoparser-1.1.1/test/ike/test_version.py +73 -0
  26. cryptoparser-1.1.1/test/ssh/__init__.py +0 -0
  27. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/test/ssh/test_key.py +3 -0
  28. cryptoparser-1.1.1/test/tls/__init__.py +0 -0
  29. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/.coveragerc +0 -0
  30. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/.flake8 +0 -0
  31. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/.gitignore +0 -0
  32. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/.gitlab-ci.yml +0 -0
  33. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/.gitmodules +0 -0
  34. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/.pylintrc +0 -0
  35. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/.readthedocs.yaml +0 -0
  36. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/CONTRIBUTING.rst +0 -0
  37. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/CryptoParser.egg-info/dependency_links.txt +0 -0
  38. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/LICENSE.txt +0 -0
  39. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/MANIFEST.in +0 -0
  40. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/README.rst +0 -0
  41. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/cryptoparser/__init__.py +0 -0
  42. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/cryptoparser/__setup__.py +0 -0
  43. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/cryptoparser/common/__init__.py +0 -0
  44. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/cryptoparser/common/base.py +0 -0
  45. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/cryptoparser/common/classes.py +0 -0
  46. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/cryptoparser/common/field.py +0 -0
  47. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/cryptoparser/common/utils.py +0 -0
  48. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/cryptoparser/common/x509.py +0 -0
  49. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/cryptoparser/dnsrec/__init__.py +0 -0
  50. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/cryptoparser/dnsrec/record.py +0 -0
  51. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/cryptoparser/dnsrec/txt.py +0 -0
  52. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/cryptoparser/httpx/__init__.py +0 -0
  53. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/cryptoparser/httpx/header.py +0 -0
  54. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/cryptoparser/httpx/parse.py +0 -0
  55. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/cryptoparser/httpx/version.py +0 -0
  56. {cryptoparser-1.0.2/cryptoparser/ssh → cryptoparser-1.1.1/cryptoparser/ike}/__init__.py +0 -0
  57. {cryptoparser-1.0.2/cryptoparser/tls → cryptoparser-1.1.1/cryptoparser/ssh}/__init__.py +0 -0
  58. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/cryptoparser/ssh/record.py +0 -0
  59. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/cryptoparser/ssh/subprotocol.py +0 -0
  60. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/cryptoparser/ssh/version.py +0 -0
  61. {cryptoparser-1.0.2/test → cryptoparser-1.1.1/cryptoparser/tls}/__init__.py +0 -0
  62. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/cryptoparser/tls/algorithm.py +0 -0
  63. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/cryptoparser/tls/ciphersuite.py +0 -0
  64. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/cryptoparser/tls/extension.py +0 -0
  65. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/cryptoparser/tls/grease.py +0 -0
  66. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/cryptoparser/tls/ldap.py +0 -0
  67. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/cryptoparser/tls/mysql.py +0 -0
  68. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/cryptoparser/tls/openvpn.py +0 -0
  69. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/cryptoparser/tls/postgresql.py +0 -0
  70. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/cryptoparser/tls/rdp.py +0 -0
  71. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/cryptoparser/tls/record.py +0 -0
  72. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/cryptoparser/tls/subprotocol.py +0 -0
  73. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/cryptoparser/tls/version.py +0 -0
  74. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/docs/.gitignore +0 -0
  75. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/docs/changelog.rst +0 -0
  76. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/docs/conf.py +0 -0
  77. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/docs/development.rst +0 -0
  78. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/setup.cfg +0 -0
  79. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/setup.py +0 -0
  80. {cryptoparser-1.0.2/test/common → cryptoparser-1.1.1/test}/__init__.py +0 -0
  81. {cryptoparser-1.0.2/test/dnsrec → cryptoparser-1.1.1/test/common}/__init__.py +0 -0
  82. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/test/common/certs/ecc256.badssl.com.pem +0 -0
  83. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/test/common/certs/rsa8192.badssl.com.pem +0 -0
  84. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/test/common/certs/rsa8192.badssl.com_certificate.crt +0 -0
  85. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/test/common/certs/rsa8192.badssl.com_root_ca.crt +0 -0
  86. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/test/common/certs/snakeoil_cert.pem +0 -0
  87. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/test/common/classes.py +0 -0
  88. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/test/common/test_algorithm.py +0 -0
  89. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/test/common/test_base.py +0 -0
  90. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/test/common/test_classes.py +0 -0
  91. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/test/common/test_exception.py +0 -0
  92. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/test/common/test_field.py +0 -0
  93. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/test/common/test_parse.py +0 -0
  94. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/test/common/test_utils.py +0 -0
  95. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/test/common/test_x509.py +0 -0
  96. {cryptoparser-1.0.2/test/httpx → cryptoparser-1.1.1/test/dnsrec}/__init__.py +0 -0
  97. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/test/dnsrec/test_record.py +0 -0
  98. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/test/dnsrec/test_txt.py +0 -0
  99. {cryptoparser-1.0.2/test/ssh → cryptoparser-1.1.1/test/httpx}/__init__.py +0 -0
  100. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/test/httpx/classes.py +0 -0
  101. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/test/httpx/test_header.py +0 -0
  102. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/test/httpx/test_version.py +0 -0
  103. {cryptoparser-1.0.2/test/tls → cryptoparser-1.1.1/test/ike}/__init__.py +0 -0
  104. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/test/ssh/test_ciphersuites.py +0 -0
  105. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/test/ssh/test_record.py +0 -0
  106. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/test/ssh/test_subprotocol.py +0 -0
  107. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/test/ssh/test_version.py +0 -0
  108. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/test/tls/classes.py +0 -0
  109. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/test/tls/test_alert.py +0 -0
  110. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/test/tls/test_application_data.py +0 -0
  111. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/test/tls/test_change_cipher_spec.py +0 -0
  112. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/test/tls/test_ciphersuite.py +0 -0
  113. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/test/tls/test_extension.py +0 -0
  114. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/test/tls/test_grease.py +0 -0
  115. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/test/tls/test_handshake.py +0 -0
  116. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/test/tls/test_ldap.py +0 -0
  117. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/test/tls/test_mysql.py +0 -0
  118. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/test/tls/test_openvpn.py +0 -0
  119. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/test/tls/test_postgresql.py +0 -0
  120. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/test/tls/test_rdp.py +0 -0
  121. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/test/tls/test_record.py +0 -0
  122. {cryptoparser-1.0.2 → cryptoparser-1.1.1}/test/tls/test_version.py +0 -0
@@ -2,6 +2,30 @@
2
2
  Changelog
3
3
  =========
4
4
 
5
+ ------------------
6
+ 1.1.1 - 2026-05-03
7
+ ------------------
8
+
9
+ Notable fixes
10
+ =============
11
+
12
+ - SSH
13
+
14
+ - add missing key size property (#96)
15
+
16
+ -------------------
17
+ 1.1.0 - 2026-02-13
18
+ -------------------
19
+
20
+ Features
21
+ ========
22
+
23
+ - IKE (``ike``)
24
+
25
+ - add ISAKMP header parsing (#91)
26
+ - add parser/composer for mandatory IKEv2 protocol elements (#91)
27
+ - add parser/composer for mandatory IKEv1 protocol elements (#91)
28
+
5
29
  -------------------
6
30
  1.0.2 - 2025-12-30
7
31
  -------------------
@@ -33,7 +57,7 @@ Refactor
33
57
 
34
58
  - Generic
35
59
 
36
- - Support only Python version greater or euqal than 3.9
60
+ - Support only Python version greater than or equal to 3.9
37
61
  - Use pyproject.toml instead of setup.py
38
62
 
39
63
  -------------------
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: CryptoParser
3
- Version: 1.0.2
3
+ Version: 1.1.1
4
4
  Summary: An analysis oriented security protocol parser and generator
5
5
  Author-email: Szilárd Pfeiffer <coroner@pfeifferszilard.hu>
6
6
  Maintainer-email: Szilárd Pfeiffer <coroner@pfeifferszilard.hu>
@@ -10,7 +10,7 @@ Project-URL: Changelog, https://cryptoparser.readthedocs.io/en/latest/changelog
10
10
  Project-URL: Documentation, https://cryptoparser.readthedocs.io/en/latest/
11
11
  Project-URL: Issues, https://gitlab.com/coroner/cryptoparser/-/issues
12
12
  Project-URL: Source, https://gitlab.com/coroner/cryptoparser
13
- Keywords: ssl,tls,gost,ja3,ldap,rdp,ssh,hsts,dns
13
+ Keywords: ssl,tls,gost,ja3,ldap,rdp,ssh,hsts,dns,ike
14
14
  Classifier: Development Status :: 5 - Production/Stable
15
15
  Classifier: Environment :: Console
16
16
  Classifier: Framework :: tox
@@ -40,7 +40,7 @@ Description-Content-Type: text/x-rst
40
40
  License-File: LICENSE.txt
41
41
  Requires-Dist: asn1crypto
42
42
  Requires-Dist: attrs
43
- Requires-Dist: cryptodatahub==1.0.2
43
+ Requires-Dist: cryptodatahub==1.1.1
44
44
  Requires-Dist: urllib3
45
45
  Provides-Extra: tests
46
46
  Requires-Dist: pyfakefs; extra == "tests"
@@ -34,6 +34,12 @@ cryptoparser/httpx/__init__.py
34
34
  cryptoparser/httpx/header.py
35
35
  cryptoparser/httpx/parse.py
36
36
  cryptoparser/httpx/version.py
37
+ cryptoparser/ike/__init__.py
38
+ cryptoparser/ike/common.py
39
+ cryptoparser/ike/ikev1.py
40
+ cryptoparser/ike/ikev2.py
41
+ cryptoparser/ike/isakmp.py
42
+ cryptoparser/ike/version.py
37
43
  cryptoparser/ssh/__init__.py
38
44
  cryptoparser/ssh/key.py
39
45
  cryptoparser/ssh/record.py
@@ -81,6 +87,15 @@ test/httpx/__init__.py
81
87
  test/httpx/classes.py
82
88
  test/httpx/test_header.py
83
89
  test/httpx/test_version.py
90
+ test/ike/__init__.py
91
+ test/ike/classes.py
92
+ test/ike/test_ikev1_payload.py
93
+ test/ike/test_ikev1_sa.py
94
+ test/ike/test_ikev2_notify.py
95
+ test/ike/test_ikev2_payload.py
96
+ test/ike/test_ikev2_sa.py
97
+ test/ike/test_isakmp.py
98
+ test/ike/test_version.py
84
99
  test/ssh/__init__.py
85
100
  test/ssh/test_ciphersuites.py
86
101
  test/ssh/test_key.py
@@ -1,6 +1,6 @@
1
1
  asn1crypto
2
2
  attrs
3
- cryptodatahub==1.0.2
3
+ cryptodatahub==1.1.1
4
4
  urllib3
5
5
 
6
6
  [docs]
@@ -1,3 +1,4 @@
1
+ build
1
2
  cryptoparser
2
3
  dist
3
4
  docs
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: CryptoParser
3
- Version: 1.0.2
3
+ Version: 1.1.1
4
4
  Summary: An analysis oriented security protocol parser and generator
5
5
  Author-email: Szilárd Pfeiffer <coroner@pfeifferszilard.hu>
6
6
  Maintainer-email: Szilárd Pfeiffer <coroner@pfeifferszilard.hu>
@@ -10,7 +10,7 @@ Project-URL: Changelog, https://cryptoparser.readthedocs.io/en/latest/changelog
10
10
  Project-URL: Documentation, https://cryptoparser.readthedocs.io/en/latest/
11
11
  Project-URL: Issues, https://gitlab.com/coroner/cryptoparser/-/issues
12
12
  Project-URL: Source, https://gitlab.com/coroner/cryptoparser
13
- Keywords: ssl,tls,gost,ja3,ldap,rdp,ssh,hsts,dns
13
+ Keywords: ssl,tls,gost,ja3,ldap,rdp,ssh,hsts,dns,ike
14
14
  Classifier: Development Status :: 5 - Production/Stable
15
15
  Classifier: Environment :: Console
16
16
  Classifier: Framework :: tox
@@ -40,7 +40,7 @@ Description-Content-Type: text/x-rst
40
40
  License-File: LICENSE.txt
41
41
  Requires-Dist: asn1crypto
42
42
  Requires-Dist: attrs
43
- Requires-Dist: cryptodatahub==1.0.2
43
+ Requires-Dist: cryptodatahub==1.1.1
44
44
  Requires-Dist: urllib3
45
45
  Provides-Extra: tests
46
46
  Requires-Dist: pyfakefs; extra == "tests"
@@ -1,11 +1,16 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
+ import typing
4
+
3
5
  import attr
4
6
 
5
7
 
6
8
  @attr.s
7
9
  class InvalidDataLength(Exception):
8
- bytes_needed = attr.ib(default=None, validator=attr.validators.optional(attr.validators.instance_of(int)))
10
+ bytes_needed: typing.Optional[int] = attr.ib(
11
+ default=None,
12
+ validator=attr.validators.optional(attr.validators.instance_of(int))
13
+ )
9
14
 
10
15
 
11
16
  @attr.s
@@ -1,4 +1,5 @@
1
1
  # -*- coding: utf-8 -*-
2
+ # pylint: disable=too-many-lines
2
3
 
3
4
  import abc
4
5
  import collections.abc
@@ -6,6 +7,7 @@ import datetime
6
7
  import enum
7
8
  import struct
8
9
  import time
10
+ import typing
9
11
 
10
12
  import attr
11
13
 
@@ -88,9 +90,12 @@ class ByteOrder(enum.Enum):
88
90
 
89
91
  @attr.s
90
92
  class ParserBase(collections.abc.Mapping):
91
- _parsable = attr.ib(converter=bytes, validator=attr.validators.instance_of((bytes, bytearray)))
92
- _parsed_length = attr.ib(init=False, default=0)
93
- _parsed_values = attr.ib(init=False, default=None)
93
+ _parsable: typing.Union[bytes, bytearray] = attr.ib(
94
+ converter=bytes,
95
+ validator=attr.validators.instance_of((bytes, bytearray))
96
+ )
97
+ _parsed_length: int = attr.ib(init=False, default=0)
98
+ _parsed_values: typing.Dict[str, typing.Any] = attr.ib(init=False, default=None)
94
99
 
95
100
  def __attrs_post_init__(self):
96
101
  if self._parsed_values is None:
@@ -279,6 +284,7 @@ class ParserText(ParserBase):
279
284
  name, min_length, max_length, self._encoding, str
280
285
  )
281
286
  except NotEnoughData as e:
287
+ assert e.bytes_needed is not None
282
288
  raise InvalidValue(self._parsable[self._parsed_length:min_length - e.bytes_needed], type(self), name) from e
283
289
 
284
290
  if value != actual_value:
@@ -489,7 +495,7 @@ class ParserText(ParserBase):
489
495
 
490
496
  @attr.s
491
497
  class ParserBinary(ParserBase):
492
- byte_order = attr.ib(default=ByteOrder.NETWORK, validator=attr.validators.in_(ByteOrder))
498
+ byte_order: ByteOrder = attr.ib(default=ByteOrder.NETWORK, validator=attr.validators.in_(ByteOrder))
493
499
 
494
500
  def parse_timestamp(self, name, milliseconds=False, item_size=8):
495
501
  value, parsed_length = self._parse_numeric_array(name, 1, item_size, int)
@@ -543,6 +549,13 @@ class ParserBinary(ParserBase):
543
549
  self._parsed_length += parsed_length
544
550
  self._parsed_values[name] = value[0]
545
551
 
552
+ def parse_numeric_enum_coded(self, name, enum_class):
553
+ param = list(enum_class)[0].value
554
+ value, parsed_length = self._parse_numeric_array(name, 1, param.get_code_size(), enum_class.from_code)
555
+
556
+ self._parsed_length += parsed_length
557
+ self._parsed_values[name] = value[0]
558
+
546
559
  def parse_numeric_array(self, name, item_num, item_size, converter=int):
547
560
  value, parsed_length = self._parse_numeric_array(name, item_num, item_size, converter)
548
561
 
@@ -840,7 +853,7 @@ class ComposerText(ComposerBase):
840
853
 
841
854
  @attr.s
842
855
  class ComposerBinary(ComposerBase):
843
- byte_order = attr.ib(default=ByteOrder.NETWORK, validator=attr.validators.in_(ByteOrder))
856
+ byte_order: ByteOrder = attr.ib(default=ByteOrder.NETWORK, validator=attr.validators.in_(ByteOrder))
844
857
 
845
858
  def compose_timestamp(self, value, milliseconds=False, item_size=8):
846
859
  if value is None:
@@ -0,0 +1,235 @@
1
+ import abc
2
+ import enum
3
+ import typing
4
+
5
+ import attr
6
+
7
+ from cryptodatahub.common.exception import InvalidValue
8
+
9
+ from cryptoparser.common.exception import InvalidType
10
+ from cryptoparser.common.parse import ParsableBase, ParserBinary, ComposerBinary
11
+
12
+
13
+ @attr.s
14
+ class DataAttributeBase(ParsableBase):
15
+ """Data attribute base parser.
16
+
17
+ .. code-block:: text
18
+
19
+ 1 2 3
20
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
21
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
22
+ !A! Attribute Type ! AF=0 Attribute Length !
23
+ !F! ! AF=1 Attribute Value !
24
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
25
+ . AF=0 Attribute Value .
26
+ . AF=1 Not Transmitted .
27
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
28
+ """
29
+
30
+ @classmethod
31
+ @abc.abstractmethod
32
+ def _parse(cls, parsable):
33
+ raise NotImplementedError()
34
+
35
+ @abc.abstractmethod
36
+ def compose(self):
37
+ raise NotImplementedError()
38
+
39
+ @classmethod
40
+ @abc.abstractmethod
41
+ def get_type(cls):
42
+ raise NotImplementedError()
43
+
44
+ @classmethod
45
+ def _get_format(cls):
46
+ raise NotImplementedError()
47
+
48
+ @classmethod
49
+ def _parse_header(cls, parsable):
50
+ parser = ParserBinary(parsable)
51
+
52
+ parser.parse_numeric('format', 1, DataAttributeFormat)
53
+ if parser['format'] != cls._get_format():
54
+ raise InvalidType()
55
+
56
+ parser.parse_numeric_enum_coded('type', type(cls.get_type()))
57
+ if parser['type'] != cls.get_type():
58
+ raise InvalidType()
59
+
60
+ return parser
61
+
62
+ def _compose_header(self):
63
+ composer = ComposerBinary()
64
+
65
+ composer.compose_numeric(self._get_format().value, 1)
66
+ composer.compose_numeric_enum_coded(self.get_type())
67
+
68
+ return composer
69
+
70
+
71
+ class DataAttributeFormat(enum.IntEnum):
72
+ """Data attribute types."""
73
+ TYPE_LENGTH_VALUE = 0x00
74
+ TYPE_VALUE = 0x80
75
+
76
+
77
+ @attr.s
78
+ class DataAttributeTypeValue(DataAttributeBase):
79
+ """Data attribute type/value parser."""
80
+
81
+ @classmethod
82
+ @abc.abstractmethod
83
+ def get_type(cls):
84
+ raise NotImplementedError()
85
+
86
+ @classmethod
87
+ @abc.abstractmethod
88
+ def _parse(cls, parsable):
89
+ raise NotImplementedError()
90
+
91
+ @abc.abstractmethod
92
+ def compose(self):
93
+ raise NotImplementedError()
94
+
95
+ @classmethod
96
+ def _get_format(cls):
97
+ return DataAttributeFormat.TYPE_VALUE
98
+
99
+
100
+ @attr.s
101
+ class DataAttributeTypeValueEnumCoded(DataAttributeTypeValue):
102
+ """Data attribute type/value parser where the type is an enum."""
103
+
104
+ value: typing.Any = attr.ib()
105
+
106
+ @classmethod
107
+ @abc.abstractmethod
108
+ def get_type(cls):
109
+ raise NotImplementedError()
110
+
111
+ @classmethod
112
+ @abc.abstractmethod
113
+ def _get_enum_type(cls):
114
+ raise NotImplementedError()
115
+
116
+ @value.validator
117
+ def _validate_value(self, _, value):
118
+ enum_type = self._get_enum_type()
119
+ if not isinstance(value, enum_type):
120
+ raise InvalidValue(value, type(self), 'value')
121
+
122
+ @classmethod
123
+ def _parse(cls, parsable):
124
+ parser = cls._parse_header(parsable)
125
+
126
+ parser.parse_numeric_enum_coded('value', cls._get_enum_type())
127
+
128
+ return cls(value=parser['value']), parser.parsed_length
129
+
130
+ def compose(self):
131
+ composer = self._compose_header()
132
+
133
+ composer.compose_numeric_enum_coded(self.value)
134
+
135
+ return composer.composed_bytes
136
+
137
+
138
+ @attr.s
139
+ class DataAttributeKeyLength(DataAttributeTypeValue):
140
+ """Key Length transform attribute (TV format).
141
+
142
+ The Key Length attribute has the following format:
143
+
144
+ 0 1 2 3
145
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
146
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
147
+ |A| Attribute Type | Key Length (in bits) |
148
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
149
+
150
+ :ivar key_length: Key length in bits
151
+ """
152
+
153
+ value: int = attr.ib(validator=attr.validators.and_(
154
+ attr.validators.instance_of(int),
155
+ attr.validators.ge(0),
156
+ attr.validators.lt(2**64)
157
+ ))
158
+
159
+ @classmethod
160
+ @abc.abstractmethod
161
+ def get_type(cls):
162
+ raise NotImplementedError()
163
+
164
+ @classmethod
165
+ def _parse(cls, parsable):
166
+ parser = cls._parse_header(parsable)
167
+ parser.parse_numeric('value', 2)
168
+
169
+ return cls(value=parser['value']), parser.parsed_length
170
+
171
+ def compose(self):
172
+ composer = self._compose_header()
173
+
174
+ composer.compose_numeric(self.value, 2)
175
+
176
+ return composer.composed_bytes
177
+
178
+
179
+ @attr.s
180
+ class DataAttributeLength(DataAttributeBase):
181
+ """Length transform attribute (TLV format).
182
+
183
+ The Key Length attribute has the following format:
184
+
185
+ 0 1 2 3
186
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
187
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
188
+ |A| Attribute Type | Key Length (in bits) |
189
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
190
+
191
+ :ivar key_length: Key length in bits
192
+ """
193
+
194
+ value: int = attr.ib(validator=attr.validators.and_(
195
+ attr.validators.instance_of(int),
196
+ attr.validators.ge(0),
197
+ attr.validators.lt(2**64)
198
+ ))
199
+
200
+ @classmethod
201
+ @abc.abstractmethod
202
+ def get_type(cls):
203
+ raise NotImplementedError()
204
+
205
+ @classmethod
206
+ @abc.abstractmethod
207
+ def _get_size(cls):
208
+ raise NotImplementedError()
209
+
210
+ @classmethod
211
+ def _get_format(cls):
212
+ return DataAttributeFormat.TYPE_VALUE
213
+
214
+ @classmethod
215
+ def _parse(cls, parsable):
216
+ parser = cls._parse_header(parsable)
217
+
218
+ if parser['format'] == DataAttributeFormat.TYPE_LENGTH_VALUE:
219
+ parser.parse_numeric('size', 2)
220
+ parser.parse_numeric('value', parser['size'])
221
+ else:
222
+ parser.parse_numeric('value', cls._get_size())
223
+
224
+ return cls(value=parser['value']), parser.parsed_length
225
+
226
+ def compose(self):
227
+ composer = self._compose_header()
228
+
229
+ if self._get_format() == DataAttributeFormat.TYPE_LENGTH_VALUE:
230
+ composer.compose_numeric(self._get_size(), 2)
231
+ composer.compose_numeric(self.value, self._get_size())
232
+ else:
233
+ composer.compose_numeric(self.value, self._get_size())
234
+
235
+ return composer.composed_bytes