logo
Expand description

RustCrypto: SSH Key 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 RFC4253 and RFC4716 as well as OpenSSH’s PROTOCOL.key format specification and authorized_keys files.

Features

  • Constant-time Base64 decoding/encoding using the base64ct crate
  • no_std support including support for “heapless” (no-alloc) targets
  • Decoding/encoding OpenSSH-formatted public & private keys:
    • DSA (no_std + alloc)
    • ECDSA (no_std “heapless”)
    • Ed25519 (no_std “heapless”)
    • RSA (no_std + alloc)
  • Fingerprint support (SHA-256 only)
  • Parsing authorized_keys files
  • Built-in zeroize support for private keys
TODO
  • Encrypted private key support
  • SSH certificate support
  • Legacy SSH key (pre-OpenSSH) format support
  • Integrations with other RustCrypto crates (e.g. ecdsa, ed25519, rsa)
  • FIDO2 key support

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

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

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()
   )
}

Re-exports

pub use crate::authorized_keys::AuthorizedKeys;
pub use crate::private::PrivateKey;
pub use crate::public::PublicKey;
pub use sec1;

Modules

Parser for AuthorizedKeysFile-formatted data.

SSH private key support.

SSH public key support.

Structs

Key Derivation Function (KDF) options.

MPIntalloc

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

SSH key fingerprints calculated using the SHA-256 hash function.

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 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.