1use crate::{Error, Mpint, Result, public::DsaPublicKey};
4use core::fmt;
5use ctutils::{Choice, CtEq};
6use encoding::{CheckedSum, Decode, Encode, Reader, Writer};
7use zeroize::Zeroize;
8
9#[cfg(feature = "dsa")]
10use encoding::Uint;
11#[cfg(all(feature = "dsa", feature = "rand_core"))]
12use rand_core::CryptoRng;
13
14#[derive(Clone)]
21pub struct DsaPrivateKey {
22 inner: Mpint,
24}
25
26impl DsaPrivateKey {
27 pub fn new(x: Mpint) -> Result<Self> {
32 if x.is_positive() {
33 Ok(Self { inner: x })
34 } else {
35 Err(Error::FormatEncoding)
36 }
37 }
38
39 #[must_use]
41 pub fn as_bytes(&self) -> &[u8] {
42 self.inner.as_bytes()
43 }
44
45 #[must_use]
47 pub fn as_mpint(&self) -> &Mpint {
48 &self.inner
49 }
50}
51
52impl AsRef<[u8]> for DsaPrivateKey {
53 fn as_ref(&self) -> &[u8] {
54 self.as_bytes()
55 }
56}
57
58impl CtEq for DsaPrivateKey {
59 fn ct_eq(&self, other: &Self) -> Choice {
60 self.inner.ct_eq(&other.inner)
61 }
62}
63
64impl Eq for DsaPrivateKey {}
65
66impl PartialEq for DsaPrivateKey {
67 fn eq(&self, other: &Self) -> bool {
68 self.ct_eq(other).into()
69 }
70}
71
72impl TryFrom<Mpint> for DsaPrivateKey {
73 type Error = Error;
74
75 fn try_from(x: Mpint) -> Result<Self> {
76 Self::new(x)
77 }
78}
79
80impl Decode for DsaPrivateKey {
81 type Error = Error;
82
83 fn decode(reader: &mut impl Reader) -> Result<Self> {
84 Self::new(Mpint::decode(reader)?)
85 }
86}
87
88impl Encode for DsaPrivateKey {
89 fn encoded_len(&self) -> encoding::Result<usize> {
90 self.inner.encoded_len()
91 }
92
93 fn encode(&self, writer: &mut impl Writer) -> encoding::Result<()> {
94 self.inner.encode(writer)
95 }
96}
97
98impl fmt::Debug for DsaPrivateKey {
99 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
100 f.debug_struct("DsaPrivateKey").finish_non_exhaustive()
101 }
102}
103
104impl Drop for DsaPrivateKey {
105 fn drop(&mut self) {
106 self.inner.zeroize();
107 }
108}
109
110#[cfg(feature = "dsa")]
111impl From<&dsa::SigningKey> for DsaPrivateKey {
112 fn from(key: &dsa::SigningKey) -> DsaPrivateKey {
113 DsaPrivateKey {
114 inner: key.x().as_ref().into(),
115 }
116 }
117}
118
119#[cfg(feature = "dsa")]
120impl From<dsa::SigningKey> for DsaPrivateKey {
121 fn from(key: dsa::SigningKey) -> DsaPrivateKey {
122 DsaPrivateKey::from(&key)
123 }
124}
125
126#[cfg(feature = "dsa")]
127impl TryFrom<DsaPrivateKey> for Uint {
128 type Error = Error;
129
130 fn try_from(key: DsaPrivateKey) -> Result<Uint> {
131 Ok(Uint::try_from(&key.inner)?)
132 }
133}
134
135#[cfg(feature = "dsa")]
136impl TryFrom<&DsaPrivateKey> for Uint {
137 type Error = Error;
138
139 fn try_from(key: &DsaPrivateKey) -> Result<Uint> {
140 Ok(Uint::try_from(&key.inner)?)
141 }
142}
143
144#[derive(Clone)]
146pub struct DsaKeypair {
147 public: DsaPublicKey,
149
150 private: DsaPrivateKey,
152}
153
154impl DsaKeypair {
155 #[cfg(all(feature = "dsa", feature = "rand_core"))]
157 #[allow(deprecated)]
158 pub(crate) const KEY_SIZE: dsa::KeySize = dsa::KeySize::DSA_1024_160;
159
160 #[cfg(all(feature = "dsa", feature = "rand_core"))]
162 #[expect(clippy::missing_errors_doc, reason = "TODO")]
163 pub fn random<R: CryptoRng + ?Sized>(rng: &mut R) -> Result<Self> {
164 let Ok(components) =
165 dsa::Components::try_generate_from_rng_with_key_size(rng, Self::KEY_SIZE);
166 let Ok(sk) = dsa::SigningKey::try_generate_from_rng_with_components(rng, components);
167 Ok(sk.into())
168 }
169
170 pub fn new(public: DsaPublicKey, private: DsaPrivateKey) -> Result<Self> {
175 Ok(Self { public, private })
177 }
178
179 #[must_use]
181 pub fn public(&self) -> &DsaPublicKey {
182 &self.public
183 }
184
185 #[must_use]
187 pub fn private(&self) -> &DsaPrivateKey {
188 &self.private
189 }
190}
191
192impl CtEq for DsaKeypair {
193 fn ct_eq(&self, other: &Self) -> Choice {
194 Choice::from(u8::from(self.public == other.public)) & self.private.ct_eq(&other.private)
195 }
196}
197
198impl PartialEq for DsaKeypair {
199 fn eq(&self, other: &Self) -> bool {
200 self.ct_eq(other).into()
201 }
202}
203
204impl Eq for DsaKeypair {}
205
206impl Decode for DsaKeypair {
207 type Error = Error;
208
209 fn decode(reader: &mut impl Reader) -> Result<Self> {
210 let public = DsaPublicKey::decode(reader)?;
211 let private = DsaPrivateKey::decode(reader)?;
212 DsaKeypair::new(public, private)
213 }
214}
215
216impl Encode for DsaKeypair {
217 fn encoded_len(&self) -> encoding::Result<usize> {
218 [self.public.encoded_len()?, self.private.encoded_len()?].checked_sum()
219 }
220
221 fn encode(&self, writer: &mut impl Writer) -> encoding::Result<()> {
222 self.public.encode(writer)?;
223 self.private.encode(writer)
224 }
225}
226
227impl From<DsaKeypair> for DsaPublicKey {
228 fn from(keypair: DsaKeypair) -> DsaPublicKey {
229 keypair.public
230 }
231}
232
233impl From<&DsaKeypair> for DsaPublicKey {
234 fn from(keypair: &DsaKeypair) -> DsaPublicKey {
235 keypair.public.clone()
236 }
237}
238
239impl fmt::Debug for DsaKeypair {
240 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
241 f.debug_struct("DsaKeypair")
242 .field("public", &self.public)
243 .finish_non_exhaustive()
244 }
245}
246
247#[cfg(feature = "dsa")]
248impl TryFrom<DsaKeypair> for dsa::SigningKey {
249 type Error = Error;
250
251 fn try_from(key: DsaKeypair) -> Result<dsa::SigningKey> {
252 dsa::SigningKey::try_from(&key)
253 }
254}
255
256#[cfg(feature = "dsa")]
257impl TryFrom<&DsaKeypair> for dsa::SigningKey {
258 type Error = Error;
259
260 fn try_from(key: &DsaKeypair) -> Result<dsa::SigningKey> {
261 Ok(dsa::SigningKey::from_components(
262 dsa::VerifyingKey::try_from(&key.public)?,
263 key.private.as_mpint().try_into()?,
264 )?)
265 }
266}
267
268#[cfg(feature = "dsa")]
269impl From<dsa::SigningKey> for DsaKeypair {
270 fn from(key: dsa::SigningKey) -> DsaKeypair {
271 DsaKeypair::from(&key)
272 }
273}
274
275#[cfg(feature = "dsa")]
276impl From<&dsa::SigningKey> for DsaKeypair {
277 fn from(key: &dsa::SigningKey) -> DsaKeypair {
278 DsaKeypair {
279 private: key.into(),
280 public: key.verifying_key().into(),
281 }
282 }
283}