import logging import os from exec.cmd import run_cmd from exec.file import get_temp_dir, makedir, write_file GPG_ARGS = ["--batch", "--no-tty"] def get_gpg_creation_script( key_name: str = "Kupfer Local Signing", email: str = "local@kupfer.mobi", comment: str = "Generated by kupferbootstrap", ): return f""" %echo Generating a new ed25519 GPG key for "{key_name} <{email}> # {comment}" %no-protection Key-Type: eddsa Key-Curve: Ed25519 Key-Usage: cert,sign Subkey-Type: ecdh Subkey-Curve: Curve25519 Subkey-Usage: encrypt Name-Real: {key_name} Name-Comment: {comment} Name-Email: {email} Expire-Date: 0 # Do a commit here, so that we can later print "done" %commit %echo done """ def create_secret_key(location: str, *, gpg_binary: str = "gpg", **creation_args): makedir(os.path.dirname(location)) temp_dir = get_temp_dir() script_file = os.path.join(temp_dir, "__gpg_creation_script") write_file(script_file, content=get_gpg_creation_script(**creation_args)) logging.info(f"Creating new GPG key for {location!r}") run_cmd([gpg_binary, *GPG_ARGS, "--homedir", temp_dir, "--generate-key", script_file]).check_returncode() res = run_cmd( [gpg_binary, *GPG_ARGS, "--homedir", temp_dir, "--armor", "--export-secret-keys"], capture_output=True ) if not (res.stdout and res.stdout.strip()): raise Exception(f"Failed to get secret GPG key from stdout: {res.stdout=}\n{res.stderr=}") logging.debug(f"Writing GPG private key to {location}") write_file(location, content=res.stdout, mode="600")