Skip to main content

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