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
File details
Details for the file sshkey-tools-0.4.post2384544826.tar.gz
.
File metadata
- Download URL: sshkey-tools-0.4.post2384544826.tar.gz
- Upload date:
- Size: 34.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.0 CPython/3.10.4
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 8ed1c8893286a4e577cbab641a6641ce31279f83b2776f09d885ce81432d99b4 |
|
MD5 | 77a28d11c6ff81be3fa33263c3d6d594 |
|
BLAKE2b-256 | 2e00ff589c7f2f083a3cb4d9f601f5f2597761034f45275dbc2bdafd6ae2ceb1 |
File details
Details for the file sshkey_tools-0.4.post2384544826-py3-none-any.whl
.
File metadata
- Download URL: sshkey_tools-0.4.post2384544826-py3-none-any.whl
- Upload date:
- Size: 34.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.0 CPython/3.10.4
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 3b334e20f11115364094661c8ff09fd0aa16bf130c0577238bf7119b73b3af87 |
|
MD5 | 3b15a80e0e737ece482ef286b08c14bc |
|
BLAKE2b-256 | b956a15056aea15906c79bb5389f09ecd6b86d88300c7daac9c855c3ceb19c01 |