diff --git a/docs/development/test-vectors.rst b/docs/development/test-vectors.rst index 192682aac64e..6444dc55e3d2 100644 --- a/docs/development/test-vectors.rst +++ b/docs/development/test-vectors.rst @@ -755,6 +755,12 @@ Custom X.509 Request Vectors attribute whose value's tag is encoded in the long form. * ``zero-element-attribute.pem`` - A certificate signing request containing an attribute whose value has zero elements. +* ``mldsa-mlkem768.pem`` and ``mldsa-mlkem768-signing-pubkey.pem`` - A + certificate signing request signed using an ML-DSA private key, and + containing a ML-KEM-768 public key. +* ``mldsa-mlkem1024.pem`` and ``mldsa-mlkem1024-signing-pubkey.pem`` - A + certificate signing request signed using an ML-DSA private key, and + containing a ML-KEM-1024 public key. Custom X.509 Certificate Revocation List Vectors ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/x509/reference.rst b/docs/x509/reference.rst index 1dfc9975af8e..e6e56643c0d1 100644 --- a/docs/x509/reference.rst +++ b/docs/x509/reference.rst @@ -1615,6 +1615,23 @@ X.509 CSR (Certificate Signing Request) Builder Object :returns: A new :class:`~cryptography.x509.CertificateSigningRequest`. + .. method:: verify_directly_signed_by(public_key) + + .. versionadded:: 51.0.0 + + :param public_key: One of + :data:`~cryptography.hazmat.primitives.asymmetric.types.PublicKeyTypes`. + + Validates that the request is signed by the private key belonging to + provided public key. + + :return: None + :raise ValueError: If the signature algorithms of the request and + provided public key do not match. + :raise TypeError: If the signer does not have a supported public + key type. + :raise cryptography.exceptions.InvalidSignature: If the + signature fails to verify. .. class:: Name :canonical: cryptography.x509.name.Name diff --git a/src/cryptography/hazmat/bindings/_rust/x509.pyi b/src/cryptography/hazmat/bindings/_rust/x509.pyi index 4438cc77778c..ebe242aa17da 100644 --- a/src/cryptography/hazmat/bindings/_rust/x509.pyi +++ b/src/cryptography/hazmat/bindings/_rust/x509.pyi @@ -14,6 +14,7 @@ from cryptography.hazmat.primitives.asymmetric.types import ( CertificateIssuerPublicKeyTypes, CertificatePublicKeyTypes, PrivateKeyTypes, + PublicKeyTypes, ) from cryptography.x509 import certificate_transparency @@ -210,6 +211,10 @@ class CertificateSigningRequest: def tbs_certrequest_bytes(self) -> bytes: ... @property def is_signature_valid(self) -> bool: ... + def verify_directly_signed_by( + self, + public_key: PublicKeyTypes, + ) -> None: ... class PolicyBuilder: def time(self, time: datetime.datetime) -> PolicyBuilder: ... diff --git a/src/cryptography/x509/base.py b/src/cryptography/x509/base.py index 3ded5dc705a4..8d1d861f1d3b 100644 --- a/src/cryptography/x509/base.py +++ b/src/cryptography/x509/base.py @@ -183,6 +183,7 @@ class CertificateSigningRequestBuilder: def __init__( self, subject_name: Name | None = None, + public_key: CertificatePublicKeyTypes | None = None, extensions: list[Extension[ExtensionType]] = [], attributes: list[tuple[ObjectIdentifier, bytes, int | None]] = [], ): @@ -190,6 +191,7 @@ def __init__( Creates an empty X.509 certificate request (v1). """ self._subject_name = subject_name + self._public_key = public_key self._extensions = extensions self._attributes = attributes @@ -202,7 +204,45 @@ def subject_name(self, name: Name) -> CertificateSigningRequestBuilder: if self._subject_name is not None: raise ValueError("The subject name may only be set once.") return CertificateSigningRequestBuilder( - name, self._extensions, self._attributes + name, self._public_key, self._extensions, self._attributes + ) + + def public_key( + self, + public_key: CertificatePublicKeyTypes, + ) -> CertificateSigningRequestBuilder: + """ + Sets the requestor's public key. + """ + if not isinstance( + public_key, + ( + dsa.DSAPublicKey, + rsa.RSAPublicKey, + ec.EllipticCurvePublicKey, + ed25519.Ed25519PublicKey, + ed448.Ed448PublicKey, + mldsa.MLDSA44PublicKey, + mldsa.MLDSA65PublicKey, + mldsa.MLDSA87PublicKey, + mlkem.MLKEM768PublicKey, + mlkem.MLKEM1024PublicKey, + x25519.X25519PublicKey, + x448.X448PublicKey, + ), + ): + raise TypeError( + "Expecting one of DSAPublicKey, RSAPublicKey," + " EllipticCurvePublicKey, Ed25519PublicKey," + " Ed448PublicKey, MLDSA44PublicKey, MLDSA65PublicKey," + " MLDSA87PublicKey, MLKEM768PublicKey, MLKEM1024PublicKey," + " X25519PublicKey or X448PublicKey." + ) + + if self._public_key is not None: + raise ValueError("The public key may only be set once.") + return CertificateSigningRequestBuilder( + self._subject_name, public_key, self._extensions, self._attributes ) def add_extension( @@ -219,6 +259,7 @@ def add_extension( return CertificateSigningRequestBuilder( self._subject_name, + self._public_key, [*self._extensions, extension], self._attributes, ) @@ -251,6 +292,7 @@ def add_attribute( return CertificateSigningRequestBuilder( self._subject_name, + self._public_key, self._extensions, [*self._attributes, (oid, value, tag)], ) @@ -265,7 +307,9 @@ def sign( ecdsa_deterministic: bool | None = None, ) -> CertificateSigningRequest: """ - Signs the request using the requestor's private key. + Signs the request using the requestor's private key. If no public key + was indicated, the public key associated with specified private key + will be included instead. """ if self._subject_name is None: raise ValueError("A CertificateSigningRequest must have a subject") diff --git a/src/rust/src/x509/csr.rs b/src/rust/src/x509/csr.rs index 55389c703fcf..8a5a1159f337 100644 --- a/src/rust/src/x509/csr.rs +++ b/src/rust/src/x509/csr.rs @@ -187,14 +187,21 @@ impl CertificateSigningRequest { #[getter] fn is_signature_valid(&self, py: pyo3::Python<'_>) -> CryptographyResult { let public_key = self.public_key(py)?; - Ok(sign::verify_signature_with_signature_algorithm( + Ok(self.verify_directly_signed_by(py, public_key).is_ok()) + } + + fn verify_directly_signed_by<'p>( + &self, + py: pyo3::Python<'p>, + public_key: pyo3::Bound<'p, pyo3::PyAny>, + ) -> CryptographyResult<()> { + sign::verify_signature_with_signature_algorithm( py, public_key, &self.raw.borrow_dependent().signature_alg, self.raw.borrow_dependent().signature.as_bytes(), &asn1::write_single(&self.raw.borrow_dependent().csr_info)?, ) - .is_ok()) } } @@ -265,8 +272,12 @@ pub(crate) fn create_x509_csr( rsa_padding.clone(), )?; - let spki_bytes = private_key - .call_method0(pyo3::intern!(py, "public_key"))? + let public_key = match builder.getattr(pyo3::intern!(py, "_public_key"))? { + pk if pk.is_none() => private_key.call_method0(pyo3::intern!(py, "public_key"))?, + pk => pk, + }; + + let spki_bytes = public_key .call_method1( pyo3::intern!(py, "public_bytes"), ( diff --git a/tests/x509/test_x509.py b/tests/x509/test_x509.py index 19bb40152821..2d480b781709 100644 --- a/tests/x509/test_x509.py +++ b/tests/x509/test_x509.py @@ -2037,6 +2037,29 @@ def test_admissions_extension(self): assert ext.value == x509.Admissions(authority=None, admissions=[]) +class TestCertificateRequest: + def test_public_key_must_be_public_key( + self, rsa_key_2048: rsa.RSAPrivateKey + ): + private_key = rsa_key_2048 + builder = x509.CertificateSigningRequestBuilder() + + with pytest.raises(TypeError): + builder.public_key(typing.cast(typing.Any, private_key)) + + def test_public_key_may_only_be_set_once( + self, rsa_key_2048: rsa.RSAPrivateKey + ): + private_key = rsa_key_2048 + public_key = private_key.public_key() + builder = x509.CertificateSigningRequestBuilder().public_key( + public_key + ) + + with pytest.raises(ValueError): + builder.public_key(public_key) + + class TestRSACertificateRequest: @pytest.mark.parametrize( ("path", "loader_func"), @@ -6391,6 +6414,144 @@ def test_tbs_certrequest_bytes(self, backend): ) +class TestMLKEMCertificateRequest: + @pytest.mark.supported( + only_if=lambda backend: ( + backend.mldsa_supported() and backend.mlkem_supported() + ), + skip_message="Does not support ML-DSA and/or ML-KEM", + ) + @pytest.mark.parametrize( + ( + "enclosed_key_path", + "enclosed_pub_key_cls", + "signing_pub_key_path", + "signing_pub_key_cls", + "signature_algorithm_oid", + ), + [ + ( + os.path.join("x509", "requests", "mldsa-mlkem768.pem"), + mlkem.MLKEM768PublicKey, + os.path.join( + "x509", "requests", "mldsa-mlkem768-signing-pubkey.pem" + ), + mldsa.MLDSA65PublicKey, + SignatureAlgorithmOID.ML_DSA_65, + ), + ( + os.path.join("x509", "requests", "mldsa-mlkem1024.pem"), + mlkem.MLKEM1024PublicKey, + os.path.join( + "x509", "requests", "mldsa-mlkem1024-signing-pubkey.pem" + ), + mldsa.MLDSA65PublicKey, + SignatureAlgorithmOID.ML_DSA_65, + ), + ], + ) + def test_load_request_mldsa_mlkem( + self, + enclosed_key_path, + enclosed_pub_key_cls, + signing_pub_key_path, + signing_pub_key_cls, + signature_algorithm_oid, + ): + request = _load_cert(enclosed_key_path, x509.load_pem_x509_csr) + + signing_key = _load_cert( + signing_pub_key_path, serialization.load_pem_public_key + ) + + assert isinstance(request.public_key(), enclosed_pub_key_cls) + assert isinstance(signing_key, signing_pub_key_cls) + + assert request.signature_algorithm_oid == signature_algorithm_oid + + assert isinstance(request.subject, x509.Name) + assert list(request.subject) == [ + x509.NameAttribute(NameOID.COUNTRY_NAME, "US"), + ] + + assert not request.is_signature_valid + request.verify_directly_signed_by(signing_key) + + with pytest.raises(TypeError): + unsupported_algorithm = request.public_key() + request.verify_directly_signed_by(unsupported_algorithm) + + with pytest.raises(ValueError): + wrong_algorithm = ec.generate_private_key( + ec.SECP256R1() + ).public_key() + request.verify_directly_signed_by(wrong_algorithm) + + with pytest.raises(InvalidSignature): + wrong_pub_key = mldsa.MLDSA65PrivateKey.generate().public_key() + request.verify_directly_signed_by(wrong_pub_key) + + @pytest.mark.supported( + only_if=lambda backend: ( + backend.mldsa_supported() and backend.mlkem_supported() + ), + skip_message="Does not support ML-DSA and/or ML-KEM", + ) + @pytest.mark.parametrize( + ( + "enclosed_key_cls", + "enclosed_pub_key_cls", + "signing_key_cls", + "signature_algorithm_oid", + ), + [ + ( + mlkem.MLKEM768PrivateKey, + mlkem.MLKEM768PublicKey, + mldsa.MLDSA65PrivateKey, + SignatureAlgorithmOID.ML_DSA_65, + ), + ( + mlkem.MLKEM1024PrivateKey, + mlkem.MLKEM1024PublicKey, + mldsa.MLDSA65PrivateKey, + SignatureAlgorithmOID.ML_DSA_65, + ), + ], + ) + def test_build_request_mldsa_mlkem( + self, + enclosed_key_cls, + enclosed_pub_key_cls, + signing_key_cls, + signature_algorithm_oid, + ): + enclosed_key = enclosed_key_cls.generate() + signing_key = signing_key_cls.generate() + + request = ( + x509.CertificateSigningRequestBuilder() + .subject_name( + x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) + ) + .public_key(enclosed_key.public_key()) + .sign(signing_key, None) + ) + + public_key = request.public_key() + assert isinstance(public_key, enclosed_pub_key_cls) + + assert request.signature_algorithm_oid == signature_algorithm_oid + + assert isinstance(request.subject, x509.Name) + assert list(request.subject) == [ + x509.NameAttribute(NameOID.COUNTRY_NAME, "US"), + ] + + assert not request.is_signature_valid + request.verify_directly_signed_by(signing_key.public_key()) + + class TestOtherCertificate: def test_unsupported_subject_public_key_info(self): cert = _load_cert( diff --git a/vectors/cryptography_vectors/x509/requests/mldsa-mlkem1024-signing-pubkey.pem b/vectors/cryptography_vectors/x509/requests/mldsa-mlkem1024-signing-pubkey.pem new file mode 100644 index 000000000000..6b34c7539878 --- /dev/null +++ b/vectors/cryptography_vectors/x509/requests/mldsa-mlkem1024-signing-pubkey.pem @@ -0,0 +1,44 @@ +-----BEGIN PUBLIC KEY----- +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 +vCZ/GVKv +-----END PUBLIC KEY----- diff --git a/vectors/cryptography_vectors/x509/requests/mldsa-mlkem1024.pem b/vectors/cryptography_vectors/x509/requests/mldsa-mlkem1024.pem new file mode 100644 index 000000000000..ecce71e5e5d3 --- /dev/null +++ b/vectors/cryptography_vectors/x509/requests/mldsa-mlkem1024.pem @@ -0,0 +1,106 @@ +-----BEGIN CERTIFICATE REQUEST----- +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 +Lg== +-----END CERTIFICATE REQUEST----- diff --git a/vectors/cryptography_vectors/x509/requests/mldsa-mlkem768-signing-pubkey.pem b/vectors/cryptography_vectors/x509/requests/mldsa-mlkem768-signing-pubkey.pem new file mode 100644 index 000000000000..eb58408fe808 --- /dev/null +++ b/vectors/cryptography_vectors/x509/requests/mldsa-mlkem768-signing-pubkey.pem @@ -0,0 +1,44 @@ +-----BEGIN PUBLIC KEY----- +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 +0zoohoYm +-----END PUBLIC KEY----- diff --git a/vectors/cryptography_vectors/x509/requests/mldsa-mlkem768.pem b/vectors/cryptography_vectors/x509/requests/mldsa-mlkem768.pem new file mode 100644 index 000000000000..a77d6b1108af --- /dev/null +++ b/vectors/cryptography_vectors/x509/requests/mldsa-mlkem768.pem @@ -0,0 +1,98 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIRzTCCBMoCAQAwDTELMAkGA1UEBhMCVVMwggSyMAsGCWCGSAFlAwQEAgOCBKEA +chktkLe8k5EexbAJ1EifhEYizxGh0yJalqeBTiCpKEtEnGC/mfkjRrQ8xiqfq6kW +cRghS+YgJHIjrMguOkso/xsSsAwiRPoKFGZ+qDGhhCWDl0hwt/KeSWrLI9dGdfrB +AyFumFl7NBFz+EqOMFhhhDeX58oswqaMiON5tjerXvkslNGOrVp47nkAYrWQGdIe +YpsFJSihPxEvCPylxhI3ORuhU9V359dkuBuGu/YqDhNcjQmZMoJQfoKP4oOxJRF9 +tjSb1OwR4Ps0eGq26BqocsYKMpk+CELAe8t1YPRAYtIxOlcPEkqKDhYBxOMQUkor +9shXGEQzonVC18hINfRKYBQQahHFJiC5zPKteymHZ4Q2dwTIwdhUKFsBQ2l70yYr +kKgM4saIqraOQuCYM9RsgYtfaShQL8eTeIwn+0qd0vqSqZtFLKRIKEHPj0DMR/mu +/Ednyek3FmeWZyVHl5cdT6GL9HWLUhgQwqBWlgBNx9Vs7RUV3WOstBqmilSknApm +qLouZya4Y3uRmDQIEEFxqxeiGXJiFiukC6YWaXNcQ+sHWZAIudgjYUbPkVPNqMtg +WlVp+NEJ5MdlLSe0g4KzMzeNJPFt/KR5J6uFcylGuMQbDQoAFWgiEWogzqRshSdB +fFQjISuYS5Q8mxbIpCpZIrM4T/wBQIKqMLR9QfQgwweOLnETr2UkRmtoApOCcoZm +xBJYS7gX48OPZiRM2luvy4ITyWCWtVYu3GyuuOxEP/IWFnUOpWNemKSLi7WkSdQQ +bhcgwQiApCJgkutvexioTtdNscEYJutD+ZN1vbvOg9w/+EuIM7YVK3lPx2Akeba7 +SPTCbnuXUPIYtmLOv/Y9WdGZJRavJdK/HBcjbYgH6yWn10M0T8U8AzqYNFQOqfJN +AE2VAWefXnmtTxYdZid/KzLB6+e/zaQOIzcIA/KOtyMxFNSKa3ygd8Vr5pNTQuob +ICqLAUWlKqAy5/NxApjHCWRAw3Vn8pkwg6fDS4EC7UaeMsBG/eQn72GDFIEj0MSL +Xgd/bsslorRtt0sSZWQLMGFVjCR0TezPiQBqO2qS+kc+/hmCdkagENdZkoJ468Az +0yBpq4DBQTUd1dsUJGKbEPHAWkPJQvBA1mwUeMls89xw0lY6MGtG+fFZQcDCcecd +ydlYFqlwlUNMUFZ8pXRdlZBhvwvJWVKZCSlVxrEF1rFsemq0B8N4pxo69gWxIcmJ +lDisWxVJf0hlGzRpzKJ9wHFkEPMPC5bG8WByFmwGjFCJguZDfiqpisUYl2kFH/w4 +Z4IVg1GM9qOMlprLwPd75ISTAya8RVmglTRVw0t0fRubjHrAPDHEociQ5/tZ0Rhq +6xd9+yPNzaFYbjTNuOlCjfdXz6ytN0c24yAnSWweq6NzmueXyatsOxqsoGxnjLVo +KRRhfYQywHh+ISPKJpVVXjGBHAEleyY5tonP26ZGOia7hNxbyuatzKq9F9ecGaex +EVoRRao+njR7p1OkYAOf/CEYQVRNennGSShSxDcyLeZSdwQIQmx9BxhVKDG8Shoa +O6Ep2meKWs0+DkrelE3bljXVH3bzmvpbyr8lAv90rCOgADALBglghkgBZQMEAxID +ggzuAKjOJFKV1DsI3vUAg9wxlG0P5Cn3tks2D8apLYtKsjybN5CnveLKy2Smm4Tk +QrPF9IqfztH5qbR2C585pS5BwOW3ydMhmxLUWN3n8FFX1aIddMuqCtzSkcrm+zM9 +h43oYkJtFimBqXqwmeQ8pf7Q1s3FhEPRyGuyfqU0jg+Nf4wXRWwv44LTVTXi+sZy +IJcYdoI4mbIImNjbr79m5b0+PBGYOkpgTT2qeX4l3hTgG47uh1GV0y0urPsv0NV/ +IG2ADDky/AIQi+r4ZAp2zzhHxWyaf+a2ujCMazo1PhPKOlyPBW1F8O7NBcRHFtHO +TSMKPfsa6Ai/Lab0lm5Eix5ycHZp3be4qOvLRtTdkimUlrSWW3VXHObjxvRvo38z +aMOT8nAYdsE7rEB28oDhqftT+jiQtLkusQLpDNDfuMsgmQGpBD00jzd5zSN2dLO0 +53re5977gLKDDyx7/rSgy3K6aZAQ6g+sOs2eD1prwUiFiZgKsOYd+cB0zi726EJ3 +fv73y9waJmpbqsfRfodUCvhdeYZavu2sJMqTIZDaqFnPaLeix/kxJL/riRziUhKs +gZYk04bZqizyfWHmbfrBABUg8WVnB9MUzi1y3I2zPeaPLwnfkjVfPyRllWdOgxmL +c1vamCWcmRFDvHCKPW1FTb4oBfn7g83VbibfJtlvvLa0vdfevl+wDlJk98RO1MRK +LrqBEGemHmnPB8Bn83ZzdtP1fVIPCaZd0npNDCFniqHSg1FFjzXC+URObh0cTii1 +YkvjLQulDed04UFLAWNek2/bJIfAsJtTeLE2OotM9plAdhf09x9R8dpP+szTdGjQ +bFTKwsqlI2KkML74j8NqDPrrUYaFvfUPl2+D5Kq9vU+HmX0IUPW4nVD5QSteYJ37 +1i0ouKnCVrpIXGP3ibo7a/QSSmU9sKWMyG5KqgUQW0NMjM46T1quk938gmFTo9S8 +NVKKb2EDC4trz3uek4UXOqnx1c1Prt8HVzGcsFSOGibjIm6a7ttXiP0zDo9Q7AUO +w9969bNoBgSLqI90VCX95Qx2BEHifJEGtVBwRp5oY0TgNSKDYo18amWRVRPT4bov +hMs9wZRdSRGuUMikq2N5KiNYvhRJIcIL4thrxq2Zy/d4cv3NxzeKt0MsGkkxlWq5 +cri6KxFWeqQBr+qjdauC++NPi6WOxtlocIpJXZR8QUXcCTngTVIbQvYY4+hEk6Gy +ZrfdciYC5DgFxsxP8yinw7vGRePHMMKkWxr0Kw93nrhHDhQfhsULtig8w5JhszOA +rGWywfIh5iStr79cjS7Z0Vxr1FFbMfiSu5SecK8NLTvYwX6GF9Jp+c7Xk1GKYsTL +RB05w3ORJoEbU2AGbjR8oFBOCquxmzXF2y2eYPZXCDfSCifi+IgC7ORd5xTDUOAs +vtaQ8/QHpwoY0MPzfNKDEMihkC8VpCZuvBhYWkmPOH0IS+JX6pX2/uff1rCljxRY +mHaCd0AZHRY3pGrFTdlHudMX565KZexkvGw/EEA+ZB92skAX6fw9So1+C/bRBX0x +wwdT15VC+kNWN52WIjmJ1HuqjTZbRpcEUFM9IdqLB9JaL23Zb6C4u2/atg90ZvvY +ep5cAuBW5uHIpEe9OTS2UGlQ0hm9Q5VOP9U3lCrkd/DA+IttW75Y6U/kVjqj9ZgY +igiKEI4X3uhjU3gF+4KNWEIYA7T1kkcKrHqM2Vwpp6wQrZ7fwNKMEMNS1eP8vaI3 +VwlYJ+fIR+JA+hHkdFOE2oRO/CBTTVsl8q5EJjR7+7DqZnqTtm+6jR/3PNnnlnRn +WTim/3W75kVgkfeBZJ5efKXtBxbJ15ZtNnatVmjF1/HoqH2WEdSwTNi7FZ4phrpt +bugX9DM8OcVu6IEmicdb87aZfxxX8Ct4G/ReoPQxu80M02tls+eXyvEXTqKKN4i5 +gbKCJO7LywOntURQiGJZvy4Salt0DgOlCtK+u7TThr8n53dXFkMIBzGtP9hJdbC9 +usyitW2bDjU6xy09rgQycoHrISCZiB++bc3ZdV3BaRFGM6MW6bp9g9e0teywIhmo +CUozcGDZI6HVXzsPaxiUxZJQ5pLHQtFvGmIq7g0pUq9kk/0HgUMp746/Udw0lleC +1lb1//5MhsmxAPPF/yVmePBf811fPZNQ0UqHI17S7ZnjZ/Ywr/2Vrwm2wTaoOcNc +BtGAs8iwZqpgUTmhTjnmpB4lzvJTZhj34bKFTX9ODjs19cZW4Jg1cZuCO4/PidHH +HTtRJAQoCnZcodSCJfIU3dD6wYnSiSW4BSzJc39AQJMcVwRfZmXaQKZWT5JHJ6XI +yQpxueGczvMNDnDO4V03YOe+4/WqSP3G1XT4e2fXXhyXIBfrFONTgP/TubczZODT +feFpApTGWpc7fWzRssKZWn+Iry5KWnTLIbmkDmogCDPUmF+FNfWkrY26Goo/h4P+ +uGDNhLrHGHTnA1RBDaxj/fx9w6sNSK3VnFMhYKnlw2KpdwqkeBHQIXhn4ePdvi4g +sVF91dUfwQb4mNfslT2CKo6QogkRwDKLCXMqvzzTsfmTAxiOflkpElDvnPzzKluW +v4tQcMYdBod78wrWtudcugLdPkLu0eewMnF4cKe5Pi+qlD5RxVudogn5/nyXt2av +UZ++tl8jwi/+ZIdAdmQwbvSxgUVtoXpGHlrHbJ3Kqkj/4mHU1v0FnaH/Cb7SsF9U +G9Ekvss2+sWiOzPbNQ6x/dKt8vPDEZp35BiYwopm7TSual/G2qaONX7SitIT48NA +IVFLWWyyqXkzYrtCL8x3xhNhSBNH89PIgwLm1KLTr3ROABDb/6t612T1sX1RtBRY +ZeoGUAD8RaorwCGmq6Pc+/XLh5I1wpQ1vd7IKGZu3hZOJjmIHWgIn3DF007uLOsA +AgYweFMSomzi1nRXMJp1MMsdpBES568nEwR135pcNHHzvMtNHL1nbwf7NLTgWM3Z +CiDyGfyOm3wzU08OLroe6RVOgwut4ZJFZIDaCa4wC0TjpenTZ8oLoq5fkDA5ShLh +Cm2BKWVtRORDyEkoa55BQOyr6sYA2hEPtB6Rvc3h5Hxn9X8t4J6RPCrPQDcmc7u/ +iI8962deHgaTGji5a7dAInTDXLCaqc4n31TokofBFCCRwzANYlGNUoJCpWDjpJmc +tlxZHY5NulV6bKLXsSY0hJoyBXBekxQQS8sM+3vnH3QnuOfM7dGMVDTahKFOnTBY +RJDSIOyFsBvuGlUqWpTLqqIwZpp5htFNGx2rUfCxgZLPj5HwnzWGoTmKgTsy8VEy +oIls2aMEYO3nWuudiffZjryjAH0RVHaTqoc8NedbhVH0OxKi4RHfSSNp7Rs+hgXy +KicFqVRCbsbYdBCKg2/V0RPK+3tF3pXV0bFcoq/K1L30EPzxAbWDIH8EiQy5A+KG +fhwcvrX3iGMVUTxupgxXMDp5dnrfiWDASqB/0pl/XZDmvOt19eSdiQ1c98H3lC+0 +6vFfhOqhVH7oLWJjFDOBqEGG41UEDhNN+33z9TRaY2Y+VH54eBJF/ikjvqYoGbP/ +qQlkFJmds/Ck2Fv8eC8DfbAVrVZKMDSH+VVQJhha8EbeuBGUDw6CWdlY3kbUhJcH +a7HRP4/JEEe+xX2GRq+4T06LA9nK/p2zQJxlWdqqyYdAIFaBpwLzhmRRd3c9vVYX +oAbz7V03FQHF1blwxtVkh5qvl4PEhX4GkeCVX2t6xqvfFLLjeeoEStHp5kDjob/u +rqH2QHvktZWJeMPowqhNVjPowE3DM1yFy3XoiwvaK2vxcxMT8X1iOTSboufvISA2 +Hl0cLnEuOIb+QoUimfztYWgSbKKkD9GTAnOGbhierPJCoGcjWzkUNE4309bQTSo8 +t/EWlaHnPht73pqoGeZpkRTw61scKf8RIztxKi2SkQPWNhScCwAleI8/BSI1fqrs +Npo/kXOVjHlwayrshVc2MAQI4rRQ0s0+abYJDGgb6fYP9slCco0ewS5OtYUN2PHD +60Avj0ho4UoKxOotQrY1WSeYK4MJRfasRE8OuT1JgvhBbX9cxJt6LEmnEyQSIFfF +C/8ydrWiLEf/d2prWvpibx/G+eI1g0lAc8JrQpqkEezTS9m88Fl3AdQhm0m1n+vI +ETpX9EgnUgY4St+TQkhOxyN7ikkAYVofNP6ZLnrQB9FIgeM0oE1CkDu78IfSTeKl +lKi/1mJWu3Uflqzr5j4XcoNWSBRwtA1SuOXD3aIH3ygIqUF8GExRfvfbBAn0fJ3A +wwJvQG5WxBsiwTsSAeeFqLeJtmrBEydGlA4pTRA5h+Jo+5+70obo/hTZiTkNd0bl +tqevMOOKWDODXYie7+zzr5QKevIBPYHt9dBRmoggvkX+BjR5BhUZIDlQVI+QvsRb +Yq33ITc6Q2SRtroRIDo9anulBAc5c3eQuM8ZWl5ogZusxdfuAAAAAAAAAAsPFx4m +MA== +-----END CERTIFICATE REQUEST-----