• Bug#1106579: marked as done (unblock: python-certbot/4.0.0-2) (4/7)

    From Debian Bug Tracking System@21:1/5 to All on Mon May 26 20:00:01 2025
    [continued from previous message]

    RSA512_KEY = test_util.load_vector('rsa512_key.pem')
    +RSA512_KEY_PATH = test_util.vector_path('rsa512_key.pem')
    +RSA2048_KEY = test_util.load_vector('rsa2048_key.pem')
    RSA2048_KEY_PATH = test_util.vector_path('rsa2048_key.pem')
    CERT_PATH = test_util.vector_path('cert_512.pem')
    CERT = test_util.load_vector('cert_512.pem')
    SS_CERT_PATH = test_util.vector_path('cert_2048.pem')
    SS_CERT = test_util.load_vector('cert_2048.pem')
    P256_KEY = test_util.load_vector('nistp256_key.pem')
    +P256_KEY_PATH = test_util.vector_path('nistp256_key.pem')
    P256_CERT_PATH = test_util.vector_path('cert-nosans_nistp256.pem')
    P256_CERT = test_util.load_vector('cert-nosans_nistp256.pem')
    # CERT_LEAF is signed by CERT_ISSUER. CERT_ALT_ISSUER is a cross-sign of CERT_ISSUER.
    @@ -120,7 +125,7 @@

    def test_invalid_false(self):
    assert not self._call(
    - test_util.load_vector('csr_512.pem'), RSA256_KEY)
    + test_util.load_vector('csr_512.pem'), P256_KEY)


    class ImportCSRFileTest(unittest.TestCase):
    @@ -136,7 +141,7 @@
    data = test_util.load_vector('csr_512.der')
    data_pem = test_util.load_vector('csr_512.pem')

    - assert (OpenSSL.crypto.FILETYPE_PEM,
    + assert (acme_crypto_util.Format.PEM,
    util.CSR(file=csrfile,
    data=data_pem,
    form="pem"),
    @@ -147,7 +152,7 @@
    csrfile = test_util.vector_path('csr_512.pem')
    data = test_util.load_vector('csr_512.pem')

    - assert (OpenSSL.crypto.FILETYPE_PEM,
    + assert (acme_crypto_util.Format.PEM,
    util.CSR(file=csrfile,
    data=data,
    form="pem"),
    @@ -168,18 +173,19 @@
    from certbot.crypto_util import make_key

    # Do not test larger keys as it takes too long.
    - OpenSSL.crypto.load_privatekey(OpenSSL.crypto.FILETYPE_PEM, make_key(2048))
    + serialization.load_pem_private_key(make_key(2048), password=None)

    def test_ec(self): # pylint: disable=no-self-use
    # ECDSA Key Type Tests
    from certbot.crypto_util import make_key

    for (name, bits) in [('secp256r1', 256), ('secp384r1', 384), ('secp521r1', 521)]:
    - pkey = OpenSSL.crypto.load_privatekey(
    - OpenSSL.crypto.FILETYPE_PEM,
    - make_key(elliptic_curve=name, key_type='ecdsa')
    + pkey = serialization.load_pem_private_key(
    + make_key(elliptic_curve=name, key_type='ecdsa'),
    + password=None
    )
    - assert pkey.bits() == bits
    + assert isinstance(pkey, ec.EllipticCurvePrivateKey)
    + assert pkey.curve.key_size == bits

    def test_bad_key_sizes(self):
    from certbot.crypto_util import make_key
    @@ -199,8 +205,15 @@
    # Try a bad --key-type
    with pytest.raises(errors.Error,
    match=re.escape('Invalid key_type specified: unf. Use [rsa|ecdsa]')):
    - OpenSSL.crypto.load_privatekey(
    - OpenSSL.crypto.FILETYPE_PEM, make_key(2048, key_type='unf'))
    + make_key(2048, key_type='unf')
    +
    + def test_for_pkcs8_format(self):
    + from certbot.crypto_util import make_key
    +
    + # PKCS#1 format will instead have text like "BEGIN RSA PRIVATE KEY" or "BEGIN EC PRIVATE
    + # KEY"
    + assert b"BEGIN PRIVATE KEY" in make_key(2048)
    + assert b"BEGIN PRIVATE KEY" in make_key(elliptic_curve='secp256r1', key_type='ecdsa')


    class VerifyCertSetup(unittest.TestCase):
    @@ -291,7 +304,7 @@
    assert self._call(self.renewable_cert) is None

    def test_cert_priv_key_mismatch(self):
    - self.bad_renewable_cert.privkey = RSA256_KEY_PATH
    + self.bad_renewable_cert.privkey = P256_KEY_PATH
    self.bad_renewable_cert.cert = SS_CERT_PATH

    with pytest.raises(errors.Error):
    @@ -355,8 +368,8 @@
    self._call(test_util.load_vector('cert-5sans_512.pem'))

    def test_parse_non_cert(self):
    - with pytest.raises(OpenSSL.crypto.Error):
    - self._call("hello there")
    + with pytest.raises(ValueError):
    + self._call(b"hello there")


    class GetNamesFromReqTest(unittest.TestCase):
    @@ -381,26 +394,8 @@
    self._call(test_util.load_vector('csr-6sans_512.pem'))

    def test_der(self):
    - from OpenSSL.crypto import FILETYPE_ASN1
    assert ['Example.com'] == \
    - self._call(test_util.load_vector('csr_512.der'), typ=FILETYPE_ASN1)
    -
    -
    -class CertLoaderTest(unittest.TestCase):
    - """Tests for certbot.crypto_util.pyopenssl_load_certificate"""
    -
    - def test_load_valid_cert(self):
    - from certbot.crypto_util import pyopenssl_load_certificate
    -
    - cert, file_type = pyopenssl_load_certificate(CERT)
    - assert cert.digest('sha256') == \
    - OpenSSL.crypto.load_certificate(file_type, CERT).digest('sha256')
    -
    - def test_load_invalid_cert(self):
    - from certbot.crypto_util import pyopenssl_load_certificate
    - bad_cert_data = CERT.replace(b"BEGIN CERTIFICATE", b"ASDFASDFASDF!!!") - with pytest.raises(errors.Error):
    - pyopenssl_load_certificate(bad_cert_data)
    + self._call(test_util.load_vector('csr_512.der'), typ=acme_crypto_util.Format.DER)


    class NotBeforeTest(unittest.TestCase):
    @@ -432,20 +427,19 @@
    class CertAndChainFromFullchainTest(unittest.TestCase):
    """Tests for certbot.crypto_util.cert_and_chain_from_fullchain"""

    - def _parse_and_reencode_pem(self, cert_pem):
    - from OpenSSL import crypto
    - return crypto.dump_certificate(crypto.FILETYPE_PEM,
    - crypto.load_certificate(crypto.FILETYPE_PEM, cert_pem)).decode()
    + def _parse_and_reencode_pem(self, cert_pem:str)->str:
    + cert = x509.load_pem_x509_certificate(cert_pem.encode())
    + return cert.public_bytes(Encoding.PEM).decode()

    def test_cert_and_chain_from_fullchain(self):
    - cert_pem = CERT.decode()
    - chain_pem = cert_pem + SS_CERT.decode()
    - fullchain_pem = cert_pem + chain_pem
    - spacey_fullchain_pem = cert_pem + u'\n' + chain_pem
    - crlf_fullchain_pem = fullchain_pem.replace(u'\n', u'\r\n')
    + cert_pem: str = CERT.decode()
    + chain_pem: str = cert_pem + SS_CERT.decode()
    + fullchain_pem: str = cert_pem + chain_pem
    + spacey_fullchain_pem: str = cert_pem + u'\n' + chain_pem
    + crlf_fullchain_pem: str = fullchain_pem.replace(u'\n', u'\r\n')

    # In the ACME v1 code path, the fullchain is constructed by loading cert+chain DERs
    - # and using OpenSSL to dump them, so here we confirm that OpenSSL is producing certs
    + # and using OpenSSL to dump them, so here we confirm that cryptography is producing certs
    # that will be parseable by cert_and_chain_from_fullchain.
    acmev1_fullchain_pem = self._parse_and_reencode_pem(cert_pem) + \
    self._parse_and_reencode_pem(cert_pem) + self._parse_and_reencode_pem(SS_CERT.decode())
    diff -Nru python-certbot-2.11.0/certbot/_internal/tests/display/ops_test.py python-certbot-4.0.0/certbot/_internal/tests/display/ops_test.py
    --- python-certbot-2.11.0/certbot/_internal/tests/display/ops_test.py 2024-06-05 17:34:02.000000000 -0400
    +++ python-certbot-4.0.0/certbot/_internal/tests/display/ops_test.py 2025-04-07 18:03:33.000000000 -0400
    @@ -35,7 +35,7 @@
    with pytest.raises(errors.Error):
    self._call()
    with pytest.raises(errors.Error):
    - self._call(optional=False)
    + self._call()

    @test_util.patch_display_util()
    def test_ok_safe(self, mock_get_utility):
    @@ -55,7 +55,7 @@

    @test_util.patch_display_util()
    def test_invalid_flag(self, mock_get_utility):
    - invalid_txt = "There seem to be problems"
    + invalid_txt = "The server reported a problem"
    mock_input = mock_get_utility().input
    mock_input.return_value = (display_util.OK, "[email protected]")
    with mock.patch("certbot.display.ops.util.safe_email") as mock_safe_email:
    @@ -66,18 +66,8 @@
    assert invalid_txt in mock_input.call_args[0][0]

    @test_uti