Skip to content

Commit 6ffc821

Browse files
committed
Merge branch '72-dnssec-record-parser'
Closes: #72
2 parents cf3ff7a + 7871e6a commit 6ffc821

File tree

14 files changed

+1388
-301
lines changed

14 files changed

+1388
-301
lines changed

CHANGELOG.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,17 @@
11
Changelog
22
=========
33

4+
0.10.1
5+
------
6+
7+
- DNS
8+
9+
- add parser for DNSSEC-related records (#72)
10+
11+
- `DNSKEY <https://www.rfc-editor.org/rfc/rfc4034#section-2>`__
12+
- `DS <https://www.rfc-editor.org/rfc/rfc4034#section-5>`__
13+
- `RRSIG <https://www.rfc-editor.org/rfc/rfc4034#section-3>`__
14+
415
0.10.0 - 2023-08-03
516
-------------------
617

cryptoparser/common/key.py

Lines changed: 0 additions & 42 deletions
This file was deleted.

cryptoparser/common/parse.py

Lines changed: 61 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -457,11 +457,11 @@ def parse_time_delta(self, name):
457457
class ParserBinary(ParserBase):
458458
byte_order = attr.ib(default=ByteOrder.NETWORK, validator=attr.validators.in_(ByteOrder))
459459

460-
def parse_timestamp(self, name, milliseconds=False):
461-
value, parsed_length = self._parse_numeric_array(name, 1, 8, int)
460+
def parse_timestamp(self, name, milliseconds=False, item_size=8):
461+
value, parsed_length = self._parse_numeric_array(name, 1, item_size, int)
462462

463463
self._parsed_length += parsed_length
464-
if value[0] == 0xffffffffffffffff:
464+
if value[0] == (2 ** (8 * item_size) - 1):
465465
self._parsed_values[name] = None
466466
else:
467467
value = value[0]
@@ -523,22 +523,14 @@ def parse_numeric_flags(self, name, size, flags_class, shift_left=0):
523523
self._parsed_length += parsed_length
524524
self._parsed_values[name] = value
525525

526-
def parse_ssh_mpint(self, name):
527-
if self.unparsed_length < 4:
528-
raise NotEnoughData(bytes_needed=4 - self.unparsed_length)
529-
530-
mpint_length, parsed_length = self._parse_numeric_array(name, 1, 4, int)
531-
mpint_length = mpint_length[0]
532-
533-
negative = (mpint_length and (six.indexbytes(self._parsable, self._parsed_length + 4) >= 0x80))
534-
526+
def _parse_mpint(self, mpint_length, mpint_offset, negative):
535527
if mpint_length % 4:
536528
pad_byte = six.int2byte(0xff) if negative else six.int2byte(0x00)
537529
pad_bytes = (4 - (mpint_length % 4)) * pad_byte
538530
else:
539531
pad_bytes = b''
540532

541-
parsable = pad_bytes + self._parsable[self._parsed_length + 4:]
533+
parsable = pad_bytes + self._parsable[self._parsed_length + mpint_offset:]
542534
parser = ParserBinary(parsable)
543535
parser.parse_numeric_array('mpint_part_array', (mpint_length + len(pad_bytes)) // 4, 4, int)
544536

@@ -549,6 +541,25 @@ def parse_ssh_mpint(self, name):
549541
complement = 1 << (8 * (mpint_length + len(pad_bytes)))
550542
value -= complement
551543

544+
return value
545+
546+
def parse_mpint(self, name, mpint_length):
547+
value = self._parse_mpint(mpint_length, 0, False)
548+
549+
self._parsed_values[name] = value
550+
self._parsed_length += mpint_length
551+
552+
def parse_ssh_mpint(self, name):
553+
if self.unparsed_length < 4:
554+
raise NotEnoughData(bytes_needed=4 - self.unparsed_length)
555+
556+
mpint_length, parsed_length = self._parse_numeric_array(name, 1, 4, int)
557+
mpint_length = mpint_length[0]
558+
559+
negative = (mpint_length and (six.indexbytes(self._parsable, self._parsed_length + 4) >= 0x80))
560+
561+
value = self._parse_mpint(mpint_length, 4, negative)
562+
552563
self._parsed_values[name] = value
553564
self._parsed_length += parsed_length + mpint_length
554565

@@ -787,7 +798,7 @@ def compose_time_delta(self, value):
787798
class ComposerBinary(ComposerBase):
788799
byte_order = attr.ib(default=ByteOrder.NETWORK, validator=attr.validators.in_(ByteOrder))
789800

790-
def compose_timestamp(self, value, milliseconds=False):
801+
def compose_timestamp(self, value, milliseconds=False, item_size=8):
791802
if value is None:
792803
timestamp = 0xffffffffffffffff
793804
else:
@@ -797,7 +808,7 @@ def compose_timestamp(self, value, milliseconds=False):
797808
timestamp *= 1000
798809
timestamp += value.microsecond // 1000
799810

800-
return self._compose_numeric_array([timestamp, ], 8)
811+
return self._compose_numeric_array([timestamp, ], item_size)
801812

802813
def _compose_numeric_array(self, values, item_size):
803814
composed_bytes = bytearray()
@@ -842,33 +853,57 @@ def compose_numeric_flags(self, values, item_size, shift_right=0):
842853
flag |= value >> shift_right
843854
self._compose_numeric_array([flag, ], item_size)
844855

845-
def compose_ssh_mpint(self, value):
856+
@staticmethod
857+
def _compose_mpint(value, length, byte_order):
846858
negative = value < 0
847-
array_length = value.bit_length() // 32
848859

849-
if value.bit_length() % 32:
850-
array_length += 1
851860
if negative:
852861
positive_value = (1 << ((value.bit_length() // 8 * 8) + 8)) + value
853862
else:
854863
positive_value = value
855864

856865
value_numeric_array = []
857-
for mpint_offset in range(0, array_length * 32, 32):
866+
for mpint_offset in range(0, length * 32, 32):
858867
value_numeric_array.append(positive_value >> mpint_offset & 0xffffffff)
859868

860-
composer = ComposerBinary()
869+
composer = ComposerBinary(byte_order=byte_order)
861870
composer.compose_numeric_array(reversed(value_numeric_array), 4)
862-
value_bytes = composer.composed_bytes.lstrip(b'\x00')
863871

864-
if value_bytes and bool(value_bytes[0] & 0x80) != negative:
872+
mpint_bytes = composer.composed_bytes.lstrip(b'\x00')
873+
if byte_order in [ByteOrder.LITTLE_ENDIAN, ByteOrder.NATIVE]:
874+
mpint_bytes = mpint_bytes.rstrip(b'\x00')
875+
876+
return mpint_bytes
877+
878+
def compose_mpint(self, value, length):
879+
mpint_bytes = self._compose_mpint(value, length, self.byte_order)
880+
if length < len(mpint_bytes):
881+
raise InvalidValue(length, type(self), 'mpint_length')
882+
883+
pad_byte = b'\xff' if value < 0 else b'\x00'
884+
if self.byte_order in [ByteOrder.BIG_ENDIAN, ByteOrder.NETWORK]:
885+
self.compose_raw((length - len(mpint_bytes)) * pad_byte)
886+
self.compose_raw(mpint_bytes)
887+
else:
888+
self.compose_raw(mpint_bytes)
889+
self.compose_raw((length - len(mpint_bytes)) * pad_byte)
890+
891+
def compose_ssh_mpint(self, value):
892+
negative = value < 0
893+
length = value.bit_length() // 32
894+
if value.bit_length() % 32:
895+
length += 1
896+
897+
mpint_bytes = self._compose_mpint(value, length, self.byte_order)
898+
899+
if mpint_bytes and bool(mpint_bytes[0] & 0x80) != negative:
865900
pad_byte = b'\xff' if negative else b'\x00'
866901
else:
867902
pad_byte = b''
868903

869-
self.compose_numeric(len(pad_byte) + len(value_bytes), 4)
870-
871-
self._composed += pad_byte + value_bytes
904+
self.compose_numeric(len(pad_byte) + len(mpint_bytes), 4)
905+
self.compose_raw(pad_byte)
906+
self.compose_raw(mpint_bytes)
872907

873908
def compose_parsable(self, value, item_size=None):
874909
composed = value.compose()

cryptoparser/dnsrec/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)