ssh_key/
signature.rs

1//! Signatures (e.g. CA signatures over SSH certificates)
2
3use crate::{private, public, Algorithm, EcdsaCurve, Error, Mpint, PrivateKey, PublicKey, Result};
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    bigint::BigUint,
16    sha1::Sha1,
17    signature::{DigestSigner, DigestVerifier},
18};
19
20#[cfg(any(feature = "p256", feature = "p384", feature = "p521"))]
21use crate::{
22    private::{EcdsaKeypair, EcdsaPrivateKey},
23    public::EcdsaPublicKey,
24};
25
26#[cfg(any(feature = "dsa", feature = "p256", feature = "p384", feature = "p521"))]
27use core::iter;
28
29#[cfg(feature = "rsa")]
30use {
31    crate::{private::RsaKeypair, public::RsaPublicKey, HashAlg},
32    sha2::Sha512,
33};
34
35#[cfg(any(feature = "ed25519", feature = "rsa", feature = "p256"))]
36use sha2::Sha256;
37
38#[cfg(any(feature = "dsa", feature = "ed25519", feature = "p256"))]
39use sha2::Digest;
40
41const DSA_SIGNATURE_SIZE: usize = 40;
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, 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    /// # Returns
103    /// - [`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 { hash: Some(_) } => (),
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    pub fn algorithm(&self) -> Algorithm {
124        self.algorithm.clone()
125    }
126
127    /// Get the raw signature as bytes.
128    pub fn as_bytes(&self) -> &[u8] {
129        &self.data
130    }
131
132    /// Placeholder signature used by the certificate builder.
133    ///
134    /// This is guaranteed generate an error if anything attempts to encode it.
135    pub(crate) fn placeholder() -> Self {
136        Self {
137            algorithm: Algorithm::default(),
138            data: Vec::new(),
139        }
140    }
141
142    /// Check if this signature is the placeholder signature.
143    pub(crate) fn is_placeholder(&self) -> bool {
144        self.algorithm == Algorithm::default() && self.data.is_empty()
145    }
146}
147
148/// Returns Ok() if data holds an ecdsa signature with components of appropriate size
149/// according to curve.
150fn ecdsa_sig_size(data: &Vec<u8>, curve: EcdsaCurve, sk_trailer: bool) -> Result<()> {
151    let reader = &mut data.as_slice();
152
153    for _ in 0..2 {
154        let component = Mpint::decode(reader)?;
155
156        if component.as_positive_bytes().ok_or(Error::Crypto)?.len() > curve.field_size() {
157            return Err(encoding::Error::Length.into());
158        }
159    }
160    if sk_trailer {
161        reader.drain(SK_SIGNATURE_TRAILER_SIZE)?;
162    }
163    reader
164        .finish(())
165        .map_err(|_| encoding::Error::Length.into())
166}
167
168impl AsRef<[u8]> for Signature {
169    fn as_ref(&self) -> &[u8] {
170        self.as_bytes()
171    }
172}
173
174impl Decode for Signature {
175    type Error = Error;
176
177    fn decode(reader: &mut impl Reader) -> Result<Self> {
178        let algorithm = Algorithm::decode(reader)?;
179        let mut data = Vec::decode(reader)?;
180
181        if algorithm == Algorithm::SkEd25519 || algorithm == Algorithm::SkEcdsaSha2NistP256 {
182            let flags = u8::decode(reader)?;
183            let counter = u32::decode(reader)?;
184
185            data.push(flags);
186            data.extend(counter.to_be_bytes());
187        }
188        Self::new(algorithm, data)
189    }
190}
191
192impl Encode for Signature {
193    fn encoded_len(&self) -> encoding::Result<usize> {
194        [
195            self.algorithm().encoded_len()?,
196            self.as_bytes().encoded_len()?,
197        ]
198        .checked_sum()
199    }
200
201    fn encode(&self, writer: &mut impl Writer) -> encoding::Result<()> {
202        if self.is_placeholder() {
203            return Err(encoding::Error::Length);
204        }
205
206        self.algorithm().encode(writer)?;
207
208        if self.algorithm == Algorithm::SkEd25519 {
209            let signature_length = self
210                .as_bytes()
211                .len()
212                .checked_sub(SK_SIGNATURE_TRAILER_SIZE)
213                .ok_or(encoding::Error::Length)?;
214            self.as_bytes()[..signature_length].encode(writer)?;
215            writer.write(&self.as_bytes()[signature_length..])?;
216        } else {
217            self.as_bytes().encode(writer)?;
218        }
219
220        Ok(())
221    }
222}
223
224impl SignatureEncoding for Signature {
225    type Repr = Vec<u8>;
226}
227
228/// Decode [`Signature`] from an [`Algorithm`]-prefixed OpenSSH-encoded bytestring.
229impl TryFrom<&[u8]> for Signature {
230    type Error = Error;
231
232    fn try_from(mut bytes: &[u8]) -> Result<Self> {
233        Self::decode(&mut bytes)
234    }
235}
236
237impl TryFrom<Signature> for Vec<u8> {
238    type Error = Error;
239
240    fn try_from(signature: Signature) -> Result<Vec<u8>> {
241        let mut ret = Vec::<u8>::new();
242        signature.encode(&mut ret)?;
243        Ok(ret)
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(Sha1::new_with_prefix(message))
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::new();
335
336        for component in [signature.r(), signature.s()] {
337            let mut bytes = component.to_bytes_be();
338            let pad_len = (DSA_SIGNATURE_SIZE / 2).saturating_sub(bytes.len());
339            data.extend(iter::repeat(0).take(pad_len));
340            data.append(&mut 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 data = signature.data.as_slice();
358                if data.len() != DSA_SIGNATURE_SIZE {
359                    return Err(signature::Error::new());
360                }
361                let (r, s) = data.split_at(DSA_SIGNATURE_SIZE / 2);
362                let signature = dsa::Signature::from_components(
363                    BigUint::from_bytes_be(r),
364                    BigUint::from_bytes_be(s),
365                )?;
366                dsa::VerifyingKey::try_from(self)?
367                    .verify_digest(Sha1::new_with_prefix(message), &signature)
368                    .map_err(|_| signature::Error::new())
369            }
370            _ => Err(signature.algorithm().unsupported_error().into()),
371        }
372    }
373}
374
375#[cfg(feature = "ed25519")]
376impl TryFrom<Signature> for ed25519_dalek::Signature {
377    type Error = Error;
378
379    fn try_from(signature: Signature) -> Result<ed25519_dalek::Signature> {
380        ed25519_dalek::Signature::try_from(&signature)
381    }
382}
383
384#[cfg(feature = "ed25519")]
385impl TryFrom<&Signature> for ed25519_dalek::Signature {
386    type Error = Error;
387
388    fn try_from(signature: &Signature) -> Result<ed25519_dalek::Signature> {
389        match signature.algorithm {
390            Algorithm::Ed25519 | Algorithm::SkEd25519 => {
391                Ok(ed25519_dalek::Signature::try_from(signature.as_bytes())?)
392            }
393            _ => Err(Error::AlgorithmUnknown),
394        }
395    }
396}
397
398#[cfg(feature = "ed25519")]
399impl Signer<Signature> for Ed25519Keypair {
400    fn try_sign(&self, message: &[u8]) -> signature::Result<Signature> {
401        let signature = ed25519_dalek::SigningKey::try_from(self)?.sign(message);
402
403        Ok(Signature {
404            algorithm: Algorithm::Ed25519,
405            data: signature.to_vec(),
406        })
407    }
408}
409
410#[cfg(feature = "ed25519")]
411impl Verifier<Signature> for Ed25519PublicKey {
412    fn verify(&self, message: &[u8], signature: &Signature) -> signature::Result<()> {
413        let signature = ed25519_dalek::Signature::try_from(signature)?;
414        ed25519_dalek::VerifyingKey::try_from(self)?.verify(message, &signature)
415    }
416}
417
418#[cfg(feature = "ed25519")]
419impl Verifier<Signature> for public::SkEd25519 {
420    fn verify(&self, message: &[u8], signature: &Signature) -> signature::Result<()> {
421        let (signature, flags_and_counter) = split_sk_signature(signature)?;
422        let signature = ed25519_dalek::Signature::try_from(signature)?;
423        ed25519_dalek::VerifyingKey::try_from(self.public_key())?.verify(
424            &make_sk_signed_data(self.application(), flags_and_counter, message),
425            &signature,
426        )
427    }
428}
429
430#[cfg(feature = "p256")]
431impl Verifier<Signature> for public::SkEcdsaSha2NistP256 {
432    fn verify(&self, message: &[u8], signature: &Signature) -> signature::Result<()> {
433        let (signature_bytes, flags_and_counter) = split_sk_signature(signature)?;
434        let signature = p256_signature_from_openssh_bytes(signature_bytes)?;
435        p256::ecdsa::VerifyingKey::from_encoded_point(self.ec_point())?.verify(
436            &make_sk_signed_data(self.application(), flags_and_counter, message),
437            &signature,
438        )
439    }
440}
441
442#[cfg(any(feature = "p256", feature = "ed25519"))]
443fn make_sk_signed_data(application: &str, flags_and_counter: &[u8], message: &[u8]) -> Vec<u8> {
444    const SHA256_OUTPUT_LENGTH: usize = 32;
445    const SIGNED_SK_DATA_LENGTH: usize = 2 * SHA256_OUTPUT_LENGTH + SK_SIGNATURE_TRAILER_SIZE;
446
447    let mut signed_data = Vec::with_capacity(SIGNED_SK_DATA_LENGTH);
448    signed_data.extend(Sha256::digest(application));
449    signed_data.extend(flags_and_counter);
450    signed_data.extend(Sha256::digest(message));
451    signed_data
452}
453
454#[cfg(any(feature = "p256", feature = "ed25519"))]
455fn split_sk_signature(signature: &Signature) -> Result<(&[u8], &[u8])> {
456    let signature_bytes = signature.as_bytes();
457    let signature_len = signature_bytes
458        .len()
459        .checked_sub(SK_SIGNATURE_TRAILER_SIZE)
460        .ok_or(Error::Encoding(encoding::Error::Length))?;
461    Ok((
462        &signature_bytes[..signature_len],
463        &signature_bytes[signature_len..],
464    ))
465}
466
467macro_rules! impl_signature_for_curve {
468    ($krate:ident, $feature:expr, $curve:ident, $size:expr) => {
469        #[cfg(feature = $feature)]
470        impl TryFrom<$krate::ecdsa::Signature> for Signature {
471            type Error = Error;
472
473            fn try_from(signature: $krate::ecdsa::Signature) -> Result<Signature> {
474                Signature::try_from(&signature)
475            }
476        }
477
478        #[cfg(feature = $feature)]
479        impl TryFrom<&$krate::ecdsa::Signature> for Signature {
480            type Error = Error;
481
482            fn try_from(signature: &$krate::ecdsa::Signature) -> Result<Signature> {
483                let (r, s) = signature.split_bytes();
484
485                #[allow(clippy::arithmetic_side_effects)]
486                let mut data = Vec::with_capacity($size * 2 + 4 * 2 + 2);
487
488                Mpint::from_positive_bytes(&r)?.encode(&mut data)?;
489                Mpint::from_positive_bytes(&s)?.encode(&mut data)?;
490
491                Ok(Signature {
492                    algorithm: Algorithm::Ecdsa {
493                        curve: EcdsaCurve::$curve,
494                    },
495                    data,
496                })
497            }
498        }
499
500        #[cfg(feature = $feature)]
501        impl TryFrom<Signature> for $krate::ecdsa::Signature {
502            type Error = Error;
503
504            fn try_from(signature: Signature) -> Result<$krate::ecdsa::Signature> {
505                $krate::ecdsa::Signature::try_from(&signature)
506            }
507        }
508
509        #[cfg(feature = $feature)]
510        impl Signer<Signature> for EcdsaPrivateKey<$size> {
511            fn try_sign(&self, message: &[u8]) -> signature::Result<Signature> {
512                let signing_key = $krate::ecdsa::SigningKey::from_slice(self.as_ref())?;
513                let signature: $krate::ecdsa::Signature = signing_key.try_sign(message)?;
514                Ok(signature.try_into()?)
515            }
516        }
517    };
518}
519
520impl_signature_for_curve!(p256, "p256", NistP256, 32);
521impl_signature_for_curve!(p384, "p384", NistP384, 48);
522impl_signature_for_curve!(p521, "p521", NistP521, 66);
523
524/// Build a generic sized object from a `u8` iterator, with leading zero padding
525#[cfg(any(feature = "p256", feature = "p384", feature = "p521"))]
526fn zero_pad_field_bytes<B: FromIterator<u8> + Copy>(m: Mpint) -> Option<B> {
527    use core::mem::size_of;
528
529    let bytes = m.as_positive_bytes()?;
530    size_of::<B>()
531        .checked_sub(bytes.len())
532        .map(|i| B::from_iter(iter::repeat(0u8).take(i).chain(bytes.iter().cloned())))
533}
534
535#[cfg(feature = "p256")]
536impl TryFrom<&Signature> for p256::ecdsa::Signature {
537    type Error = Error;
538
539    fn try_from(signature: &Signature) -> Result<p256::ecdsa::Signature> {
540        match signature.algorithm {
541            Algorithm::Ecdsa {
542                curve: EcdsaCurve::NistP256,
543            } => p256_signature_from_openssh_bytes(signature.as_bytes()),
544            _ => Err(signature.algorithm.clone().unsupported_error()),
545        }
546    }
547}
548#[cfg(feature = "p256")]
549fn p256_signature_from_openssh_bytes(mut signature_bytes: &[u8]) -> Result<p256::ecdsa::Signature> {
550    let reader = &mut signature_bytes;
551    let r = Mpint::decode(reader)?;
552    let s = Mpint::decode(reader)?;
553
554    match (
555        zero_pad_field_bytes::<p256::FieldBytes>(r),
556        zero_pad_field_bytes::<p256::FieldBytes>(s),
557    ) {
558        (Some(r), Some(s)) => Ok(p256::ecdsa::Signature::from_scalars(r, s)?),
559        _ => Err(Error::Crypto),
560    }
561}
562
563#[cfg(feature = "p384")]
564impl TryFrom<&Signature> for p384::ecdsa::Signature {
565    type Error = Error;
566
567    fn try_from(signature: &Signature) -> Result<p384::ecdsa::Signature> {
568        match signature.algorithm {
569            Algorithm::Ecdsa {
570                curve: EcdsaCurve::NistP384,
571            } => {
572                let reader = &mut signature.as_bytes();
573                let r = Mpint::decode(reader)?;
574                let s = Mpint::decode(reader)?;
575
576                match (
577                    zero_pad_field_bytes::<p384::FieldBytes>(r),
578                    zero_pad_field_bytes::<p384::FieldBytes>(s),
579                ) {
580                    (Some(r), Some(s)) => Ok(p384::ecdsa::Signature::from_scalars(r, s)?),
581                    _ => Err(Error::Crypto),
582                }
583            }
584            _ => Err(signature.algorithm.clone().unsupported_error()),
585        }
586    }
587}
588
589#[cfg(feature = "p521")]
590impl TryFrom<&Signature> for p521::ecdsa::Signature {
591    type Error = Error;
592
593    fn try_from(signature: &Signature) -> Result<p521::ecdsa::Signature> {
594        match signature.algorithm {
595            Algorithm::Ecdsa {
596                curve: EcdsaCurve::NistP521,
597            } => {
598                let reader = &mut signature.as_bytes();
599                let r = Mpint::decode(reader)?;
600                let s = Mpint::decode(reader)?;
601
602                match (
603                    zero_pad_field_bytes::<p521::FieldBytes>(r),
604                    zero_pad_field_bytes::<p521::FieldBytes>(s),
605                ) {
606                    (Some(r), Some(s)) => Ok(p521::ecdsa::Signature::from_scalars(r, s)?),
607                    _ => Err(Error::Crypto),
608                }
609            }
610            _ => Err(signature.algorithm.clone().unsupported_error()),
611        }
612    }
613}
614
615#[cfg(any(feature = "p256", feature = "p384", feature = "p521"))]
616impl Signer<Signature> for EcdsaKeypair {
617    fn try_sign(&self, message: &[u8]) -> signature::Result<Signature> {
618        match self {
619            #[cfg(feature = "p256")]
620            Self::NistP256 { private, .. } => private.try_sign(message),
621            #[cfg(feature = "p384")]
622            Self::NistP384 { private, .. } => private.try_sign(message),
623            #[cfg(feature = "p521")]
624            Self::NistP521 { private, .. } => private.try_sign(message),
625            #[cfg(not(all(feature = "p256", feature = "p384", feature = "p521")))]
626            _ => Err(self.algorithm().unsupported_error().into()),
627        }
628    }
629}
630
631#[cfg(any(feature = "p256", feature = "p384", feature = "p521"))]
632impl Verifier<Signature> for EcdsaPublicKey {
633    fn verify(&self, message: &[u8], signature: &Signature) -> signature::Result<()> {
634        match signature.algorithm {
635            Algorithm::Ecdsa { curve } => match curve {
636                #[cfg(feature = "p256")]
637                EcdsaCurve::NistP256 => {
638                    let verifying_key = p256::ecdsa::VerifyingKey::try_from(self)?;
639                    let signature = p256::ecdsa::Signature::try_from(signature)?;
640                    verifying_key.verify(message, &signature)
641                }
642
643                #[cfg(feature = "p384")]
644                EcdsaCurve::NistP384 => {
645                    let verifying_key = p384::ecdsa::VerifyingKey::try_from(self)?;
646                    let signature = p384::ecdsa::Signature::try_from(signature)?;
647                    verifying_key.verify(message, &signature)
648                }
649
650                #[cfg(feature = "p521")]
651                EcdsaCurve::NistP521 => {
652                    let verifying_key = p521::ecdsa::VerifyingKey::try_from(self)?;
653                    let signature = p521::ecdsa::Signature::try_from(signature)?;
654                    verifying_key.verify(message, &signature)
655                }
656
657                #[cfg(not(all(feature = "p256", feature = "p384", feature = "p521")))]
658                _ => Err(signature.algorithm().unsupported_error().into()),
659            },
660            _ => Err(signature.algorithm().unsupported_error().into()),
661        }
662    }
663}
664
665#[cfg(feature = "rsa")]
666impl Signer<Signature> for RsaKeypair {
667    fn try_sign(&self, message: &[u8]) -> signature::Result<Signature> {
668        let data = rsa::pkcs1v15::SigningKey::<Sha512>::try_from(self)?
669            .try_sign(message)
670            .map_err(|_| signature::Error::new())?;
671
672        Ok(Signature {
673            algorithm: Algorithm::Rsa {
674                hash: Some(HashAlg::Sha512),
675            },
676            data: data.to_vec(),
677        })
678    }
679}
680
681#[cfg(feature = "rsa")]
682impl Verifier<Signature> for RsaPublicKey {
683    fn verify(&self, message: &[u8], signature: &Signature) -> signature::Result<()> {
684        match signature.algorithm {
685            Algorithm::Rsa { hash: Some(hash) } => {
686                let signature = rsa::pkcs1v15::Signature::try_from(signature.data.as_ref())?;
687
688                match hash {
689                    HashAlg::Sha256 => rsa::pkcs1v15::VerifyingKey::<Sha256>::try_from(self)?
690                        .verify(message, &signature)
691                        .map_err(|_| signature::Error::new()),
692                    HashAlg::Sha512 => rsa::pkcs1v15::VerifyingKey::<Sha512>::try_from(self)?
693                        .verify(message, &signature)
694                        .map_err(|_| signature::Error::new()),
695                }
696            }
697            _ => Err(signature.algorithm().unsupported_error().into()),
698        }
699    }
700}
701
702#[cfg(test)]
703mod tests {
704    use super::Signature;
705    use crate::{Algorithm, EcdsaCurve, HashAlg};
706    use alloc::vec::Vec;
707    use encoding::Encode;
708    use hex_literal::hex;
709
710    #[cfg(feature = "ed25519")]
711    use {
712        super::Ed25519Keypair,
713        signature::{Signer, Verifier},
714    };
715
716    #[cfg(feature = "p256")]
717    use super::{zero_pad_field_bytes, Mpint};
718
719    const DSA_SIGNATURE: &[u8] = &hex!("000000077373682d6473730000002866725bf3c56100e975e21fff28a60f73717534d285ea3e1beefc2891f7189d00bd4d94627e84c55c");
720    const ECDSA_SHA2_P256_SIGNATURE: &[u8] = &hex!("0000001365636473612d736861322d6e6973747032353600000048000000201298ab320720a32139cda8a40c97a13dc54ce032ea3c6f09ea9e87501e48fa1d0000002046e4ac697a6424a9870b9ef04ca1182cd741965f989bd1f1f4a26fd83cf70348");
721    const ED25519_SIGNATURE: &[u8] = &hex!("0000000b7373682d65643235353139000000403d6b9906b76875aef1e7b2f1e02078a94f439aebb9a4734da1a851a81e22ce0199bbf820387a8de9c834c9c3cc778d9972dcbe70f68d53cc6bc9e26b02b46d04");
722    const SK_ED25519_SIGNATURE: &[u8] = &hex!("0000001a736b2d7373682d65643235353139406f70656e7373682e636f6d000000402f5670b6f93465d17423878a74084bf331767031ed240c627c8eb79ab8fa1b935a1fd993f52f5a13fec1797f8a434f943a6096246aea8dd5c8aa922cba3d95060100000009");
723    const RSA_SHA512_SIGNATURE: &[u8] = &hex!("0000000c7273612d736861322d3531320000018085a4ad1a91a62c00c85de7bb511f38088ff2bce763d76f4786febbe55d47624f9e2cffce58a680183b9ad162c7f0191ea26cab001ac5f5055743eced58e9981789305c208fc98d2657954e38eb28c7e7f3fbe92393a14324ed77aebb772a41aa7a107b38cb9bd1d9ad79b275135d1d7e019bb1d56d74f2450be6db0771f48f6707d3fcf9789592ca2e55595acc16b6e8d0139b56c5d1360b3a1e060f4151a3d7841df2c2a8c94d6f8a1bf633165ee0bcadac5642763df0dd79d3235ae5506595145f199d8abe8f9980411bf70a16e30f273736324d047043317044c36374d6a5ed34cac251e01c6795e4578393f9090bf4ae3e74a0009275a197315fc9c62f1c9aec1ba3b2d37c3b207e5500df19e090e7097ebc038fb9c9e35aea9161479ba6b5190f48e89e1abe51e8ec0e120ef89776e129687ca52d1892c8e88e6ef062a7d96b8a87682ca6a42ff1df0cdf5815c3645aeed7267ca7093043db0565e0f109b796bf117b9d2bb6d6debc0c67a4c9fb3aae3e29b00c7bd70f6c11cf53c295ff");
724
725    /// Example test vector for signing.
726    #[cfg(feature = "ed25519")]
727    const EXAMPLE_MSG: &[u8] = b"Hello, world!";
728
729    #[cfg(feature = "p256")]
730    #[test]
731    fn convert_ecdsa_sha2_p256() {
732        let p256_signature = p256::ecdsa::Signature::try_from(hex!("00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001").as_ref()).unwrap();
733        let _ssh_signature = Signature::try_from(p256_signature).unwrap();
734    }
735
736    #[cfg(feature = "p256")]
737    #[test]
738    fn zero_pad_field_bytes_p256() {
739        let i = Mpint::from_bytes(&hex!(
740            "1122334455667788112233445566778811223344556677881122334455667788"
741        ))
742        .unwrap();
743        let fb = zero_pad_field_bytes::<p256::FieldBytes>(i);
744        assert!(fb.is_some());
745
746        // too long
747        let i = Mpint::from_bytes(&hex!(
748            "991122334455667788112233445566778811223344556677881122334455667788"
749        ))
750        .unwrap();
751        let fb = zero_pad_field_bytes::<p256::FieldBytes>(i);
752        assert!(fb.is_none());
753
754        // short is okay
755        let i = Mpint::from_bytes(&hex!(
756            "22334455667788112233445566778811223344556677881122334455667788"
757        ))
758        .unwrap();
759        let fb = zero_pad_field_bytes::<p256::FieldBytes>(i)
760            .expect("failed to build FieldBytes from short hex string");
761        assert_eq!(fb[0], 0x00);
762        assert_eq!(fb[1], 0x22);
763    }
764
765    #[test]
766    fn decode_dsa() {
767        let signature = Signature::try_from(DSA_SIGNATURE).unwrap();
768        assert_eq!(Algorithm::Dsa, signature.algorithm());
769    }
770
771    #[test]
772    fn decode_ecdsa_sha2_p256() {
773        let signature = Signature::try_from(ECDSA_SHA2_P256_SIGNATURE).unwrap();
774        assert_eq!(
775            Algorithm::Ecdsa {
776                curve: EcdsaCurve::NistP256
777            },
778            signature.algorithm()
779        );
780    }
781
782    #[test]
783    fn decode_ed25519() {
784        let signature = Signature::try_from(ED25519_SIGNATURE).unwrap();
785        assert_eq!(Algorithm::Ed25519, signature.algorithm());
786    }
787
788    #[test]
789    fn decode_sk_ed25519() {
790        let signature = Signature::try_from(SK_ED25519_SIGNATURE).unwrap();
791        assert_eq!(Algorithm::SkEd25519, signature.algorithm());
792    }
793
794    #[test]
795    fn decode_rsa() {
796        let signature = Signature::try_from(RSA_SHA512_SIGNATURE).unwrap();
797        assert_eq!(
798            Algorithm::Rsa {
799                hash: Some(HashAlg::Sha512)
800            },
801            signature.algorithm()
802        );
803    }
804
805    #[test]
806    fn encode_dsa() {
807        let signature = Signature::try_from(DSA_SIGNATURE).unwrap();
808
809        let mut result = Vec::new();
810        signature.encode(&mut result).unwrap();
811        assert_eq!(DSA_SIGNATURE, &result);
812    }
813
814    #[test]
815    fn encode_ecdsa_sha2_p256() {
816        let signature = Signature::try_from(ECDSA_SHA2_P256_SIGNATURE).unwrap();
817
818        let mut result = Vec::new();
819        signature.encode(&mut result).unwrap();
820        assert_eq!(ECDSA_SHA2_P256_SIGNATURE, &result);
821    }
822
823    #[test]
824    fn encode_ed25519() {
825        let signature = Signature::try_from(ED25519_SIGNATURE).unwrap();
826
827        let mut result = Vec::new();
828        signature.encode(&mut result).unwrap();
829        assert_eq!(ED25519_SIGNATURE, &result);
830    }
831
832    #[test]
833    fn encode_sk_ed25519() {
834        let signature = Signature::try_from(SK_ED25519_SIGNATURE).unwrap();
835
836        let mut result = Vec::new();
837        signature.encode(&mut result).unwrap();
838        assert_eq!(SK_ED25519_SIGNATURE, &result);
839    }
840
841    #[cfg(feature = "dsa")]
842    #[test]
843    fn try_sign_and_verify_dsa() {
844        use super::{DsaKeypair, DSA_SIGNATURE_SIZE};
845        use encoding::Decode as _;
846        use signature::{Signer as _, Verifier as _};
847
848        fn check_signature_component_lens(
849            keypair: &DsaKeypair,
850            data: &[u8],
851            r_len: usize,
852            s_len: usize,
853        ) {
854            use sha1::{Digest as _, Sha1};
855            use signature::DigestSigner as _;
856
857            let signature = dsa::SigningKey::try_from(keypair)
858                .expect("valid DSA signing key")
859                .try_sign_digest(Sha1::new_with_prefix(data))
860                .expect("valid DSA signature");
861
862            let r = signature.r().to_bytes_be();
863            assert_eq!(
864                r.len(),
865                r_len,
866                "dsa signature component `r` has len {} != {}",
867                r.len(),
868                r_len
869            );
870            let s = signature.s().to_bytes_be();
871            assert_eq!(
872                s.len(),
873                s_len,
874                "dsa signature component `s` has len {} != {}",
875                s.len(),
876                s_len
877            );
878        }
879
880        let keypair = hex!("0000008100c161fb30c9e4e3602c8510f93bbd48d813da845dfcc75f3696e440cd019d609809608cd592b8430db901d7b43740740045b547c60fb035d69f9c64d3dfbfb13bb3edd8ccfdd44705739a639eb70f4aed16b0b8355de1b21cd9d442eff250895573a8af7ce2fb71fb062e887482dab5c68139845fb8afafc5f3819dc782920d510000001500f3fb6762430332bd5950edc5cd1ae6f17b88514f0000008061ef1394d864905e8efec3b610b7288a6522893af2a475f910796e0de47c8b065d365e942e80e471d1e6d4abdee1d3d3ede7103c6996432f1a9f9a671a31388672d63555077911fc69e641a997087260d22cdbf4965aa64bb382204f88987890ec225a5a7723a977dc1ecc5e04cf678f994692b20470adbf697489f800817b920000008100a9a6f1b65fc724d65df7441908b34af66489a4a3872cbbba25ea1bcfc83f25c4af1a62e339eefc814907cfaf0cb6d2d16996212a32a27a63013f01c57d0630f0be16c8c69d16fc25438e613b904b98aeb3e7c356fa8e75ee1d474c9f82f1280c5a6c18e9e607fcf7586eefb75ea9399da893b807375ac1396fd586bf277161980000001500ced95f1c7bbb39be4987837ad1f71be31bb7b0d9");
881        let keypair = DsaKeypair::decode(&mut &keypair[..]).expect("properly encoded DSA keypair");
882
883        let data = hex!("F0000040713d5f6fffe0000e6421ab0b3a69774d3da02fd72b107d6b32b6dad7c1660bbf507bf3eac3304cc5058f7e6f81b04239b8471459b1f3b387e2626f7eb8f6bcdd3200000006626c616465320000000e7373682d636f6e6e656374696f6e00000009686f73746261736564000000077373682d647373000001b2000000077373682d6473730000008100c161fb30c9e4e3602c8510f93bbd48d813da845dfcc75f3696e440cd019d609809608cd592b8430db901d7b43740740045b547c60fb035d69f9c64d3dfbfb13bb3edd8ccfdd44705739a639eb70f4aed16b0b8355de1b21cd9d442eff250895573a8af7ce2fb71fb062e887482dab5c68139845fb8afafc5f3819dc782920d510000001500f3fb6762430332bd5950edc5cd1ae6f17b88514f0000008061ef1394d864905e8efec3b610b7288a6522893af2a475f910796e0de47c8b065d365e942e80e471d1e6d4abdee1d3d3ede7103c6996432f1a9f9a671a31388672d63555077911fc69e641a997087260d22cdbf4965aa64bb382204f88987890ec225a5a7723a977dc1ecc5e04cf678f994692b20470adbf697489f800817b920000008100a9a6f1b65fc724d65df7441908b34af66489a4a3872cbbba25ea1bcfc83f25c4af1a62e339eefc814907cfaf0cb6d2d16996212a32a27a63013f01c57d0630f0be16c8c69d16fc25438e613b904b98aeb3e7c356fa8e75ee1d474c9f82f1280c5a6c18e9e607fcf7586eefb75ea9399da893b807375ac1396fd586bf2771619800000015746f6d61746f7373682e6c6f63616c646f6d61696e00000009746f6d61746f737368");
884        check_signature_component_lens(
885            &keypair,
886            &data,
887            DSA_SIGNATURE_SIZE / 2,
888            DSA_SIGNATURE_SIZE / 2,
889        );
890        let signature = keypair.try_sign(&data[..]).expect("dsa try_sign is ok");
891        keypair
892            .public
893            .verify(&data[..], &signature)
894            .expect("dsa verify is ok");
895
896        let data = hex!("00000040713d5f6fffe0000e6421ab0b3a69774d3da02fd72b107d6b32b6dad7c1660bbf507bf3eac3304cc5058f7e6f81b04239b8471459b1f3b387e2626f7eb8f6bcdd3200000006626c616465320000000e7373682d636f6e6e656374696f6e00000009686f73746261736564000000077373682d647373000001b2000000077373682d6473730000008100c161fb30c9e4e3602c8510f93bbd48d813da845dfcc75f3696e440cd019d609809608cd592b8430db901d7b43740740045b547c60fb035d69f9c64d3dfbfb13bb3edd8ccfdd44705739a639eb70f4aed16b0b8355de1b21cd9d442eff250895573a8af7ce2fb71fb062e887482dab5c68139845fb8afafc5f3819dc782920d510000001500f3fb6762430332bd5950edc5cd1ae6f17b88514f0000008061ef1394d864905e8efec3b610b7288a6522893af2a475f910796e0de47c8b065d365e942e80e471d1e6d4abdee1d3d3ede7103c6996432f1a9f9a671a31388672d63555077911fc69e641a997087260d22cdbf4965aa64bb382204f88987890ec225a5a7723a977dc1ecc5e04cf678f994692b20470adbf697489f800817b920000008100a9a6f1b65fc724d65df7441908b34af66489a4a3872cbbba25ea1bcfc83f25c4af1a62e339eefc814907cfaf0cb6d2d16996212a32a27a63013f01c57d0630f0be16c8c69d16fc25438e613b904b98aeb3e7c356fa8e75ee1d474c9f82f1280c5a6c18e9e607fcf7586eefb75ea9399da893b807375ac1396fd586bf2771619800000015746f6d61746f7373682e6c6f63616c646f6d61696e00000009746f6d61746f737368");
897        // verify that this data produces signature with `r` integer component that is less than 160 bits/20 bytes.
898        check_signature_component_lens(
899            &keypair,
900            &data,
901            DSA_SIGNATURE_SIZE / 2 - 1,
902            DSA_SIGNATURE_SIZE / 2,
903        );
904        let signature = keypair
905            .try_sign(&data[..])
906            .expect("dsa try_sign for r.len() == 19 is ok");
907        keypair
908            .public
909            .verify(&data[..], &signature)
910            .expect("dsa verify is ok");
911    }
912
913    #[cfg(feature = "ed25519")]
914    #[test]
915    fn sign_and_verify_ed25519() {
916        let keypair = Ed25519Keypair::from_seed(&[42; 32]);
917        let signature = keypair.sign(EXAMPLE_MSG);
918        assert!(keypair.public.verify(EXAMPLE_MSG, &signature).is_ok());
919    }
920
921    #[test]
922    fn placeholder() {
923        assert!(!Signature::try_from(ED25519_SIGNATURE)
924            .unwrap()
925            .is_placeholder());
926
927        let placeholder = Signature::placeholder();
928        assert!(placeholder.is_placeholder());
929
930        let mut writer = Vec::new();
931        assert_eq!(
932            placeholder.encode(&mut writer),
933            Err(encoding::Error::Length)
934        );
935    }
936}