logo
Expand description

RustCrypto: SSH Key and Certificate Formats

crate Docs Build Status Apache2/MIT licensed Rust Version Project Chat

Documentation

About

Pure Rust implementation of SSH key file format decoders/encoders as described in RFC4251 and RFC4253 as well as OpenSSH’s PROTOCOL.key format specification.

Additionally provides support for OpenSSH certificates as specified in PROTOCOL.certkeys including certificate validation and certificate authority (CA) support, as well as FIDO/U2F keys as specified in PROTOCOL.u2f (and certificates thereof), and also the authorized_keys and known_hosts file formats.

Supports a minimal profile which works on heapless no_std targets. See “Supported algorithms” table below for which key formats work on heapless targets and which algorithms require alloc.

When the ed25519, p256, and/or rsa features of this crate are enabled, provides key generation and certificate signing/verification support for that respective SSH key algorithm.

Features

  • Constant-time Base64 decoder/encoder using base64ct/pem-rfc7468 crates
  • OpenSSH-compatible decoder/encoders for the following formats:
    • OpenSSH public keys
    • OpenSSH private keys (i.e. BEGIN OPENSSH PRIVATE KEY)
    • OpenSSH certificates
  • OpenSSH certificates
    • Certificate validation
    • Certificate authority (CA) support i.e. cert builder/signer
  • Private key encryption/decryption (bcrypt-pbkdf + aes256-ctr only)
  • Private key generation support: Ed25519, ECDSA/P-256, and RSA
  • FIDO/U2F key support (sk-*) as specified in PROTOCOL.u2f
  • Fingerprint support
  • no_std support including support for “heapless” (no-alloc) targets
  • Parsing authorized_keys files
  • Parsing known_hosts files
  • serde support
  • zeroize support for private keys
TODO
  • ECDSA/P-384 support
  • ECDSA/P-512 support
  • FIDO/U2F signature support
  • Legacy (pre-OpenSSH) SSH key format support
    • PKCS#1
    • PKCS#8
    • RFC4716 public keys
    • SEC1

Supported algorithms

NameDecodeEncodeCertKeygenSignVerifyFeatureno_std
ecdsa‑sha2‑nistp256✅️✅️✅️p256heapless
ecdsa‑sha2‑nistp384⛔️⛔️⛔️heapless
ecdsa‑sha2‑nistp521⛔️⛔ ️⛔️heapless
ssh‑dsa⛔️⛔️alloc
ssh‑ed25519✅️✅️ed25519heapless
ssh‑rsa✅️✅️rsaalloc
sk‑ecdsa‑sha2‑nistp256@openssh.com⛔️⛔️alloc
sk‑ssh‑ed25519@openssh.com⛔️⛔️alloc

Note: the “Feature” section lists the name of ssh-key crate features which can be enabled to provide full support for the “Keygen”, “Sign”, and “Verify” functionality for a particular SSH key algorithm.

Minimum Supported Rust Version

This crate requires Rust 1.57 at a minimum.

We may change the MSRV in the future, but it will be accompanied by a minor version bump.

License

Licensed under either of:

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Usage

The main types provided by this library are:

  • Certificate: OpenSSH certificates
  • Fingerprint: public key fingerprints (i.e. hashes)
  • PrivateKey: SSH private keys (i.e. digital signature keys)
  • PublicKey: SSH public keys (i.e. signature verification keys)

Parsing OpenSSH Public Keys

OpenSSH-formatted public keys have the form:

<algorithm id> <base64 data> <comment>
Example
use ssh_key::PublicKey;

let encoded_key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILM+rvN+ot98qgEN796jTiQfZfG1KaT0PtFDJ/XFSqti user@example.com";
let public_key = PublicKey::from_openssh(encoded_key)?;

// Key attributes
assert_eq!(public_key.algorithm(), ssh_key::Algorithm::Ed25519);
assert_eq!(public_key.comment(), "user@example.com");

// Key data: in this example an Ed25519 key
if let Some(ed25519_public_key) = public_key.key_data().ed25519() {
    assert_eq!(
        ed25519_public_key.as_ref(),
        [
            0xb3, 0x3e, 0xae, 0xf3, 0x7e, 0xa2, 0xdf, 0x7c, 0xaa, 0x1, 0xd, 0xef, 0xde, 0xa3,
            0x4e, 0x24, 0x1f, 0x65, 0xf1, 0xb5, 0x29, 0xa4, 0xf4, 0x3e, 0xd1, 0x43, 0x27, 0xf5,
            0xc5, 0x4a, 0xab, 0x62
        ].as_ref()
    );
}

Parsing OpenSSH Private Keys

NOTE: for more private key usage examples, see the private module.

OpenSSH-formatted private keys are PEM-encoded and begin with the following:

-----BEGIN OPENSSH PRIVATE KEY-----
Example
use ssh_key::PrivateKey;

// WARNING: don't actually hardcode private keys in source code!!!
let encoded_key = r#"
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACCzPq7zfqLffKoBDe/eo04kH2XxtSmk9D7RQyf1xUqrYgAAAJgAIAxdACAM
XQAAAAtzc2gtZWQyNTUxOQAAACCzPq7zfqLffKoBDe/eo04kH2XxtSmk9D7RQyf1xUqrYg
AAAEC2BsIi0QwW2uFscKTUUXNHLsYX4FxlaSDSblbAj7WR7bM+rvN+ot98qgEN796jTiQf
ZfG1KaT0PtFDJ/XFSqtiAAAAEHVzZXJAZXhhbXBsZS5jb20BAgMEBQ==
-----END OPENSSH PRIVATE KEY-----
"#;

let private_key = PrivateKey::from_openssh(encoded_key)?;

// Key attributes
assert_eq!(private_key.algorithm(), ssh_key::Algorithm::Ed25519);
assert_eq!(private_key.comment(), "user@example.com");

// Key data: in this example an Ed25519 key
if let Some(ed25519_keypair) = private_key.key_data().ed25519() {
   assert_eq!(
       ed25519_keypair.public.as_ref(),
       [
           0xb3, 0x3e, 0xae, 0xf3, 0x7e, 0xa2, 0xdf, 0x7c, 0xaa, 0x1, 0xd, 0xef, 0xde, 0xa3,
           0x4e, 0x24, 0x1f, 0x65, 0xf1, 0xb5, 0x29, 0xa4, 0xf4, 0x3e, 0xd1, 0x43, 0x27, 0xf5,
           0xc5, 0x4a, 0xab, 0x62
       ].as_ref()
   );

   assert_eq!(
       ed25519_keypair.private.as_ref(),
       [
           0xb6, 0x6, 0xc2, 0x22, 0xd1, 0xc, 0x16, 0xda, 0xe1, 0x6c, 0x70, 0xa4, 0xd4, 0x51,
           0x73, 0x47, 0x2e, 0xc6, 0x17, 0xe0, 0x5c, 0x65, 0x69, 0x20, 0xd2, 0x6e, 0x56, 0xc0,
           0x8f, 0xb5, 0x91, 0xed
       ].as_ref()
   )
}

serde support

When the serde feature of this crate is enabled, the Certificate, Fingerprint, and PublicKey types receive impls of serde’s Deserialize and Serialize traits.

Serializing/deserializing PrivateKey using serde is presently unsupported.

Re-exports

pub use crate::authorized_keys::AuthorizedKeys;
pub use crate::private::PrivateKey;
pub use crate::public::PublicKey;
pub use pem_rfc7468 as pem;
pub use crate::certificate::Certificate;
pub use crate::known_hosts::KnownHosts;
pub use sec1;
pub use rand_core;

Modules

Parser for AuthorizedKeysFile-formatted data.

OpenSSH certificate support.

Parser for KnownHostsFile-formatted data.

SSH private key support.

SSH public key support.

Structs

MPIntalloc

Multiple precision integer, a.k.a. “mpint”.

Digital signature (e.g. DSA, ECDSA, Ed25519).

Enums

SSH key algorithms.

Cipher algorithms.

Elliptic curves supported for use with ECDSA.

Error type.

Fingerprintfingerprint

SSH public key fingerprints.

Hashing algorithms a.k.a. digest functions.

Key Derivation Functions (KDF).

Key Derivation Function (KDF) algorithms.

Line endings: variants of newline characters that can be used with Base64.

Type Definitions

Result type with ssh-key’s Error as the error type.