1
0

dependencies: support and require dnspython 2.0, rm monkey patches

- dnspython 2.0 requires cryptography 2.6 so we now always require that
  (no longer a choice between cryptography and pycryptodomex)
- test_dnssec.py is deleted as it was testing the monkey-patch

related: #6538
This commit is contained in:
SomberNight
2020-12-08 16:35:29 +01:00
parent f74ac1a741
commit 14372e0a94
6 changed files with 12 additions and 175 deletions

View File

@@ -58,135 +58,6 @@ import dns.rdtypes.ANY.TXT
import dns.rdtypes.IN.A
import dns.rdtypes.IN.AAAA
# Pure-Python version of dns.dnssec._validate_rsig
import ecdsa
from . import rsakey
def python_validate_rrsig(rrset, rrsig, keys, origin=None, now=None):
from dns.dnssec import ValidationFailure, ECDSAP256SHA256, ECDSAP384SHA384
from dns.dnssec import _find_candidate_keys, _make_hash, _is_ecdsa, _is_rsa, _to_rdata, _make_algorithm_id
if isinstance(origin, str):
origin = dns.name.from_text(origin, dns.name.root)
for candidate_key in _find_candidate_keys(keys, rrsig):
if not candidate_key:
raise ValidationFailure('unknown key')
# For convenience, allow the rrset to be specified as a (name, rdataset)
# tuple as well as a proper rrset
if isinstance(rrset, tuple):
rrname = rrset[0]
rdataset = rrset[1]
else:
rrname = rrset.name
rdataset = rrset
if now is None:
now = time.time()
if rrsig.expiration < now:
raise ValidationFailure('expired')
if rrsig.inception > now:
raise ValidationFailure('not yet valid')
hash = _make_hash(rrsig.algorithm)
if _is_rsa(rrsig.algorithm):
keyptr = candidate_key.key
(bytes,) = struct.unpack('!B', keyptr[0:1])
keyptr = keyptr[1:]
if bytes == 0:
(bytes,) = struct.unpack('!H', keyptr[0:2])
keyptr = keyptr[2:]
rsa_e = keyptr[0:bytes]
rsa_n = keyptr[bytes:]
n = int.from_bytes(rsa_n, byteorder='big', signed=False)
e = int.from_bytes(rsa_e, byteorder='big', signed=False)
pubkey = rsakey.RSAKey(n, e)
sig = rrsig.signature
elif _is_ecdsa(rrsig.algorithm):
if rrsig.algorithm == ECDSAP256SHA256:
curve = ecdsa.curves.NIST256p
key_len = 32
elif rrsig.algorithm == ECDSAP384SHA384:
curve = ecdsa.curves.NIST384p
key_len = 48
else:
# shouldn't happen
raise ValidationFailure('unknown ECDSA curve')
keyptr = candidate_key.key
x = int.from_bytes(keyptr[0:key_len], byteorder='big', signed=False)
y = int.from_bytes(keyptr[key_len:key_len * 2], byteorder='big', signed=False)
assert ecdsa.ecdsa.point_is_valid(curve.generator, x, y)
point = ecdsa.ellipticcurve.Point(curve.curve, x, y, curve.order)
verifying_key = ecdsa.keys.VerifyingKey.from_public_point(point, curve)
r = rrsig.signature[:key_len]
s = rrsig.signature[key_len:]
sig = ecdsa.ecdsa.Signature(int.from_bytes(r, byteorder='big', signed=False),
int.from_bytes(s, byteorder='big', signed=False))
else:
raise ValidationFailure('unknown algorithm %u' % rrsig.algorithm)
hash.update(_to_rdata(rrsig, origin)[:18])
hash.update(rrsig.signer.to_digestable(origin))
if rrsig.labels < len(rrname) - 1:
suffix = rrname.split(rrsig.labels + 1)[1]
rrname = dns.name.from_text('*', suffix)
rrnamebuf = rrname.to_digestable(origin)
rrfixed = struct.pack('!HHI', rdataset.rdtype, rdataset.rdclass,
rrsig.original_ttl)
rrlist = sorted(rdataset)
for rr in rrlist:
hash.update(rrnamebuf)
hash.update(rrfixed)
rrdata = rr.to_digestable(origin)
rrlen = struct.pack('!H', len(rrdata))
hash.update(rrlen)
hash.update(rrdata)
digest = hash.digest()
if _is_rsa(rrsig.algorithm):
digest = _make_algorithm_id(rrsig.algorithm) + digest
if pubkey.verify(bytearray(sig), bytearray(digest)):
return
elif _is_ecdsa(rrsig.algorithm):
diglong = int.from_bytes(digest, byteorder='big', signed=False)
if verifying_key.pubkey.verifies(diglong, sig):
return
else:
raise ValidationFailure('unknown algorithm %s' % rrsig.algorithm)
raise ValidationFailure('verify failure')
class PyCryptodomexHashAlike:
def __init__(self, hashlib_func):
self._hash = hashlib_func
def new(self):
return self._hash()
# replace validate_rrsig
dns.dnssec._validate_rrsig = python_validate_rrsig
dns.dnssec.validate_rrsig = python_validate_rrsig
dns.dnssec.validate = dns.dnssec._validate
dns.dnssec._have_ecdsa = True
dns.dnssec.MD5 = PyCryptodomexHashAlike(hashlib.md5)
dns.dnssec.SHA1 = PyCryptodomexHashAlike(hashlib.sha1)
dns.dnssec.SHA256 = PyCryptodomexHashAlike(hashlib.sha256)
dns.dnssec.SHA384 = PyCryptodomexHashAlike(hashlib.sha384)
dns.dnssec.SHA512 = PyCryptodomexHashAlike(hashlib.sha512)
from .logging import get_logger