ssh_key/
lib.rs

1#![no_std]
2#![cfg_attr(docsrs, feature(doc_auto_cfg))]
3#![doc = include_str!("../README.md")]
4#![doc(
5    html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg",
6    html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg"
7)]
8#![allow(unexpected_cfgs)] // `ed25519` is temporarily disabled
9#![forbid(unsafe_code)]
10#![warn(
11    clippy::alloc_instead_of_core,
12    clippy::arithmetic_side_effects,
13    clippy::mod_module_files,
14    clippy::panic,
15    clippy::panic_in_result_fn,
16    clippy::std_instead_of_alloc,
17    clippy::std_instead_of_core,
18    clippy::unwrap_used,
19    missing_docs,
20    rust_2018_idioms,
21    unused_lifetimes,
22    unused_qualifications
23)]
24
25//! ## Usage
26//!
27//! The main types provided by this library are:
28//!
29//! - [`Certificate`]: OpenSSH certificates
30//! - [`Fingerprint`]: public key fingerprints (i.e. hashes)
31//! - [`PrivateKey`]: SSH private keys (i.e. digital signature keys)
32//! - [`PublicKey`]: SSH public keys (i.e. signature verification keys)
33//! - [`SshSig`]: signatures with SSH keys ala `ssh-keygen -Y sign`/`ssh-keygen -Y verify`
34//!
35//! ### Parsing OpenSSH Public Keys
36//!
37//! OpenSSH-formatted public keys have the form:
38//!
39//! ```text
40//! <algorithm id> <base64 data> <comment>
41//! ```
42//!
43//! #### Example
44//!
45#![cfg_attr(feature = "std", doc = "```")]
46#![cfg_attr(not(feature = "std"), doc = "```ignore")]
47//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
48//! use ssh_key::PublicKey;
49//!
50//! let encoded_key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILM+rvN+ot98qgEN796jTiQfZfG1KaT0PtFDJ/XFSqti user@example.com";
51//! let public_key = PublicKey::from_openssh(encoded_key)?;
52//!
53//! // Key attributes
54//! assert_eq!(public_key.algorithm(), ssh_key::Algorithm::Ed25519);
55//! assert_eq!(public_key.comment().as_bytes(), b"user@example.com");
56//!
57//! // Key data: in this example an Ed25519 key
58//! if let Some(ed25519_public_key) = public_key.key_data().ed25519() {
59//!     assert_eq!(
60//!         ed25519_public_key.as_ref(),
61//!         &[
62//!             0xb3, 0x3e, 0xae, 0xf3, 0x7e, 0xa2, 0xdf, 0x7c, 0xaa, 0x1, 0xd, 0xef, 0xde, 0xa3,
63//!             0x4e, 0x24, 0x1f, 0x65, 0xf1, 0xb5, 0x29, 0xa4, 0xf4, 0x3e, 0xd1, 0x43, 0x27, 0xf5,
64//!             0xc5, 0x4a, 0xab, 0x62
65//!         ]
66//!     );
67//! }
68//! # Ok(())
69//! # }
70//! ```
71//!
72//! ### Parsing OpenSSH Private Keys
73//!
74//! *NOTE: for more private key usage examples, see the [`private`] module.*
75//!
76//! OpenSSH-formatted private keys are PEM-encoded and begin with the following:
77//!
78//! ```text
79//! -----BEGIN OPENSSH PRIVATE KEY-----
80//! ```
81//!
82//! #### Example
83//!
84#![cfg_attr(feature = "std", doc = " ```")]
85#![cfg_attr(not(feature = "std"), doc = " ```ignore")]
86//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
87//! use ssh_key::PrivateKey;
88//!
89//! // WARNING: don't actually hardcode private keys in source code!!!
90//! let encoded_key = r#"
91//! -----BEGIN OPENSSH PRIVATE KEY-----
92//! b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
93//! QyNTUxOQAAACCzPq7zfqLffKoBDe/eo04kH2XxtSmk9D7RQyf1xUqrYgAAAJgAIAxdACAM
94//! XQAAAAtzc2gtZWQyNTUxOQAAACCzPq7zfqLffKoBDe/eo04kH2XxtSmk9D7RQyf1xUqrYg
95//! AAAEC2BsIi0QwW2uFscKTUUXNHLsYX4FxlaSDSblbAj7WR7bM+rvN+ot98qgEN796jTiQf
96//! ZfG1KaT0PtFDJ/XFSqtiAAAAEHVzZXJAZXhhbXBsZS5jb20BAgMEBQ==
97//! -----END OPENSSH PRIVATE KEY-----
98//! "#;
99//!
100//! let private_key = PrivateKey::from_openssh(encoded_key)?;
101//!
102//! // Key attributes
103//! assert_eq!(private_key.algorithm(), ssh_key::Algorithm::Ed25519);
104//! assert_eq!(private_key.comment().as_bytes(), b"user@example.com");
105//!
106//! // Key data: in this example an Ed25519 key
107//! if let Some(ed25519_keypair) = private_key.key_data().ed25519() {
108//!     assert_eq!(
109//!         ed25519_keypair.public.as_ref(),
110//!         &[
111//!             0xb3, 0x3e, 0xae, 0xf3, 0x7e, 0xa2, 0xdf, 0x7c, 0xaa, 0x1, 0xd, 0xef, 0xde, 0xa3,
112//!             0x4e, 0x24, 0x1f, 0x65, 0xf1, 0xb5, 0x29, 0xa4, 0xf4, 0x3e, 0xd1, 0x43, 0x27, 0xf5,
113//!             0xc5, 0x4a, 0xab, 0x62
114//!         ]
115//!     );
116//!
117//!     assert_eq!(
118//!         ed25519_keypair.private.as_ref(),
119//!         &[
120//!             0xb6, 0x6, 0xc2, 0x22, 0xd1, 0xc, 0x16, 0xda, 0xe1, 0x6c, 0x70, 0xa4, 0xd4, 0x51,
121//!             0x73, 0x47, 0x2e, 0xc6, 0x17, 0xe0, 0x5c, 0x65, 0x69, 0x20, 0xd2, 0x6e, 0x56, 0xc0,
122//!             0x8f, 0xb5, 0x91, 0xed
123//!         ]
124//!     )
125//! }
126//! # Ok(())
127//! # }
128//! ```
129//!
130//! ## `serde` support
131//!
132//! When the `serde` feature of this crate is enabled, the [`Certificate`],
133//! [`Fingerprint`], and [`PublicKey`] types receive impls of `serde`'s
134//! [`Deserialize`][`serde::Deserialize`] and [`Serialize`][`serde::Serialize`]
135//! traits.
136//!
137//! Serializing/deserializing [`PrivateKey`] using `serde` is presently
138//! unsupported.
139
140#[cfg(feature = "alloc")]
141#[macro_use]
142extern crate alloc;
143#[cfg(feature = "std")]
144extern crate std;
145
146pub mod authorized_keys;
147pub mod private;
148pub mod public;
149
150#[cfg(feature = "alloc")]
151pub mod certificate;
152#[cfg(feature = "alloc")]
153pub mod known_hosts;
154
155mod algorithm;
156mod error;
157mod fingerprint;
158mod kdf;
159
160#[cfg(feature = "alloc")]
161mod comment;
162#[cfg(feature = "std")]
163mod dot_ssh;
164#[cfg(feature = "ppk")]
165mod ppk;
166#[cfg(feature = "alloc")]
167mod signature;
168#[cfg(feature = "alloc")]
169mod sshsig;
170
171pub use crate::{
172    algorithm::{Algorithm, EcdsaCurve, HashAlg, KdfAlg},
173    authorized_keys::AuthorizedKeys,
174    error::{Error, Result},
175    fingerprint::Fingerprint,
176    kdf::Kdf,
177    private::PrivateKey,
178    public::PublicKey,
179};
180pub use cipher::Cipher;
181pub use encoding::pem::LineEnding;
182pub use sha2;
183
184#[cfg(feature = "alloc")]
185pub use {
186    crate::{
187        algorithm::AlgorithmName,
188        certificate::Certificate,
189        comment::Comment,
190        known_hosts::KnownHosts,
191        signature::{Signature, SigningKey},
192        sshsig::SshSig,
193    },
194    encoding::Mpint,
195};
196
197#[cfg(feature = "ecdsa")]
198pub use sec1;
199
200#[cfg(feature = "rand_core")]
201pub use rand_core;
202
203#[cfg(feature = "std")]
204pub use crate::dot_ssh::DotSsh;