Skip to main content

A Python module for generating, parsing and handling OpenSSH keys and certificates

Project description

sshkey-tools (Work in progress)

Python and CLI tools for managing OpenSSH keypairs and certificates

Usage

sshkey --help

Table of Contents

Python Usage

Private keys

Generalized class

from sshkey_tools.keys import PrivateKey

# Load from keyfile (Returns sshkey_tools.keys.RSAPrivateKey, etc.)
key = PrivateKey.from_file('id_rsa')

# Load from string/file contents (Returns sshkey_tools.keys.RSAPrivateKey for RSA, etc.)
key = PrivateKey.from_string('-----Begin.......... End-----')

# Load from key bytes (inner bytes, without comment and key type prefix)
key = PrivateKey.from_bytes(b'%x00%x00......')

# If the key is password protected, set the password variable
key = PrivateKey.from_...('', password='abc123')

Specific key classes

In addition to specifically loading e.g. an RSA key with the from_bytes, from_string or from_file methods above, you can also specifically load a key type with that function with e.g. RSAPrivateKey.from_file('filename')

from sshkey_tools.keys import (
    RSAPrivateKey,
    DSAPrivateKey,
    ECDSAPrivateKey,
    ED25519PrivateKey
)


# Generate new RSA key
key = RSAPrivateKey.generate(
    key_size=4096,
    public_exponent=65537
)

# Generate new DSA/DSS key
key = DSAPrivateKey.generate(
    key_size=4096,
)

# Generate new ECDSA key
key = ECDSAPrivateKey.generate(
    curve=ECDSA_CURVES.SECP384R1()
)

# Generate new ED25519 key
key = ED25519PrivateKey.generate()

# Load RSA key from numbers
key = RSAPrivateKey.from_numbers(
    n=123123,
    e=123123,
    p=123123,
    q=123123,    # Optional
    d=123123,    # Optional
    dmp1=123123, # Optional
    dmq1=123123, # Optional
    iqmp=123123  # Optional
)

# Load DSA key from numbers
key = DSAPrivateKey.from_numbers(
    p=123123,
    q=123123,
    g=123123,
    y=123123,
    x=123123
)

# Load ECDSA key from numbers
key = ECDSAPrivateKey.from_numbers(
    private_number=123123,
    x=123123,
    y=123123,
    curve=ECDSA_CURVES.SECP384R1()
)


# ED25519 keys don't support loading from numbers

Exporting private keys

The export class looks the same on all the PrivateKey-classes, the example below will use the general PrivateKey class but everything works the same for the specific classes

from sshkey_tools.keys import FORMAT

# key is an instance of PrivateKey or any of its subclasses

key_str = key.to_string(FORMAT.OpenSSH)
print(key_str)
"""
-----BEGIN OPENSSH PRIVATE KEY-----
ABCDEFG.......
-----END OPENSSH PRIVATE KEY-----
"""

# Produces the same output as above, but writes it directly to file
key.to_file('samplekey', FORMAT.OpenSSH)

key_bin = key.to_bytes(FORMAT.BARE)
print(key_bin)
b"""
%x0f%x00%x12.......
"""

Public Keys

Generalized class

from sshkey_tools.keys import PrivateKey, PublicKey

# Load from keyfile (Returns sshkey_tools.keys.RSAPrivateKey, etc.)
public_key = PublicKey.from_file('id_rsa.pub')

# Load from string/file contents (Returns sshkey_tools.keys.RSAPublicKey for RSA, etc.)
public_key = PublicKey.from_string('ssh-rsa AA.......... someone@somehost')

# Load from key bytes (inner bytes, without comment and key type prefix)
public_key = PublicKey.from_bytes(b'%x00%x00......')

# Load public key from private key class 
private_key = PrivateKey.from_file('id_rsa')
public_key = private_key.public_key()

Specific key classes

In addition to specifically loading e.g. an RSA key with the from_bytes, from_string or from_file methods above, you can also specifically load a key type with that function with e.g. RSAPrivateKey.from_file('filename')

from sshkey_tools.keys import (
    RSAPublicKey,
    DSAPublicKey,
    ECDSAPublicKey,
    ED25519PublicKey
)

# Load RSA public key from numbers
key = RSAPublicKey.from_numbers(
    n=123123,
    e=123123
)

# Load DSA public key from numbers
key = DSAPublicKey.from_numbers(
    p=123123,
    q=123123,
    g=123123,
    y=123123
)

# Load ECDSA public key from numbers
key = ECDSAPublicKey.from_numbers(
    x=123123,
    y=123123,
    curve=ECDSA_CURVES.SECP384R1()
)


# ED25519 keys don't support loading from numbers

Exporting public keys

# pubkey can be an instance of any of the PublicKeyClass children

Certificates

Generalized classes

from sshkey_tools.cert import SSHCertificate

## Existing certificates

# Load from file (Returns specific class, e.g. sshkey_tools.cert.RSACertificate)
certificate = SSHCertificate.from_file('id_rsa-cert.pub')

# Load from string/file contents
certificate = SSHCertificate.from_string('ssh-rsa-cert-v01@openssh.com AA.......... someone@somehost')

# Load from key bytes (inner bytes, without comment and type prefix)
certificate = SSHCertificate.from_bytes(b'%x00%x00.......')

## New certificates


# Create a blank certificate for a specific public key, automatically returns the right certificate class
certificate = SSHCertificate.from_public(PublicKeyClass pubkey)

# Create a certificate from a dictionary with values
# The only mandatory value at this stage is the public_key that is to be signed
cert_val = {
    "serial": "abcdef",
    "key_id": 123123,
    "public_key": pubkey
}

certificate = SSHCertificate.from_dict(cert_val)

Specific certificate classes

from sshkey_tools.cert import (
    RSACertificate,
    DSACertificate,
    ECDSACertificate,
    ED25519Certificate
)

The signing process

The signing process consists of three main steps

  1. Create a certificate object for a public key
  2. Add attributes
  3. Sign the certificate with your CA

Create a certificate for a public key

from sshkey_tools.keys import PublicKey, PrivateKey
from sshkey_tools.cert import SSHCertificate

# Load the client public key and the CA private key
client_pubkey = PublicKey.from_file('client.pub')
ca_privkey = PrivateKey.from_file('ca_key')

# Create a blank certificate object from the client public key
# The certificate type is defined by the client key, not the CA
certificate = SSHCertificate.from_public(client_pubkey)

# Add the required attributes to the key
# All attributes can be set either by set_[name](value) or via the set_array function
certificate.set_type(USER)
certificate.set_array(
    "serial": "abc123",
    "key_id": 123,
    "principals": [
        'webservers',
        'database'
    ]
    .....
)

# Once done, make sure the certificate has all the required attributes
# Then, feed the CA Private key to the sign function
if certificate.can_sign():
    certificate.sign(ca_privkey)

# You can check if the certificate has been successfully signed with the is_signature_valid() function
# Then, export the certificate to file, string or bytes
if certificate.is_signature_valid():
    # If no filename is provided, the certificate is saved as [user_pubkey_name]-cert.pub
    certificate.to_file('id_rsa-cert.pub')
    cert_string = certificate.to_string()
    cert_bytes = certificate.to_bytes()

TODO

  • PrivateKey.to_file/string/bytes
  • PublicKey.to_file/string/bytes
  • Certificate.to_file/string/bytes
  • Exceptions.py

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

sshkey-tools-0.4.post2384544826.tar.gz (34.3 kB view details)

Uploaded Source

Built Distribution

sshkey_tools-0.4.post2384544826-py3-none-any.whl (34.4 kB view details)

Uploaded Python 3

File details

Details for the file sshkey-tools-0.4.post2384544826.tar.gz.

File metadata

File hashes

Hashes for sshkey-tools-0.4.post2384544826.tar.gz
Algorithm Hash digest
SHA256 8ed1c8893286a4e577cbab641a6641ce31279f83b2776f09d885ce81432d99b4
MD5 77a28d11c6ff81be3fa33263c3d6d594
BLAKE2b-256 2e00ff589c7f2f083a3cb4d9f601f5f2597761034f45275dbc2bdafd6ae2ceb1

See more details on using hashes here.

File details

Details for the file sshkey_tools-0.4.post2384544826-py3-none-any.whl.

File metadata

File hashes

Hashes for sshkey_tools-0.4.post2384544826-py3-none-any.whl
Algorithm Hash digest
SHA256 3b334e20f11115364094661c8ff09fd0aa16bf130c0577238bf7119b73b3af87
MD5 3b15a80e0e737ece482ef286b08c14bc
BLAKE2b-256 b956a15056aea15906c79bb5389f09ecd6b86d88300c7daac9c855c3ceb19c01

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page