From ad27d482f033fef9f3693f3bcdff2b84d9b5bffa51fbe897d1367a40ccdece48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Chv=C3=A1tal?= Date: Wed, 9 May 2018 13:46:46 +0000 Subject: [PATCH 1/2] - Add patch pycryptodome.patch to work with pycryptodome: * pycryptodome.patch OBS-URL: https://build.opensuse.org/package/show/devel:languages:python/python-dnspython?expand=0&rev=40 --- pycryptodome.patch | 461 +++++++++++++++++++++++++++++++++++++++ python-dnspython.changes | 6 + python-dnspython.spec | 15 +- 3 files changed, 476 insertions(+), 6 deletions(-) create mode 100644 pycryptodome.patch diff --git a/pycryptodome.patch b/pycryptodome.patch new file mode 100644 index 0000000..a0b378f --- /dev/null +++ b/pycryptodome.patch @@ -0,0 +1,461 @@ +From 10b8a42c90d037880fbfc81fb71adb27251252e3 Mon Sep 17 00:00:00 2001 +From: Daniel Robbins +Date: Thu, 21 Dec 2017 09:24:40 -0700 +Subject: [PATCH] Update DNSSEC code to use pycryptodome instead of pycrypto. + These changes make dnspython *incompatible* with pycrypto -- pycryptodome + must be used. The ecdsa module continues to be used for ECDSA support. + +--- + ChangeLog | 5 ++ + dns/__init__.py | 1 - + dns/dnssec.py | 161 +++++++++++++++++++++++++++------------------------ + dns/hash.py | 31 ---------- + dns/tsig.py | 4 +- + doc/dnssec.rst | 9 ++- + doc/installation.rst | 4 +- + tests/test_dnssec.py | 16 ++--- + 8 files changed, 105 insertions(+), 126 deletions(-) + delete mode 100644 dns/hash.py + +diff --git a/dns/__init__.py b/dns/__init__.py +index c848e48..3852729 100644 +--- a/dns/__init__.py ++++ b/dns/__init__.py +@@ -22,7 +22,6 @@ + 'entropy', + 'exception', + 'flags', +- 'hash', + 'inet', + 'ipv4', + 'ipv6', +diff --git a/dns/dnssec.py b/dns/dnssec.py +index b91a64f..2b5d5b2 100644 +--- a/dns/dnssec.py ++++ b/dns/dnssec.py +@@ -20,7 +20,6 @@ + import time + + import dns.exception +-import dns.hash + import dns.name + import dns.node + import dns.rdataset +@@ -28,7 +27,8 @@ + import dns.rdatatype + import dns.rdataclass + from ._compat import string_types +- ++from Crypto.Hash import MD5, SHA1, SHA256, SHA384, SHA512 ++from Crypto.Signature import pkcs1_15, DSS + + class UnsupportedAlgorithm(dns.exception.DNSException): + """The DNSSEC algorithm is not supported.""" +@@ -39,27 +39,27 @@ class ValidationFailure(dns.exception.DNSException): + + + #: RSAMD5 +-RSAMD5 = 1 ++ALGO_RSAMD5 = 1 + #: DH +-DH = 2 ++ALGO_DH = 2 + #: DSA +-DSA = 3 ++ALGO_DSA = 3 + #: ECC +-ECC = 4 ++ALGO_ECC = 4 + #: RSASHA1 +-RSASHA1 = 5 ++ALGO_RSASHA1 = 5 + #: DSANSEC3SHA1 +-DSANSEC3SHA1 = 6 ++ALGO_DSANSEC3SHA1 = 6 + #: RSASHA1NSEC3SHA1 +-RSASHA1NSEC3SHA1 = 7 ++ALGO_RSASHA1NSEC3SHA1 = 7 + #: RSASHA256 +-RSASHA256 = 8 ++ALGO_RSASHA256 = 8 + #: RSASHA512 +-RSASHA512 = 10 ++ALGO_RSASHA512 = 10 + #: ECDSAP256SHA256 +-ECDSAP256SHA256 = 13 ++ALGO_ECDSAP256SHA256 = 13 + #: ECDSAP384SHA384 +-ECDSAP384SHA384 = 14 ++ALGO_ECDSAP384SHA384 = 14 + #: INDIRECT + INDIRECT = 252 + #: PRIVATEDNS +@@ -68,18 +68,18 @@ class ValidationFailure(dns.exception.DNSException): + PRIVATEOID = 254 + + _algorithm_by_text = { +- 'RSAMD5': RSAMD5, +- 'DH': DH, +- 'DSA': DSA, +- 'ECC': ECC, +- 'RSASHA1': RSASHA1, +- 'DSANSEC3SHA1': DSANSEC3SHA1, +- 'RSASHA1NSEC3SHA1': RSASHA1NSEC3SHA1, +- 'RSASHA256': RSASHA256, +- 'RSASHA512': RSASHA512, ++ 'RSAMD5': ALGO_RSAMD5, ++ 'DH': ALGO_DH, ++ 'DSA': ALGO_DSA, ++ 'ECC': ALGO_ECC, ++ 'RSASHA1': ALGO_RSASHA1, ++ 'DSANSEC3SHA1': ALGO_DSANSEC3SHA1, ++ 'RSASHA1NSEC3SHA1': ALGO_RSASHA1NSEC3SHA1, ++ 'RSASHA256': ALGO_RSASHA256, ++ 'RSASHA512': ALGO_RSASHA512, + 'INDIRECT': INDIRECT, +- 'ECDSAP256SHA256': ECDSAP256SHA256, +- 'ECDSAP384SHA384': ECDSAP384SHA384, ++ 'ECDSAP256SHA256': ALGO_ECDSAP256SHA256, ++ 'ECDSAP384SHA384': ALGO_ECDSAP384SHA384, + 'PRIVATEDNS': PRIVATEDNS, + 'PRIVATEOID': PRIVATEOID, + } +@@ -132,7 +132,7 @@ def key_id(key, origin=None): + + rdata = _to_rdata(key, origin) + rdata = bytearray(rdata) +- if key.algorithm == RSAMD5: ++ if key.algorithm == ALGO_RSAMD5: + return (rdata[-3] << 8) + rdata[-2] + else: + total = 0 +@@ -164,10 +164,10 @@ def make_ds(name, key, algorithm, origin=None): + + if algorithm.upper() == 'SHA1': + dsalg = 1 +- hash = dns.hash.hashes['SHA1']() ++ hash = SHA1.new() + elif algorithm.upper() == 'SHA256': + dsalg = 2 +- hash = dns.hash.hashes['SHA256']() ++ hash = SHA256.new() + else: + raise UnsupportedAlgorithm('unsupported algorithm "%s"' % algorithm) + +@@ -203,51 +203,51 @@ def _find_candidate_keys(keys, rrsig): + + + def _is_rsa(algorithm): +- return algorithm in (RSAMD5, RSASHA1, +- RSASHA1NSEC3SHA1, RSASHA256, +- RSASHA512) ++ return algorithm in (ALGO_RSAMD5, ALGO_RSASHA1, ++ ALGO_RSASHA1NSEC3SHA1, ALGO_RSASHA256, ++ ALGO_RSASHA512) + + + def _is_dsa(algorithm): +- return algorithm in (DSA, DSANSEC3SHA1) ++ return algorithm in (ALGO_DSA, ALGO_DSANSEC3SHA1) + + + def _is_ecdsa(algorithm): +- return _have_ecdsa and (algorithm in (ECDSAP256SHA256, ECDSAP384SHA384)) ++ return _have_ecdsa and (algorithm in (ALGO_ECDSAP256SHA256, ALGO_ECDSAP384SHA384)) + + + def _is_md5(algorithm): +- return algorithm == RSAMD5 ++ return algorithm == ALGO_RSAMD5 + + + def _is_sha1(algorithm): +- return algorithm in (DSA, RSASHA1, +- DSANSEC3SHA1, RSASHA1NSEC3SHA1) ++ return algorithm in (ALGO_DSA, ALGO_RSASHA1, ++ ALGO_DSANSEC3SHA1, ALGO_RSASHA1NSEC3SHA1) + + + def _is_sha256(algorithm): +- return algorithm in (RSASHA256, ECDSAP256SHA256) ++ return algorithm in (ALGO_RSASHA256, ALGO_ECDSAP256SHA256) + + + def _is_sha384(algorithm): +- return algorithm == ECDSAP384SHA384 ++ return algorithm == ALGO_ECDSAP384SHA384 + + + def _is_sha512(algorithm): +- return algorithm == RSASHA512 ++ return algorithm == ALGO_RSASHA512 + + + def _make_hash(algorithm): + if _is_md5(algorithm): +- return dns.hash.hashes['MD5']() ++ return MD5.new() + if _is_sha1(algorithm): +- return dns.hash.hashes['SHA1']() ++ return SHA1.new() + if _is_sha256(algorithm): +- return dns.hash.hashes['SHA256']() ++ return SHA256.new() + if _is_sha384(algorithm): +- return dns.hash.hashes['SHA384']() ++ return SHA384.new() + if _is_sha512(algorithm): +- return dns.hash.hashes['SHA512']() ++ return SHA512.new() + raise ValidationFailure('unknown hash for algorithm %u' % algorithm) + + +@@ -326,11 +326,13 @@ def _validate_rrsig(rrset, rrsig, keys, origin=None, now=None): + keyptr = keyptr[2:] + rsa_e = keyptr[0:bytes_] + rsa_n = keyptr[bytes_:] +- keylen = len(rsa_n) * 8 +- pubkey = Crypto.PublicKey.RSA.construct( +- (Crypto.Util.number.bytes_to_long(rsa_n), +- Crypto.Util.number.bytes_to_long(rsa_e))) +- sig = (Crypto.Util.number.bytes_to_long(rrsig.signature),) ++ try: ++ pubkey = Crypto.PublicKey.RSA.construct( ++ (Crypto.Util.number.bytes_to_long(rsa_n), ++ Crypto.Util.number.bytes_to_long(rsa_e))) ++ except ValueError: ++ raise ValidationFailure('invalid public key') ++ sig = rrsig.signature + elif _is_dsa(rrsig.algorithm): + keyptr = candidate_key.key + (t,) = struct.unpack('!B', keyptr[0:1]) +@@ -348,20 +350,19 @@ def _validate_rrsig(rrset, rrsig, keys, origin=None, now=None): + Crypto.Util.number.bytes_to_long(dsa_g), + Crypto.Util.number.bytes_to_long(dsa_p), + Crypto.Util.number.bytes_to_long(dsa_q))) +- (dsa_r, dsa_s) = struct.unpack('!20s20s', rrsig.signature[1:]) +- sig = (Crypto.Util.number.bytes_to_long(dsa_r), +- Crypto.Util.number.bytes_to_long(dsa_s)) ++ sig = rrsig.signature[1:] + elif _is_ecdsa(rrsig.algorithm): +- if rrsig.algorithm == ECDSAP256SHA256: ++ # use ecdsa for NIST-384p -- not currently supported by pycryptodome ++ ++ keyptr = candidate_key.key ++ ++ if rrsig.algorithm == ALGO_ECDSAP256SHA256: + curve = ecdsa.curves.NIST256p + key_len = 32 +- elif rrsig.algorithm == ECDSAP384SHA384: ++ elif rrsig.algorithm == ALGO_ECDSAP384SHA384: + curve = ecdsa.curves.NIST384p + key_len = 48 +- else: +- # shouldn't happen +- raise ValidationFailure('unknown ECDSA curve') +- keyptr = candidate_key.key ++ + x = Crypto.Util.number.bytes_to_long(keyptr[0:key_len]) + y = Crypto.Util.number.bytes_to_long(keyptr[key_len:key_len * 2]) + if not ecdsa.ecdsa.point_is_valid(curve.generator, x, y): +@@ -374,6 +375,7 @@ def _validate_rrsig(rrset, rrsig, keys, origin=None, now=None): + s = rrsig.signature[key_len:] + sig = ecdsa.ecdsa.Signature(Crypto.Util.number.bytes_to_long(r), + Crypto.Util.number.bytes_to_long(s)) ++ + else: + raise ValidationFailure('unknown algorithm %u' % rrsig.algorithm) + +@@ -395,24 +397,31 @@ def _validate_rrsig(rrset, rrsig, keys, origin=None, now=None): + hash.update(rrlen) + hash.update(rrdata) + +- digest = hash.digest() +- +- if _is_rsa(rrsig.algorithm): +- # PKCS1 algorithm identifier goop +- digest = _make_algorithm_id(rrsig.algorithm) + digest +- padlen = keylen // 8 - len(digest) - 3 +- digest = struct.pack('!%dB' % (2 + padlen + 1), +- *([0, 1] + [0xFF] * padlen + [0])) + digest +- elif _is_dsa(rrsig.algorithm) or _is_ecdsa(rrsig.algorithm): +- pass +- else: +- # Raise here for code clarity; this won't actually ever happen +- # since if the algorithm is really unknown we'd already have +- # raised an exception above +- raise ValidationFailure('unknown algorithm %u' % rrsig.algorithm) +- +- if pubkey.verify(digest, sig): ++ try: ++ if _is_rsa(rrsig.algorithm): ++ verifier = pkcs1_15.new(pubkey) ++ # will raise ValueError if verify fails: ++ verifier.verify(hash, sig) ++ elif _is_dsa(rrsig.algorithm): ++ verifier = DSS.new(pubkey, 'fips-186-3') ++ verifier.verify(hash, sig) ++ elif _is_ecdsa(rrsig.algorithm): ++ digest = hash.digest() ++ if pubkey.verify(digest, sig): ++ return ++ else: ++ raise ValueError ++ else: ++ # Raise here for code clarity; this won't actually ever happen ++ # since if the algorithm is really unknown we'd already have ++ # raised an exception above ++ raise ValidationFailure('unknown algorithm %u' % rrsig.algorithm) ++ # If we got here, we successfully verified so we can return without error + return ++ except ValueError: ++ # this happens on an individual validation failure ++ continue ++ # nothing verified -- raise failure: + raise ValidationFailure('verify failure') + + +@@ -444,10 +453,8 @@ def _validate(rrset, rrsigset, keys, origin=None, now=None): + rrname = rrset.name + + if isinstance(rrsigset, tuple): +- rrsigname = rrsigset[0] + rrsigrdataset = rrsigset[1] + else: +- rrsigname = rrsigset.name + rrsigrdataset = rrsigset + + rrname = rrname.choose_relativity(origin) +@@ -465,7 +472,7 @@ def _validate(rrset, rrsigset, keys, origin=None, now=None): + + + def _need_pycrypto(*args, **kwargs): +- raise NotImplementedError("DNSSEC validation requires pycrypto") ++ raise NotImplementedError("DNSSEC validation requires pycryptodome") + + try: + import Crypto.PublicKey.RSA +diff --git a/dns/hash.py b/dns/hash.py +deleted file mode 100644 +index 966838a..0000000 +--- a/dns/hash.py ++++ /dev/null +@@ -1,31 +0,0 @@ +-# Copyright (C) 2011 Nominum, Inc. +-# +-# Permission to use, copy, modify, and distribute this software and its +-# documentation for any purpose with or without fee is hereby granted, +-# provided that the above copyright notice and this permission notice +-# appear in all copies. +-# +-# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +-# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +-# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +-# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +-# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +-# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +-# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +- +-"""Hashing backwards compatibility wrapper""" +- +-import hashlib +- +- +-hashes = {} +-hashes['MD5'] = hashlib.md5 +-hashes['SHA1'] = hashlib.sha1 +-hashes['SHA224'] = hashlib.sha224 +-hashes['SHA256'] = hashlib.sha256 +-hashes['SHA384'] = hashlib.sha384 +-hashes['SHA512'] = hashlib.sha512 +- +- +-def get(algorithm): +- return hashes[algorithm.upper()] +diff --git a/dns/tsig.py b/dns/tsig.py +index c57d879..fd9d56a 100644 +--- a/dns/tsig.py ++++ b/dns/tsig.py +@@ -19,9 +19,9 @@ + import struct + + import dns.exception +-import dns.hash + import dns.rdataclass + import dns.name ++import dns.dnssec + from ._compat import long, string_types, text_type + + class BadTime(dns.exception.DNSException): +@@ -211,7 +211,7 @@ def get_algorithm(algorithm): + algorithm = dns.name.from_text(algorithm) + + try: +- return (algorithm.to_digestable(), dns.hash.hashes[_hashes[algorithm]]) ++ return (algorithm.to_digestable(), dns.dnssec._make_hash(algorithm)) + except KeyError: + raise NotImplementedError("TSIG algorithm " + str(algorithm) + + " is not supported") +diff --git a/tests/test_dnssec.py b/tests/test_dnssec.py +index 80bd626..9fb037e 100644 +--- a/tests/test_dnssec.py ++++ b/tests/test_dnssec.py +@@ -156,22 +156,22 @@ + abs_ecdsa384_soa_rrsig = dns.rrset.from_text('example.', 86400, 'IN', 'RRSIG', + "SOA 14 1 86400 20130929021229 20130921230729 63571 example. CrnCu34EeeRz0fEhL9PLlwjpBKGYW8QjBjFQTwd+ViVLRAS8tNkcDwQE NhSV89NEjj7ze1a/JcCfcJ+/mZgnvH4NHLNg3Tf6KuLZsgs2I4kKQXEk 37oIHravPEOlGYNI") + +-@unittest.skipUnless(import_ok, "skipping DNSSEC tests because pycrypto is not" ++@unittest.skipUnless(import_ok, "skipping DNSSEC tests because pycryptodome is not" + " installed") + class DNSSECValidatorTestCase(unittest.TestCase): + + @unittest.skipUnless(dns.dnssec._have_pycrypto, +- "PyCrypto cannot be imported") ++ "Pycryptodome cannot be imported") + def testAbsoluteRSAGood(self): + dns.dnssec.validate(abs_soa, abs_soa_rrsig, abs_keys, None, when) + + @unittest.skipUnless(dns.dnssec._have_pycrypto, +- "PyCrypto cannot be imported") ++ "Pycryptodome cannot be imported") + def testDuplicateKeytag(self): + dns.dnssec.validate(abs_soa, abs_soa_rrsig, abs_keys_duplicate_keytag, None, when) + + @unittest.skipUnless(dns.dnssec._have_pycrypto, +- "PyCrypto cannot be imported") ++ "Pycryptodome cannot be imported") + def testAbsoluteRSABad(self): + def bad(): + dns.dnssec.validate(abs_other_soa, abs_soa_rrsig, abs_keys, None, +@@ -179,13 +179,13 @@ def bad(): + self.failUnlessRaises(dns.dnssec.ValidationFailure, bad) + + @unittest.skipUnless(dns.dnssec._have_pycrypto, +- "PyCrypto cannot be imported") ++ "Pycryptodome cannot be imported") + def testRelativeRSAGood(self): + dns.dnssec.validate(rel_soa, rel_soa_rrsig, rel_keys, + abs_dnspython_org, when) + + @unittest.skipUnless(dns.dnssec._have_pycrypto, +- "PyCrypto cannot be imported") ++ "Pycryptodome cannot be imported") + def testRelativeRSABad(self): + def bad(): + dns.dnssec.validate(rel_other_soa, rel_soa_rrsig, rel_keys, +@@ -197,13 +197,13 @@ def testMakeSHA256DS(self): + self.failUnless(ds == good_ds) + + @unittest.skipUnless(dns.dnssec._have_pycrypto, +- "PyCrypto cannot be imported") ++ "Pycryptodome cannot be imported") + def testAbsoluteDSAGood(self): + dns.dnssec.validate(abs_dsa_soa, abs_dsa_soa_rrsig, abs_dsa_keys, None, + when2) + + @unittest.skipUnless(dns.dnssec._have_pycrypto, +- "PyCrypto cannot be imported") ++ "Pycryptodome cannot be imported") + def testAbsoluteDSABad(self): + def bad(): + dns.dnssec.validate(abs_other_dsa_soa, abs_dsa_soa_rrsig, diff --git a/python-dnspython.changes b/python-dnspython.changes index 249e689..547d085 100644 --- a/python-dnspython.changes +++ b/python-dnspython.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Wed May 9 13:42:40 UTC 2018 - tchvatal@suse.com + +- Add patch pycryptodome.patch to work with pycryptodome: + * pycryptodome.patch + ------------------------------------------------------------------- Tue May 2 21:42:12 UTC 2017 - sor.alexei@meowr.ru diff --git a/python-dnspython.spec b/python-dnspython.spec index 1504ec9..bd906fa 100644 --- a/python-dnspython.spec +++ b/python-dnspython.spec @@ -1,7 +1,7 @@ # # spec file for package python-dnspython # -# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -23,7 +23,7 @@ Release: 0 Summary: A DNS toolkit for Python License: ISC Group: Development/Languages/Python -Url: http://dnspython.org/ +URL: http://dnspython.org/ Source: http://dnspython.org/kits/%{version}/dnspython-%{version}.tar.gz Source2: http://dnspython.org/kits/%{version}/dnspython-%{version}.tar.gz.asc Source3: python-dnspython.keyring @@ -31,17 +31,19 @@ Source3: python-dnspython.keyring Patch0: 210.patch # PATCH-FEATURE-OPENSUSE readme.patch -- Add the readme as patch as not included in the tarball. Patch1: readme.patch +# PATCH-FIX-UPSTREAM pycryptodome.patch tchvatal@suse.com -- use pycryptodome https://github.com/rthalley/dnspython/pull/290 +Patch2: pycryptodome.patch BuildRequires: %{python_module devel} BuildRequires: %{python_module ecdsa} BuildRequires: %{python_module idna} -BuildRequires: %{python_module pycrypto} +BuildRequires: %{python_module pycryptodome} BuildRequires: %{python_module setuptools} BuildRequires: fdupes BuildRequires: netcfg BuildRequires: python-rpm-macros Recommends: python-ecdsa Recommends: python-idna -Recommends: python-pycrypto +Recommends: python-pycryptodome BuildArch: noarch %description @@ -65,6 +67,7 @@ allowed it to be opened under a BSD-style licence. chmod -x examples/* %patch0 %patch1 +%patch2 -p1 %build %python_build @@ -79,8 +82,8 @@ test -f tests/test_resolver.py && rm tests/test_resolver.py %python_exec setup.py test %files %{python_files} -%defattr(-,root,root) -%doc ChangeLog LICENSE README.md examples/ +%license LICENSE +%doc ChangeLog README.md examples/ %{python_sitelib}/dns/ %{python_sitelib}/dnspython-%{version}-py%{python_version}.egg-info From 4a234f3edc388fbda0a4eb14f243657fde96854bc4530a93a241a0fa36b80dce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Chv=C3=A1tal?= Date: Wed, 9 May 2018 13:48:08 +0000 Subject: [PATCH 2/2] OBS-URL: https://build.opensuse.org/package/show/devel:languages:python/python-dnspython?expand=0&rev=41 --- pycryptodome.patch | 117 ++++++++++++++++++++------------------------- 1 file changed, 52 insertions(+), 65 deletions(-) diff --git a/pycryptodome.patch b/pycryptodome.patch index a0b378f..1f55d08 100644 --- a/pycryptodome.patch +++ b/pycryptodome.patch @@ -17,11 +17,11 @@ Subject: [PATCH] Update DNSSEC code to use pycryptodome instead of pycrypto. 8 files changed, 105 insertions(+), 126 deletions(-) delete mode 100644 dns/hash.py -diff --git a/dns/__init__.py b/dns/__init__.py -index c848e48..3852729 100644 ---- a/dns/__init__.py -+++ b/dns/__init__.py -@@ -22,7 +22,6 @@ +Index: dnspython-1.15.0/dns/__init__.py +=================================================================== +--- dnspython-1.15.0.orig/dns/__init__.py ++++ dnspython-1.15.0/dns/__init__.py +@@ -22,7 +22,6 @@ __all__ = [ 'entropy', 'exception', 'flags', @@ -29,11 +29,11 @@ index c848e48..3852729 100644 'inet', 'ipv4', 'ipv6', -diff --git a/dns/dnssec.py b/dns/dnssec.py -index b91a64f..2b5d5b2 100644 ---- a/dns/dnssec.py -+++ b/dns/dnssec.py -@@ -20,7 +20,6 @@ +Index: dnspython-1.15.0/dns/dnssec.py +=================================================================== +--- dnspython-1.15.0.orig/dns/dnssec.py ++++ dnspython-1.15.0/dns/dnssec.py +@@ -20,7 +20,6 @@ import struct import time import dns.exception @@ -41,7 +41,7 @@ index b91a64f..2b5d5b2 100644 import dns.name import dns.node import dns.rdataset -@@ -28,7 +27,8 @@ +@@ -28,7 +27,8 @@ import dns.rdata import dns.rdatatype import dns.rdataclass from ._compat import string_types @@ -50,47 +50,35 @@ index b91a64f..2b5d5b2 100644 +from Crypto.Signature import pkcs1_15, DSS class UnsupportedAlgorithm(dns.exception.DNSException): - """The DNSSEC algorithm is not supported.""" -@@ -39,27 +39,27 @@ class ValidationFailure(dns.exception.DNSException): +@@ -39,34 +39,34 @@ class ValidationFailure(dns.exception.DN + + """The DNSSEC signature is invalid.""" - #: RSAMD5 -RSAMD5 = 1 -+ALGO_RSAMD5 = 1 - #: DH -DH = 2 -+ALGO_DH = 2 - #: DSA -DSA = 3 -+ALGO_DSA = 3 - #: ECC -ECC = 4 -+ALGO_ECC = 4 - #: RSASHA1 -RSASHA1 = 5 -+ALGO_RSASHA1 = 5 - #: DSANSEC3SHA1 -DSANSEC3SHA1 = 6 -+ALGO_DSANSEC3SHA1 = 6 - #: RSASHA1NSEC3SHA1 -RSASHA1NSEC3SHA1 = 7 -+ALGO_RSASHA1NSEC3SHA1 = 7 - #: RSASHA256 -RSASHA256 = 8 -+ALGO_RSASHA256 = 8 - #: RSASHA512 -RSASHA512 = 10 -+ALGO_RSASHA512 = 10 - #: ECDSAP256SHA256 -ECDSAP256SHA256 = 13 -+ALGO_ECDSAP256SHA256 = 13 - #: ECDSAP384SHA384 -ECDSAP384SHA384 = 14 ++ALGO_RSAMD5 = 1 ++ALGO_DH = 2 ++ALGO_DSA = 3 ++ALGO_ECC = 4 ++ALGO_RSASHA1 = 5 ++ALGO_DSANSEC3SHA1 = 6 ++ALGO_RSASHA1NSEC3SHA1 = 7 ++ALGO_RSASHA256 = 8 ++ALGO_RSASHA512 = 10 ++ALGO_ECDSAP256SHA256 = 13 +ALGO_ECDSAP384SHA384 = 14 - #: INDIRECT INDIRECT = 252 - #: PRIVATEDNS -@@ -68,18 +68,18 @@ class ValidationFailure(dns.exception.DNSException): + PRIVATEDNS = 253 PRIVATEOID = 254 _algorithm_by_text = { @@ -120,8 +108,8 @@ index b91a64f..2b5d5b2 100644 'PRIVATEDNS': PRIVATEDNS, 'PRIVATEOID': PRIVATEOID, } -@@ -132,7 +132,7 @@ def key_id(key, origin=None): - +@@ -107,7 +107,7 @@ def _to_rdata(record, origin): + def key_id(key, origin=None): rdata = _to_rdata(key, origin) rdata = bytearray(rdata) - if key.algorithm == RSAMD5: @@ -129,8 +117,8 @@ index b91a64f..2b5d5b2 100644 return (rdata[-3] << 8) + rdata[-2] else: total = 0 -@@ -164,10 +164,10 @@ def make_ds(name, key, algorithm, origin=None): - +@@ -123,10 +123,10 @@ def key_id(key, origin=None): + def make_ds(name, key, algorithm, origin=None): if algorithm.upper() == 'SHA1': dsalg = 1 - hash = dns.hash.hashes['SHA1']() @@ -142,7 +130,7 @@ index b91a64f..2b5d5b2 100644 else: raise UnsupportedAlgorithm('unsupported algorithm "%s"' % algorithm) -@@ -203,51 +203,51 @@ def _find_candidate_keys(keys, rrsig): +@@ -162,51 +162,51 @@ def _find_candidate_keys(keys, rrsig): def _is_rsa(algorithm): @@ -210,7 +198,7 @@ index b91a64f..2b5d5b2 100644 raise ValidationFailure('unknown hash for algorithm %u' % algorithm) -@@ -326,11 +326,13 @@ def _validate_rrsig(rrset, rrsig, keys, origin=None, now=None): +@@ -284,11 +284,13 @@ def _validate_rrsig(rrset, rrsig, keys, keyptr = keyptr[2:] rsa_e = keyptr[0:bytes_] rsa_n = keyptr[bytes_:] @@ -229,7 +217,7 @@ index b91a64f..2b5d5b2 100644 elif _is_dsa(rrsig.algorithm): keyptr = candidate_key.key (t,) = struct.unpack('!B', keyptr[0:1]) -@@ -348,20 +350,19 @@ def _validate_rrsig(rrset, rrsig, keys, origin=None, now=None): +@@ -306,20 +308,19 @@ def _validate_rrsig(rrset, rrsig, keys, Crypto.Util.number.bytes_to_long(dsa_g), Crypto.Util.number.bytes_to_long(dsa_p), Crypto.Util.number.bytes_to_long(dsa_q))) @@ -257,8 +245,8 @@ index b91a64f..2b5d5b2 100644 + x = Crypto.Util.number.bytes_to_long(keyptr[0:key_len]) y = Crypto.Util.number.bytes_to_long(keyptr[key_len:key_len * 2]) - if not ecdsa.ecdsa.point_is_valid(curve.generator, x, y): -@@ -374,6 +375,7 @@ def _validate_rrsig(rrset, rrsig, keys, origin=None, now=None): + assert ecdsa.ecdsa.point_is_valid(curve.generator, x, y) +@@ -331,6 +332,7 @@ def _validate_rrsig(rrset, rrsig, keys, s = rrsig.signature[key_len:] sig = ecdsa.ecdsa.Signature(Crypto.Util.number.bytes_to_long(r), Crypto.Util.number.bytes_to_long(s)) @@ -266,7 +254,7 @@ index b91a64f..2b5d5b2 100644 else: raise ValidationFailure('unknown algorithm %u' % rrsig.algorithm) -@@ -395,24 +397,31 @@ def _validate_rrsig(rrset, rrsig, keys, origin=None, now=None): +@@ -352,24 +354,31 @@ def _validate_rrsig(rrset, rrsig, keys, hash.update(rrlen) hash.update(rrdata) @@ -315,7 +303,7 @@ index b91a64f..2b5d5b2 100644 raise ValidationFailure('verify failure') -@@ -444,10 +453,8 @@ def _validate(rrset, rrsigset, keys, origin=None, now=None): +@@ -401,10 +410,8 @@ def _validate(rrset, rrsigset, keys, ori rrname = rrset.name if isinstance(rrsigset, tuple): @@ -326,7 +314,7 @@ index b91a64f..2b5d5b2 100644 rrsigrdataset = rrsigset rrname = rrname.choose_relativity(origin) -@@ -465,7 +472,7 @@ def _validate(rrset, rrsigset, keys, origin=None, now=None): +@@ -422,7 +429,7 @@ def _validate(rrset, rrsigset, keys, ori def _need_pycrypto(*args, **kwargs): @@ -335,10 +323,9 @@ index b91a64f..2b5d5b2 100644 try: import Crypto.PublicKey.RSA -diff --git a/dns/hash.py b/dns/hash.py -deleted file mode 100644 -index 966838a..0000000 ---- a/dns/hash.py +Index: dnspython-1.15.0/dns/hash.py +=================================================================== +--- dnspython-1.15.0.orig/dns/hash.py +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright (C) 2011 Nominum, Inc. @@ -372,11 +359,11 @@ index 966838a..0000000 - -def get(algorithm): - return hashes[algorithm.upper()] -diff --git a/dns/tsig.py b/dns/tsig.py -index c57d879..fd9d56a 100644 ---- a/dns/tsig.py -+++ b/dns/tsig.py -@@ -19,9 +19,9 @@ +Index: dnspython-1.15.0/dns/tsig.py +=================================================================== +--- dnspython-1.15.0.orig/dns/tsig.py ++++ dnspython-1.15.0/dns/tsig.py +@@ -19,9 +19,9 @@ import hmac import struct import dns.exception @@ -396,11 +383,11 @@ index c57d879..fd9d56a 100644 except KeyError: raise NotImplementedError("TSIG algorithm " + str(algorithm) + " is not supported") -diff --git a/tests/test_dnssec.py b/tests/test_dnssec.py -index 80bd626..9fb037e 100644 ---- a/tests/test_dnssec.py -+++ b/tests/test_dnssec.py -@@ -156,22 +156,22 @@ +Index: dnspython-1.15.0/tests/test_dnssec.py +=================================================================== +--- dnspython-1.15.0.orig/tests/test_dnssec.py ++++ dnspython-1.15.0/tests/test_dnssec.py +@@ -156,22 +156,22 @@ abs_other_ecdsa384_soa = dns.rrset.from_ abs_ecdsa384_soa_rrsig = dns.rrset.from_text('example.', 86400, 'IN', 'RRSIG', "SOA 14 1 86400 20130929021229 20130921230729 63571 example. CrnCu34EeeRz0fEhL9PLlwjpBKGYW8QjBjFQTwd+ViVLRAS8tNkcDwQE NhSV89NEjj7ze1a/JcCfcJ+/mZgnvH4NHLNg3Tf6KuLZsgs2I4kKQXEk 37oIHravPEOlGYNI") @@ -427,7 +414,7 @@ index 80bd626..9fb037e 100644 def testAbsoluteRSABad(self): def bad(): dns.dnssec.validate(abs_other_soa, abs_soa_rrsig, abs_keys, None, -@@ -179,13 +179,13 @@ def bad(): +@@ -179,13 +179,13 @@ class DNSSECValidatorTestCase(unittest.T self.failUnlessRaises(dns.dnssec.ValidationFailure, bad) @unittest.skipUnless(dns.dnssec._have_pycrypto, @@ -443,7 +430,7 @@ index 80bd626..9fb037e 100644 def testRelativeRSABad(self): def bad(): dns.dnssec.validate(rel_other_soa, rel_soa_rrsig, rel_keys, -@@ -197,13 +197,13 @@ def testMakeSHA256DS(self): +@@ -197,13 +197,13 @@ class DNSSECValidatorTestCase(unittest.T self.failUnless(ds == good_ds) @unittest.skipUnless(dns.dnssec._have_pycrypto,