????
Your IP : 3.145.196.175
3
گa�g� @s&dZddlZddlZddlZddlZddlmZddlmZddlmZddlm Z ddlm
Z
ddlmZdd lmZddl
Z
dd
lmZddlmZddlmZdd
lmZddlmZddlmZddlmZddlmZddlmZddlmZddl m!Z!ddl"m#Z#ddl"m$Z$ddl"m%Z%ddl&Z&ddl'm(Z(ddl'm)Z)ddl*Z*ddl+Z,ddl-m.Z/ddl0m1Z1ddl0m2Z2ddl0m3Z3ddl4m5Z5e�r�ddl6m7Z7dd l8m9Z9ej:e;�Z<d~e=e>e>e>e>e?e3j@d%�d&d'�ZAde=e>e>e>e>e3j@d(�d)d*�ZBd�e3j@eee>e e>fe>e?e?e3jCd,�d-d.�ZDe3j@e e>e>e3jCd/�d0d1�ZEeFe?d2�d3d4�ZGeFeFe?d5�d6d7�ZHe>eFe
e=e3jCee>fd8�d9d:�ZId�e=e>ee>eFd<�d=d>�ZJe>e?d?�d@dA�ZKe2jLddB�dCdD�ZMe2jLddB�dEdF�ZNeedGdHee!feFeFejOddI�dJdK�ZPe>e>ddL�dMdN�ZQe2jLddB�dOdP�ZReFe
e(jSe=fdQ�dRdS�ZTe(jUfeFee=eFgee(jSe(jVffe=ee(jSe(jVfdT�dUdV�ZWe(jUfeFee=eFgee(jSe(jVffe=ee>dT�dWdX�ZXe(jUfeFe=ee>dY�dZd[�ZYeFee=eFgee(jSe(jVffe=ee>d\�d]d^�ZZee(jSe(jVfee>d_�d`da�Z[e(jUfeFe=ee>dY�dbdc�Z\e(jUfeFe=ee>dd�dedf�Z]e(jUfeee(jSee&j^fe=eFdg�dhdi�Z_e>ejdj�dkdl�Z`e>ejdj�dmdn�Zae>ee(jSgeeFfejdo�dpdq�Zbe>e>dr�dsdt�Zcejddueje�Zfe>e
e>e>fdv�dwdx�Zge>e=dj�dydz�Zhd�ee>e>e?e>d{�d|d}�ZidS)�z�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)�Callable)�List)�Optional)�Set)�Tuple)�
TYPE_CHECKING)�Union)�x509)�InvalidSignature)�UnsupportedAlgorithm)�default_backend)�hashes)�ec)�DSAPublicKey)�ECDSA)�EllipticCurvePublicKey)�PKCS1v15)�RSAPublicKey)�Encoding)�NoEncryption)�
PrivateFormat)�crypto)�SSL)�crypto_util)�errors)�
interfaces)�util)�os)�Ed448PublicKey)�Ed25519PublicKey�rsa� secp256r1�key-certbot.pemT)�key_size�key_dir�key_type�elliptic_curve�keyname�strict_permissions�returnc
Cs�yt||pd|d�}WnDtk
rZ}z(tjddd�tjdt|��|�WYdd}~XnXtj|d|�tjt j
j||�d d
�\}} |�|j|�WdQRX|dkr�tjd|| �ntjd
|| �tj
| |�S)aInitializes 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: key size in bits if key size is rsa.
:param str key_dir: Key save directory.
:param str key_type: Key Type [rsa, ecdsa]
:param str elliptic_curve: Name of the elliptic curve if key type is ecdsa.
:param str keyname: Filename of key
:param bool strict_permissions: If true and key_dir exists, an exception is raised if
the directory doesn't have 0700 permissions or isn't owned by the current user.
:returns: Key
:rtype: :class:`certbot.util.Key`
:raises ValueError: If unable to generate the key given key_size.
r!)�bitsr&r%�T)�exc_infoz&Encountered error while making key: %sNi�i��wbr z Generating RSA key (%d bits): %sz"Generating ECDSA key (%d bits): %s)�make_key�
ValueError�logger�debug�error�strr�make_or_verify_dir�unique_filer�path�join�write�Key)
r#r$r%r&r'r(Zkey_pem�errZkey_f�key_path�r<�!/usr/lib/python3.6/crypto_util.py�generate_key8s r>)r#r$r%r&r'r)cCs0tjdt�tjjtj�}t||||||j d�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.
.. deprecated:: 1.16.0
Use :func:`generate_key` instead.
:param int key_size: key size in bits if key size is rsa.
:param str key_dir: Key save directory.
:param str key_type: Key Type [rsa, ecdsa]
:param str elliptic_curve: Name of the elliptic curve if key type is ecdsa.
:param str keyname: Filename of key
:returns: Key
:rtype: :class:`certbot.util.Key`
:raises ValueError: If unable to generate the key given key_size.
zecertbot.crypto_util.init_save_key is deprecated, please use certbot.crypto_util.generate_key instead.)r%r&r'r()
�warnings�warn�DeprecationWarning�zope� component�
getUtilityr�IConfigr>r()r#r$r%r&r'�configr<r<r=�
init_save_keyhs
rGF)�privkey�namesr6�must_stapler(r)cCsptj|j||d�}tj|d|�tjtjj|d�dd�\}}|�|j |�WdQRXt
jd|�tj||d�S) a: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.
:param bool must_staple: If true, include the TLS Feature extension "OCSP Must Staple"
:param bool strict_permissions: If true and path exists, an exception is raised if
the directory doesn't have 0755 permissions or isn't owned by the current user.
:returns: CSR
:rtype: :class:`certbot.util.CSR`
)rJi�zcsr-certbot.pemi�r-NzCreating CSR: %s�pem)
�acme_crypto_utilZmake_csrrKrr4r5rr6r7r8r0r1�CSR)rHrIr6rJr(Zcsr_pemZcsr_fZcsr_filenamer<r<r=�generate_csr�srN)rHrIr6r)cCs0tjdt�tjjtj�}t||||j |j
d�S)awInitialize a CSR with the given private key.
.. deprecated:: 1.16.0
Use :func:`generate_csr` instead.
: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`
zecertbot.crypto_util.init_save_csr is deprecated, please use certbot.crypto_util.generate_csr instead.)rJr()r?r@rArBrCrDrrErNrJr()rHrIr6rFr<r<r=�
init_save_csr�s
rO)�csrr)cCsFytjtj|�}|j|j��Stjk
r@tjddd�dSXdS)z�Validate CSR.
Check if `csr` is a valid CSR for the given domains.
:param bytes csr: CSR in PEM.
:returns: Validity of CSR.
:rtype: bool
r+T)r,FN)r�load_certificate_request�FILETYPE_PEM�verifyZ
get_pubkey�Errorr0r1)rP�reqr<r<r=� valid_csr�s
rV)rPrHr)cCsPtjtj|�}tjtj|�}y
|j|�Stjk
rJtjddd�dSXdS)z�Does private key correspond to the subject public key in the CSR?
:param bytes csr: CSR in PEM.
:param bytes privkey: Private key file contents (PEM)
:returns: Correspondence of private key to CSR subject public key.
:rtype: bool
r+T)r,FN)rrQrR�load_privatekeyrSrTr0r1)rPrHrUZpkeyr<r<r=�csr_matches_pubkey�s
rX)�csrfile�datar)cCs�tj}tj}y|tj|�}WnLtjk
rhy|||�}Wn&tjk
rbtjdj|���YnXYnXt|�}tj||�}|t j
||dd�|fS)a1Import a CSR file, which can be either PEM or DER.
:param str csrfile: CSR filename
:param bytes 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
zFailed to parse CSR file: {0}rK)�filerZZform)rrRrQ�
FILETYPE_ASN1rTr�format�"_get_names_from_loaded_cert_or_reqZdump_certificate_requestrrM)rYrZ�PEM�loadrPZdomainsZdata_pemr<r<r=�import_csr_file�sra�)r*r%r&r)cCs.|dkr8|dkr tjdj|���tj�}|jtj|�n�|dk�r|sPtjd��yD|j�}|dkr�tj t
t|j�d ��t�d
�}ntjdj|���WnTtk
r�tjdj|���Yn2t
k
r�}z|tjt|���WYd d }~XnX|jtjtjt�d�}tjtj|�}ntjd
j|���tjtj|�S)a�Generate PEM encoded RSA|EC key.
:param int bits: Number of bits if key_type=rsa. At least 1024 for RSA.
:param str key_type: The type of key to generate, but be rsa or ecdsa
:param str elliptic_curve: The elliptic curve to use.
:returns: new RSA or ECDSA key in PEM form with specified number of bits
or of type ec_curve when key_type ecdsa is used.
:rtype: str
r izUnsupported RSA key length: {}Zecdsaz3When key_type == ecdsa, elliptic_curve must be set.� SECP256R1� SECP384R1� SECP521R1N)ZcurveZbackendzUnsupported elliptic curve: {})�encodingr]Zencryption_algorithmz0Invalid key_type specified: {}. Use [rsa|ecdsa])rcrdre)rrTr]rZPKeyr>ZTYPE_RSA�upperrZgenerate_private_key�getattrr� TypeErrorrr3Z
private_bytesrr_rZTraditionalOpenSSLrrWrRZdump_privatekey)r*r%r&�key�nameZ_key�eZ_key_pemr<r<r=r.
s4
"
r.)rHr)cCs2ytjtj|�j�Sttjfk
r,dSXdS)z�Is valid RSA private key?
:param str privkey: Private key file contents in PEM
:returns: Validity of private key.
:rtype: bool
FN)rrWrRZcheckrirT)rHr<r<r=�
valid_privkey>s
rm)�renewable_certr)cCs"t|�t|�t|j|j�dS)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 renewable_cert: cert to verify
:type renewable_cert: certbot.interfaces.RenewableCert
:raises errors.Error: If verification fails.
N)�verify_renewable_cert_sig�verify_fullchain�verify_cert_matches_priv_key� cert_pathr;)rnr<r<r=�verify_renewable_certNs
rscCs�ytt|jd��}tj|j�t��}WdQRXt|jd��}tj|j�t��}WdQRX|j�}t||j |j
|j�WnJtt
tfk
r�}z(dj|j|�}tj|�tj|��WYdd}~XnXdS)z�Verifies the signature of a RenewableCert object.
:param renewable_cert: cert to verify
:type renewable_cert: certbot.interfaces.RenewableCert
:raises errors.Error: If signature verification fails.
�rbNzbverifying the signature of the certificate located at {0} has failed. Details: {1})�open�
chain_pathr �load_pem_x509_certificate�readrrr�
public_key�verify_signed_payload� signatureZtbs_certificate_bytes�signature_hash_algorithm�IOErrorr/r
r]r0� exceptionrrT)rn�
chain_file�chain� cert_file�certZpkrl� error_strr<r<r=ro`s
rorr)ryr{�payloadr|r)cCsJt|t�r|j||t�|�n(t|t�r<|j||t|��n
tjd��dS)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 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
zUnsupported public key type.N)�
isinstancerrSrrrrrT)ryr{r�r|r<r<r=rzws
rz)rrr;r)cCs|y,tjtj�}|j|�|j|�|j�WnJttjfk
rv}z(dj|||�}t j
|�tj|��WYdd}~XnXdS)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 certificate located at {0} matches the private key located at {1} has failed. Details: {2}N)rZContextZ
SSLv23_METHODZuse_certificate_fileZuse_privatekey_fileZcheck_privatekeyr}rTr]r0r~r)rrr;�contextrlr�r<r<r=rq�s
rqc Cs�y�t|j��}|j�}WdQRXt|j��}|j�}WdQRXt|j��}|j�}WdQRX|||kr�d}|j|j�}tj|��Wnft k
r�}z$dj|�}t
j|�tj|��WYdd}~Xn(tjk
r�}z
|�WYdd}~XnXdS)z� Verifies that fullchain is indeed cert concatenated with chain.
:param renewable_cert: cert to verify
:type renewable_cert: certbot.interfaces.RenewableCert
:raises errors.Error: If cert and chain do not combine to fullchain.
Nz.fullchain does not match cert + chain for {0}!z8reading one of cert, chain, or fullchain has failed: {0})rurvrxrrZfullchain_pathr]ZlineagenamerrTr}r0r~) rnrr�r�r�Zfullchain_fileZ fullchainr�rlr<r<r=rp�s"
rp)rZr)cCs~g}xTtjtjfD]D}ytj||�|fStjk
rT}z|j|�WYdd}~XqXqWtjdjdjdd�|D�����dS)z:Load PEM/DER certificate.
:raises errors.Error:
NzUnable to load: {0}�,css|]}t|�VqdS)N)r3)�.0r2r<r<r=� <genexpr>�sz-pyopenssl_load_certificate.<locals>.<genexpr>) rrRr\�load_certificaterT�appendrr]r7)rZZopenssl_errorsZ file_typer2r<r<r=�pyopenssl_load_certificate�s r�)�cert_or_req_str� load_func�typr)cCsTy
|||�Stjk
rN}z&tjddd�tjdt|���WYdd}~XnXdS)Nr+T)r,z6Encountered error while loading certificate or csr: %s)rrTr0r1r2r3)r�r�r�r:r<r<r=�_load_cert_or_req�s
r�cCstjt|||��S)N)rLZ_pyopenssl_cert_or_req_sanr�)r�r�r�r<r<r=�_get_sans_from_cert_or_req�sr�)r�r�r)cCst|tj|�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
)r�rr�)r�r�r<r<r=�get_sans_from_cert�s
r�)�cert_or_reqr�r�r)cCst|||�}t|�S)N)r�r^)r�r�r��loaded_cert_or_reqr<r<r=�_get_names_from_cert_or_req�sr�)r�r)cCs
tj|�S)N)rLZ _pyopenssl_cert_or_req_all_names)r�r<r<r=r^�sr^cCst|tj|�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�rr�)r�r�r<r<r=�get_names_from_certs
r�)rPr�r)cCst|tj|�S)z�Get a list of domains from a CSR, including the CN if it is set.
:param str csr: CSR (encoded).
:param typ: `crypto.FILETYPE_PEM` or `crypto.FILETYPE_ASN1`
:returns: A list of domain names.
:rtype: list
)r�rrQ)rPr�r<r<r=�get_names_from_reqs r�)r��filetyper)cCstj||�S)z�Dump certificate chain into a bundle.
:param list chain: List of `crypto.X509` (or wrapped in
:class:`josepy.util.ComparableX509`).
)rL�dump_pyopenssl_chain)r�r�r<r<r=r�s
r�)rrr)cCst|tjj�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)rrr<r<r=� notBefore+s r�cCst|tjj�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�rr�Zget_notAfter)rrr<r<r=�notAfter7s r�)rr�methodr)cCs�t|d��}tjtj|j��}WdQRX||�}|s>tjd��|dd�d|dd�d|dd�d |dd
�d|d
d�d|dd�g}d
j|�}|jd�}t j
|�S)aPInternal 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`
rtNz>Error while invoking timestamp method, None has been returned.r��-���T�
�:���ascii)rurr�rRrxrrTr7�decode� pyrfc3339�parse)rrr��fr Z timestampZreformatted_timestampZtimestamp_bytesZ
timestamp_strr<r<r=r�Cs
r�)�filenamer)c
Cs:tj�}t|d��}|j|j�jd��WdQRX|j�S)aNCompute 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
�rzUTF-8N)�hashlib�sha256ru�updaterx�encodeZ hexdigest)r�r�Zfile_dr<r<r=� sha256sum_sr�s@-----BEGIN CERTIFICATE-----
?
.+?
?
-----END CERTIFICATE-----
?
)�
fullchain_pemr)cCsLtj|j��}t|�dkr$tjd
��dd�|D�}|ddj|dd ��fS)aSplit 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
:raises errors.Error: If there are less than 2 certificates in the chain.
�z/failed to parse fullchain into cert and chain: z!less than 2 certificates in chaincSs(g|] }tjtjtjtj|��j��qSr<)rZdump_certificaterRr�r�)r�r�r<r<r=�
<listcomp>�sz1cert_and_chain_from_fullchain.<locals>.<listcomp>rr+�NzPfailed to parse fullchain into cert and chain: less than 2 certificates in chain)�CERT_PEM_REGEX�findallr��lenrrTr7)r��certsZcerts_normalizedr<r<r=�cert_and_chain_from_fullchainzsr�c
Cs0t|d��}tjtj|j��}WdQRX|j�S)z�Retrieve the serial number of a certificate from certificate path
:param str cert_path: path to a cert in PEM format
:returns: serial number of the certificate
:rtype: int
rtN)rurr�rRrxZget_serial_number)rrr�r r<r<r=�get_serial_from_cert�s r�)�
fullchains� issuer_cn�warn_on_no_matchr)cCslxR|D]J}tj|j��}tj|dt��}|jjtjj �}|r|dj
|kr|SqW|rdtjd|�|dS)a'Chooses the first certificate chain from fullchains whose topmost
intermediate has an Issuer Common Name matching issuer_cn (in other words
the first chain which chains to a root whose name matches issuer_cn).
:param fullchains: The list of fullchains in PEM chain format.
:type fullchains: `list` of `str`
:param `str` issuer_cn: The exact Subject Common Name to match against any
issuer in the certificate chain.
:returns: The best-matching fullchain, PEM-encoded, or the first if none match.
:rtype: `str`
r�rz�Certbot has been configured to prefer certificate chains with issuer '%s', but no chain from the CA matched this issuer. Using the default certificate chain instead.���)
r�r�r�r rwrZissuerZget_attributes_for_oidZNameOIDZCOMMON_NAME�valuer0Zwarning)r�r�r�r�r�Ztop_certZ
top_issuer_cnr<r<r=�find_chain_with_issuer�s
r�)r r!r"T)r r!r")FT)rbr N)F)j�__doc__Zdatetimer�Zlogging�reZtypingrrrrrrrr?Zcryptographyr Zcryptography.exceptionsr
rZcryptography.hazmat.backendsrZcryptography.hazmat.primitivesr
Z)cryptography.hazmat.primitives.asymmetricrZ-cryptography.hazmat.primitives.asymmetric.dsarZ,cryptography.hazmat.primitives.asymmetric.ecrrZ1cryptography.hazmat.primitives.asymmetric.paddingrZ-cryptography.hazmat.primitives.asymmetric.rsarZ,cryptography.hazmat.primitives.serializationrrrZjosepyZOpenSSLrrr�Zzope.componentrBZacmerrLZcertbotrrrZcertbot.compatrZ/cryptography.hazmat.primitives.asymmetric.ed448rZ1cryptography.hazmat.primitives.asymmetric.ed25519rZ getLogger�__name__r0�intr3�boolr9r>rGrMrNrO�bytesrVrXrar.rmZ
RenewableCertrsroZ
HashAlgorithmrzrqrpr�r�rRZX509Reqr�r�r�r�r^r�r�ZComparableX509r�r�r�r�r��compile�DOTALLr�r�r�r�r<r<r<r=�<module>s�
.!."0>6
,"