def make_ds(name, key, algorithm, origin=None): """Create a DS record for a DNSSEC key. *name* is the owner name of the DS record. *key* is a ``dns.rdtypes.ANY.DNSKEY``. *algorithm* is a string describing which hash algorithm to use. The currently supported hashes are "SHA1" and "SHA256". Case does not matter for these strings. *origin* is a ``dns.name.Name`` and will be used as the origin if *key* is a relative name. Returns a ``dns.rdtypes.ANY.DS``. """ if algorithm.upper() == 'SHA1': dsalg = 1 hash = dns.hash.hashes['SHA1']() elif algorithm.upper() == 'SHA256': dsalg = 2 hash = dns.hash.hashes['SHA256']() else: raise UnsupportedAlgorithm('unsupported algorithm "%s"' % algorithm) if isinstance(name, string_types): name = dns.name.from_text(name, origin) hash.update(name.canonicalize().to_wire()) hash.update(_to_rdata(key, origin)) digest = hash.digest() dsrdata = struct.pack("!HBB", key_id(key), key.algorithm, dsalg) + digest return dns.rdata.from_wire(dns.rdataclass.IN, dns.rdatatype.DS, dsrdata, 0, len(dsrdata))
def make_ds(name, key, algorithm, origin=None): if algorithm.upper() == 'SHA1': dsalg = 1 hash = dns.hash.get('SHA1')() elif algorithm.upper() == 'SHA256': dsalg = 2 hash = dns.hash.get('SHA256')() else: raise UnsupportedAlgorithm, 'unsupported algorithm "%s"' % algorithm if isinstance(name, (str, unicode)): name = dns.name.from_text(name, origin) hash.update(name.canonicalize().to_wire()) hash.update(_to_rdata(key, origin)) digest = hash.digest() dsrdata = struct.pack("!HBB", key_id(key), key.algorithm, dsalg) + digest return dns.rdata.from_wire(dns.rdataclass.IN, dns.rdatatype.DS, dsrdata, 0, len(dsrdata))
def _validate_rrsig(rrset, rrsig, keys, origin=None, now=None): """Validate an RRset against a single signature rdata The owner name of *rrsig* is assumed to be the same as the owner name of *rrset*. *rrset* is the RRset to validate. It can be a ``dns.rrset.RRset`` or a ``(dns.name.Name, dns.rdataset.Rdataset)`` tuple. *rrsig* is a ``dns.rrset.Rdata``, the signature to validate. *keys* is the key dictionary, used to find the DNSKEY associated with a given name. The dictionary is keyed by a ``dns.name.Name``, and has ``dns.node.Node`` or ``dns.rdataset.Rdataset`` values. *origin* is a ``dns.name.Name``, the origin to use for relative names. *now* is an ``int``, the time to use when validating the signatures, in seconds since the UNIX epoch. The default is the current time. """ if isinstance(origin, string_types): origin = dns.name.from_text(origin, dns.name.root) candidate_keys = _find_candidate_keys(keys, rrsig) if candidate_keys is None: raise ValidationFailure('unknown key') for candidate_key in candidate_keys: # 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_:] 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),) elif _is_dsa(rrsig.algorithm): keyptr = candidate_key.key (t,) = struct.unpack('!B', keyptr[0:1]) keyptr = keyptr[1:] octets = 64 + t * 8 dsa_q = keyptr[0:20] keyptr = keyptr[20:] dsa_p = keyptr[0:octets] keyptr = keyptr[octets:] dsa_g = keyptr[0:octets] keyptr = keyptr[octets:] dsa_y = keyptr[0:octets] pubkey = Crypto.PublicKey.DSA.construct( (Crypto.Util.number.bytes_to_long(dsa_y), 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)) 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 = 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): raise ValidationFailure('invalid ECDSA key') point = ecdsa.ellipticcurve.Point(curve.curve, x, y, curve.order) verifying_key = ecdsa.keys.VerifyingKey.from_public_point(point, curve) pubkey = ECKeyWrapper(verifying_key, key_len) r = rrsig.signature[:key_len] 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) 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): # 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): return raise ValidationFailure('verify failure')
def _validate_rrsig(rrset, rrsig, keys, origin=None, now=None): """Validate an RRset against a single signature rdata The owner name of the rrsig is assumed to be the same as the owner name of the rrset. @param rrset: The RRset to validate @type rrset: dns.rrset.RRset or (dns.name.Name, dns.rdataset.Rdataset) tuple @param rrsig: The signature rdata @type rrsig: dns.rrset.Rdata @param keys: The key dictionary. @type keys: a dictionary keyed by dns.name.Name with node or rdataset values @param origin: The origin to use for relative names @type origin: dns.name.Name or None @param now: The time to use when validating the signatures. The default is the current time. @type now: int """ if isinstance(origin, (str, unicode)): 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:] 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),) elif _is_dsa(rrsig.algorithm): keyptr = candidate_key.key (t,) = struct.unpack('!B', keyptr[0:1]) keyptr = keyptr[1:] octets = 64 + t * 8 dsa_q = keyptr[0:20] keyptr = keyptr[20:] dsa_p = keyptr[0:octets] keyptr = keyptr[octets:] dsa_g = keyptr[0:octets] keyptr = keyptr[octets:] dsa_y = keyptr[0:octets] pubkey = Crypto.PublicKey.DSA.construct( (Crypto.Util.number.bytes_to_long(dsa_y), 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)) elif _is_ecdsa(rrsig.algorithm): if rrsig.algorithm == ECDSAP256SHA256: curve = ecdsa.curves.NIST256p key_len = 32 digest_len = 32 elif rrsig.algorithm == ECDSAP384SHA384: curve = ecdsa.curves.NIST384p key_len = 48 digest_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]) 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) pubkey = ECKeyWrapper(verifying_key, key_len) r = rrsig.signature[:key_len] 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 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): # PKCS1 algorithm identifier goop digest = _make_algorithm_id(rrsig.algorithm) + digest padlen = keylen // 8 - len(digest) - 3 digest = chr(0) + chr(1) + chr(0xFF) * padlen + chr(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): return raise ValidationFailure, 'verify failure'
def _validate_rrsig(rrset, rrsig, keys, origin=None, now=None): """Validate an RRset against a single signature rdata The owner name of the rrsig is assumed to be the same as the owner name of the rrset. @param rrset: The RRset to validate @type rrset: dns.rrset.RRset or (dns.name.Name, dns.rdataset.Rdataset) tuple @param rrsig: The signature rdata @type rrsig: dns.rrset.Rdata @param keys: The key dictionary. @type keys: a dictionary keyed by dns.name.Name with node or rdataset values @param origin: The origin to use for relative names @type origin: dns.name.Name or None @param now: The time to use when validating the signatures. The default is the current time. @type now: int """ if isinstance(origin, (str, unicode)): 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:] 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),) elif _is_dsa(rrsig.algorithm): keyptr = candidate_key.key (t,) = struct.unpack('!B', keyptr[0:1]) keyptr = keyptr[1:] octets = 64 + t * 8 dsa_q = keyptr[0:20] keyptr = keyptr[20:] dsa_p = keyptr[0:octets] keyptr = keyptr[octets:] dsa_g = keyptr[0:octets] keyptr = keyptr[octets:] dsa_y = keyptr[0:octets] pubkey = Crypto.PublicKey.DSA.construct( (Crypto.Util.number.bytes_to_long(dsa_y), 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)) 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): # PKCS1 algorithm identifier goop digest = _make_algorithm_id(rrsig.algorithm) + digest padlen = keylen // 8 - len(digest) - 3 digest = chr(0) + chr(1) + chr(0xFF) * padlen + chr(0) + digest elif _is_dsa(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): return raise ValidationFailure, 'verify failure'
def _validate_rrsig(rrset, rrsig, keys, origin=None, now=None): """Validate an RRset against a single signature rdata The owner name of *rrsig* is assumed to be the same as the owner name of *rrset*. *rrset* is the RRset to validate. It can be a ``dns.rrset.RRset`` or a ``(dns.name.Name, dns.rdataset.Rdataset)`` tuple. *rrsig* is a ``dns.rrset.Rdata``, the signature to validate. *keys* is the key dictionary, used to find the DNSKEY associated with a given name. The dictionary is keyed by a ``dns.name.Name``, and has ``dns.node.Node`` or ``dns.rdataset.Rdataset`` values. *origin* is a ``dns.name.Name``, the origin to use for relative names. *now* is an ``int``, the time to use when validating the signatures, in seconds since the UNIX epoch. The default is the current time. """ if isinstance(origin, string_types): 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_:] 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), ) elif _is_dsa(rrsig.algorithm): keyptr = candidate_key.key (t, ) = struct.unpack('!B', keyptr[0:1]) keyptr = keyptr[1:] octets = 64 + t * 8 dsa_q = keyptr[0:20] keyptr = keyptr[20:] dsa_p = keyptr[0:octets] keyptr = keyptr[octets:] dsa_g = keyptr[0:octets] keyptr = keyptr[octets:] dsa_y = keyptr[0:octets] pubkey = Crypto.PublicKey.DSA.construct( (Crypto.Util.number.bytes_to_long(dsa_y), 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)) 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 = Crypto.Util.number.bytes_to_long(keyptr[0:key_len]) y = Crypto.Util.number.bytes_to_long(keyptr[key_len:key_len * 2]) 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) pubkey = ECKeyWrapper(verifying_key, key_len) r = rrsig.signature[:key_len] 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) 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): # 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): return raise ValidationFailure('verify failure')
def _validate_rrsig(rrset, rrsig, keys, origin=None, now=None): """Validate an RRset against a single signature rdata The owner name of the rrsig is assumed to be the same as the owner name of the rrset. @param rrset: The RRset to validate @type rrset: dns.rrset.RRset or (dns.name.Name, dns.rdataset.Rdataset) tuple @param rrsig: The signature rdata @type rrsig: dns.rrset.Rdata @param keys: The key dictionary. @type keys: a dictionary keyed by dns.name.Name with node or rdataset values @param origin: The origin to use for relative names @type origin: dns.name.Name or None @param now: The time to use when validating the signatures. The default is the current time. @type now: int """ 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 (count,) = struct.unpack('!B', keyptr[0:1]) keyptr = keyptr[1:] if count == 0: (count,) = struct.unpack('!H', keyptr[0:2]) keyptr = keyptr[2:] rsa_e = keyptr[0:count] rsa_n = keyptr[count:] 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),) elif _is_dsa(rrsig.algorithm): keyptr = candidate_key.key (t,) = struct.unpack('!B', keyptr[0:1]) keyptr = keyptr[1:] octets = 64 + t * 8 dsa_q = keyptr[0:20] keyptr = keyptr[20:] dsa_p = keyptr[0:octets] keyptr = keyptr[octets:] dsa_g = keyptr[0:octets] keyptr = keyptr[octets:] dsa_y = keyptr[0:octets] pubkey = Crypto.PublicKey.DSA.construct( (Crypto.Util.number.bytes_to_long(dsa_y), 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)) 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): # PKCS1 algorithm identifier goop digest = _make_algorithm_id(rrsig.algorithm) + digest padlen = keylen // 8 - len(digest) - 3 digest = bytes([0]) + bytes([1]) + bytes([0xFF]) * padlen + \ bytes([0]) + digest elif _is_dsa(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): return raise ValidationFailure('verify failure')