diff --git a/Cargo.lock b/Cargo.lock index 77917b8..9d065f0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -968,6 +968,15 @@ dependencies = [ "zeroize", ] +[[package]] +name = "secrecy" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e" +dependencies = [ + "zeroize", +] + [[package]] name = "semver" version = "1.0.22" @@ -1071,6 +1080,7 @@ dependencies = [ "rand", "rsa", "rstest", + "secrecy", "service-binding", "sha1", "signature", diff --git a/Cargo.toml b/Cargo.toml index db14a2e..d9468a8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,6 +32,7 @@ thiserror = "1.0.58" #uuid = { version = "1.8.0", features = ["v4"] } subtle = { version = "2", default-features = false } signature = { version = "2.2.0", features = ["alloc"] } +secrecy = "0.8.0" [features] default = ["agent"] diff --git a/src/proto/message.rs b/src/proto/message.rs index a443b4e..a1c4606 100644 --- a/src/proto/message.rs +++ b/src/proto/message.rs @@ -2,6 +2,7 @@ use core::str::FromStr; +use secrecy::{ExposeSecret as _, SecretString}; use ssh_encoding::{CheckedSum, Decode, Encode, Error as EncodingError, Reader, Writer}; use ssh_key::{ certificate::Certificate, private::KeypairData, public::KeyData, Algorithm, Error, Signature, @@ -349,7 +350,7 @@ impl Encode for RemoveIdentity { /// This structure is sent in a [`Request::AddSmartcardKey`] (`SSH_AGENTC_ADD_SMARTCARD_KEY`) message. /// /// Described in [draft-miller-ssh-agent-14 ยง 3.2](https://www.ietf.org/archive/id/draft-miller-ssh-agent-14.html#section-3.2) -#[derive(Clone, PartialEq, Debug)] +#[derive(Clone, Debug)] pub struct SmartcardKey { /// An opaque identifier for the hardware token /// @@ -358,7 +359,7 @@ pub struct SmartcardKey { pub id: String, /// An optional password to unlock the key - pub pin: String, + pub pin: SecretString, } impl Decode for SmartcardKey { @@ -366,7 +367,7 @@ impl Decode for SmartcardKey { fn decode(reader: &mut impl Reader) -> Result { let id = String::decode(reader)?; - let pin = String::decode(reader)?; + let pin = String::decode(reader)?.into(); Ok(Self { id, pin }) } @@ -374,17 +375,27 @@ impl Decode for SmartcardKey { impl Encode for SmartcardKey { fn encoded_len(&self) -> ssh_encoding::Result { - [self.id.encoded_len()?, self.pin.encoded_len()?].checked_sum() + [ + self.id.encoded_len()?, + self.pin.expose_secret().encoded_len()?, + ] + .checked_sum() } fn encode(&self, writer: &mut impl Writer) -> ssh_encoding::Result<()> { self.id.encode(writer)?; - self.pin.encode(writer)?; + self.pin.expose_secret().encode(writer)?; Ok(()) } } +impl PartialEq for SmartcardKey { + fn eq(&self, other: &Self) -> bool { + self.id == other.id && self.pin.expose_secret() == other.pin.expose_secret() + } +} + /// A key constraint, used to place limitations on how and where a key can be used. /// /// Key constraints are set along with a key when are added to an agent.