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 rddl3m4Z4dd 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/d0ZFeEeEe@d1d2d3ZGe?eEe e>e0jCee?fd4d5d6ZHd~e>e?ee?eEd8d9d:ZIe e?eEfe@d;dd?d@ZLe/jKdd>dAdBZMe edCdDee dEdFfeEeEejNddGdHdIZOe?e?ddJdKdLZPe/jKdd>dMdNZQeEe e'jRe>fdOdPdQZSe'jTfeEee>eEge e'jRe'jUffe>e e'jRe'jUfdRdSdTZVe'jTfeEee>eEge e'jRe'jUffe>ee?dRdUdVZWe'jTfeEe>ee?dWdXdYZXeEee>eEge e'jRe'jUffe>ee?dZd[d\ZYe e'jRe'jUfee?d]d^d_ZZe'jTfeEe>ee?dWd`daZ[e'jTfeEe>ee?dbdcddZ\e'jTfe ee'jRee%j]fe>eEdedfdgZ^e?ejdhdidjZ_e?ejdhdkdlZ`e?ee'jRgeeEfejdmdndoZae?e?dpdqdrZbecdsejdZee?e e?e?fdtdudvZfe?e>dhdwdxZgdee?e?e@e?dydzd{ZhdS)zCertbot 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)X25519PublicKeyrsa secp256r1key-certbot.pemT)key_sizekey_dirkey_typeelliptic_curvekeynamestrict_permissionsreturnc Cszt||p d|d}WnFty\}z.tjdddtdt||WYd}~n d}~00d}|rt|d|tt j ||d d \} }| | |Wdn1s0Y|d krtd ||ntd ||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'Texc_infoz&Encountered error while making key: %sNiiwbr"z Generating RSA key (%d bits): %sz"Generating ECDSA key (%d bits): %s)make_key ValueErrorloggerdebugerrorstrrmake_or_verify_dir unique_filerpathjoinwriteKey) r%r&r'r(r)r*Zkey_pemerrkey_pathZkey_fr?4C:\Program Files\Certbot\pkgs\certbot\crypto_util.py generate_key8s( (rAF)privkeynamesr9 must_stapler*r+cCstj|j||d}d}|r~t|d|ttj|ddd\}}|| |Wdn1sh0Yt d|t ||dS) 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` )rDNizcsr-certbot.pemir0zCreating CSR: %spem) acme_crypto_utilZmake_csrrErr7r8rr9r:r;r3r4CSR)rBrCr9rDr*Zcsr_pemZ csr_filenameZcsr_fr?r?r@ generate_csris( rH)csrr+cCsHzttj|}||WStjyBtjdddYdS0dS)zValidate 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)rload_certificate_request FILETYPE_PEMverifyZ get_pubkeyErrorr3r4)rIreqr?r?r@ valid_csrs rO)rIrBr+cCsRttj|}ttj|}z ||WStjyLtjdddYdS0dS)zDoes 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)rrJrKload_privatekeyrLrMr3r4)rIrBrNZpkeyr?r?r@csr_matches_pubkeys  rQ)csrfiledatar+c Cstj}tj}z|tj|}WnHtjydz|||}Wn$tjy^td|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_ASN1rMrformat"_get_names_from_loaded_cert_or_reqZdump_certificate_requestrrG)rRrSPEMloadrIZdomainsZdata_pemr?r?r@import_csr_files  rZ)r,r'r(r+c CsD|dkr8|dkr td|t}|tj|n|dkr&|sPtdzZ|}|dvrtt |}|std|t j |t d}ntd |WnTt ytd |Yn4t y}z|tt|WYd }~n d }~00|jtjtjtd }ttj|}ntd |ttj|S) aGenerate 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_RSAuppergetattrrZgenerate_private_keyr TypeErrorr r6Z private_bytesrrXrZTraditionalOpenSSLrrPrKZdump_privatekey) r,r'r(keynamer\Z_keyeZ_key_pemr?r?r@r1s>    &r1)rBr+c Cs4zttj|WSttjfy.YdS0dS)zIs valid RSA private key? :param privkey: Private key file contents in PEM :returns: Validity of private key. :rtype: bool FN)rrPrKcheckr`rM)rBr?r?r@ valid_privkeys  re)renewable_certr+cCs"t|t|t|j|jdS)aFor 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_sigverify_fullchainverify_cert_matches_priv_key cert_pathr>)rfr?r?r@verify_renewable_certs rkc Cszt|jd"}t|t}Wdn1s60Yt|jd"}t|t}Wdn1st0Y|}|jsJt ||j |j |jWnLt t tfy}z.d|j|}t|t|WYd}~n d}~00dS)zVerifies 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_certificatereadr rj public_keysignature_hash_algorithmverify_signed_payload signatureZtbs_certificate_bytesIOErrorr2r rVr3 exceptionrrM)rf chain_filechain cert_filecertZpkrc error_strr?r?r@rg%s 00   rgrrr!r )rqrtpayloadrrr+cCsJt|tr|||t|n(t|tr<|||t|n tddS)aCheck 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,ttj}|||||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. zverifying 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 Cs4zt|j}|}Wdn1s*0Yt|j}|}Wdn1s\0Yt|j}|}Wdn1s0Y|||krd}||j}t|Wnnt y}z*d|}t |t|WYd}~n4d}~0tjy.}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 Csg}tjtjfD]L}zt|||fWStjyZ}z||WYd}~qd}~00qtdddd|DdS)z:Load PEM/DER certificate. :raises errors.Error: NzUnable to load: {0},css|]}t|VqdSN)r6).0r5r?r?r@ sz-pyopenssl_load_certificate..) rrKrUload_certificaterMappendrrVr:)rSZopenssl_errorsZ file_typer5r?r?r@pyopenssl_load_certificates"r)cert_or_req_str load_functypr+c CsXz |||WStjyR}z,tjdddtdt|WYd}~n d}~00dS)Nr-Tr.z6Encountered error while loading certificate or csr: %s)rrMr3r4r5r6)rrrr=r?r?r@_load_cert_or_reqs  rcCstt|||Sr)rFZ_pyopenssl_cert_or_req_sanr)rrrr?r?r@_get_sans_from_cert_or_reqsr)rzrr+cCst|tj|S)zGet 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 )rrrrzrr?r?r@get_sans_from_certs r) cert_or_reqrrr+cCst|||}t|Sr)rrW)rrrloaded_cert_or_reqr?r?r@_get_names_from_cert_or_reqs r)rr+cCs t|Sr)rFZ _pyopenssl_cert_or_req_all_names)rr?r?r@rWsrWcCst|tj|S)zGet 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 )rrrrr?r?r@get_names_from_certs r)rIrr+cCst|tj|S)zGet 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 )rrrJ)rIrr?r?r@get_names_from_reqs r)rxfiletyper+cCs t||S)zDump certificate chain into a bundle. :param list chain: List of `crypto.X509` (or wrapped in :class:`josepy.util.ComparableX509`). )rFdump_pyopenssl_chain)rxrr?r?r@rs r)rjr+cCst|tjjS)zWhen 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` )_notAfterBeforerX509Z get_notBeforerjr?r?r@ notBefores rcCst|tjjS)zWhen 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` )rrrZ get_notAfterrr?r?r@notAfters r)rjmethodr+c Cst|d"}ttj|}Wdn1s20Y||}|sRtd|ddd|ddd|ddd |dd d |d d d |d dg }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) rmrrrKrprrMr:decode pyrfc3339parse)rjrfr Z timestampZreformatted_timestampZtimestamp_bytesZ timestamp_strr?r?r@r s 0   r)filenamer+cCsNt}t|d$}||dWdn1s<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)hashlibsha256rmupdaterpencodeZ hexdigest)rrZfile_dr?r?r@ sha256sum&s  2rs@-----BEGIN CERTIFICATE----- ? .+? ? -----END CERTIFICATE----- ? ) fullchain_pemr+cCsLt|}t|dkr$tddd|D}|dd|ddfS) 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|] }ttjttj|qSr?)rZdump_certificaterKrr)rrzr?r?r@ Vs z1cert_and_chain_from_fullchain..rr-N)CERT_PEM_REGEXfindallrlenrrMr:)rcertsZcerts_normalizedr?r?r@cert_and_chain_from_fullchainAs  rcCsDt|d"}ttj|}Wdn1s20Y|S)zRetrieve 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)rmrrrKrpZget_serial_number)rjrr r?r?r@get_serial_from_cert]s 0r) fullchains issuer_cnwarn_on_no_matchr+cCsl|D]N}t|}t|dt}|jtjj }|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` rzCertbot 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.) rrrr ror ZissuerZget_attributes_for_oidZNameOIDZ COMMON_NAMEvaluer3Zwarning)rrrrxrZtop_certZ top_issuer_cnr?r?r@find_chain_with_issuerks r)r"r#r$T)FT)r[r"N)F)i__doc__ZdatetimerZloggingretypingrrrrrrrZ 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.serializationrrrZjosepyZOpenSSLrrrZacmerrFZcertbotrrrZcertbot.compatrZ/cryptography.hazmat.primitives.asymmetric.ed448rZ1cryptography.hazmat.primitives.asymmetric.ed25519rZ.cryptography.hazmat.primitives.asymmetric.x448r Z0cryptography.hazmat.primitives.asymmetric.x25519r!Z getLogger__name__r3intr6boolr<rArGrHbytesrOrQrZr1reZ RenewableCertrkrgZ HashAlgorithmrsrirhrrrKZX509ReqrrrrrWrrZComparableX509rrrrrcompileDOTALLrrrrr?r?r?r@s                                   2 %" 0