Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/dns/rdtypes/ANY/ZONEMD.py: 36%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

45 statements  

1# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 

2 

3import binascii 

4import struct 

5 

6import dns.immutable 

7import dns.rdata 

8import dns.rdatatype 

9import dns.zonetypes 

10 

11 

12@dns.immutable.immutable 

13class ZONEMD(dns.rdata.Rdata): 

14 """ZONEMD record""" 

15 

16 # See RFC 8976 

17 

18 __slots__ = ["serial", "scheme", "hash_algorithm", "digest"] 

19 

20 def __init__(self, rdclass, rdtype, serial, scheme, hash_algorithm, digest): 

21 super().__init__(rdclass, rdtype) 

22 self.serial = self._as_uint32(serial) 

23 self.scheme = dns.zonetypes.DigestScheme.make(scheme) 

24 self.hash_algorithm = dns.zonetypes.DigestHashAlgorithm.make(hash_algorithm) 

25 self.digest = self._as_bytes(digest) 

26 

27 if self.scheme == 0: # reserved, RFC 8976 Sec. 5.2 

28 raise ValueError("scheme 0 is reserved") 

29 if self.hash_algorithm == 0: # reserved, RFC 8976 Sec. 5.3 

30 raise ValueError("hash_algorithm 0 is reserved") 

31 

32 # RFC 8976 Sec. 2.2.4: the digest is never shorter than 12 octets, 

33 # regardless of the hash algorithm, including private-use ones. 

34 if len(self.digest) < 12: 

35 raise ValueError("digest must be at least 12 octets") 

36 

37 hasher = dns.zonetypes._digest_hashers.get(self.hash_algorithm) 

38 if hasher and hasher().digest_size != len(self.digest): 

39 raise ValueError("digest length inconsistent with hash algorithm") 

40 

41 def to_styled_text(self, style: dns.rdata.RdataStyle) -> str: 

42 digest = dns.rdata._styled_hexify(self.digest, style, True) 

43 return f"{self.serial} {self.scheme} {self.hash_algorithm} {digest}" 

44 

45 @classmethod 

46 def from_text( 

47 cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None 

48 ): 

49 serial = tok.get_uint32() 

50 scheme = tok.get_uint8() 

51 hash_algorithm = tok.get_uint8() 

52 digest = tok.concatenate_remaining_identifiers().encode() 

53 digest = binascii.unhexlify(digest) 

54 return cls(rdclass, rdtype, serial, scheme, hash_algorithm, digest) 

55 

56 def _to_wire(self, file, compress=None, origin=None, canonicalize=False): 

57 header = struct.pack("!IBB", self.serial, self.scheme, self.hash_algorithm) 

58 file.write(header) 

59 file.write(self.digest) 

60 

61 @classmethod 

62 def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): 

63 header = parser.get_struct("!IBB") 

64 digest = parser.get_remaining() 

65 return cls(rdclass, rdtype, header[0], header[1], header[2], digest)