From ab475c626edc12d5bd5bb17bea1239428f3163dd Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Sat, 14 Oct 2023 17:19:49 -0600 Subject: [PATCH] ssh-key: add `SshSig` signing example Complements #166 with an example for how to produce signatures --- ssh-key/src/private.rs | 34 ++++++++++++++++++++++++++++++++++ ssh-key/src/public.rs | 15 +++++++++++---- ssh-key/src/sshsig.rs | 6 ++++-- 3 files changed, 49 insertions(+), 6 deletions(-) diff --git a/ssh-key/src/private.rs b/ssh-key/src/private.rs index 5e5ad8d..c672226 100644 --- a/ssh-key/src/private.rs +++ b/ssh-key/src/private.rs @@ -275,6 +275,40 @@ impl PrivateKey { /// /// See [PROTOCOL.sshsig] for more information. /// + /// # Usage + /// + /// See also: [`PublicKey::verify`]. + /// + #[cfg_attr(feature = "ed25519", doc = "```")] + #[cfg_attr(not(feature = "ed25519"), doc = "```ignore")] + /// # fn main() -> Result<(), ssh_key::Error> { + /// use ssh_key::{PrivateKey, HashAlg, SshSig}; + /// + /// // Message to be signed. + /// let message = b"testing"; + /// + /// // Example domain/namespace used for the message. + /// let namespace = "example"; + /// + /// // Private key to use when computing the signature. + /// // WARNING: don't actually hardcode private keys in source code!!! + /// let encoded_private_key = r#" + /// -----BEGIN OPENSSH PRIVATE KEY----- + /// b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW + /// QyNTUxOQAAACCzPq7zfqLffKoBDe/eo04kH2XxtSmk9D7RQyf1xUqrYgAAAJgAIAxdACAM + /// XQAAAAtzc2gtZWQyNTUxOQAAACCzPq7zfqLffKoBDe/eo04kH2XxtSmk9D7RQyf1xUqrYg + /// AAAEC2BsIi0QwW2uFscKTUUXNHLsYX4FxlaSDSblbAj7WR7bM+rvN+ot98qgEN796jTiQf + /// ZfG1KaT0PtFDJ/XFSqtiAAAAEHVzZXJAZXhhbXBsZS5jb20BAgMEBQ== + /// -----END OPENSSH PRIVATE KEY----- + /// "#; + /// + /// let private_key = encoded_private_key.parse::()?; + /// let signature = private_key.sign(namespace, HashAlg::default(), message)?; + /// // assert!(private_key.public_key().verify(namespace, message, &signature).is_ok()); + /// # Ok(()) + /// # } + /// ``` + /// /// [PROTOCOL.sshsig]: https://cvsweb.openbsd.org/src/usr.bin/ssh/PROTOCOL.sshsig?annotate=HEAD #[cfg(feature = "alloc")] pub fn sign(&self, namespace: &str, hash_alg: HashAlg, msg: &[u8]) -> Result { diff --git a/ssh-key/src/public.rs b/ssh-key/src/public.rs index e88a9b3..7d8be56 100644 --- a/ssh-key/src/public.rs +++ b/ssh-key/src/public.rs @@ -50,6 +50,9 @@ use serde::{de, ser, Deserialize, Serialize}; #[cfg(feature = "std")] use std::{fs, path::Path}; +#[cfg(doc)] +use crate::PrivateKey; + /// SSH public key. /// /// # OpenSSH encoding @@ -172,6 +175,8 @@ impl PublicKey { /// /// # Usage /// + /// See also: [`PrivateKey::sign`]. + /// #[cfg_attr(feature = "ed25519", doc = "```")] #[cfg_attr(not(feature = "ed25519"), doc = "```ignore")] /// # fn main() -> Result<(), ssh_key::Error> { @@ -184,17 +189,19 @@ impl PublicKey { /// let namespace = "example"; /// /// // Public key which computed the signature. - /// let public_key_str = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILM+rvN+ot98qgEN796jTiQfZfG1KaT0PtFDJ/XFSqti user@example.com"; + /// let encoded_public_key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILM+rvN+ot98qgEN796jTiQfZfG1KaT0PtFDJ/XFSqti user@example.com"; /// /// // Example signature to be verified. - /// let signature_str = "-----BEGIN SSH SIGNATURE----- + /// let signature_str = r#" + /// -----BEGIN SSH SIGNATURE----- /// U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAgsz6u836i33yqAQ3v3qNOJB9l8b /// UppPQ+0UMn9cVKq2IAAAAHZXhhbXBsZQAAAAAAAAAGc2hhNTEyAAAAUwAAAAtzc2gtZWQy /// NTUxOQAAAEBPEav+tMGNnox4MuzM7rlHyVBajCn8B0kAyiOWwPKprNsG3i6X+voz/WCSik /// /FowYwqhgCABUJSvRX3AERVBUP - /// -----END SSH SIGNATURE-----"; + /// -----END SSH SIGNATURE----- + /// "#; /// - /// let public_key = public_key_str.parse::()?; + /// let public_key = encoded_public_key.parse::()?; /// let signature = signature_str.parse::()?; /// public_key.verify(namespace, message, &signature)?; /// # Ok(()) diff --git a/ssh-key/src/sshsig.rs b/ssh-key/src/sshsig.rs index f460a75..80e146d 100644 --- a/ssh-key/src/sshsig.rs +++ b/ssh-key/src/sshsig.rs @@ -10,7 +10,7 @@ use encoding::{ use signature::Verifier; #[cfg(doc)] -use crate::PublicKey; +use crate::{PrivateKey, PublicKey}; type Version = u32; @@ -28,7 +28,7 @@ type Version = u32; /// /// # Usage /// -/// See [`SshSig::sign`] and [`PublicKey::verify`] for usage information. +/// See [`PrivateKey::sign`] and [`PublicKey::verify`] for usage information. /// /// [PROTOCOL.sshsig]: https://cvsweb.openbsd.org/src/usr.bin/ssh/PROTOCOL.sshsig?annotate=HEAD #[derive(Clone, Debug, Eq, PartialEq)] @@ -96,6 +96,8 @@ impl SshSig { } /// Sign the given message with the provided signing key. + /// + /// See also: [`PrivateKey::sign`]. pub fn sign( signing_key: &S, namespace: &str,