1use super::ed25519::Ed25519Keypair;
4use crate::{Algorithm, Error, Result, public};
5use ctutils::{Choice, CtEq};
6use encoding::{CheckedSum, Decode, Encode, Reader, Writer};
7
8#[cfg(feature = "alloc")]
9use {
10 super::{DsaKeypair, OpaqueKeypair, RsaKeypair, SkEd25519},
11 alloc::vec::Vec,
12};
13
14#[cfg(feature = "ecdsa")]
15use super::EcdsaKeypair;
16
17#[cfg(all(feature = "alloc", feature = "ecdsa"))]
18use super::SkEcdsaSha2NistP256;
19
20#[derive(Clone, Debug)]
26#[non_exhaustive]
27pub enum KeypairData {
28 #[cfg(feature = "alloc")]
30 Dsa(DsaKeypair),
31
32 #[cfg(feature = "ecdsa")]
34 Ecdsa(EcdsaKeypair),
35
36 Ed25519(Ed25519Keypair),
38
39 #[cfg(feature = "alloc")]
41 Encrypted(Vec<u8>),
42
43 #[cfg(feature = "alloc")]
45 Rsa(RsaKeypair),
46
47 #[cfg(all(feature = "alloc", feature = "ecdsa"))]
51 SkEcdsaSha2NistP256(SkEcdsaSha2NistP256),
52
53 #[cfg(feature = "alloc")]
57 SkEd25519(SkEd25519),
58
59 #[cfg(feature = "alloc")]
61 Other(OpaqueKeypair),
62}
63
64impl KeypairData {
65 pub fn algorithm(&self) -> Result<Algorithm> {
70 Ok(match self {
71 #[cfg(feature = "alloc")]
72 Self::Dsa(_) => Algorithm::Dsa,
73 #[cfg(feature = "ecdsa")]
74 Self::Ecdsa(key) => key.algorithm(),
75 Self::Ed25519(_) => Algorithm::Ed25519,
76 #[cfg(feature = "alloc")]
77 Self::Encrypted(_) => return Err(Error::Encrypted),
78 #[cfg(feature = "alloc")]
79 Self::Rsa(_) => Algorithm::Rsa { hash: None },
80 #[cfg(all(feature = "alloc", feature = "ecdsa"))]
81 Self::SkEcdsaSha2NistP256(_) => Algorithm::SkEcdsaSha2NistP256,
82 #[cfg(feature = "alloc")]
83 Self::SkEd25519(_) => Algorithm::SkEd25519,
84 #[cfg(feature = "alloc")]
85 Self::Other(key) => key.algorithm(),
86 })
87 }
88
89 #[cfg(feature = "alloc")]
91 #[must_use]
92 pub fn dsa(&self) -> Option<&DsaKeypair> {
93 match self {
94 Self::Dsa(key) => Some(key),
95 _ => None,
96 }
97 }
98
99 #[cfg(feature = "ecdsa")]
101 #[must_use]
102 pub fn ecdsa(&self) -> Option<&EcdsaKeypair> {
103 match self {
104 Self::Ecdsa(keypair) => Some(keypair),
105 _ => None,
106 }
107 }
108
109 #[must_use]
111 pub fn ed25519(&self) -> Option<&Ed25519Keypair> {
112 match self {
113 Self::Ed25519(key) => Some(key),
114 #[allow(unreachable_patterns)]
115 _ => None,
116 }
117 }
118
119 #[cfg(feature = "alloc")]
121 #[must_use]
122 pub fn encrypted(&self) -> Option<&[u8]> {
123 match self {
124 Self::Encrypted(ciphertext) => Some(ciphertext),
125 _ => None,
126 }
127 }
128
129 #[cfg(feature = "alloc")]
131 #[must_use]
132 pub fn rsa(&self) -> Option<&RsaKeypair> {
133 match self {
134 Self::Rsa(key) => Some(key),
135 _ => None,
136 }
137 }
138
139 #[cfg(all(feature = "alloc", feature = "ecdsa"))]
141 #[must_use]
142 pub fn sk_ecdsa_p256(&self) -> Option<&SkEcdsaSha2NistP256> {
143 match self {
144 Self::SkEcdsaSha2NistP256(sk) => Some(sk),
145 _ => None,
146 }
147 }
148
149 #[cfg(feature = "alloc")]
151 #[must_use]
152 pub fn sk_ed25519(&self) -> Option<&SkEd25519> {
153 match self {
154 Self::SkEd25519(sk) => Some(sk),
155 _ => None,
156 }
157 }
158
159 #[cfg(feature = "alloc")]
161 #[must_use]
162 pub fn other(&self) -> Option<&OpaqueKeypair> {
163 match self {
164 Self::Other(key) => Some(key),
165 _ => None,
166 }
167 }
168
169 #[cfg(feature = "alloc")]
171 #[must_use]
172 pub fn is_dsa(&self) -> bool {
173 matches!(self, Self::Dsa(_))
174 }
175
176 #[cfg(feature = "ecdsa")]
178 #[must_use]
179 pub fn is_ecdsa(&self) -> bool {
180 matches!(self, Self::Ecdsa(_))
181 }
182
183 #[must_use]
185 pub fn is_ed25519(&self) -> bool {
186 matches!(self, Self::Ed25519(_))
187 }
188
189 #[cfg(not(feature = "alloc"))]
191 #[must_use]
192 pub fn is_encrypted(&self) -> bool {
193 false
194 }
195
196 #[cfg(feature = "alloc")]
198 #[must_use]
199 pub fn is_encrypted(&self) -> bool {
200 matches!(self, Self::Encrypted(_))
201 }
202
203 #[cfg(feature = "alloc")]
205 #[must_use]
206 pub fn is_rsa(&self) -> bool {
207 matches!(self, Self::Rsa(_))
208 }
209
210 #[cfg(all(feature = "alloc", feature = "ecdsa"))]
212 #[must_use]
213 pub fn is_sk_ecdsa_p256(&self) -> bool {
214 matches!(self, Self::SkEcdsaSha2NistP256(_))
215 }
216
217 #[cfg(feature = "alloc")]
219 #[must_use]
220 pub fn is_sk_ed25519(&self) -> bool {
221 matches!(self, Self::SkEd25519(_))
222 }
223
224 #[cfg(feature = "alloc")]
226 #[must_use]
227 pub fn is_other(&self) -> bool {
228 matches!(self, Self::Other(_))
229 }
230
231 pub(super) fn checkint(&self) -> u32 {
236 let bytes = match self {
237 #[cfg(feature = "alloc")]
238 Self::Dsa(dsa) => dsa.private().as_bytes(),
239 #[cfg(feature = "ecdsa")]
240 Self::Ecdsa(ecdsa) => ecdsa.private_key_bytes(),
241 Self::Ed25519(ed25519) => ed25519.private.as_ref(),
242 #[cfg(feature = "alloc")]
243 Self::Encrypted(ciphertext) => ciphertext.as_ref(),
244 #[cfg(feature = "alloc")]
245 Self::Rsa(rsa) => rsa.private().d().as_bytes(),
246 #[cfg(all(feature = "alloc", feature = "ecdsa"))]
247 Self::SkEcdsaSha2NistP256(sk) => sk.key_handle(),
248 #[cfg(feature = "alloc")]
249 Self::SkEd25519(sk) => sk.key_handle(),
250 #[cfg(feature = "alloc")]
251 Self::Other(key) => key.private.as_ref(),
252 };
253
254 let mut n = 0u32;
255
256 for chunk in bytes.chunks_exact(4) {
257 n ^= u32::from_be_bytes(chunk.try_into().expect("not 4 bytes"));
258 }
259
260 n
261 }
262
263 pub fn decode_as(reader: &mut impl Reader, algorithm: Algorithm) -> Result<Self> {
270 match algorithm {
271 #[cfg(feature = "alloc")]
272 Algorithm::Dsa => DsaKeypair::decode(reader).map(Self::Dsa),
273 #[cfg(feature = "ecdsa")]
274 Algorithm::Ecdsa { curve } => match EcdsaKeypair::decode(reader)? {
275 keypair if keypair.curve() == curve => Ok(Self::Ecdsa(keypair)),
276 _ => Err(Error::AlgorithmUnknown),
277 },
278 Algorithm::Ed25519 => Ed25519Keypair::decode(reader).map(Self::Ed25519),
279 #[cfg(feature = "alloc")]
280 Algorithm::Rsa { .. } => RsaKeypair::decode(reader).map(Self::Rsa),
281 #[cfg(all(feature = "alloc", feature = "ecdsa"))]
282 Algorithm::SkEcdsaSha2NistP256 => {
283 SkEcdsaSha2NistP256::decode(reader).map(Self::SkEcdsaSha2NistP256)
284 }
285 #[cfg(feature = "alloc")]
286 Algorithm::SkEd25519 => SkEd25519::decode(reader).map(Self::SkEd25519),
287 #[cfg(feature = "alloc")]
288 algorithm @ Algorithm::Other(_) => {
289 OpaqueKeypair::decode_as(reader, algorithm).map(Self::Other)
290 }
291 #[allow(unreachable_patterns)]
292 _ => Err(Error::AlgorithmUnknown),
293 }
294 }
295}
296
297impl CtEq for KeypairData {
298 fn ct_eq(&self, other: &Self) -> Choice {
299 match (self, other) {
301 #[cfg(feature = "alloc")]
302 (Self::Dsa(a), Self::Dsa(b)) => a.ct_eq(b),
303 #[cfg(feature = "ecdsa")]
304 (Self::Ecdsa(a), Self::Ecdsa(b)) => a.ct_eq(b),
305 (Self::Ed25519(a), Self::Ed25519(b)) => a.ct_eq(b),
306 #[cfg(feature = "alloc")]
307 (Self::Encrypted(a), Self::Encrypted(b)) => a.ct_eq(b),
308 #[cfg(feature = "alloc")]
309 (Self::Rsa(a), Self::Rsa(b)) => a.ct_eq(b),
310 #[cfg(all(feature = "alloc", feature = "ecdsa"))]
311 (Self::SkEcdsaSha2NistP256(a), Self::SkEcdsaSha2NistP256(b)) => {
312 Choice::from(u8::from(a == b))
315 }
316 #[cfg(feature = "alloc")]
317 (Self::SkEd25519(a), Self::SkEd25519(b)) => {
318 Choice::from(u8::from(a == b))
321 }
322 #[cfg(feature = "alloc")]
323 (Self::Other(a), Self::Other(b)) => a.ct_eq(b),
324 #[allow(unreachable_patterns)]
325 _ => Choice::from(0),
326 }
327 }
328}
329
330impl Eq for KeypairData {}
331
332impl PartialEq for KeypairData {
333 fn eq(&self, other: &Self) -> bool {
334 self.ct_eq(other).into()
335 }
336}
337
338impl Decode for KeypairData {
339 type Error = Error;
340
341 fn decode(reader: &mut impl Reader) -> Result<Self> {
342 let algorithm = Algorithm::decode(reader)?;
343 Self::decode_as(reader, algorithm)
344 }
345}
346
347impl Encode for KeypairData {
348 fn encoded_len(&self) -> encoding::Result<usize> {
349 let alg_len = self
350 .algorithm()
351 .ok()
352 .map(|alg| alg.encoded_len())
353 .transpose()?
354 .unwrap_or(0);
355
356 let key_len = match self {
357 #[cfg(feature = "alloc")]
358 Self::Dsa(key) => key.encoded_len()?,
359 #[cfg(feature = "ecdsa")]
360 Self::Ecdsa(key) => key.encoded_len()?,
361 Self::Ed25519(key) => key.encoded_len()?,
362 #[cfg(feature = "alloc")]
363 Self::Encrypted(ciphertext) => return Ok(ciphertext.len()),
364 #[cfg(feature = "alloc")]
365 Self::Rsa(key) => key.encoded_len()?,
366 #[cfg(all(feature = "alloc", feature = "ecdsa"))]
367 Self::SkEcdsaSha2NistP256(sk) => sk.encoded_len()?,
368 #[cfg(feature = "alloc")]
369 Self::SkEd25519(sk) => sk.encoded_len()?,
370 #[cfg(feature = "alloc")]
371 Self::Other(key) => key.encoded_len()?,
372 };
373
374 [alg_len, key_len].checked_sum()
375 }
376
377 fn encode(&self, writer: &mut impl Writer) -> encoding::Result<()> {
378 if let Ok(alg) = self.algorithm() {
379 alg.encode(writer)?;
380 }
381
382 match self {
383 #[cfg(feature = "alloc")]
384 Self::Dsa(key) => key.encode(writer)?,
385 #[cfg(feature = "ecdsa")]
386 Self::Ecdsa(key) => key.encode(writer)?,
387 Self::Ed25519(key) => key.encode(writer)?,
388 #[cfg(feature = "alloc")]
389 Self::Encrypted(ciphertext) => writer.write(ciphertext)?,
390 #[cfg(feature = "alloc")]
391 Self::Rsa(key) => key.encode(writer)?,
392 #[cfg(all(feature = "alloc", feature = "ecdsa"))]
393 Self::SkEcdsaSha2NistP256(sk) => sk.encode(writer)?,
394 #[cfg(feature = "alloc")]
395 Self::SkEd25519(sk) => sk.encode(writer)?,
396 #[cfg(feature = "alloc")]
397 Self::Other(key) => key.encode(writer)?,
398 }
399
400 Ok(())
401 }
402}
403
404impl TryFrom<&KeypairData> for public::KeyData {
405 type Error = Error;
406
407 fn try_from(keypair_data: &KeypairData) -> Result<public::KeyData> {
408 Ok(match keypair_data {
409 #[cfg(feature = "alloc")]
410 KeypairData::Dsa(dsa) => public::KeyData::Dsa(dsa.into()),
411 #[cfg(feature = "ecdsa")]
412 KeypairData::Ecdsa(ecdsa) => public::KeyData::Ecdsa(ecdsa.into()),
413 KeypairData::Ed25519(ed25519) => public::KeyData::Ed25519(ed25519.into()),
414 #[cfg(feature = "alloc")]
415 KeypairData::Encrypted(_) => return Err(Error::Encrypted),
416 #[cfg(feature = "alloc")]
417 KeypairData::Rsa(rsa) => public::KeyData::Rsa(rsa.into()),
418 #[cfg(all(feature = "alloc", feature = "ecdsa"))]
419 KeypairData::SkEcdsaSha2NistP256(sk) => {
420 public::KeyData::SkEcdsaSha2NistP256(sk.public().clone())
421 }
422 #[cfg(feature = "alloc")]
423 KeypairData::SkEd25519(sk) => public::KeyData::SkEd25519(sk.public().clone()),
424 #[cfg(feature = "alloc")]
425 KeypairData::Other(key) => public::KeyData::Other(key.into()),
426 })
427 }
428}
429
430#[cfg(feature = "alloc")]
431impl From<DsaKeypair> for KeypairData {
432 fn from(keypair: DsaKeypair) -> KeypairData {
433 Self::Dsa(keypair)
434 }
435}
436
437#[cfg(feature = "ecdsa")]
438impl From<EcdsaKeypair> for KeypairData {
439 fn from(keypair: EcdsaKeypair) -> KeypairData {
440 Self::Ecdsa(keypair)
441 }
442}
443
444impl From<Ed25519Keypair> for KeypairData {
445 fn from(keypair: Ed25519Keypair) -> KeypairData {
446 Self::Ed25519(keypair)
447 }
448}
449
450#[cfg(feature = "alloc")]
451impl From<RsaKeypair> for KeypairData {
452 fn from(keypair: RsaKeypair) -> KeypairData {
453 Self::Rsa(keypair)
454 }
455}
456
457#[cfg(all(feature = "alloc", feature = "ecdsa"))]
458impl From<SkEcdsaSha2NistP256> for KeypairData {
459 fn from(keypair: SkEcdsaSha2NistP256) -> KeypairData {
460 Self::SkEcdsaSha2NistP256(keypair)
461 }
462}
463
464#[cfg(feature = "alloc")]
465impl From<SkEd25519> for KeypairData {
466 fn from(keypair: SkEd25519) -> KeypairData {
467 Self::SkEd25519(keypair)
468 }
469}