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
- Create a certificate object for a public key
- Add attributes
- 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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Hashes for sshkey_tools-0.8-py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 91ac36a5aa76853b04f290ca8f832d25215412c1ebd9317a058881a0bc96437c |
|
MD5 | 7ad143b8d05015f10339d613105e04e3 |
|
BLAKE2b-256 | c62f6dc29e747d72ee983f4782cb68749c24e555dcb441a0f050da74eb9183e2 |