RustCrypto SSH

repository·master·Indexed 42 days ago

https://github.com/rustcrypto/ssh

A collection of pure Rust implementations for SSH protocols, including ssh-key for handling keys, certificates, and signatures; ssh-cipher for symmetric encryption algorithms (such as AES-GCM and ChaCha20-Poly1305); ssh-encoding for RFC4251 data type decoders and encoders; and ssh-derive for procedural macros to automate encoding and decoding traits.

Tokens
28K
Snippets
84
Records
113
Agent score
53%

What's inside RustCrypto SSH

  1. Overview of ssh-key capabilities

    master

    The ssh-key crate is a pure Rust implementation of SSH key file format decoders and encoders. It supports formats described in RFC4251, RFC4253, and OpenSSH's PROTOCOL.key specification.

    Key capabilities include:

    • Encoding/Decoding: OpenSSH public keys, private keys (BEGIN OPENSSH PRIVATE KEY), certificates, and signatures (sshsig).
    • Certificates: Support for OpenSSH certificates, including validation and Certificate Authority (CA) functionality (builder/signer).
    • File Formats: Parsing of authorized_keys and known_hosts files.
    • Security: Constant-time Base64 encoding/decoding, zeroize support for private keys, and private key encryption/decryption (using bcrypt-pbkdf + aes256-ctr).
    • Hardware Keys: Support for FIDO/U2F keys (sk-*) as specified in PROTOCOL.u2f.
    • Environments: Supports no_std targets, including a 'heapless' profile for no-alloc environments.
  2. Overview of ssh-cipher symmetric encryption algorithms

    master

    ssh-cipher is a pure Rust implementation of SSH symmetric encryption algorithms. It provides support for modern authenticated encryption algorithms used by OpenSSH, as well as legacy ciphers. It is built on top of the core cryptography implementations maintained by the RustCrypto organization.

    Supported Algorithms:

    • Modern: aes128-gcm@openssh.com, aes256-gcm@openssh.com, and chacha20-poly1305@openssh.com.
    • Legacy: Support for older SSH ciphers is also included.
  3. Use `ssh-derive` for custom `Decode` and `Encode` implementations

    master
    The ssh-derive crate provides procedural macros to automatically implement the Decode and Encode traits from the ssh-encoding crate. This allows you to define custom SSH-encoded data structures by simply applying derive attributes to your structs or enums, rather than manually writing the encoding and decoding logic.
  4. Enable cryptographic features in ssh-key

    master

    By default, no SSH signature algorithms are enabled. If you attempt to use them without enabling the appropriate features, you will receive an Error::AlgorithmUnsupported error.

    To use cryptographic functionality such as key generation, signing, or verification, you must enable the specific feature for the algorithm you intend to use. The features correspond to the underlying cryptographic primitives.

  5. Use the ssh-protocol public API modules

    master

    The ssh-protocol crate provides a unified interface for SSH protocol components. It re-exports key modules for symmetric ciphers, encoding/decoding, and key management.

    Note: This crate is #![no_std] compatible. If you require Signature or Certificate types, you must enable the alloc feature.

    // Example of the primary modules available via re-exports
    use ssh_protocol::cipher;
    use ssh_protocol::encoding;
    use ssh_protocol::key;
  6. What is the Rfc4251String trait?

    master

    The Rfc4251String trait is a marker trait used to identify types that follow the RFC4251 string encoding format (a uint32 length prefix followed by data).

    It is primarily used to enable the Encode implementation for slices [T]. When you encode a slice of Rfc4251String items, the library treats the entire collection as one large SSH string, calculating the total length of all elements combined to create a single overarching length prefix.

  7. Understand `Marker` types in `known_hosts`

    master

    Markers are optional prefixes in a known_hosts entry that change how the entry is interpreted. There can only be one marker per entry.

    Supported markers:

    • Marker::CertAuthority (@cert-authority): Indicates the public key is for a certificate authority's private key.
    • Marker::Revoked (@revoked): Indicates the host entry's public key has been revoked and should not be allowed to connect.
  8. Convert between standard and OpenSSH certificate algorithm names

    master

    The AlgorithmName API allows for seamless conversion between standard SSH algorithm identifiers and the OpenSSH certificate format.

    1. Standard to Certificate: Use .certificate_type() to transform a name@domainname string into a name-cert-v01@domainname string.
    2. Certificate to Standard: Use AlgorithmName::from_certificate_type(id) to strip the -cert-v01 suffix and return the original name@domainname identifier.

    This is useful when working with SSH keys that require specific certificate-type identifiers for compatibility with OpenSSH.

    let alg = AlgorithmName::new("ed25519@openssh.com").unwrap();
    let cert_id = alg.certificate_type(); // "ed25519-cert-v01@openssh.com"
    
    let back_to_alg = AlgorithmName::from_certificate_type(&cert_id).unwrap();
    assert_eq!(back_to_alg.as_str(), "ed25519@openssh.com");
  9. Use the OpenSSH variant of ChaCha20Poly1305

    master

    The ChaCha20Poly1305 type provides an AEAD primitive specifically for the chacha20-poly1305@openssh.com construction.

    Key Differences from RFC 8439 (IETF):

    • Nonce: Uses a 64-bit nonce instead of 96-bit (uses the legacy "djb" ChaCha20 variant).
    • Padding: AAD and ciphertext inputs to Poly1305 are not padded.
    • Authentication: The lengths of ciphertext and AAD are not authenticated using Poly1305.
    • AAD Limit: The maximum supported AAD size is 16 bytes.

    Usage Contexts:

    • SSH Packet Encryption: AAD is typically 4 bytes (the encrypted length).
    • SSH Key Encryption: AAD is typically empty.

    Important Implementation Note:

    This type implements the AEAD primitive using a 32-byte (256-bit) key. However, the full OpenSSH packet encryption construction requires a 64-byte (512-bit) key, which must be split into two 32-byte keys (K_1 and K_2). K_1 is used for length encryption, and K_2 is used for the packet body and authentication.

    use ssh_cipher::{ChaCha20Poly1305, ChaChaKey, ChaChaNonce, Tag, aead::{AeadInOut, KeyInit}, cipher::{KeyIvInit, StreamCipher}};
  10. Use the Mpint type for SSH multiple precision integers

    master

    The Mpint type represents multiple precision integers in two's complement format, as described in RFC4251 § 5. It stores integers as big-endian byte strings.

    Key characteristics:

    • Positive numbers: If the most significant bit (MSB) is set, a leading zero byte is added to ensure the number is interpreted as positive.
    • Negative numbers: Represented in two's complement where the MSB of the first byte is 1.
    • Zero: Stored as an empty byte string.
    • Normalization: Unnecessary leading bytes (0 or 255) must not be included.
    /// Example representations:
    /// | value (hex)     | representation (hex) |
    /// |-----------------|----------------------|
    /// | 0               | `00 00 00 00`         |
    /// | 9a378f9b2e332a7 | `00 00 00 08 09 a3 78 f9 b2 e3 32 a7` |
    /// | 80              | `00 00 00 02 00 80`   |
    /// |-1234            | `00 00 00 02 ed cc`   |