U
    ÓZjc?  ã                   @   sÞ  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m	Z	 ddlm
Z
 ddlmZ ddlmZ ddlmZ ddlmZ dd	lmZ dd
lmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlm Z  ddl!m"Z" e #e$¡Z%dEd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(„ Z0d)d*„ Z1d+d,„ Z2e
j3fd-d.„Z4e
j3fd/d0„Z5e
j3fd1d2„Z6d3d4„ Z7d5d6„ Z8e
j3fd7d8„Z9e
j3fd9d:„Z:d;d<„ Z;d=d>„ Z<d?d@„ Z=dAdB„ Z>dCdD„ Z?dS )Fz¦Certbot client crypto utility functions.

.. todo:: Make the transition to use PSS rather than PKCS1_v1_5 when the server
    is capable of handling the signatures.

é    N)ÚSSL)Úcrypto)Úx509)ÚInvalidSignature)Údefault_backend)ÚECDSA)ÚEllipticCurvePublicKey)ÚPKCS1v15)ÚRSAPublicKey)Úcrypto_util)ÚIO)Úerrors)Ú
interfaces)Úutil)Úosúkey-certbot.pemc              
   C   s°   zt | ƒ}W n4 tk
r@ } ztjddd� |‚W 5 d}~X Y nX tj tj¡}t	 
|d|j¡ t	 tj ||¡dd¡\}}|� | |¡ W 5 Q R X t d| |¡ t	 ||¡S )	aÚ  Initializes and saves a privkey.

    Inits key and saves it in PEM format on the filesystem.

    .. note:: keyname is the attempted filename, it may be different if a file
        already exists at the path.

    :param int key_size: RSA key size in bits
    :param str key_dir: Key save directory.
    :param str keyname: Filename of key

    :returns: Key
    :rtype: :class:`certbot.util.Key`

    :raises ValueError: If unable to generate the key given key_size.

    Ú T©Úexc_infoNiÀ  i€  ÚwbzGenerating key (%d bits): %s)Úmake_keyÚ
ValueErrorÚloggerÚerrorÚzopeÚ	componentÚ
getUtilityr   ÚIConfigr   Úmake_or_verify_dirÚstrict_permissionsÚunique_filer   ÚpathÚjoinÚwriteÚdebugÚKey)Zkey_sizeZkey_dirZkeynameZkey_pemÚerrÚconfigZkey_fÚkey_path© r)   úV/var/www/html/TRUCKING_PROJECT/venv/lib/python3.8/site-packages/certbot/crypto_util.pyÚinit_save_key%   s       ÿr+   c              	   C   s‚   t j tj¡}tj| j||jd�}t	 
|d|j¡ t	 tj |d¡dd¡\}}|� | |¡ W 5 Q R X t d|¡ t	 ||d¡S )a2  Initialize a CSR with the given private key.

    :param privkey: Key to include in the CSR
    :type privkey: :class:`certbot.util.Key`

    :param set names: `str` names to include in the CSR

    :param str path: Certificate save directory.

    :returns: CSR
    :rtype: :class:`certbot.util.CSR`

    )Úmust_stapleií  zcsr-certbot.pemi¤  r   zCreating CSR: %sÚpem)r   r   r   r   r   Úacme_crypto_utilZmake_csrr-   r,   r   r   r   r    r   r!   r"   r#   r   r$   ÚCSR)ÚprivkeyÚnamesr!   r'   Zcsr_pemZcsr_fZcsr_filenamer)   r)   r*   Úinit_save_csrI   s       ÿ  ÿr2   c                 C   sJ   zt  t j| ¡}| | ¡ ¡W S  t jk
rD   tjddd� Y dS X dS )zŸValidate CSR.

    Check if `csr` is a valid CSR for the given domains.

    :param str csr: CSR in PEM.

    :returns: Validity of CSR.
    :rtype: bool

    r   Tr   FN)r   Úload_certificate_requestÚFILETYPE_PEMÚverifyZ
get_pubkeyÚErrorr   r$   )ÚcsrÚreqr)   r)   r*   Ú	valid_csrl   s     ÿr9   c                 C   sT   t  t j| ¡}t  t j|¡}z| |¡W S  t jk
rN   tjddd� Y dS X dS )zùDoes private key correspond to the subject public key in the CSR?

    :param str csr: CSR in PEM.
    :param str privkey: Private key file contents (PEM)

    :returns: Correspondence of private key to CSR subject public key.
    :rtype: bool

    r   Tr   FN)r   r3   r4   Úload_privatekeyr5   r6   r   r$   )r7   r0   r8   Úpkeyr)   r)   r*   Úcsr_matches_pubkey€   s    
 ÿr<   c                 C   s”   t j}t j}z|t j|ƒ}W nL t jk
rh   z|||ƒ}W n& t jk
rb   t d | ¡¡‚Y nX Y nX t|ƒ}t  ||¡}|t	j
| |dd�|fS )a/  Import a CSR file, which can be either PEM or DER.

    :param str csrfile: CSR filename
    :param str data: contents of the CSR file

    :returns: (`crypto.FILETYPE_PEM`,
               util.CSR object representing the CSR,
               list of domains requested in the CSR)
    :rtype: tuple

    zFailed to parse CSR file: {0}r-   )ÚfileÚdataÚform)r   r4   r3   ÚFILETYPE_ASN1r6   r   ÚformatÚ"_get_names_from_loaded_cert_or_reqZdump_certificate_requestr   r/   )Zcsrfiler>   ZPEMÚloadr7   ÚdomainsZdata_pemr)   r)   r*   Úimport_csr_file”   s    rE   c                 C   s0   | dkst ‚t ¡ }| tj| ¡ t tj|¡S )z­Generate PEM encoded RSA key.

    :param int bits: Number of bits, at least 1024.

    :returns: new RSA key in PEM form with specified number of bits
    :rtype: str

    i   )ÚAssertionErrorr   ZPKeyZgenerate_keyZTYPE_RSAZdump_privatekeyr4   )ÚbitsÚkeyr)   r)   r*   r   ±   s    	r   c              	   C   s6   zt  t j| ¡ ¡ W S  tt jfk
r0   Y dS X dS )z’Is valid RSA private key?

    :param str privkey: Private key file contents in PEM

    :returns: Validity of private key.
    :rtype: bool

    FN)r   r:   r4   ÚcheckÚ	TypeErrorr6   )r0   r)   r)   r*   Úvalid_privkeyÀ   s    	 ÿ
rK   c                 C   s"   t | ƒ t| ƒ t| j| jƒ dS )a‡  For checking that your certs were not corrupted on disk.

    Several things are checked:
        1. Signature verification for the cert.
        2. That fullchain matches cert and chain when concatenated.
        3. Check that the private key matches the certificate.

    :param `.storage.RenewableCert` renewable_cert: cert to verify

    :raises errors.Error: If verification fails.
    N)Úverify_renewable_cert_sigÚverify_fullchainÚverify_cert_matches_priv_keyÚcertr0   )Úrenewable_certr)   r)   r*   Úverify_renewable_certÐ   s    rQ   c              
   C   sØ   zˆt | jdƒ�}t | ¡ tƒ ¡}W 5 Q R X t | jdƒ�}t | ¡ tƒ ¡}W 5 Q R X | ¡ }t 	¡ � t
||j|j|jƒ W 5 Q R X W nJ tttfk
rÒ } z&d | j|¡}t |¡ t |¡‚W 5 d}~X Y nX dS )zÁVerifies the signature of a `.storage.RenewableCert` object.

    :param `.storage.RenewableCert` renewable_cert: cert to verify

    :raises errors.Error: If signature verification fails.
    Úrbz[verifying the signature of the cert located at {0} has failed.                 Details: {1}N)ÚopenÚchainr   Zload_pem_x509_certificateÚreadr   rO   Ú
public_keyÚwarningsÚcatch_warningsÚverify_signed_payloadÚ	signatureZtbs_certificate_bytesÚsignature_hash_algorithmÚIOErrorr   r   rA   r   Ú	exceptionr   r6   )rP   Ú
chain_filerT   Ú	cert_filerO   ÚpkÚeÚ	error_strr)   r)   r*   rL   á   s"    
ÿ ÿ
rL   c              	   C   sˆ   t  ¡ �v t  d¡ t| tƒrB|  |tƒ |¡}| |¡ | ¡  n8t| t	ƒrp|  |t
|ƒ¡}| |¡ | ¡  n
t d¡‚W 5 Q R X dS )aå  Check the signature of a payload.

    :param RSAPublicKey/EllipticCurvePublicKey public_key: the public_key to check signature
    :param bytes signature: the signature bytes
    :param bytes payload: the payload bytes
    :param cryptography.hazmat.primitives.hashes.HashAlgorithm
           signature_hash_algorithm: algorithm used to hash the payload

    :raises InvalidSignature: If signature verification fails.
    :raises errors.Error: If public key type is not supported
    ÚignorezUnsupported public key typeN)rW   rX   ÚsimplefilterÚ
isinstancer
   Úverifierr	   Úupdater5   r   r   r   r6   )rV   rZ   Úpayloadr[   rf   r)   r)   r*   rY   ø   s$    


  ÿ


 ÿ

rY   c              
   C   s|   z,t  t j¡}| | ¡ | |¡ | ¡  W nJ tt jfk
rv } z&d | ||¡}t	 
|¡ t |¡‚W 5 d}~X Y nX dS )zÏ Verifies that the private key and cert match.

    :param str cert_path: path to a cert in PEM format
    :param str key_path: path to a private key file

    :raises errors.Error: If they don't match.
    z�verifying the cert located at {0} matches the                 private key located at {1} has failed.                 Details: {2}N)r   ÚContextZSSLv23_METHODZuse_certificate_fileZuse_privatekey_fileZcheck_privatekeyr\   r6   rA   r   r]   r   )Ú	cert_pathr(   Úcontextra   rb   r)   r)   r*   rN     s    

 ý
rN   c           	   
   C   sð   z„t | jƒ�}| ¡ }W 5 Q R X t | jƒ�}| ¡ }W 5 Q R X t | jƒ�}| ¡ }W 5 Q R X || |kr‚d}| | j¡}t |¡‚W nf t	k
rÄ } z"d |¡}t
 |¡ t |¡‚W 5 d}~X Y n( tjk
rê } z|‚W 5 d}~X Y nX dS )zÓ Verifies that fullchain is indeed cert concatenated with chain.

    :param `.storage.RenewableCert` renewable_cert: cert to verify

    :raises errors.Error: If cert and chain do not combine to fullchain.
    z.fullchain does not match cert + chain for {0}!z8reading one of cert, chain, or fullchain has failed: {0}N)rS   rT   rU   rO   Ú	fullchainrA   Zlineagenamer   r6   r\   r   r]   )	rP   r^   rT   r_   rO   Zfullchain_filerl   rb   ra   r)   r)   r*   rM   -  s"    

rM   c                 C   s€   g }t jt jfD ]J}zt  || ¡|fW   S  t jk
rX } z| |¡ W 5 d}~X Y qX qt d d dd„ |D ƒ¡¡¡‚dS )z:Load PEM/DER certificate.

    :raises errors.Error:

    NzUnable to load: {0}ú,c                 s   s   | ]}t |ƒV  qd S ©N)Ústr)Ú.0r   r)   r)   r*   Ú	<genexpr>U  s    z-pyopenssl_load_certificate.<locals>.<genexpr>)	r   r4   r@   Úload_certificater6   Úappendr   rA   r"   )r>   Zopenssl_errorsÚ	file_typer   r)   r)   r*   Úpyopenssl_load_certificateG  s    ÿru   c                 C   s8   z||| ƒW S  t jk
r2   tjddd� ‚ Y nX d S )Nr   Tr   )r   r6   r   r   ©Zcert_or_req_strÚ	load_funcÚtypr)   r)   r*   Ú_load_cert_or_reqY  s
    ry   c                 C   s   t  t| ||ƒ¡S rn   )r.   Z_pyopenssl_cert_or_req_sanry   rv   r)   r)   r*   Ú_get_sans_from_cert_or_reqb  s
      ÿrz   c                 C   s   t | tj|ƒS )zóGet a list of Subject Alternative Names from a certificate.

    :param str cert: Certificate (encoded).
    :param typ: `crypto.FILETYPE_PEM` or `crypto.FILETYPE_ASN1`

    :returns: A list of Subject Alternative Names.
    :rtype: list

    )rz   r   rr   )rO   rx   r)   r)   r*   Úget_sans_from_certi  s
    
  ÿr{   c                 C   s   t | ||ƒ}t|ƒS rn   )ry   rB   )Zcert_or_reqrw   rx   Úloaded_cert_or_reqr)   r)   r*   Ú_get_names_from_cert_or_reqw  s    r}   c                 C   s
   t  | ¡S rn   )r.   Z _pyopenssl_cert_or_req_all_names)r|   r)   r)   r*   rB   |  s    rB   c                 C   s   t | tj|ƒS )zìGet a list of domains from a cert, including the CN if it is set.

    :param str cert: Certificate (encoded).
    :param typ: `crypto.FILETYPE_PEM` or `crypto.FILETYPE_ASN1`

    :returns: A list of domain names.
    :rtype: list

    )r}   r   rr   )r7   rx   r)   r)   r*   Úget_names_from_cert�  s
    
  ÿr~   c                 C   s   t  | |¡S )z–Dump certificate chain into a bundle.

    :param list chain: List of `crypto.X509` (or wrapped in
        :class:`josepy.util.ComparableX509`).

    )r.   Údump_pyopenssl_chain)rT   Zfiletyper)   r)   r*   r   �  s    	r   c                 C   s   t | tjjƒS )zÕWhen does the cert at cert_path start being valid?

    :param str cert_path: path to a cert in PEM format

    :returns: the notBefore value from the cert at cert_path
    :rtype: :class:`datetime.datetime`

    )Ú_notAfterBeforer   ÚX509Zget_notBefore©rj   r)   r)   r*   Ú	notBefore›  s    	rƒ   c                 C   s   t | tjjƒS )zÓWhen does the cert at cert_path stop being valid?

    :param str cert_path: path to a cert in PEM format

    :returns: the notAfter value from the cert at cert_path
    :rtype: :class:`datetime.datetime`

    )r€   r   r�   Zget_notAfterr‚   r)   r)   r*   ÚnotAfter§  s    	r„   c                 C   sœ   t | ƒ�}t tj| ¡ ¡}W 5 Q R X ||ƒ}|dd… d|dd… d|dd… d|dd… d|dd	… d|d	d
… g}d |¡}tjr’| d¡}t	 
|¡S )aP  Internal helper function for finding notbefore/notafter.

    :param str cert_path: path to a cert in PEM format
    :param function method: one of ``crypto.X509.get_notBefore``
        or ``crypto.X509.get_notAfter``

    :returns: the notBefore or notAfter value from the cert at cert_path
    :rtype: :class:`datetime.datetime`

    r   é   ó   -é   é   ó   Té
   ó   :é   Nó    Úascii)rS   r   rr   r4   rU   r"   ÚsixÚPY3ÚdecodeÚ	pyrfc3339Úparse)rj   ÚmethodÚfr   Ú	timestampZreformatted_timestampZtimestamp_strr)   r)   r*   r€   ³  s$    
ÿ
  
 
  
þ

r€   c              	   C   s:   t  ¡ }t| dƒ�}| | ¡  d¡¡ W 5 Q R X | ¡ S )aN  Compute a sha256sum of a file.

    NB: In given file, platform specific newlines characters will be converted
    into their equivalent unicode counterparts before calculating the hash.

    :param str filename: path to the file whose hash will be computed

    :returns: sha256 digest of the file in hexadecimal
    :rtype: str
    ÚrzUTF-8)ÚhashlibÚsha256rS   rg   rU   ÚencodeÚ	hexdigest)Úfilenamer™   Zfile_dr)   r)   r*   Ú	sha256sumÏ  s    r�   c                 C   s8   t  t jt  t j| ¡¡ ¡ }| t|ƒd…  ¡ }||fS )z¶Split fullchain_pem into cert_pem and chain_pem

    :param str fullchain_pem: concatenated cert + chain

    :returns: tuple of string cert_pem and chain_pem
    :rtype: tuple

    N)r   Zdump_certificater4   rr   r‘   ÚlenÚlstrip)Zfullchain_pemrO   rT   r)   r)   r*   Úcert_and_chain_from_fullchainß  s
    	ÿr    )r   )@Ú__doc__r˜   ÚloggingrW   r’   r�   Zzope.componentr   ZOpenSSLr   r   Zcryptographyr   Zcryptography.exceptionsr   Zcryptography.hazmat.backendsr   Z,cryptography.hazmat.primitives.asymmetric.ecr   r   Z1cryptography.hazmat.primitives.asymmetric.paddingr	   Z-cryptography.hazmat.primitives.asymmetric.rsar
   Zacmer   r.   Zacme.magic_typingr   Zcertbotr   r   r   Zcertbot.compatr   Ú	getLoggerÚ__name__r   r+   r2   r9   r<   rE   r   rK   rQ   rL   rY   rN   rM   ru   r4   ry   rz   r{   r}   rB   r~   r   rƒ   r„   r€   r�   r    r)   r)   r)   r*   Ú<module>   sb   

$#ÿ

ÿ
