ssh_key/private/
dsa.rs

1//! Digital Signature Algorithm (DSA) private keys.
2
3use crate::{
4    checked::CheckedSum, decode::Decode, encode::Encode, public::DsaPublicKey, reader::Reader,
5    writer::Writer, MPInt, Result,
6};
7use core::fmt;
8use zeroize::Zeroize;
9
10#[cfg(feature = "subtle")]
11use subtle::{Choice, ConstantTimeEq};
12
13/// Digital Signature Algorithm (DSA) private key.
14///
15/// Uniformly random integer `x`, such that `0 < x < q`, i.e. `x` is in the
16/// range `[1, q–1]`.
17///
18/// Described in [FIPS 186-4 § 4.1](https://csrc.nist.gov/publications/detail/fips/186/4/final).
19#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
20#[derive(Clone)]
21pub struct DsaPrivateKey {
22    /// Integer representing a DSA private key.
23    inner: MPInt,
24}
25
26impl DsaPrivateKey {
27    /// Get the serialized private key as bytes.
28    pub fn as_bytes(&self) -> &[u8] {
29        self.inner.as_bytes()
30    }
31
32    /// Get the inner [`MPInt`].
33    pub fn as_mpint(&self) -> &MPInt {
34        &self.inner
35    }
36}
37
38impl AsRef<[u8]> for DsaPrivateKey {
39    fn as_ref(&self) -> &[u8] {
40        self.as_bytes()
41    }
42}
43
44impl Decode for DsaPrivateKey {
45    fn decode(reader: &mut impl Reader) -> Result<Self> {
46        Ok(Self {
47            inner: MPInt::decode(reader)?,
48        })
49    }
50}
51
52impl Drop for DsaPrivateKey {
53    fn drop(&mut self) {
54        self.inner.zeroize();
55    }
56}
57
58impl Encode for DsaPrivateKey {
59    fn encoded_len(&self) -> Result<usize> {
60        self.inner.encoded_len()
61    }
62
63    fn encode(&self, writer: &mut impl Writer) -> Result<()> {
64        self.inner.encode(writer)
65    }
66}
67
68impl fmt::Debug for DsaPrivateKey {
69    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
70        f.debug_struct("DsaPrivateKey").finish_non_exhaustive()
71    }
72}
73
74#[cfg(feature = "subtle")]
75#[cfg_attr(docsrs, doc(cfg(feature = "subtle")))]
76impl ConstantTimeEq for DsaPrivateKey {
77    fn ct_eq(&self, other: &Self) -> Choice {
78        self.inner.ct_eq(&other.inner)
79    }
80}
81
82#[cfg(feature = "subtle")]
83#[cfg_attr(docsrs, doc(cfg(feature = "subtle")))]
84impl PartialEq for DsaPrivateKey {
85    fn eq(&self, other: &Self) -> bool {
86        self.ct_eq(other).into()
87    }
88}
89
90#[cfg(feature = "subtle")]
91#[cfg_attr(docsrs, doc(cfg(feature = "subtle")))]
92impl Eq for DsaPrivateKey {}
93
94/// Digital Signature Algorithm (DSA) private/public keypair.
95#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
96#[derive(Clone)]
97pub struct DsaKeypair {
98    /// Public key.
99    pub public: DsaPublicKey,
100
101    /// Private key.
102    pub private: DsaPrivateKey,
103}
104
105impl Decode for DsaKeypair {
106    fn decode(reader: &mut impl Reader) -> Result<Self> {
107        let public = DsaPublicKey::decode(reader)?;
108        let private = DsaPrivateKey::decode(reader)?;
109        Ok(DsaKeypair { public, private })
110    }
111}
112
113impl Encode for DsaKeypair {
114    fn encoded_len(&self) -> Result<usize> {
115        [self.public.encoded_len()?, self.private.encoded_len()?].checked_sum()
116    }
117
118    fn encode(&self, writer: &mut impl Writer) -> Result<()> {
119        self.public.encode(writer)?;
120        self.private.encode(writer)
121    }
122}
123
124impl From<DsaKeypair> for DsaPublicKey {
125    fn from(keypair: DsaKeypair) -> DsaPublicKey {
126        keypair.public
127    }
128}
129
130impl From<&DsaKeypair> for DsaPublicKey {
131    fn from(keypair: &DsaKeypair) -> DsaPublicKey {
132        keypair.public.clone()
133    }
134}
135
136impl fmt::Debug for DsaKeypair {
137    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
138        f.debug_struct("DsaKeypair")
139            .field("public", &self.public)
140            .finish_non_exhaustive()
141    }
142}
143
144#[cfg(feature = "subtle")]
145#[cfg_attr(docsrs, doc(cfg(feature = "subtle")))]
146impl ConstantTimeEq for DsaKeypair {
147    fn ct_eq(&self, other: &Self) -> Choice {
148        Choice::from((self.public == other.public) as u8) & self.private.ct_eq(&other.private)
149    }
150}
151
152#[cfg(feature = "subtle")]
153#[cfg_attr(docsrs, doc(cfg(feature = "subtle")))]
154impl PartialEq for DsaKeypair {
155    fn eq(&self, other: &Self) -> bool {
156        self.ct_eq(other).into()
157    }
158}
159
160#[cfg(feature = "subtle")]
161#[cfg_attr(docsrs, doc(cfg(feature = "subtle")))]
162impl Eq for DsaKeypair {}