ssh-keygen wrapper in Python 3.6

mksshkey

I prefer separate SSH keys for remote services, especially if I don’t control the other end of the connection. To make it easier to accomplish, I have been using the following script for a while. Since this is not a part of any project I have published, here it is:

#!/usr/bin/env python3
#
# mksshkey.py
#
import os
import click
import pyperclip
from plumbum import local


SUPPORTED_KEY_TYPES = ["ed25519", "ecdsa", "rsa"]


@click.command()
@click.option('--hostname', prompt="Create SSH key for hostname/service")
@click.option('--key-type', default="ed25519", type=click.Choice(SUPPORTED_KEY_TYPES))
@click.option('--debug', is_flag=True, default=False)
def cli(hostname: str, key_type: str, debug: bool):
    """
    Generate new SSH keypair for a remote service (and copy to clipboard).
    """
    ssh_keygen = local["ssh-keygen"]
    username = os.path.expanduser("~").split("/").pop()
    ssh_key_path = os.path.expanduser(f"~/.ssh/{hostname}")

    if os.path.exists(ssh_key_path):
        click.echo(f"{ssh_key_path} exists!")
        raise click.Abort()

    if key_type == "ed25519":
        command = f"-t ed25519 -f {ssh_key_path} -C {username}@{hostname}"
    elif key_type == "ecdsa":
        command = f"-t ecdsa -b 521 -f {ssh_key_path} -C {username}@{hostname}"
    elif key_type == "rsa":
        command = f"-t rsa -b 4096 -f {ssh_key_path} -C {username}@{hostname}"
    else:
        click.echo(f"Unsupported key type: {key_type}")
        raise click.Abort()

    if debug:
        click.echo("ssh-keygen " + command)
    ssh_keygen(command.split())
    public_key = open(f"{ssh_key_path}.pub").read()

    try:
        pyperclip.copy(public_key)
        click.echo(f"Public key for {hostname} copied to clipboard.")
    except Exception:
        click.echo(f"Public key for {hostname} saved to ~/.ssh/{hostname}.pub")


cli()
Note: Requires Python 3.6+. and python packages: click, plumbum, pyperclip.

Install it like any good ol’ shell script you found on the Internet (and read the source to verify it does nothing nasty!)…

  • pip3 install --user click plumbum pypeprclip.
  • Copy the contents into a file at ~/bin/mksshkey.
  • Make it executable with chmod +x ~/bin/mksshkey.
  • sh: add set PATH="$PATH:~/bin"  ;export PATH to your ~/.profile.
  • bash: add export PATH="$PATH:~/bin" to your ~/.bash_profile.
  • logout and login again, or in bash, run soure ~/.bash_profile.

To use mksshkey, simply type out the command name and hit enter.

$ mksshkey
Create SSH key for hostname/service: blogtest
Public key for blogtest copied to clipboard.

It automatically creates an ed25519 SSH keypair with the name provided, adds a comment as local-username@remote-hostname and copies the public key to clipboard.

You can find the newly generated keys where you expect them:

$ ls ~/.ssh/ | grep blogtest
blogtest
blogtest.pub

You can add the public key copied to clipboard to the remote host and call it a day :)

I prefer user interfaces where I am not forced to make the same decisions and recall the choices verbatim from memory X) When I found myself looking up what options I was supposed to use to generate ssh keys more than once, trying to recall whether it was ed25519 or ed22519 or ed25119… this script was created to help the situation.

The source code listed above is released into Public Domain.