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