a
    sd_I                     @   s2  d Z ddlZddlZddlZddlZddlZddlZddlZddl	Zddl
ZddlZddlZddlZG dd dejjZG dd dejjZG dd dejjZe ej d	d
 Zdd Zdd ZG dd dejjZdCddZdd Zdd Zdd Zdd Z dd Z!dd Z"dd  Z#d!d" Z$d#d$ Z%d%d& Z&d'd( Z'd)d* Z(d+d, Z)dDd-d.Z*dEd/d0Z+G d1d2 d2ejjZ,d3d4 Z-d5d6 Z.z|dd7l/m0Z0 dd8l1m2Z2 dd9l3m4Z4 dd:l5m6Z6 dd;l5m7Z7 dd<l5m8Z8 dd=l5m9Z9 dd>l5m:Z: dd?l5m;Z; dd@l5m<Z< W n  e=y    e.Z>e.Z?dAZ@Y n0 e+Z>e*Z?dBZ@dS )Fz.Common DNSSEC-related functions and constants.    Nc                   @   s   e Zd ZdZdS )UnsupportedAlgorithmz&The DNSSEC algorithm is not supported.N__name__
__module____qualname____doc__ r   r   ,/usr/lib/python3/dist-packages/dns/dnssec.pyr   #   s   r   c                   @   s   e Zd ZdZdS )ValidationFailurez The DNSSEC signature is invalid.Nr   r   r   r   r	   r
   '   s   r
   c                   @   s\   e Zd ZdZdZdZdZdZdZdZ	dZ
d	Zd
ZdZdZdZdZdZdZdZedd ZdS )	Algorithm                        
                           c                 C   s   dS N   r   clsr   r   r	   _maximum>   s    zAlgorithm._maximumN)r   r   r   RSAMD5ZDHDSAZECCRSASHA1DSANSEC3SHA1RSASHA1NSEC3SHA1	RSASHA256	RSASHA512ECCGOSTECDSAP256SHA256ECDSAP384SHA384ED25519ED448ZINDIRECTZ
PRIVATEDNSZ
PRIVATEOIDclassmethodr!   r   r   r   r	   r   +   s&   r   c                 C   s
   t | S )zConvert text into a DNSSEC algorithm value.

    *text*, a ``str``, the text to convert to into an algorithm value.

    Returns an ``int``.
    )r   	from_text)textr   r   r	   algorithm_from_textF   s    r1   c                 C   s
   t | S )zConvert a DNSSEC algorithm value to text

    *value*, an ``int`` a DNSSEC algorithm.

    Returns a ``str``, the name of a DNSSEC algorithm.
    )r   Zto_text)valuer   r   r	   algorithm_to_textQ   s    r3   c                 C   s   |   }| jtjkr(|d d> |d  S d}tt|d D ](}||d|  d> |d| d   7 }q<t|d dkr||t|d  d> 7 }||d? d@ 7 }|d@ S d	S )
zReturn the key id (a 16-bit number) for the specified key.

    *key*, a ``dns.rdtypes.ANY.DNSKEY.DNSKEY``

    Returns an ``int`` between 0 and 65535
    r   r   r   r   r   i  N)to_wire	algorithmr   r"   rangelen)keyrdatatotalir   r   r	   key_id\   s    r>   c                   @   s(   e Zd ZdZdZdZdZedd ZdS )DSDigestz(DNSSEC Delgation Signer Digest Algorithmr   r   r   c                 C   s   dS r   r   r   r   r   r	   r!   x   s    zDSDigest._maximumN)	r   r   r   r   SHA1SHA256SHA384r.   r!   r   r   r   r	   r?   q   s   r?   c                 C   s   zt |trt|  }W n ty8   td| Y n0 |tjkrNt }n4|tj	krbt
 }n |tjkrvt }ntd| t | trtj| |} ||    ||j|d | }tdt||j|| }tjtjjtjj|dt|S )aq  Create a DS record for a DNSSEC key.

    *name*, a ``dns.name.Name`` or ``str``, the owner name of the DS record.

    *key*, a ``dns.rdtypes.ANY.DNSKEY.DNSKEY``, the key the DS is about.

    *algorithm*, a ``str`` or ``int`` specifying the hash algorithm.
    The currently supported hashes are "SHA1", "SHA256", and "SHA384". Case
    does not matter for these strings.

    *origin*, a ``dns.name.Name`` or ``None``.  If `key` is a relative name,
    then it will be made absolute using the specified origin.

    Raises ``UnsupportedAlgorithm`` if the algorithm is unknown.

    Returns a ``dns.rdtypes.ANY.DS.DS``
    zunsupported algorithm "%s"originz!HBBr   )
isinstancestrr?   upper	Exceptionr   r@   hashlibsha1rA   Zsha256rB   Zsha384dnsnamer/   updatecanonicalizer6   digeststructpackr>   r7   r;   Z	from_wire
rdataclassIN	rdatatypeZDSr9   )rL   r:   r7   rD   ZdshashrO   Zdsrdatar   r   r	   make_ds}   s.    







rU   c                 C   s   g }|  |j}|d u rd S t|tjjrZz|tjjtj	j
}W q^ tyV   Y d S 0 n|}|D ](}|j|jkrbt||jkrb|| qb|S N)getsignerrE   rK   ZnodeZNodeZfind_rdatasetrR   rS   rT   ZDNSKEYKeyErrorr7   r>   Zkey_tagappend)keysrrsigcandidate_keysr2   rdatasetr;   r   r   r	   _find_candidate_keys   s$    

r_   c                 C   s   | t jt jt jt jt jfv S rV   )r   r"   r$   r&   r'   r(   r7   r   r   r	   _is_rsa   s    
ra   c                 C   s   | t jt jfv S rV   )r   r#   r%   r`   r   r   r	   _is_dsa   s    rb   c                 C   s   | t jt jfv S rV   )r   r*   r+   r`   r   r   r	   	_is_ecdsa   s    rc   c                 C   s   | t jt jfv S rV   )r   r,   r-   r`   r   r   r	   	_is_eddsa   s    rd   c                 C   s
   | t jkS rV   )r   r)   r`   r   r   r	   _is_gost   s    re   c                 C   s
   | t jkS rV   )r   r"   r`   r   r   r	   _is_md5   s    rf   c                 C   s   | t jt jt jt jfv S rV   )r   r#   r$   r%   r&   r`   r   r   r	   _is_sha1   s    
rg   c                 C   s   | t jt jfv S rV   )r   r'   r*   r`   r   r   r	   
_is_sha256   s    rh   c                 C   s
   | t jkS rV   )r   r+   r`   r   r   r	   
_is_sha384   s    ri   c                 C   s
   | t jkS rV   )r   r(   r`   r   r   r	   
_is_sha512   s    rj   c                 C   s   t | rt S t| r t S t| r0t S t| r@t S t	| rPt
 S | tjkrbt
 S | tjkrvtdS td|  d S )Nr   zunknown hash for algorithm %u)rf   hashesZMD5rg   r@   rh   rA   ri   rB   rj   ZSHA512r   r,   r-   ZSHAKE256r
   r`   r   r   r	   
_make_hash   s    


rm   c                 C   s   t | dS )NZbig)int
from_bytes)br   r   r	   _bytes_to_long   s    rq   c           $   
   C   s\  t |trtj|tjj}t||}|du r6td|D ]}t | tr\| d }| d }n
| j}| }|du rvt		 }|j
|k rtd|j|krtdt|jrX|j}	td|	dd \}
|	dd }	|
dkrtd|	dd	 \}
|	d	d }	|	d|
 }|	|
d }z tt|t|t }W n tyL   td
Y n0 |j}nrt|jrp|j}	td|	dd \}|	dd }	d|d  }|	dd }|	dd }	|	d| }|	|d }	|	d| }|	|d }	|	d| }z2tt|tt|t|t|t }W n ty:   td
Y n0 |jdd }|jdd }tt|t|}nZt|jr:|j}	|jtj krt!" }d}nt!# }d}|	d| }|	||d	  }z$t!j$|t|t|dt }W n ty   td
Y n0 |jd| }|j|d }tt|t|}nt%|jr|j}	|jtj&krbt'j(}nt)j*}z|+|	}W n ty   td
Y n0 |j}n.t,|jrt-dt.|j ntd|j d}||j/|ddd 7 }||j01|7 }|j2t3|d k r,|4|j2d d }tjd|}|1|}t5d|j6|j7|j8}t9|}|D ]@} ||7 }||7 }| 1|}!t5dt3|!}"||"7 }||!7 }qXt:|j}#zt|jr|;||t<= |# nft|jr|;|||# nJt|jr|;||t!>|# n(t%|jr |;|| ntd|j W  dS  t?yL   Y q:Y q:0 q:tddS )a*  Validate an RRset against a single signature rdata, throwing an
    exception if validation is not successful.

    *rrset*, the RRset to validate.  This can be a
    ``dns.rrset.RRset`` or a (``dns.name.Name``, ``dns.rdataset.Rdataset``)
    tuple.

    *rrsig*, a ``dns.rdata.Rdata``, the signature to validate.

    *keys*, 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*, a ``dns.name.Name`` or ``None``, the origin to use for relative
    names.

    *now*, an ``int`` or ``None``, the time, in seconds since the epoch, to
    use as the current time when validating.  If ``None``, the actual current
    time is used.

    Raises ``ValidationFailure`` if the signature is expired, not yet valid,
    the public key is invalid, the algorithm is unknown, the verification
    fails, etc.

    Raises ``UnsupportedAlgorithm`` if the algorithm is recognized by
    dnspython but not implemented.
    Nzunknown keyr   r   Zexpiredznot yet validz!Bz!Hr   zinvalid public key@   r             0   )curvexyz)algorithm "%s" not supported by dnspythonzunknown algorithm %u    rC      *z!HHIzverify failure)@rE   rF   rK   rL   r/   rootr_   r
   tupletimeZ
expirationZ	inceptionra   r7   r:   rP   ZunpackrsaZRSAPublicNumbersrq   
public_keydefault_backend
ValueErrorZ	signaturerb   dsaZDSAPublicNumbersZDSAParameterNumbersutilsZencode_dss_signaturerc   r   r*   ecZ	SECP256R1Z	SECP384R1ZEllipticCurvePublicNumbersrd   r,   ed25519ZEd25519PublicKeyed448ZEd448PublicKeyZfrom_public_bytesre   r   r3   r6   rX   Zto_digestablelabelsr9   splitrQ   ZrdtypeZrdclassZoriginal_ttlsortedrm   ZverifypaddingZPKCS1v15ZECDSAInvalidSignature)$rrsetr\   r[   rD   nowr]   Zcandidate_keyrrnamer^   ZkeyptrZbytes_Zrsa_eZrsa_nr   ZsigtZoctetsZdsa_qZdsa_pZdsa_gZdsa_yZsig_rZsig_srw   Zecdsa_xZecdsa_yloaderdatasuffixZ	rrnamebufZrrfixedZrrlistZrrZrrdataZrrlenZchosen_hashr   r   r	   _validate_rrsig  s   












r   c           	   
   C   s   t |trtj|tjj}t | tr0| d }n| j}t |trR|d }|d }n
|j}|}||}||}||krtd|D ]4}zt	| |||| W  dS  tt
fy   Y q0 qtddS )a  Validate an RRset against a signature RRset, throwing an exception
    if none of the signatures validate.

    *rrset*, the RRset to validate.  This can be a
    ``dns.rrset.RRset`` or a (``dns.name.Name``, ``dns.rdataset.Rdataset``)
    tuple.

    *rrsigset*, the signature RRset.  This can be a
    ``dns.rrset.RRset`` or a (``dns.name.Name``, ``dns.rdataset.Rdataset``)
    tuple.

    *keys*, 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*, a ``dns.name.Name``, the origin to use for relative names;
    defaults to None.

    *now*, an ``int`` or ``None``, the time, in seconds since the epoch, to
    use as the current time when validating.  If ``None``, the actual current
    time is used.

    Raises ``ValidationFailure`` if the signature is expired, not yet valid,
    the public key is invalid, the algorithm is unknown, the verification
    fails, etc.
    r   r   zowner names do not matchNzno RRSIGs validated)rE   rF   rK   rL   r/   r}   r~   Zchoose_relativityr
   r   r   )	r   Zrrsigsetr[   rD   r   r   Z	rrsignameZrrsigrdatasetr\   r   r   r	   	_validate  s*    






r   c                   @   s    e Zd ZdZdZedd ZdS )	NSEC3HashzNSEC3 hash algorithmr   c                 C   s   dS r   r   r   r   r   r	   r!     s    zNSEC3Hash._maximumN)r   r   r   r   r@   r.   r!   r   r   r   r	   r     s   r   c           
      C   s
  t dd}zt|t r$t|  }W n ty@   tdY n0 |tjkrTtd|}|du rfd}n.t|t rt|d dkrt	
|}ntdt| tjjstj| } |   }t||  }t|D ]}t||  }qt|d	}	|	|}	|	S )
a  
    Calculate the NSEC3 hash, according to
    https://tools.ietf.org/html/rfc5155#section-5

    *domain*, a ``dns.name.Name`` or ``str``, the name to hash.

    *salt*, a ``str``, ``bytes``, or ``None``, the hash salt.  If a
    string, it is decoded as a hex string.

    *iterations*, an ``int``, the number of iterations.

    *algorithm*, a ``str`` or ``int``, the hash algorithm.
    The only defined algorithm is SHA1.

    Returns a ``str``, the encoded NSEC3 hash.
    Z ABCDEFGHIJKLMNOPQRSTUVWXYZ234567Z 0123456789ABCDEFGHIJKLMNOPQRSTUVz-Wrong hash algorithm (only SHA1 is supported)Nrz   r   r   zInvalid salt lengthzutf-8)rF   	maketransrE   r   rG   rH   r   r@   r9   bytesfromhexrK   rL   Namer/   rN   r6   rI   rJ   rO   r8   base64Z	b32encodedecode	translate)
ZdomainZsaltZ
iterationsr7   Zb32_conversionZsalt_encodedZdomain_encodedrO   r=   outputr   r   r	   
nsec3_hash  s4    



r   c                  O   s   t dd S )Nz.DNSSEC validation requires python cryptography)ImportError)argskwargsr   r   r	   
_need_pyca.  s    r   )r   )r   )rl   )r   )r   )r   )r   )r   )r   )r   FT)N)NN)NN)Ar   rI   rP   r   r   Zdns.enumrK   Zdns.exceptionZdns.nameZdns.nodeZdns.rdatasetZ	dns.rdataZdns.rdatatypeZdns.rdataclassZ	exceptionZDNSExceptionr   r
   enumIntEnumr   globalsrM   __members__r1   r3   r>   r?   rU   r_   ra   rb   rc   rd   re   rf   rg   rh   ri   rj   rm   rq   r   r   r   r   r   Zcryptography.exceptionsr   Zcryptography.hazmat.backendsr   Zcryptography.hazmat.primitivesrl   Z)cryptography.hazmat.primitives.asymmetricr   r   r   r   r   r   r   r   ZvalidateZvalidate_rrsigZ
_have_pycar   r   r   r	   <module>   st   
.
 5
:	6
