1
0
mirror of https://github.com/moepman/acertmgr.git synced 2024-06-26 06:25:08 +02:00

tools/configuration: Add support for EC/Ed25519/Ed448 generation

This commit is contained in:
Kishi85 2019-04-19 15:16:06 +02:00
parent 4f0fe2c74a
commit 6a07ab1188
5 changed files with 56 additions and 21 deletions

View File

@ -69,9 +69,12 @@ By default the directory (work_dir) containing the working data (csr,certificate
| authority_tos_agreement | d,**g**,c | Indicates agreement to the ToS of the certificate authority (--authority-tos-agreement on command line) | |
| authority_contact_email | d,**g** | (v2 API only) Contact e-mail to be registered with your account key | |
| account_key | d,**g** | Path to the account key | {work_dir}/account.key |
| account_key_algorithm | d,**g** | Key-algorithm for newly generated account keys (RSA, EC, ED25519, ED448) | RSA |
| account_key_length | d,**g** | Key-length for newly generated RSA account keys (in bits) or EC curve (256=P-256, 384=P-384, 521=P-521) | depends on account_key_algorithm |
| ttl_days | d,**g** | Renew certificate if it has less than this value validity left | 30 |
| cert_dir | d,**g** | Directory containing all certificate related data (crt,key,csr) | {work_dir} |
| key_length | d,**g** | Key-length for newly generated private keys | 4096 |
| key_algorithm | d,**g** | Key-algorithm for newly generated private keys (RSA, EC, ED25519, ED448) | RSA |
| key_length | d,**g** | Key-length for newly generated RSA private keys (in bits) or EC curve (256=P-256, 384=P-384, 521=P-521) | depends on key_algorithm |
| csr_static | **d**,g | Whether to re-use a static CSR or generate a new dynamic CSR | false |
| csr_file | **d**,g | Path to store (and load) the certificate CSR file | {cert_dir}/{cert_id}.csr |
| ca_static | **d**,g | Whether to re-use a static CA or download a CA file | false |

View File

@ -35,12 +35,11 @@ def cert_get(settings):
# create ssl key
key_file = settings['key_file']
key_length = settings['key_length']
if os.path.isfile(key_file):
key = tools.read_pem_file(key_file, key=True)
else:
log("SSL key not found at '{0}'. Creating {1} bit key.".format(key_file, key_length))
key = tools.new_ssl_key(key_file, key_length)
log("SSL key not found at '{0}'. Creating key.".format(key_file))
key = tools.new_ssl_key(key_file, settings['key_algorithm'], settings['key_length'])
# create ssl csr
csr_file = settings['csr_file']

View File

@ -28,7 +28,7 @@ def authority(settings):
acc_key = tools.read_pem_file(acc_file, key=True)
else:
log("Account key not found at '{0}'. Creating key.".format(acc_file))
acc_key = tools.new_account_key(acc_file)
acc_key = tools.new_account_key(acc_file, settings['account_key_algorithm'], settings['account_key_size'])
authority_module = importlib.import_module("acertmgr.authority.{0}".format(settings["api"]))
authority_class = getattr(authority_module, "ACMEAuthority")

View File

@ -32,7 +32,6 @@ LEGACY_AUTHORITY_TOS_AGREEMENT = "true"
# Configuration defaults to use if not specified otherwise
DEFAULT_CONF_FILE = "/etc/acertmgr/acertmgr.conf"
DEFAULT_CONF_DIR = "/etc/acertmgr"
DEFAULT_KEY_LENGTH = 4096 # bits
DEFAULT_TTL = 30 # days
DEFAULT_API = "v2"
DEFAULT_AUTHORITY = "https://acme-v02.api.letsencrypt.org"
@ -105,6 +104,14 @@ def parse_authority(localconfig, globalconfig, runtimeconfig):
# - Account key path
update_config_value(authority, 'account_key', localconfig, globalconfig,
os.path.join(runtimeconfig['work_dir'], "account.key"))
# - Account key algorithm (if key has to be (re-)generated)
update_config_value(authority, 'account_key_algorithm', localconfig, globalconfig, None)
# - Account key length (if key has to be (re-)generated, converted to int)
update_config_value(authority, 'account_key_length', localconfig, globalconfig, None)
authority['account_key_length'] = int(authority['account_key_length']) if authority['account_key_length'] else None
return authority
@ -162,9 +169,12 @@ def parse_config_entry(entry, globalconfig, runtimeconfig):
globalconfig.get('server_key',
os.path.join(config['cert_dir'], "{}.key".format(config['id']))))
# SSL key algorithm (if key has to be (re-)generated)
update_config_value(config, 'key_algorithm', localconfig, globalconfig, None)
# SSL key length (if key has to be (re-)generated, converted to int)
update_config_value(config, 'key_length', localconfig, globalconfig, DEFAULT_KEY_LENGTH)
config['key_length'] = int(config['key_length'])
update_config_value(config, 'key_length', localconfig, globalconfig, None)
config['key_length'] = int(config['key_length']) if config['key_length'] else None
# SSL CA location / use static
update_config_value(config, 'ca_file', localconfig, globalconfig,

View File

@ -116,24 +116,47 @@ def new_cert_request(names, key, must_staple=False):
# @brief generate a new account key
# @param path path where the new key file should be written in PEM format (optional)
def new_account_key(path=None, key_size=4096):
return new_ssl_key(path, key_size)
def new_account_key(path=None, key_algo=None, key_size=None):
return new_ssl_key(path, key_algo, key_size)
# @brief generate a new ssl key
# @param path path where the new key file should be written in PEM format (optional)
def new_ssl_key(path=None, key_size=4096):
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=key_size,
backend=default_backend()
)
pem = private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.TraditionalOpenSSL,
encryption_algorithm=serialization.NoEncryption()
)
def new_ssl_key(path=None, key_algo=None, key_size=None):
if not key_algo or key_algo.lower() == 'rsa':
if not key_size:
key_size = 4096
key_format = serialization.PrivateFormat.TraditionalOpenSSL
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=key_size,
backend=default_backend()
)
elif key_algo.lower() == 'ec':
if not key_size or key_size == 256:
key_curve = ec.SECP256R1
elif key_size == 384:
key_curve = ec.SECP384R1
elif key_size == 521:
key_curve = ec.SECP521R1
else:
raise ValueError("Unsupported EC curve size parameter: {}".format(key_size))
key_format = serialization.PrivateFormat.PKCS8
private_key = ec.generate_private_key(curve=key_curve, backend=default_backend())
elif key_algo.lower() == 'ed25519' and "cryptography.hazmat.primitives.asymmetric.ed25519":
key_format = serialization.PrivateFormat.PKCS8
private_key = ed25519.Ed25519PrivateKey.generate()
elif key_algo.lower() == 'ed448' and "cryptography.hazmat.primitives.asymmetric.ed448":
key_format = serialization.PrivateFormat.PKCS8
private_key = ed448.Ed448PrivateKey.generate()
else:
raise ValueError("Unsupported key algorithm: {}".format(key_algo))
if path is not None:
pem = private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=key_format,
encryption_algorithm=serialization.NoEncryption(),
)
with io.open(path, 'wb') as pem_out:
pem_out.write(pem)
try: