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