ssh_key/
signature.rs

1//! Signatures (e.g. CA signatures over SSH certificates)
2
3use crate::{Algorithm, EcdsaCurve, Error, Mpint, PrivateKey, PublicKey, Result, private, public};
4use alloc::vec::Vec;
5use core::fmt;
6use encoding::{CheckedSum, Decode, Encode, Reader, Writer};
7use signature::{SignatureEncoding, Signer, Verifier};
8
9#[cfg(feature = "ed25519")]
10use crate::{private::Ed25519Keypair, public::Ed25519PublicKey};
11
12#[cfg(feature = "dsa")]
13use {
14    crate::{private::DsaKeypair, public::DsaPublicKey},
15    encoding::Uint,
16    signature::{DigestSigner, DigestVerifier},
17};
18
19#[cfg(any(feature = "p256", feature = "p384", feature = "p521"))]
20use crate::{
21    private::{EcdsaKeypair, EcdsaPrivateKey},
22    public::EcdsaPublicKey,
23};
24
25#[cfg(feature = "rsa")]
26use {
27    crate::{HashAlg, private::RsaKeypair, public::RsaPublicKey},
28    sha2::Sha512,
29};
30
31#[cfg(any(all(feature = "sha1", feature = "rsa"), feature = "dsa"))]
32use sha1::Sha1;
33
34#[cfg(any(feature = "ed25519", feature = "rsa", feature = "p256"))]
35use sha2::Sha256;
36
37#[cfg(any(feature = "dsa", feature = "ed25519", feature = "p256"))]
38use sha2::Digest;
39
40const DSA_SIGNATURE_SIZE: usize = 40;
41const ED25519_SIGNATURE_SIZE: usize = 64;
42const SK_SIGNATURE_TRAILER_SIZE: usize = 5; // flags(u8), counter(u32)
43const SK_ED25519_SIGNATURE_SIZE: usize = ED25519_SIGNATURE_SIZE + SK_SIGNATURE_TRAILER_SIZE;
44
45/// Trait for signing keys which produce a [`Signature`].
46///
47/// This trait is automatically impl'd for any types which impl the
48/// [`Signer`] trait for the SSH [`Signature`] type and also support a [`From`]
49/// conversion for [`public::KeyData`].
50pub trait SigningKey: Signer<Signature> {
51    /// Get the [`public::KeyData`] for this signing key.
52    fn public_key(&self) -> public::KeyData;
53}
54
55impl<T> SigningKey for T
56where
57    T: Signer<Signature>,
58    public::KeyData: for<'a> From<&'a T>,
59{
60    fn public_key(&self) -> public::KeyData {
61        self.into()
62    }
63}
64
65/// Low-level digital signature (e.g. DSA, ECDSA, Ed25519).
66///
67/// These are low-level signatures used as part of the OpenSSH certificate
68/// format to represent signatures by certificate authorities (CAs), as well
69/// as the higher-level [`SshSig`][`crate::SshSig`] format, which provides
70/// general-purpose signing functionality using SSH keys.
71///
72/// From OpenSSH's [PROTOCOL.certkeys] specification:
73///
74/// > Signatures are computed and encoded according to the rules defined for
75/// > the CA's public key algorithm ([RFC4253 section 6.6] for ssh-rsa and
76/// > ssh-dss, [RFC5656] for the ECDSA types, and [RFC8032] for Ed25519).
77///
78/// RSA signature support is implemented using the SHA2 family extensions as
79/// described in [RFC8332].
80///
81/// [PROTOCOL.certkeys]: https://cvsweb.openbsd.org/src/usr.bin/ssh/PROTOCOL.certkeys?annotate=HEAD
82/// [RFC4253 section 6.6]: https://datatracker.ietf.org/doc/html/rfc4253#section-6.6
83/// [RFC5656]: https://datatracker.ietf.org/doc/html/rfc5656
84/// [RFC8032]: https://datatracker.ietf.org/doc/html/rfc8032
85/// [RFC8332]: https://datatracker.ietf.org/doc/html/rfc8332
86#[derive(Clone, Eq, PartialEq, PartialOrd, Ord)]
87pub struct Signature {
88    /// Signature algorithm.
89    algorithm: Algorithm,
90
91    /// Raw signature serialized as algorithm-specific byte encoding.
92    data: Vec<u8>,
93}
94
95impl Signature {
96    /// Create a new signature with the given algorithm and raw signature data.
97    ///
98    /// See specifications in toplevel [`Signature`] documentation for how to
99    /// format the raw signature data for a given algorithm.
100    ///
101    /// # Returns
102    /// - [`Error::Encoding`] if the signature is not the correct length.
103    pub fn new(algorithm: Algorithm, data: impl Into<Vec<u8>>) -> Result<Self> {
104        let data = data.into();
105
106        // Validate signature is well-formed per OpenSSH encoding
107        match algorithm {
108            Algorithm::Dsa if data.len() == DSA_SIGNATURE_SIZE => (),
109            Algorithm::Ecdsa { curve } => ecdsa_sig_size(&data, curve, false)?,
110            Algorithm::Ed25519 if data.len() == ED25519_SIGNATURE_SIZE => (),
111            Algorithm::SkEd25519 if data.len() == SK_ED25519_SIGNATURE_SIZE => (),
112            Algorithm::SkEcdsaSha2NistP256 => ecdsa_sig_size(&data, EcdsaCurve::NistP256, true)?,
113            Algorithm::Rsa { .. } => (),
114            Algorithm::Other(_) if !data.is_empty() => (),
115            _ => return Err(encoding::Error::Length.into()),
116        }
117
118        Ok(Self { algorithm, data })
119    }
120
121    /// Get the [`Algorithm`] associated with this signature.
122    pub fn algorithm(&self) -> Algorithm {
123        self.algorithm.clone()
124    }
125
126    /// Get the raw signature as bytes.
127    pub fn as_bytes(&self) -> &[u8] {
128        &self.data
129    }
130
131    /// Placeholder signature used by the certificate builder.
132    ///
133    /// This is guaranteed to generate an error if anything attempts to encode it.
134    pub(crate) fn placeholder() -> Self {
135        Self {
136            algorithm: Algorithm::default(),
137            data: Vec::new(),
138        }
139    }
140
141    /// Check if this signature is the placeholder signature.
142    pub(crate) fn is_placeholder(&self) -> bool {
143        self.algorithm == Algorithm::default() && self.data.is_empty()
144    }
145}
146
147/// Returns Ok() if data holds an ecdsa signature with components of appropriate size
148/// according to curve.
149fn ecdsa_sig_size(mut data: &[u8], curve: EcdsaCurve, sk_trailer: bool) -> Result<()> {
150    let reader = &mut data;
151
152    for _ in 0..2 {
153        let component = Mpint::decode(reader)?;
154        let bytes = component.as_positive_bytes().ok_or(Error::FormatEncoding)?;
155        if bytes.len() > curve.field_size() {
156            return Err(encoding::Error::Length.into());
157        }
158    }
159
160    if sk_trailer {
161        reader.drain(SK_SIGNATURE_TRAILER_SIZE)?;
162    }
163
164    Ok(reader.finish(())?)
165}
166
167impl AsRef<[u8]> for Signature {
168    fn as_ref(&self) -> &[u8] {
169        self.as_bytes()
170    }
171}
172
173impl Decode for Signature {
174    type Error = Error;
175
176    fn decode(reader: &mut impl Reader) -> Result<Self> {
177        let algorithm = Algorithm::decode(reader)?;
178        let mut data = Vec::decode(reader)?;
179
180        if algorithm == Algorithm::SkEd25519 || algorithm == Algorithm::SkEcdsaSha2NistP256 {
181            let flags = u8::decode(reader)?;
182            let counter = u32::decode(reader)?;
183
184            data.push(flags);
185            data.extend(counter.to_be_bytes());
186        }
187        Self::new(algorithm, data)
188    }
189}
190
191impl Encode for Signature {
192    fn encoded_len(&self) -> encoding::Result<usize> {
193        [
194            self.algorithm().encoded_len()?,
195            self.as_bytes().encoded_len()?,
196        ]
197        .checked_sum()
198    }
199
200    fn encode(&self, writer: &mut impl Writer) -> encoding::Result<()> {
201        if self.is_placeholder() {
202            return Err(encoding::Error::Length);
203        }
204
205        self.algorithm().encode(writer)?;
206
207        if self.algorithm == Algorithm::SkEd25519 {
208            let signature_length = self
209                .as_bytes()
210                .len()
211                .checked_sub(SK_SIGNATURE_TRAILER_SIZE)
212                .ok_or(encoding::Error::Length)?;
213            self.as_bytes()[..signature_length].encode(writer)?;
214            writer.write(&self.as_bytes()[signature_length..])?;
215        } else {
216            self.as_bytes().encode(writer)?;
217        }
218
219        Ok(())
220    }
221}
222
223impl SignatureEncoding for Signature {
224    type Repr = Vec<u8>;
225}
226
227/// Decode [`Signature`] from an [`Algorithm`]-prefixed OpenSSH-encoded bytestring.
228impl TryFrom<&[u8]> for Signature {
229    type Error = Error;
230
231    fn try_from(mut bytes: &[u8]) -> Result<Self> {
232        Self::decode(&mut bytes)
233    }
234}
235
236impl TryFrom<Signature> for Vec<u8> {
237    type Error = Error;
238
239    fn try_from(signature: Signature) -> Result<Vec<u8>> {
240        Ok(signature.encode_vec()?)
241    }
242}
243
244impl fmt::Debug for Signature {
245    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
246        write!(
247            f,
248            "Signature {{ algorithm: {:?}, data: {:X} }}",
249            self.algorithm, self
250        )
251    }
252}
253
254impl fmt::LowerHex for Signature {
255    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
256        for byte in self.as_ref() {
257            write!(f, "{byte:02x}")?;
258        }
259        Ok(())
260    }
261}
262
263impl fmt::UpperHex for Signature {
264    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
265        for byte in self.as_ref() {
266            write!(f, "{byte:02X}")?;
267        }
268        Ok(())
269    }
270}
271
272impl Signer<Signature> for PrivateKey {
273    fn try_sign(&self, message: &[u8]) -> signature::Result<Signature> {
274        self.key_data().try_sign(message)
275    }
276}
277
278impl Signer<Signature> for private::KeypairData {
279    #[allow(unused_variables)]
280    fn try_sign(&self, message: &[u8]) -> signature::Result<Signature> {
281        match self {
282            #[cfg(feature = "dsa")]
283            Self::Dsa(keypair) => keypair.try_sign(message),
284            #[cfg(any(feature = "p256", feature = "p384", feature = "p521"))]
285            Self::Ecdsa(keypair) => keypair.try_sign(message),
286            #[cfg(feature = "ed25519")]
287            Self::Ed25519(keypair) => keypair.try_sign(message),
288            #[cfg(feature = "rsa")]
289            Self::Rsa(keypair) => keypair.try_sign(message),
290            _ => Err(self.algorithm()?.unsupported_error().into()),
291        }
292    }
293}
294
295impl Verifier<Signature> for PublicKey {
296    fn verify(&self, message: &[u8], signature: &Signature) -> signature::Result<()> {
297        self.key_data().verify(message, signature)
298    }
299}
300
301impl Verifier<Signature> for public::KeyData {
302    #[allow(unused_variables)]
303    fn verify(&self, message: &[u8], signature: &Signature) -> signature::Result<()> {
304        match self {
305            #[cfg(feature = "dsa")]
306            Self::Dsa(pk) => pk.verify(message, signature),
307            #[cfg(any(feature = "p256", feature = "p384", feature = "p521"))]
308            Self::Ecdsa(pk) => pk.verify(message, signature),
309            #[cfg(feature = "ed25519")]
310            Self::Ed25519(pk) => pk.verify(message, signature),
311            #[cfg(feature = "ed25519")]
312            Self::SkEd25519(pk) => pk.verify(message, signature),
313            #[cfg(feature = "p256")]
314            Self::SkEcdsaSha2NistP256(pk) => pk.verify(message, signature),
315            #[cfg(feature = "rsa")]
316            Self::Rsa(pk) => pk.verify(message, signature),
317            #[allow(unreachable_patterns)]
318            _ => Err(self.algorithm().unsupported_error().into()),
319        }
320    }
321}
322
323#[cfg(feature = "dsa")]
324impl Signer<Signature> for DsaKeypair {
325    fn try_sign(&self, message: &[u8]) -> signature::Result<Signature> {
326        let signature = dsa::SigningKey::try_from(self)?
327            .try_sign_digest(|digest: &mut Sha1| {
328                digest.update(message);
329                Ok(())
330            })
331            .map_err(|_| signature::Error::new())?;
332
333        // Encode the format specified in RFC4253 section 6.6: two raw 80-bit integers concatenated
334        let mut data = Vec::with_capacity(DSA_SIGNATURE_SIZE);
335
336        for component in [signature.r(), signature.s()] {
337            let bytes = component.to_be_bytes_trimmed_vartime();
338            let pad_len = (DSA_SIGNATURE_SIZE / 2).saturating_sub(bytes.len());
339            data.extend(core::iter::repeat_n(0, pad_len));
340            data.extend_from_slice(&bytes);
341        }
342
343        debug_assert_eq!(data.len(), DSA_SIGNATURE_SIZE);
344
345        Ok(Signature {
346            algorithm: Algorithm::Dsa,
347            data,
348        })
349    }
350}
351
352#[cfg(feature = "dsa")]
353impl Verifier<Signature> for DsaPublicKey {
354    fn verify(&self, message: &[u8], signature: &Signature) -> signature::Result<()> {
355        match signature.algorithm {
356            Algorithm::Dsa => {
357                let signature = dsa::Signature::try_from(signature)?;
358                dsa::VerifyingKey::try_from(self)?
359                    .verify_digest(
360                        |digest: &mut Sha1| {
361                            digest.update(message);
362                            Ok(())
363                        },
364                        &signature,
365                    )
366                    .map_err(|_| signature::Error::new())
367            }
368            _ => Err(signature.algorithm().unsupported_error().into()),
369        }
370    }
371}
372
373#[cfg(feature = "dsa")]
374impl TryFrom<Signature> for dsa::Signature {
375    type Error = Error;
376
377    fn try_from(signature: Signature) -> Result<Self> {
378        dsa::Signature::try_from(&signature)
379    }
380}
381
382#[cfg(feature = "dsa")]
383impl TryFrom<&Signature> for dsa::Signature {
384    type Error = Error;
385
386    fn try_from(signature: &Signature) -> Result<Self> {
387        let data = signature.data.as_slice();
388        if data.len() != DSA_SIGNATURE_SIZE {
389            return Err(encoding::Error::Length.into());
390        }
391
392        let component_size = DSA_SIGNATURE_SIZE / 2;
393        let component_bits = component_size.saturating_mul(8) as u32;
394        let components = data.split_at(component_size);
395
396        let r = Uint::from_be_slice(components.0, component_bits)?;
397        let s = Uint::from_be_slice(components.1, component_bits)?;
398        Ok(Self::from_components(r, s).ok_or(encoding::Error::MpintEncoding)?)
399    }
400}
401
402#[cfg(feature = "ed25519")]
403impl TryFrom<Signature> for ed25519_dalek::Signature {
404    type Error = Error;
405
406    fn try_from(signature: Signature) -> Result<ed25519_dalek::Signature> {
407        ed25519_dalek::Signature::try_from(&signature)
408    }
409}
410
411#[cfg(feature = "ed25519")]
412impl TryFrom<&Signature> for ed25519_dalek::Signature {
413    type Error = Error;
414
415    fn try_from(signature: &Signature) -> Result<ed25519_dalek::Signature> {
416        match signature.algorithm {
417            Algorithm::Ed25519 | Algorithm::SkEd25519 => {
418                Ok(ed25519_dalek::Signature::try_from(signature.as_bytes())?)
419            }
420            _ => Err(Error::AlgorithmUnknown),
421        }
422    }
423}
424
425#[cfg(feature = "ed25519")]
426impl Signer<Signature> for Ed25519Keypair {
427    fn try_sign(&self, message: &[u8]) -> signature::Result<Signature> {
428        let signature = ed25519_dalek::SigningKey::try_from(self)?.sign(message);
429
430        Ok(Signature {
431            algorithm: Algorithm::Ed25519,
432            data: signature.to_vec(),
433        })
434    }
435}
436
437#[cfg(feature = "ed25519")]
438impl Verifier<Signature> for Ed25519PublicKey {
439    fn verify(&self, message: &[u8], signature: &Signature) -> signature::Result<()> {
440        let signature = ed25519_dalek::Signature::try_from(signature)?;
441        ed25519_dalek::VerifyingKey::try_from(self)?.verify(message, &signature)
442    }
443}
444
445#[cfg(feature = "ed25519")]
446impl Verifier<Signature> for public::SkEd25519 {
447    fn verify(&self, message: &[u8], signature: &Signature) -> signature::Result<()> {
448        let (signature, flags_and_counter) = split_sk_signature(signature)?;
449        let signature = ed25519_dalek::Signature::try_from(signature)?;
450        ed25519_dalek::VerifyingKey::try_from(self.public_key())?.verify(
451            &make_sk_signed_data(self.application(), flags_and_counter, message),
452            &signature,
453        )
454    }
455}
456
457#[cfg(feature = "p256")]
458impl Verifier<Signature> for public::SkEcdsaSha2NistP256 {
459    fn verify(&self, message: &[u8], signature: &Signature) -> signature::Result<()> {
460        let (signature_bytes, flags_and_counter) = split_sk_signature(signature)?;
461        let signature = p256_signature_from_openssh_bytes(signature_bytes)?;
462        p256::ecdsa::VerifyingKey::from_encoded_point(self.ec_point())?.verify(
463            &make_sk_signed_data(self.application(), flags_and_counter, message),
464            &signature,
465        )
466    }
467}
468
469#[cfg(any(feature = "p256", feature = "ed25519"))]
470fn make_sk_signed_data(application: &str, flags_and_counter: &[u8], message: &[u8]) -> Vec<u8> {
471    const SHA256_OUTPUT_LENGTH: usize = 32;
472    const SIGNED_SK_DATA_LENGTH: usize = 2 * SHA256_OUTPUT_LENGTH + SK_SIGNATURE_TRAILER_SIZE;
473
474    let mut signed_data = Vec::with_capacity(SIGNED_SK_DATA_LENGTH);
475    signed_data.extend(Sha256::digest(application));
476    signed_data.extend(flags_and_counter);
477    signed_data.extend(Sha256::digest(message));
478    signed_data
479}
480
481#[cfg(any(feature = "p256", feature = "ed25519"))]
482fn split_sk_signature(signature: &Signature) -> Result<(&[u8], &[u8])> {
483    let signature_bytes = signature.as_bytes();
484    let signature_len = signature_bytes
485        .len()
486        .checked_sub(SK_SIGNATURE_TRAILER_SIZE)
487        .ok_or(Error::Encoding(encoding::Error::Length))?;
488    Ok((
489        &signature_bytes[..signature_len],
490        &signature_bytes[signature_len..],
491    ))
492}
493
494macro_rules! impl_signature_for_curve {
495    ($krate:ident, $feature:expr, $curve:ident, $size:expr) => {
496        #[cfg(feature = $feature)]
497        impl TryFrom<$krate::ecdsa::Signature> for Signature {
498            type Error = Error;
499
500            fn try_from(signature: $krate::ecdsa::Signature) -> Result<Signature> {
501                Signature::try_from(&signature)
502            }
503        }
504
505        #[cfg(feature = $feature)]
506        impl TryFrom<&$krate::ecdsa::Signature> for Signature {
507            type Error = Error;
508
509            fn try_from(signature: &$krate::ecdsa::Signature) -> Result<Signature> {
510                let (r, s) = signature.split_bytes();
511
512                #[allow(clippy::arithmetic_side_effects)]
513                let mut data = Vec::with_capacity($size * 2 + 4 * 2 + 2);
514
515                Mpint::from_positive_bytes(&r)?.encode(&mut data)?;
516                Mpint::from_positive_bytes(&s)?.encode(&mut data)?;
517
518                Ok(Signature {
519                    algorithm: Algorithm::Ecdsa {
520                        curve: EcdsaCurve::$curve,
521                    },
522                    data,
523                })
524            }
525        }
526
527        #[cfg(feature = $feature)]
528        impl TryFrom<Signature> for $krate::ecdsa::Signature {
529            type Error = Error;
530
531            fn try_from(signature: Signature) -> Result<$krate::ecdsa::Signature> {
532                $krate::ecdsa::Signature::try_from(&signature)
533            }
534        }
535
536        #[cfg(feature = $feature)]
537        impl Signer<Signature> for EcdsaPrivateKey<$size> {
538            fn try_sign(&self, message: &[u8]) -> signature::Result<Signature> {
539                let signing_key = $krate::ecdsa::SigningKey::from_slice(self.as_ref())?;
540                let signature: $krate::ecdsa::Signature = signing_key.try_sign(message)?;
541                Ok(signature.try_into()?)
542            }
543        }
544    };
545}
546
547impl_signature_for_curve!(p256, "p256", NistP256, 32);
548impl_signature_for_curve!(p384, "p384", NistP384, 48);
549impl_signature_for_curve!(p521, "p521", NistP521, 66);
550
551/// Build a generic sized object from a `u8` iterator, with leading zero padding
552#[cfg(any(feature = "p256", feature = "p384", feature = "p521"))]
553fn zero_pad_field_bytes<B: FromIterator<u8> + Copy>(m: Mpint) -> Option<B> {
554    use core::mem::size_of;
555
556    let bytes = m.as_positive_bytes()?;
557    size_of::<B>()
558        .checked_sub(bytes.len())
559        .map(|i| B::from_iter(core::iter::repeat_n(0u8, i).chain(bytes.iter().cloned())))
560}
561
562#[cfg(feature = "p256")]
563impl TryFrom<&Signature> for p256::ecdsa::Signature {
564    type Error = Error;
565
566    fn try_from(signature: &Signature) -> Result<p256::ecdsa::Signature> {
567        match signature.algorithm {
568            Algorithm::Ecdsa {
569                curve: EcdsaCurve::NistP256,
570            } => p256_signature_from_openssh_bytes(signature.as_bytes()),
571            _ => Err(signature.algorithm.clone().unsupported_error()),
572        }
573    }
574}
575#[cfg(feature = "p256")]
576fn p256_signature_from_openssh_bytes(mut signature_bytes: &[u8]) -> Result<p256::ecdsa::Signature> {
577    let reader = &mut signature_bytes;
578    let r = Mpint::decode(reader)?;
579    let s = Mpint::decode(reader)?;
580
581    match (
582        zero_pad_field_bytes::<p256::FieldBytes>(r),
583        zero_pad_field_bytes::<p256::FieldBytes>(s),
584    ) {
585        (Some(r), Some(s)) => Ok(p256::ecdsa::Signature::from_scalars(r, s)?),
586        _ => Err(Error::Crypto),
587    }
588}
589
590#[cfg(feature = "p384")]
591impl TryFrom<&Signature> for p384::ecdsa::Signature {
592    type Error = Error;
593
594    fn try_from(signature: &Signature) -> Result<p384::ecdsa::Signature> {
595        match signature.algorithm {
596            Algorithm::Ecdsa {
597                curve: EcdsaCurve::NistP384,
598            } => {
599                let reader = &mut signature.as_bytes();
600                let r = Mpint::decode(reader)?;
601                let s = Mpint::decode(reader)?;
602
603                match (
604                    zero_pad_field_bytes::<p384::FieldBytes>(r),
605                    zero_pad_field_bytes::<p384::FieldBytes>(s),
606                ) {
607                    (Some(r), Some(s)) => Ok(p384::ecdsa::Signature::from_scalars(r, s)?),
608                    _ => Err(Error::Crypto),
609                }
610            }
611            _ => Err(signature.algorithm.clone().unsupported_error()),
612        }
613    }
614}
615
616#[cfg(feature = "p521")]
617impl TryFrom<&Signature> for p521::ecdsa::Signature {
618    type Error = Error;
619
620    fn try_from(signature: &Signature) -> Result<p521::ecdsa::Signature> {
621        match signature.algorithm {
622            Algorithm::Ecdsa {
623                curve: EcdsaCurve::NistP521,
624            } => {
625                let reader = &mut signature.as_bytes();
626                let r = Mpint::decode(reader)?;
627                let s = Mpint::decode(reader)?;
628
629                match (
630                    zero_pad_field_bytes::<p521::FieldBytes>(r),
631                    zero_pad_field_bytes::<p521::FieldBytes>(s),
632                ) {
633                    (Some(r), Some(s)) => Ok(p521::ecdsa::Signature::from_scalars(r, s)?),
634                    _ => Err(Error::Crypto),
635                }
636            }
637            _ => Err(signature.algorithm.clone().unsupported_error()),
638        }
639    }
640}
641
642#[cfg(any(feature = "p256", feature = "p384", feature = "p521"))]
643impl Signer<Signature> for EcdsaKeypair {
644    fn try_sign(&self, message: &[u8]) -> signature::Result<Signature> {
645        match self {
646            #[cfg(feature = "p256")]
647            Self::NistP256 { private, .. } => private.try_sign(message),
648            #[cfg(feature = "p384")]
649            Self::NistP384 { private, .. } => private.try_sign(message),
650            #[cfg(feature = "p521")]
651            Self::NistP521 { private, .. } => private.try_sign(message),
652            #[cfg(not(all(feature = "p256", feature = "p384", feature = "p521")))]
653            _ => Err(self.algorithm().unsupported_error().into()),
654        }
655    }
656}
657
658#[cfg(any(feature = "p256", feature = "p384", feature = "p521"))]
659impl Verifier<Signature> for EcdsaPublicKey {
660    fn verify(&self, message: &[u8], signature: &Signature) -> signature::Result<()> {
661        match signature.algorithm {
662            Algorithm::Ecdsa { curve } => match curve {
663                #[cfg(feature = "p256")]
664                EcdsaCurve::NistP256 => {
665                    let verifying_key = p256::ecdsa::VerifyingKey::try_from(self)?;
666                    let signature = p256::ecdsa::Signature::try_from(signature)?;
667                    verifying_key.verify(message, &signature)
668                }
669
670                #[cfg(feature = "p384")]
671                EcdsaCurve::NistP384 => {
672                    let verifying_key = p384::ecdsa::VerifyingKey::try_from(self)?;
673                    let signature = p384::ecdsa::Signature::try_from(signature)?;
674                    verifying_key.verify(message, &signature)
675                }
676
677                #[cfg(feature = "p521")]
678                EcdsaCurve::NistP521 => {
679                    let verifying_key = p521::ecdsa::VerifyingKey::try_from(self)?;
680                    let signature = p521::ecdsa::Signature::try_from(signature)?;
681                    verifying_key.verify(message, &signature)
682                }
683
684                #[cfg(not(all(feature = "p256", feature = "p384", feature = "p521")))]
685                _ => Err(signature.algorithm().unsupported_error().into()),
686            },
687            _ => Err(signature.algorithm().unsupported_error().into()),
688        }
689    }
690}
691
692#[cfg(feature = "rsa")]
693impl Signer<Signature> for (&RsaKeypair, Option<HashAlg>) {
694    fn try_sign(&self, message: &[u8]) -> signature::Result<Signature> {
695        let data = match self.1 {
696            Some(HashAlg::Sha512) => {
697                rsa::pkcs1v15::SigningKey::<Sha512>::try_from(self.0)?.try_sign(message)
698            }
699            Some(HashAlg::Sha256) => {
700                rsa::pkcs1v15::SigningKey::<Sha256>::try_from(self.0)?.try_sign(message)
701            }
702            #[cfg(all(feature = "rsa", feature = "sha1"))]
703            None => rsa::pkcs1v15::SigningKey::<Sha1>::try_from(self.0)?.try_sign(message),
704            #[cfg(not(all(feature = "rsa", feature = "sha1")))]
705            None => return Err(Algorithm::Rsa { hash: None }.unsupported_error().into()),
706        }
707        .map_err(|_| signature::Error::new())?;
708
709        Ok(Signature {
710            algorithm: Algorithm::Rsa { hash: self.1 },
711            data: data.to_vec(),
712        })
713    }
714}
715
716#[cfg(feature = "rsa")]
717impl Signer<Signature> for RsaKeypair {
718    fn try_sign(&self, message: &[u8]) -> signature::Result<Signature> {
719        (self, Some(HashAlg::Sha512)).try_sign(message)
720    }
721}
722
723#[cfg(feature = "rsa")]
724impl Verifier<Signature> for RsaPublicKey {
725    fn verify(&self, message: &[u8], signature: &Signature) -> signature::Result<()> {
726        match signature.algorithm {
727            Algorithm::Rsa { hash } => {
728                let signature = rsa::pkcs1v15::Signature::try_from(signature.data.as_ref())?;
729
730                match hash {
731                    #[cfg(not(all(feature = "rsa", feature = "sha1")))]
732                    None => Err(Algorithm::Rsa { hash: None }.unsupported_error().into()),
733                    #[cfg(all(feature = "rsa", feature = "sha1"))]
734                    None => rsa::pkcs1v15::VerifyingKey::<Sha1>::try_from(self)?
735                        .verify(message, &signature)
736                        .map_err(|_| signature::Error::new()),
737                    Some(HashAlg::Sha256) => rsa::pkcs1v15::VerifyingKey::<Sha256>::try_from(self)?
738                        .verify(message, &signature)
739                        .map_err(|_| signature::Error::new()),
740                    Some(HashAlg::Sha512) => rsa::pkcs1v15::VerifyingKey::<Sha512>::try_from(self)?
741                        .verify(message, &signature)
742                        .map_err(|_| signature::Error::new()),
743                }
744            }
745            _ => Err(signature.algorithm().unsupported_error().into()),
746        }
747    }
748}
749
750#[cfg(test)]
751mod tests {
752    use super::Signature;
753    use crate::{Algorithm, EcdsaCurve, HashAlg};
754    use alloc::vec::Vec;
755    use encoding::Encode;
756    use hex_literal::hex;
757
758    #[cfg(any(feature = "ed25519", all(feature = "rsa", feature = "sha1")))]
759    use signature::Verifier;
760    #[cfg(feature = "ed25519")]
761    use {super::Ed25519Keypair, signature::Signer};
762
763    #[cfg(feature = "p256")]
764    use super::{Mpint, zero_pad_field_bytes};
765
766    const DSA_SIGNATURE: &[u8] = &hex!(
767        "000000077373682d6473730000002866725bf3c56100e975e21fff28a60f73717534d285ea3e1beefc2891f7189d00bd4d94627e84c55c"
768    );
769    const ECDSA_SHA2_P256_SIGNATURE: &[u8] = &hex!(
770        "0000001365636473612d736861322d6e6973747032353600000048000000201298ab320720a32139cda8a40c97a13dc54ce032ea3c6f09ea9e87501e48fa1d0000002046e4ac697a6424a9870b9ef04ca1182cd741965f989bd1f1f4a26fd83cf70348"
771    );
772    const ED25519_SIGNATURE: &[u8] = &hex!(
773        "0000000b7373682d65643235353139000000403d6b9906b76875aef1e7b2f1e02078a94f439aebb9a4734da1a851a81e22ce0199bbf820387a8de9c834c9c3cc778d9972dcbe70f68d53cc6bc9e26b02b46d04"
774    );
775    const SK_ED25519_SIGNATURE: &[u8] = &hex!(
776        "0000001a736b2d7373682d65643235353139406f70656e7373682e636f6d000000402f5670b6f93465d17423878a74084bf331767031ed240c627c8eb79ab8fa1b935a1fd993f52f5a13fec1797f8a434f943a6096246aea8dd5c8aa922cba3d95060100000009"
777    );
778    const RSA_SHA512_SIGNATURE: &[u8] = &hex!(
779        "0000000c7273612d736861322d3531320000018085a4ad1a91a62c00c85de7bb511f38088ff2bce763d76f4786febbe55d47624f9e2cffce58a680183b9ad162c7f0191ea26cab001ac5f5055743eced58e9981789305c208fc98d2657954e38eb28c7e7f3fbe92393a14324ed77aebb772a41aa7a107b38cb9bd1d9ad79b275135d1d7e019bb1d56d74f2450be6db0771f48f6707d3fcf9789592ca2e55595acc16b6e8d0139b56c5d1360b3a1e060f4151a3d7841df2c2a8c94d6f8a1bf633165ee0bcadac5642763df0dd79d3235ae5506595145f199d8abe8f9980411bf70a16e30f273736324d047043317044c36374d6a5ed34cac251e01c6795e4578393f9090bf4ae3e74a0009275a197315fc9c62f1c9aec1ba3b2d37c3b207e5500df19e090e7097ebc038fb9c9e35aea9161479ba6b5190f48e89e1abe51e8ec0e120ef89776e129687ca52d1892c8e88e6ef062a7d96b8a87682ca6a42ff1df0cdf5815c3645aeed7267ca7093043db0565e0f109b796bf117b9d2bb6d6debc0c67a4c9fb3aae3e29b00c7bd70f6c11cf53c295ff"
780    );
781
782    /// Example test vector for signing.
783    #[cfg(any(feature = "ed25519", all(feature = "rsa", feature = "sha1")))]
784    const EXAMPLE_MSG: &[u8] = b"Hello, world!";
785
786    #[cfg(feature = "p256")]
787    #[test]
788    fn convert_ecdsa_sha2_p256() {
789        let p256_signature = p256::ecdsa::Signature::try_from(&hex!("00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001")[..]).unwrap();
790        let _ssh_signature = Signature::try_from(p256_signature).unwrap();
791    }
792
793    #[cfg(feature = "p256")]
794    #[test]
795    fn zero_pad_field_bytes_p256() {
796        let i = Mpint::from_bytes(&hex!(
797            "1122334455667788112233445566778811223344556677881122334455667788"
798        ))
799        .unwrap();
800        let fb = zero_pad_field_bytes::<p256::FieldBytes>(i);
801        assert!(fb.is_some());
802
803        // too long
804        let i = Mpint::from_bytes(&hex!(
805            "991122334455667788112233445566778811223344556677881122334455667788"
806        ))
807        .unwrap();
808        let fb = zero_pad_field_bytes::<p256::FieldBytes>(i);
809        assert!(fb.is_none());
810
811        // short is okay
812        let i = Mpint::from_bytes(&hex!(
813            "22334455667788112233445566778811223344556677881122334455667788"
814        ))
815        .unwrap();
816        let fb = zero_pad_field_bytes::<p256::FieldBytes>(i)
817            .expect("failed to build FieldBytes from short hex string");
818        assert_eq!(fb[0], 0x00);
819        assert_eq!(fb[1], 0x22);
820    }
821
822    #[test]
823    fn decode_dsa() {
824        let signature = Signature::try_from(DSA_SIGNATURE).unwrap();
825        assert_eq!(Algorithm::Dsa, signature.algorithm());
826    }
827
828    #[test]
829    fn decode_ecdsa_sha2_p256() {
830        let signature = Signature::try_from(ECDSA_SHA2_P256_SIGNATURE).unwrap();
831        assert_eq!(
832            Algorithm::Ecdsa {
833                curve: EcdsaCurve::NistP256
834            },
835            signature.algorithm()
836        );
837    }
838
839    #[test]
840    fn decode_ed25519() {
841        let signature = Signature::try_from(ED25519_SIGNATURE).unwrap();
842        assert_eq!(Algorithm::Ed25519, signature.algorithm());
843    }
844
845    #[test]
846    fn decode_sk_ed25519() {
847        let signature = Signature::try_from(SK_ED25519_SIGNATURE).unwrap();
848        assert_eq!(Algorithm::SkEd25519, signature.algorithm());
849    }
850
851    #[test]
852    fn decode_rsa() {
853        let signature = Signature::try_from(RSA_SHA512_SIGNATURE).unwrap();
854        assert_eq!(
855            Algorithm::Rsa {
856                hash: Some(HashAlg::Sha512)
857            },
858            signature.algorithm()
859        );
860    }
861
862    #[test]
863    fn encode_dsa() {
864        let signature = Signature::try_from(DSA_SIGNATURE).unwrap();
865        let result = signature.encode_vec().unwrap();
866        assert_eq!(DSA_SIGNATURE, &result);
867    }
868
869    #[test]
870    fn encode_ecdsa_sha2_p256() {
871        let signature = Signature::try_from(ECDSA_SHA2_P256_SIGNATURE).unwrap();
872        let result = signature.encode_vec().unwrap();
873        assert_eq!(ECDSA_SHA2_P256_SIGNATURE, &result);
874    }
875
876    #[test]
877    fn encode_ed25519() {
878        let signature = Signature::try_from(ED25519_SIGNATURE).unwrap();
879        let result = signature.encode_vec().unwrap();
880        assert_eq!(ED25519_SIGNATURE, &result);
881    }
882
883    #[test]
884    fn encode_sk_ed25519() {
885        let signature = Signature::try_from(SK_ED25519_SIGNATURE).unwrap();
886        let result = signature.encode_vec().unwrap();
887        assert_eq!(SK_ED25519_SIGNATURE, &result);
888    }
889
890    #[cfg(feature = "dsa")]
891    #[test]
892    fn try_sign_and_verify_dsa() {
893        use super::{DSA_SIGNATURE_SIZE, DsaKeypair};
894        use encoding::Decode as _;
895        use signature::{Signer as _, Verifier as _};
896
897        fn check_signature_component_lengths(
898            keypair: &DsaKeypair,
899            data: &[u8],
900            r_len: usize,
901            s_len: usize,
902        ) {
903            use sha1::{Digest as _, Sha1};
904            use signature::DigestSigner as _;
905
906            let signature = dsa::SigningKey::try_from(keypair)
907                .expect("valid DSA signing key")
908                .try_sign_digest(|digest: &mut Sha1| {
909                    digest.update(data);
910                    Ok(())
911                })
912                .expect("valid DSA signature");
913
914            let r = signature.r().to_be_bytes_trimmed_vartime();
915            assert_eq!(
916                r.len(),
917                r_len,
918                "dsa signature component `r` has len {} != {}",
919                r.len(),
920                r_len
921            );
922            let s = signature.s().to_be_bytes_trimmed_vartime();
923            assert_eq!(
924                s.len(),
925                s_len,
926                "dsa signature component `s` has len {} != {}",
927                s.len(),
928                s_len
929            );
930        }
931
932        let keypair = hex!(
933            "0000008100c161fb30c9e4e3602c8510f93bbd48d813da845dfcc75f3696e440cd019d609809608cd592b8430db901d7b43740740045b547c60fb035d69f9c64d3dfbfb13bb3edd8ccfdd44705739a639eb70f4aed16b0b8355de1b21cd9d442eff250895573a8af7ce2fb71fb062e887482dab5c68139845fb8afafc5f3819dc782920d510000001500f3fb6762430332bd5950edc5cd1ae6f17b88514f0000008061ef1394d864905e8efec3b610b7288a6522893af2a475f910796e0de47c8b065d365e942e80e471d1e6d4abdee1d3d3ede7103c6996432f1a9f9a671a31388672d63555077911fc69e641a997087260d22cdbf4965aa64bb382204f88987890ec225a5a7723a977dc1ecc5e04cf678f994692b20470adbf697489f800817b920000008100a9a6f1b65fc724d65df7441908b34af66489a4a3872cbbba25ea1bcfc83f25c4af1a62e339eefc814907cfaf0cb6d2d16996212a32a27a63013f01c57d0630f0be16c8c69d16fc25438e613b904b98aeb3e7c356fa8e75ee1d474c9f82f1280c5a6c18e9e607fcf7586eefb75ea9399da893b807375ac1396fd586bf277161980000001500ced95f1c7bbb39be4987837ad1f71be31bb7b0d9"
934        );
935        let keypair = DsaKeypair::decode(&mut &keypair[..]).expect("properly encoded DSA keypair");
936
937        let data = hex!(
938            "F0000040713d5f6fffe0000e6421ab0b3a69774d3da02fd72b107d6b32b6dad7c1660bbf507bf3eac3304cc5058f7e6f81b04239b8471459b1f3b387e2626f7eb8f6bcdd3200000006626c616465320000000e7373682d636f6e6e656374696f6e00000009686f73746261736564000000077373682d647373000001b2000000077373682d6473730000008100c161fb30c9e4e3602c8510f93bbd48d813da845dfcc75f3696e440cd019d609809608cd592b8430db901d7b43740740045b547c60fb035d69f9c64d3dfbfb13bb3edd8ccfdd44705739a639eb70f4aed16b0b8355de1b21cd9d442eff250895573a8af7ce2fb71fb062e887482dab5c68139845fb8afafc5f3819dc782920d510000001500f3fb6762430332bd5950edc5cd1ae6f17b88514f0000008061ef1394d864905e8efec3b610b7288a6522893af2a475f910796e0de47c8b065d365e942e80e471d1e6d4abdee1d3d3ede7103c6996432f1a9f9a671a31388672d63555077911fc69e641a997087260d22cdbf4965aa64bb382204f88987890ec225a5a7723a977dc1ecc5e04cf678f994692b20470adbf697489f800817b920000008100a9a6f1b65fc724d65df7441908b34af66489a4a3872cbbba25ea1bcfc83f25c4af1a62e339eefc814907cfaf0cb6d2d16996212a32a27a63013f01c57d0630f0be16c8c69d16fc25438e613b904b98aeb3e7c356fa8e75ee1d474c9f82f1280c5a6c18e9e607fcf7586eefb75ea9399da893b807375ac1396fd586bf2771619800000015746f6d61746f7373682e6c6f63616c646f6d61696e00000009746f6d61746f737368"
939        );
940        check_signature_component_lengths(
941            &keypair,
942            &data,
943            DSA_SIGNATURE_SIZE / 2,
944            DSA_SIGNATURE_SIZE / 2,
945        );
946        let signature = keypair.try_sign(&data[..]).expect("dsa try_sign is ok");
947        keypair
948            .public()
949            .verify(&data[..], &signature)
950            .expect("dsa verify is ok");
951
952        let data = hex!(
953            "00000040713d5f6fffe0000e6421ab0b3a69774d3da02fd72b107d6b32b6dad7c1660bbf507bf3eac3304cc5058f7e6f81b04239b8471459b1f3b387e2626f7eb8f6bcdd3200000006626c616465320000000e7373682d636f6e6e656374696f6e00000009686f73746261736564000000077373682d647373000001b2000000077373682d6473730000008100c161fb30c9e4e3602c8510f93bbd48d813da845dfcc75f3696e440cd019d609809608cd592b8430db901d7b43740740045b547c60fb035d69f9c64d3dfbfb13bb3edd8ccfdd44705739a639eb70f4aed16b0b8355de1b21cd9d442eff250895573a8af7ce2fb71fb062e887482dab5c68139845fb8afafc5f3819dc782920d510000001500f3fb6762430332bd5950edc5cd1ae6f17b88514f0000008061ef1394d864905e8efec3b610b7288a6522893af2a475f910796e0de47c8b065d365e942e80e471d1e6d4abdee1d3d3ede7103c6996432f1a9f9a671a31388672d63555077911fc69e641a997087260d22cdbf4965aa64bb382204f88987890ec225a5a7723a977dc1ecc5e04cf678f994692b20470adbf697489f800817b920000008100a9a6f1b65fc724d65df7441908b34af66489a4a3872cbbba25ea1bcfc83f25c4af1a62e339eefc814907cfaf0cb6d2d16996212a32a27a63013f01c57d0630f0be16c8c69d16fc25438e613b904b98aeb3e7c356fa8e75ee1d474c9f82f1280c5a6c18e9e607fcf7586eefb75ea9399da893b807375ac1396fd586bf2771619800000015746f6d61746f7373682e6c6f63616c646f6d61696e00000009746f6d61746f737368"
954        );
955        // verify that this data produces signature with `r` integer component that is less than 160 bits/20 bytes.
956        check_signature_component_lengths(
957            &keypair,
958            &data,
959            DSA_SIGNATURE_SIZE / 2 - 1,
960            DSA_SIGNATURE_SIZE / 2,
961        );
962        let signature = keypair
963            .try_sign(&data[..])
964            .expect("dsa try_sign for r.len() == 19 is ok");
965        keypair
966            .public()
967            .verify(&data[..], &signature)
968            .expect("dsa verify is ok");
969    }
970
971    #[cfg(feature = "ed25519")]
972    #[test]
973    fn sign_and_verify_ed25519() {
974        let keypair = Ed25519Keypair::from_seed(&[42; 32]);
975        let signature = keypair.sign(EXAMPLE_MSG);
976        assert!(keypair.public.verify(EXAMPLE_MSG, &signature).is_ok());
977    }
978
979    #[test]
980    fn placeholder() {
981        assert!(
982            !Signature::try_from(ED25519_SIGNATURE)
983                .unwrap()
984                .is_placeholder()
985        );
986
987        let placeholder = Signature::placeholder();
988        assert!(placeholder.is_placeholder());
989
990        let mut writer = Vec::new();
991        assert_eq!(
992            placeholder.encode(&mut writer),
993            Err(encoding::Error::Length)
994        );
995    }
996
997    #[cfg(all(feature = "rsa", feature = "sha1"))]
998    #[test]
999    fn sign_and_verify_rsa_sha1() {
1000        use encoding::Decode;
1001
1002        use crate::PrivateKey;
1003
1004        let key = PrivateKey::from_openssh(include_str!("../tests/examples/id_rsa_3072")).unwrap();
1005        let key = key.key_data().rsa().unwrap();
1006        let encoded = hex!(
1007            "000000077373682d727361000001809485247d72bf853272c86dd8c1c3fa0d2bebcdea9d91a376525a4bcc4a9ca2b19d31af48cfc07da086b244c65b37f3eb8fcab9661ccf777ed2f45404dd602b405526e19323f065b44d19f1bbda3eaf87b922b01049fcd8b82f08ffab6582e8427b0af3305f32961816d499d7b4925c1293b2d658dc6ca7cfb2d47c203c7d9512c0ee33e3d74f362d339a112fc94a74e8f388fc7fd1e9b95c7dd94e62ff16c9463476b7cf0e42af0f17fd2b9e325a50fc40ffd02b4a39e692727186b47c8ce9d7037de7e94615966df462238e214e7440bedabc5fbf79cfa93b96be5f27268da7c1ae2246bcabcc18a0d2c507be8727d04e41ed38686e5c455c159ee371f477668e89720191a72fbdb4eef86f1aa5c3596cefad12b20b1a1220accf6145f8583d7559751b2d0445e2e8a8fda85bf30f24b446ac6d0b943f7c519e5a021b1468cf120ed565d95ed8ddf022f97537ec5491226198ec58dd96c6bd218ddb237aa80785ceafa7722f1d2ba3e39dce2a9fdb0038f4124e2aa27d28eef927d87c8708f6"
1008        );
1009
1010        let decoded = Signature::decode(&mut &encoded[..]).unwrap();
1011
1012        assert!(Verifier::verify(key.public(), EXAMPLE_MSG, &decoded).is_ok());
1013    }
1014}