ssh_key/private/
dsa.rs
1use 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#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
20#[derive(Clone)]
21pub struct DsaPrivateKey {
22 inner: MPInt,
24}
25
26impl DsaPrivateKey {
27 pub fn as_bytes(&self) -> &[u8] {
29 self.inner.as_bytes()
30 }
31
32 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#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
96#[derive(Clone)]
97pub struct DsaKeypair {
98 pub public: DsaPublicKey,
100
101 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 {}