a ‚oe `ã @s dZddlZddlZddlZddlZddlmZddlmZddlmZddlm Z ddlm Z ddlm Z dd lm Z dd l mZdd lmZdd lmZdd lmZddlmZddlmZddlmZddlmZddlmZddlmZddlm Z ddl!m"Z"ddl!m#Z#ddl!m$Z$ddl%Z%ddl&m'Z'ddl&m(Z(ddl)Z)ddl*m+Z,ddl-m.Z.ddl-m/Z/ddl-m0Z0ddl1m2Z2e �rºddl3m4Z4dd l5m6Z6dd!l7m8Z8dd"l9m:Z:e ;e<¡Z=d|e>ee?e?e?e?e@e0jAd'œd(d)„ZBd}e0jAe ee?e e?fee?e@e@e0jCd+œd,d-„ZDeEe@d.œd/d0„ZFeEeEe@d1œd2d3„ZGe?eEe e>e0jCee?fd4œd5d6„ZHd~e>e?ee?eEd8œd9d:„ZIe e?eEfe@d;œdœd?d@„ZLe/jKdd>œdAdB„ZMe edCdDee dEdFfeEeEejNddGœdHdI„ZOe?e?ddJœdKdL„ZPe/jKdd>œdMdN„ZQeEe e'jRe>fdOœdPdQ„ZSe'jTfeEee>eEge e'jRe'jUffe>e e'jRe'jUfdRœdSdT„ZVe'jTfeEee>eEge e'jRe'jUffe>ee?dRœdUdV„ZWe'jTfeEe>ee?dWœdXdY„ZXeEee>eEge e'jRe'jUffe>ee?dZœd[d\„ZYe e'jRe'jUfee?d]œd^d_„ZZe'jTfeEe>ee?dWœd`da„Z[e'jTfeEe>ee?dbœdcdd„Z\e'jTfe ee'jRee%j]fe>eEdeœdfdg„Z^e?ejdhœdidj„Z_e?ejdhœdkdl„Z`e?ee'jRgeeEfejdmœdndo„Zae?e?dpœdqdr„Zbe cdsejd¡Zee?e e?e?fdtœdudv„Zfe?e>dhœdwdx„Zgdee?e?e@e?dyœdzd{„ZhdS)€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)Ú X448PublicKey)ÚX25519PublicKeyÚrsaÚ secp256r1úkey-certbot.pemT)Úkey_sizeÚkey_dirÚkey_typeÚelliptic_curveÚkeynameÚstrict_permissionsÚreturnc Csðzt||p d|d�}WnFty\}z.tjddd�t dt|ƒ¡|‚WYd}~n d}~00d}|rät |d|¡t t j   ||¡d d ¡\} }| �|   |¡Wdƒn1s´0Y|d krÖt d ||¡nt 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: key size in bits if key size is rsa. :param str key_dir: Optional 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ÚerrÚkey_pathZkey_f©r?ú4C:\Program Files\Certbot\pkgs\certbot\crypto_util.pyÚ generate_key8s( ÿ ÿ(rAF)ÚprivkeyÚnamesr9Ú must_stapler*r+cCsŒtj|j||d�}d}|r~t |d|¡t tj |d¡dd¡\}}|�|  |¡Wdƒn1sh0Yt   d|¡t  ||d¡S) aCInitialize 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: Optional 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` )rDNiízcsr-certbot.pemi¤r0zCreating CSR: %sÚpem) Úacme_crypto_utilZmake_csrrErr7r8rr9r:r;r3r4ÚCSR)rBrCr9rDr*Zcsr_pemZ csr_filenameZcsr_fr?r?r@Ú generate_csrisÿÿ( rH)Úcsrr+cCsHzt tj|¡}| | ¡¡WStjyBtjddd�YdS0dS)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-Tr.FN)rÚload_certificate_requestÚ FILETYPE_PEMÚverifyZ get_pubkeyÚErrorr3r4)rIÚreqr?r?r@Ú valid_csrŽs ÿrO)rIrBr+cCsRt tj|¡}t tj|¡}z | |¡WStjyLtjddd�YdS0dS)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-Tr.FN)rrJrKÚload_privatekeyrLrMr3r4)rIrBrNZpkeyr?r?r@Úcsr_matches_pubkey¢s ÿ rQ)ÚcsrfileÚdatar+c Cs�tj}tj}z|tj|ƒ}WnHtjydz|||ƒ}Wn$tjy^t d |¡¡‚Yn0Yn0t|ƒ}t ||¡}|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}rE)ÚfilerSZform) rrKrJÚ FILETYPE_ASN1rMrÚformatÚ"_get_names_from_loaded_cert_or_reqZdump_certificate_requestrrG)rRrSÚPEMÚloadrIZdomainsZdata_pemr?r?r@Úimport_csr_file¶s  rZé)r,r'r(r+c CsD|dkr8|dkr t d |¡¡‚t ¡}| tj|¡nþ|dk�r&|sPt d¡‚zZ| ¡}|dvr˜tt | ¡ƒ}|s„t d|›�¡‚t j |ƒt ƒd�}nt d  |¡¡‚WnTt yÌt d  |¡¡‚Yn4t yþ}z|t t|ƒ¡‚WYd }~n d }~00|jtjtjtƒd �}t tj|¡}nt d  |¡¡‚t tj|¡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"r[zUnsupported RSA key length: {}Zecdsaz3When key_type == ecdsa, elliptic_curve must be set.)Z SECP256R1Z SECP384R1Z SECP521R1zInvalid curve type: )ÚcurveZbackendzUnsupported elliptic curve: {}N)ÚencodingrVZencryption_algorithmz0Invalid key_type specified: {}. Use [rsa|ecdsa])rrMrVrZPKeyrAZTYPE_RSAÚupperÚgetattrrZgenerate_private_keyr Ú TypeErrorr r6Z private_bytesrrXrZTraditionalOpenSSLrrPrKZdump_privatekey) r,r'r(ÚkeyÚnamer\Z_keyÚeZ_key_pemr?r?r@r1Ós>   þ &ýr1)rBr+c Cs4zt tj|¡ ¡WSttjfy.YdS0dS)zŽIs valid RSA private key? :param privkey: Private key file contents in PEM :returns: Validity of private key. :rtype: bool FN)rrPrKÚcheckr`rM)rBr?r?r@Ú valid_privkeys ÿ re)Ú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>)rfr?r?r@Úverify_renewable_certs rkc Csøz¦t|jdƒ�"}t | ¡tƒ¡}Wdƒn1s60Yt|jdƒ�"}t | ¡tƒ¡}Wdƒn1st0Y| ¡}|js�J‚t ||j |j |jƒWnLt t tfyò}z.d |j|¡}t |¡t |¡‚WYd}~n d}~00dS)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Úreadr rjÚ public_keyÚsignature_hash_algorithmÚverify_signed_payloadÚ signatureZtbs_certificate_bytesÚIOErrorr2r rVr3Ú exceptionrrM)rfÚ chain_fileÚchainÚ cert_fileÚcertZpkrcÚ error_strr?r?r@rg%s 00  ÿÿ rgrrr!r )rqrtÚpayloadrrr+cCsJt|tƒr| ||tƒ|¡n(t|tƒr<| ||t|ƒ¡n t d¡‚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)Ú isinstancerrLrrrrrM)rqrtr|rrr?r?r@rs=s  ÿ  ÿrs)rjr>r+c Cs~z,t tj¡}| |¡| |¡| ¡WnLttjfyx}z.d |||¡}t   |¡t  |¡‚WYd}~n d}~00dS)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_privatekeyrurMrVr3rvr)rjr>Úcontextrcr{r?r?r@riXs    ý ric Cs4zÀt|jƒ�}| ¡}Wdƒn1s*0Yt|jƒ�}| ¡}Wdƒn1s\0Yt|jƒ�}| ¡}Wdƒn1sŽ0Y|||kr¾d}| |j¡}t |¡‚Wnnt �y}z*d |¡}t   |¡t |¡‚WYd}~n4d}~0tj�y.}z|‚WYd}~n d}~00dS)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}) rmrnrprjZfullchain_pathrVZ lineagenamerrMrur3rv) rfrwrxryrzZfullchain_fileZ fullchainr{rcr?r?r@rhns" & & &    rh)rSr+c Cs‚g}tjtjfD]L}zt ||¡|fWStjyZ}z| |¡WYd}~qd}~00qt d d dd„|Dƒ¡¡¡‚dS)z:Load PEM/DER certificate. :raises errors.Error: NzUnable to load: {0}ú,css|]}t|ƒVqdS©N)r6)Ú.0r5r?r?r@Ú —sz-pyopenssl_load_certificate..) rrKrUÚload_certificaterMÚappendrrVr:)rSZopenssl_errorsZ file_typer5r?r?r@Úpyopenssl_load_certificate‰s"ÿr…)Úcert_or_req_strÚ load_funcÚtypr+c CsXz |||ƒWStjyR}z,tjddd�t dt|ƒ¡‚WYd}~n d}~00dS)Nr-Tr.z6Encountered error while loading certificate or csr: %s)rrMr3r4r5r6)r†r‡rˆr=r?r?r@Ú_load_cert_or_req›s  r‰cCst t|||ƒ¡Sr€)rFZ_pyopenssl_cert_or_req_sanr‰)r†r‡rˆr?r?r@Ú_get_sans_from_cert_or_req¦sÿrŠ)rzrˆ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ƒ©rzrˆr?r?r@Úget_sans_from_cert¯s ÿrŒ)Ú cert_or_reqr‡rˆr+cCst|||ƒ}t|ƒSr€)r‰rW)r�r‡rˆÚloaded_cert_or_reqr?r?r@Ú_get_names_from_cert_or_req½s r�)rŽr+cCs t |¡Sr€)rFZ _pyopenssl_cert_or_req_all_names)rŽr?r?r@rWÅsrWcCst|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@Úget_names_from_certËs ÿr�)rIrˆ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�rrJ)rIrˆr?r?r@Úget_names_from_reqÙs r‘)rxÚfiletyper+cCs t ||¡S)z–Dump certificate chain into a bundle. :param list chain: List of `crypto.X509` (or wrapped in :class:`josepy.util.ComparableX509`). )rFÚdump_pyopenssl_chain)rxr’r?r?r@r“ås r“)rjr+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©rjr?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•Z get_notAfterr–r?r?r@ÚnotAfterþs r˜)rjÚmethodr+c Csºt|dƒ�"}t tj| ¡¡}Wdƒn1s20Y||ƒ}|sRt d¡‚|dd…d|dd…d|dd…d |dd …d |d d …d |d d…g }d  |¡}| d¡}t   |¡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` rlNz>Error while invoking timestamp method, None has been returned.réó-ééóTé ó:é óÚascii) rmrrƒrKrprrMr:ÚdecodeÚ pyrfc3339Úparse)rjr™Úfr Z timestampZreformatted_timestampZtimestamp_bytesZ timestamp_strr?r?r@r” s 0 þ  r”)Úfilenamer+cCsNt ¡}t|dƒ�$}| | ¡ d¡¡Wdƒn1s<0Y| ¡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Úsha256rmÚupdaterpÚencodeZ hexdigest)r¨r«Zfile_dr?r?r@Ú sha256sum&s  2r®s@-----BEGIN CERTIFICATE----- ? .+? ? -----END CERTIFICATE----- ? )Ú fullchain_pemr+cCsLt | ¡¡}t|ƒdkr$t d¡‚dd„|Dƒ}|dd |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. ézPfailed to parse fullchain into cert and chain: less than 2 certificates in chainc Ss(g|] }t tjt tj|¡¡ ¡‘qSr?)rZdump_certificaterKrƒr¤)r�rzr?r?r@Ú Vsÿ ÿz1cert_and_chain_from_fullchain..rr-éN)ÚCERT_PEM_REGEXÚfindallr­ÚlenrrMr:)r¯ÚcertsZcerts_normalizedr?r?r@Úcert_and_chain_from_fullchainAs  ÿr·cCsDt|dƒ�"}t tj| ¡¡}Wdƒn1s20Y| ¡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 rlN)rmrrƒrKrpZget_serial_number)rjr§r r?r?r@Úget_serial_from_cert]s 0r¸)Ú fullchainsÚ issuer_cnÚwarn_on_no_matchr+cCsl|D]N}t | ¡¡}t |dtƒ¡}|j tjj ¡}|r|dj |kr|Sq|rdt   d|¡|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` éÿÿÿÿ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 ror ZissuerZget_attributes_for_oidZNameOIDZ COMMON_NAMEÚvaluer3Zwarning)r¹rºr»rxr¶Ztop_certZ top_issuer_cnr?r?r@Úfind_chain_with_issuerks þr¾)r"r#r$T)FT)r[r"N)F)iÚ__doc__ZdatetimerªZloggingÚreÚtypingrrrrrrrZ cryptographyr Zcryptography.exceptionsr r Zcryptography.hazmat.backendsr Zcryptography.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¥ZacmerrFZcertbotrrrZcertbot.compatrZ/cryptography.hazmat.primitives.asymmetric.ed448rZ1cryptography.hazmat.primitives.asymmetric.ed25519rZ.cryptography.hazmat.primitives.asymmetric.x448r Z0cryptography.hazmat.primitives.asymmetric.x25519r!Z getLoggerÚ__name__r3Úintr6Úboolr<rArGrHÚbytesrOrQrZr1reZ RenewableCertrkrgZ HashAlgorithmrsrirhr•r…rKZX509Reqr‰rŠrŒr�rWr�r‘ZComparableX509r“r—r˜r”r®ÚcompileÚDOTALLr³r·r¸r¾r?r?r?r@Úsè                                 þ þ 2ÿÿ %"ÿÿ 0þü þþ ýÿý ÿý ÿ  ÿÿ   ÿ û ÿ ÿ