def test_new_key(context: IntegrationTestsContext) -> None: """Tests --new-key and its interactions with --reuse-key""" def private_key(generation: int) -> Tuple[str, str]: pk_path = join(context.config_dir, f'archive/{certname}/privkey{generation}.pem') with open(pk_path, 'r') as file: return file.read(), pk_path certname = context.get_domain('newkey') context.certbot(['--domains', certname, '--reuse-key', '--key-type', 'rsa', '--rsa-key-size', '4096']) privkey1, _ = private_key(1) # renew: --new-key should replace the key, but keep reuse_key and the key type + params context.certbot(['renew', '--cert-name', certname, '--new-key']) privkey2, privkey2_path = private_key(2) assert privkey1 != privkey2 assert_saved_lineage_option(context.config_dir, certname, 'reuse_key', 'True') assert_rsa_key(privkey2_path, 4096) # certonly: it should replace the key but the key size will change context.certbot(['certonly', '-d', certname, '--reuse-key', '--new-key']) privkey3, privkey3_path = private_key(3) assert privkey2 != privkey3 assert_saved_lineage_option(context.config_dir, certname, 'reuse_key', 'True') assert_rsa_key(privkey3_path, 2048) # certonly: it should be possible to change the key type and keep reuse_key context.certbot(['certonly', '-d', certname, '--reuse-key', '--new-key', '--key-type', 'ecdsa', '--cert-name', certname]) privkey4, privkey4_path = private_key(4) assert privkey3 != privkey4 assert_saved_lineage_option(context.config_dir, certname, 'reuse_key', 'True') assert_elliptic_key(privkey4_path, SECP256R1)
def test_revoke_ecdsa_cert_key_delete(context: IntegrationTestsContext, curve: str, curve_cls: Type[EllipticCurve], skip_servers: Iterable[str]) -> None: """Test revoke and deletion for each supported curve type""" if context.acme_server in skip_servers: pytest.skip( f'ACME server {context.acme_server} does not support ECDSA curve {curve}' ) cert: str = context.get_domain('curve') context.certbot([ 'certonly', '--key-type', 'ecdsa', '--elliptic-curve', curve, '-d', cert, ]) key = join(context.config_dir, "live", cert, 'privkey.pem') cert_path = join(context.config_dir, "live", cert, 'cert.pem') assert_elliptic_key(key, curve_cls) context.certbot([ 'revoke', '--cert-path', cert_path, '--key-path', key, '--delete-after-revoke', ]) assert not exists(cert_path)
def test_revoke_ecdsa_cert_key(context: IntegrationTestsContext, curve: str, curve_cls: Type[EllipticCurve], skip_servers: Iterable[str]) -> None: """Test revoking a certificate """ if context.acme_server in skip_servers: pytest.skip( f'ACME server {context.acme_server} does not support ECDSA curve {curve}' ) cert: str = context.get_domain('curve') context.certbot([ 'certonly', '--key-type', 'ecdsa', '--elliptic-curve', curve, '-d', cert, ]) key = join(context.config_dir, "live", cert, 'privkey.pem') cert_path = join(context.config_dir, "live", cert, 'cert.pem') assert_elliptic_key(key, curve_cls) context.certbot([ 'revoke', '--cert-path', cert_path, '--key-path', key, '--no-delete-after-revoke', ]) stdout, _ = context.certbot(['certificates']) assert stdout.count( 'INVALID: REVOKED') == 1, 'Expected {0} to be REVOKED'.format(cert)
def test_default_curve_type(context: IntegrationTestsContext) -> None: """test that the curve used when not specifying any is secp256r1""" certname = context.get_domain('renew') context.certbot([ '--key-type', 'ecdsa', '--cert-name', certname, '-d', certname ]) key1 = join(context.config_dir, 'archive/{0}/privkey1.pem'.format(certname)) assert_elliptic_key(key1, SECP256R1)
def test_ecdsa_curves(context, curve, curve_cls, skip_servers): """Test issuance for each supported ECDSA curve""" if context.acme_server in skip_servers: pytest.skip('ACME server {} does not support ECDSA curve {}' .format(context.acme_server, curve)) domain = context.get_domain('curve') context.certbot([ 'certonly', '--key-type', 'ecdsa', '--elliptic-curve', curve, '--force-renewal', '-d', domain, ]) key = join(context.config_dir, "live", domain, 'privkey.pem') assert_elliptic_key(key, curve_cls)
def test_renew_with_ec_keys(context): """Test proper renew with updated private key complexity.""" certname = context.get_domain('renew') context.certbot([ 'certonly', '--cert-name', certname, '--key-type', 'ecdsa', '--elliptic-curve', 'secp256r1', '--force-renewal', '-d', certname, ]) key1 = join(context.config_dir, "archive", certname, 'privkey1.pem') assert 200 < os.stat( key1).st_size < 250 # ec keys of 256 bits are ~225 bytes assert_elliptic_key(key1, SECP256R1) assert_cert_count_for_lineage(context.config_dir, certname, 1) context.certbot(['renew', '--elliptic-curve', 'secp384r1']) assert_cert_count_for_lineage(context.config_dir, certname, 2) key2 = join(context.config_dir, 'archive', certname, 'privkey2.pem') assert_elliptic_key(key2, SECP384R1) assert 280 < os.stat( key2).st_size < 320 # ec keys of 384 bits are ~310 bytes # We expect here that the command will fail because without --key-type specified, # Certbot must error out to prevent changing an existing certificate key type, # without explicit user consent (by specifying both --cert-name and --key-type). with pytest.raises(subprocess.CalledProcessError): context.certbot(['certonly', '--force-renewal', '-d', certname]) # We expect that the previous behavior of requiring both --cert-name and # --key-type to be set to not apply to the renew subcommand. context.certbot(['renew', '--force-renewal', '--key-type', 'rsa']) assert_cert_count_for_lineage(context.config_dir, certname, 3) key3 = join(context.config_dir, 'archive', certname, 'privkey3.pem') assert_rsa_key(key3)
def test_renew_with_ec_keys(context: IntegrationTestsContext) -> None: """Test proper renew with updated private key complexity.""" certname = context.get_domain('renew') context.certbot([ 'certonly', '--cert-name', certname, '--key-type', 'ecdsa', '--elliptic-curve', 'secp256r1', '--force-renewal', '-d', certname, ]) key1 = join(context.config_dir, "archive", certname, 'privkey1.pem') assert 200 < os.stat(key1).st_size < 250 # ec keys of 256 bits are ~225 bytes assert_elliptic_key(key1, SECP256R1) assert_cert_count_for_lineage(context.config_dir, certname, 1) assert_saved_lineage_option(context.config_dir, certname, 'key_type', 'ecdsa') context.certbot(['renew', '--elliptic-curve', 'secp384r1']) assert_cert_count_for_lineage(context.config_dir, certname, 2) key2 = join(context.config_dir, 'archive', certname, 'privkey2.pem') assert 280 < os.stat(key2).st_size < 320 # ec keys of 384 bits are ~310 bytes assert_elliptic_key(key2, SECP384R1) # When running non-interactively, if --key-type is unspecified but the default value differs # to the lineage key type, Certbot should keep the lineage key type. The curve will still # change to the default value, in order to stay consistent with the behavior of certonly. context.certbot(['certonly', '--force-renewal', '-d', certname]) assert_cert_count_for_lineage(context.config_dir, certname, 3) key3 = join(context.config_dir, 'archive', certname, 'privkey3.pem') assert 200 < os.stat(key3).st_size < 250 # ec keys of 256 bits are ~225 bytes assert_elliptic_key(key3, SECP256R1) # When running non-interactively, specifying a different --key-type requires user confirmation # with both --key-type and --cert-name. with pytest.raises(subprocess.CalledProcessError) as error: context.certbot(['certonly', '--force-renewal', '-d', certname, '--key-type', 'rsa']) assert 'Please provide both --cert-name and --key-type' in error.value.stderr context.certbot(['certonly', '--force-renewal', '-d', certname, '--key-type', 'rsa', '--cert-name', certname]) assert_cert_count_for_lineage(context.config_dir, certname, 4) key4 = join(context.config_dir, 'archive', certname, 'privkey4.pem') assert_rsa_key(key4) # We expect that the previous behavior of requiring both --cert-name and # --key-type to be set to not apply to the renew subcommand. context.certbot(['renew', '--force-renewal', '--key-type', 'ecdsa']) assert_cert_count_for_lineage(context.config_dir, certname, 5) key5 = join(context.config_dir, 'archive', certname, 'privkey5.pem') assert 200 < os.stat(key5).st_size < 250 # ec keys of 256 bits are ~225 bytes assert_elliptic_key(key5, SECP256R1)