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