a }|g] @s`dZddlZddlZddlZddlZddlZddlmZddlmZddlm Z ddlm Z ddlm Z ddlm Z dd l mZdd lmZdd lmZdd lmZdd lmZddlmZddlmZddlmZddlmZddlmZddlmZddlm Z ddl!m"Z"ddl#m$Z$ddl#m%Z%ddl#m&Z&ddl'Z'ddl(m)Z)ddl(m*Z*ddl+m,Z-ddl.m/Z/ddl.m0Z0ddl.m1Z1ddl2m3Z3e rdd l4m5Z5dd!l6m7Z7dd"l8m9Z9dd#l:m;Z;edoe?ee@e@e@e@eAe1jBd(d)d*ZCdpe1jBe ee@e e@fee@eAeAe1jDd,d-d.ZEeFeAd/d0d1ZGeFeFeAd2d3d4ZHe@eFe e-jIe1jDee@fd5d6d7ZJdqe?e@ee@eFd9d:d;ZKe e@eFfeAd<d=d>ZLe0jMdd?d@dAZNe0jMdd?dBdCZOe edDdEee"dFdGfeFeFejPddHdIdJZQe@e@ddKdLdMZRe0jMdd?dNdOZSeFe e)jTe?fdPdQdRZUe-jIjVfeFe e-jIe?fee@dSdTdUZWe-jIjVfeFe e-jIe?fee@dSdVdWZXe-jIjVfeFe e-jIe?fee@dXdYdZZYe-jIjVfe ee)jTee'jZfe e-jIe?feFd[d\d]Z[e@ejd^d_d`Z\e@ejd^dadbZ]e@e@dcdddeZ^e_dfej`Zae@e e@e@fdgdhdiZbe@e?d^djdkZcdree@e@eAe@dldmdnZddS)szCertbot 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)List)Optional)Set)Tuple) TYPE_CHECKING)Union)x509)InvalidSignature)UnsupportedAlgorithm)default_backend)hashes) serialization)ec)rsa) DSAPublicKey)ECDSA)EllipticCurvePublicKey)PKCS1v15) RSAPublicKey)Encoding) NoEncryption) PrivateFormat)crypto)SSL) crypto_util)errors) interfaces)util)os)Ed448PublicKey)Ed25519PublicKey) X448PublicKey)X25519PublicKeyr 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: %sNiiwbrz 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?7/usr/lib/python3.9/site-packages/certbot/crypto_util.py generate_key9s( (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_csrjs( rH)csrr+c Cs>zt|}|jWSttfy8tjdddYdS0dS)zValidate CSR. Check if `csr` is a valid CSR with a correct self-signed signature. :param bytes csr: CSR in PEM. :returns: Validity of CSR. :rtype: bool r-Tr.FN)rload_pem_x509_csris_signature_validr2 TypeErrorr3r4)rIreqr?r?r@ valid_csrs  rN)rIrBr+cCsNt|}tj|dd}|joL|tjjtj j |tjjtj j kS)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 Npassword) rrJr load_pem_private_keyrK public_key public_bytesrDERZ PublicFormatZSubjectPublicKeyInfo)rIrBrMZpkeyr?r?r@csr_matches_pubkeys   rU)csrfiledatar+c Cszt|}WnDtyRzt|}Wn"tyLtd|Yn0Yn0t|j |j }| t j j}tjjtj||dd|fS)a9Import a CSR file, which can be either PEM or DER. :param str csrfile: CSR filename :param bytes data: contents of the CSR file :returns: (`acme_crypto_util.Format.PEM`, util.CSR object representing the CSR, list of domains requested in the CSR) :rtype: tuple zFailed to parse CSR file: {0}rE)filerWZform)rload_der_x509_csrr2rJrErrorformatrF%get_names_from_subject_and_extensionssubject extensionsrSr rPEMFormatrrG)rVrWrIZdomainsZdata_pemr?r?r@import_csr_files  ra)r,r'r(r+c Cs|dkr0|dkr td|tjd|d}n|dkr|sFtdzZ|}|dvrtt|}|sztd |tj|td }ntd |WnTt ytd |Yn4t y}z|tt |WYd }~n d }~00ntd ||j t jtjtdS)aGenerate PEM encoded RSA|EC key. :param int bits: Number of bits if key_type=rsa. At least 2048 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 rrbzUnsupported RSA key length: {}i)Zpublic_exponentr%Zecdsaz3When key_type == ecdsa, elliptic_curve must be set.)Z SECP256R1Z SECP384R1Z SECP521R1zInvalid curve type: )curveZbackendzUnsupported elliptic curve: {}Nz0Invalid key_type specified: {}. Use [rsa|ecdsa])encodingr[Zencryption_algorithm)rrZr[rZgenerate_private_keyuppergetattrrr rLr r6Z private_bytesrr_rZTraditionalOpenSSLr)r,r'r(keynamercer?r?r@r1s8   (r1)rBr+cCsBt|tr|}ztj|ddWnty8YdS0dSdS)zIs valid RSA private key? :param privkey: Private key file contents in PEM :returns: Validity of private key. :rtype: bool NrOFT) isinstancer6encoder rQr2)rBr?r?r@ valid_privkeys  rl)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>)rmr?r?r@verify_renewable_certs rrc 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_pathrload_pem_x509_certificatereadr rqrRsignature_hash_algorithmverify_signed_payload signatureZtbs_certificate_bytesOSErrorr2r r[r3 exceptionrrZ)rm chain_filechain cert_filecertZpkri error_strr?r?r@rn+s 00   rnr rr"r!)rRrzpayloadrxr+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)rjrZverifyrrrrrZ)rRrzrrxr?r?r@ryCs    ry)rqr>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_privatekeyr{rZr[r3r|r)rqr>contextrirr?r?r@rp^s     rpc 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}) rtrurwrqZfullchain_pathr[Z lineagenamerrZr{r3r|) rmr}r~rrZfullchain_fileZ fullchainrrir?r?r@rots" & & &    ro)rWr+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|VqdS)N)r6).0r5r?r?r@ sz-pyopenssl_load_certificate..) rZ FILETYPE_PEMZ FILETYPE_ASN1Zload_certificaterZappendrr[r:)rWZopenssl_errorsZ file_typer5r?r?r@pyopenssl_load_certificates"r)rtypr+cCsvt|}|tjjkr"t|}n|tjjks2Jt|}z|jtj }Wntj yfgYS0|j tj S)zGet a list of Subject Alternative Names from a certificate. :param str cert: Certificate (encoded). :param Format typ: Which format the `cert` bytes are in. :returns: A list of Subject Alternative Names. :rtype: list )rFr`r_rrvrTload_der_x509_certificater^Zget_extension_for_classZSubjectAlternativeNameZExtensionNotFoundvalueZget_values_for_typeZDNSName)rr x509_certZsan_extr?r?r@get_sans_from_certs     rcCsLt|}|tjjkr"t|}n|tjjks2Jt|}t|j|j S)zGet a list of domains from a cert, including the CN if it is set. :param str cert: Certificate (encoded). :param Format typ: Which format the `cert` bytes are in. :returns: A list of domain names. :rtype: list ) rFr`r_rrvrTrr\r]r^)rrrr?r?r@get_names_from_certs    r)rIrr+cCsLt|}|tjjkr"t|}n|tjjks2Jt|}t|j|j S)zGet a list of domains from a CSR, including the CN if it is set. :param str csr: CSR (encoded). :param acme_crypto_util.Format typ: Which format the `csr` bytes are in. :returns: A list of domain names. :rtype: list ) rFr`r_rrJrTrYr\r]r^)rIrZx509_reqr?r?r@get_names_from_reqs    r)r~filetyper+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)r~rr?r?r@rs r)rqr+cCst|d}t|}Wdn1s.0Yt0tjddd|jjt j j dWdS1sv0YdS)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` rsNignore'Properties that return.*datetime objectmessageZtzinfo) rtrrvrwwarningscatch_warningsfilterwarningsZnot_valid_beforereplacedatetimetimezoneutcrqfrr?r?r@ notBefores , rcCst|d}t|}Wdn1s.0Yt0tjddd|jjt j j dWdS1sv0YdS)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` rsNrrrr) rtrrvrwrrrZnot_valid_afterrrrrrr?r?r@notAfter s , 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)hashlibsha256rtupdaterwrkZ hexdigest)rrZfile_dr?r?r@ sha256sum s  2rs@-----BEGIN CERTIFICATE----- ? .+? ? -----END CERTIFICATE----- ? ) fullchain_pemr+cCspt|}t|dkr$tdg}|D](}t|}|t j }| | q,|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 chainrr-N)CERT_PEM_REGEXfindallrklenrrZrrvrSrr_rdecoder:)rcertsZcerts_normalizedZcert_pemrr?r?r@cert_and_chain_from_fullchain;s    rcCs>t|d}t|}Wdn1s.0Y|jS)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 rsN)rtrrvrwZ serial_numberrr?r?r@get_serial_from_certZs ,r) 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.) rrrkrrvr ZissuerZget_attributes_for_oidZNameOIDZ COMMON_NAMErr3Zwarning)rrrr~rZtop_certZ top_issuer_cnr?r?r@find_chain_with_issuergs r)rr#r$T)FT)rbrN)F)e__doc__rrZloggingrertypingrrrrrrZ cryptographyrZcryptography.exceptionsr r Zcryptography.hazmat.backendsr Zcryptography.hazmat.primitivesr r Z)cryptography.hazmat.primitives.asymmetricrrZ-cryptography.hazmat.primitives.asymmetric.dsarZ,cryptography.hazmat.primitives.asymmetric.ecrrZ1cryptography.hazmat.primitives.asymmetric.paddingrZ-cryptography.hazmat.primitives.asymmetric.rsarZ,cryptography.hazmat.primitives.serializationrrrZjosepyZOpenSSLrrZacmerrFZcertbotrrrZcertbot.compatrZ/cryptography.hazmat.primitives.asymmetric.ed448rZ1cryptography.hazmat.primitives.asymmetric.ed25519r Z.cryptography.hazmat.primitives.asymmetric.x448r!Z0cryptography.hazmat.primitives.asymmetric.x25519r"Z getLogger__name__r3intr6boolr<rArGrHbytesrNrUr`rar1rlZ RenewableCertrrrnZ HashAlgorithmryrproZX509rr_rrrZComparableX509rrrrcompileDOTALLrrrrr?r?r?r@s                                    2 % ! .