1use super::ed25519::Ed25519Keypair;
4use crate::{public, Algorithm, Error, Result};
5use encoding::{CheckedSum, Decode, Encode, Reader, Writer};
6use subtle::{Choice, ConstantTimeEq};
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> {
67 Ok(match self {
68 #[cfg(feature = "alloc")]
69 Self::Dsa(_) => Algorithm::Dsa,
70 #[cfg(feature = "ecdsa")]
71 Self::Ecdsa(key) => key.algorithm(),
72 Self::Ed25519(_) => Algorithm::Ed25519,
73 #[cfg(feature = "alloc")]
74 Self::Encrypted(_) => return Err(Error::Encrypted),
75 #[cfg(feature = "alloc")]
76 Self::Rsa(_) => Algorithm::Rsa { hash: None },
77 #[cfg(all(feature = "alloc", feature = "ecdsa"))]
78 Self::SkEcdsaSha2NistP256(_) => Algorithm::SkEcdsaSha2NistP256,
79 #[cfg(feature = "alloc")]
80 Self::SkEd25519(_) => Algorithm::SkEd25519,
81 #[cfg(feature = "alloc")]
82 Self::Other(key) => key.algorithm(),
83 })
84 }
85
86 #[cfg(feature = "alloc")]
88 pub fn dsa(&self) -> Option<&DsaKeypair> {
89 match self {
90 Self::Dsa(key) => Some(key),
91 _ => None,
92 }
93 }
94
95 #[cfg(feature = "ecdsa")]
97 pub fn ecdsa(&self) -> Option<&EcdsaKeypair> {
98 match self {
99 Self::Ecdsa(keypair) => Some(keypair),
100 _ => None,
101 }
102 }
103
104 pub fn ed25519(&self) -> Option<&Ed25519Keypair> {
106 match self {
107 Self::Ed25519(key) => Some(key),
108 #[allow(unreachable_patterns)]
109 _ => None,
110 }
111 }
112
113 #[cfg(feature = "alloc")]
115 pub fn encrypted(&self) -> Option<&[u8]> {
116 match self {
117 Self::Encrypted(ciphertext) => Some(ciphertext),
118 _ => None,
119 }
120 }
121
122 #[cfg(feature = "alloc")]
124 pub fn rsa(&self) -> Option<&RsaKeypair> {
125 match self {
126 Self::Rsa(key) => Some(key),
127 _ => None,
128 }
129 }
130
131 #[cfg(all(feature = "alloc", feature = "ecdsa"))]
133 pub fn sk_ecdsa_p256(&self) -> Option<&SkEcdsaSha2NistP256> {
134 match self {
135 Self::SkEcdsaSha2NistP256(sk) => Some(sk),
136 _ => None,
137 }
138 }
139
140 #[cfg(feature = "alloc")]
142 pub fn sk_ed25519(&self) -> Option<&SkEd25519> {
143 match self {
144 Self::SkEd25519(sk) => Some(sk),
145 _ => None,
146 }
147 }
148
149 #[cfg(feature = "alloc")]
151 pub fn other(&self) -> Option<&OpaqueKeypair> {
152 match self {
153 Self::Other(key) => Some(key),
154 _ => None,
155 }
156 }
157
158 #[cfg(feature = "alloc")]
160 pub fn is_dsa(&self) -> bool {
161 matches!(self, Self::Dsa(_))
162 }
163
164 #[cfg(feature = "ecdsa")]
166 pub fn is_ecdsa(&self) -> bool {
167 matches!(self, Self::Ecdsa(_))
168 }
169
170 pub fn is_ed25519(&self) -> bool {
172 matches!(self, Self::Ed25519(_))
173 }
174
175 #[cfg(not(feature = "alloc"))]
177 pub fn is_encrypted(&self) -> bool {
178 false
179 }
180
181 #[cfg(feature = "alloc")]
183 pub fn is_encrypted(&self) -> bool {
184 matches!(self, Self::Encrypted(_))
185 }
186
187 #[cfg(feature = "alloc")]
189 pub fn is_rsa(&self) -> bool {
190 matches!(self, Self::Rsa(_))
191 }
192
193 #[cfg(all(feature = "alloc", feature = "ecdsa"))]
195 pub fn is_sk_ecdsa_p256(&self) -> bool {
196 matches!(self, Self::SkEcdsaSha2NistP256(_))
197 }
198
199 #[cfg(feature = "alloc")]
201 pub fn is_sk_ed25519(&self) -> bool {
202 matches!(self, Self::SkEd25519(_))
203 }
204
205 #[cfg(feature = "alloc")]
207 pub fn is_other(&self) -> bool {
208 matches!(self, Self::Other(_))
209 }
210
211 pub(super) fn checkint(&self) -> u32 {
216 let bytes = match self {
217 #[cfg(feature = "alloc")]
218 Self::Dsa(dsa) => dsa.private.as_bytes(),
219 #[cfg(feature = "ecdsa")]
220 Self::Ecdsa(ecdsa) => ecdsa.private_key_bytes(),
221 Self::Ed25519(ed25519) => ed25519.private.as_ref(),
222 #[cfg(feature = "alloc")]
223 Self::Encrypted(ciphertext) => ciphertext.as_ref(),
224 #[cfg(feature = "alloc")]
225 Self::Rsa(rsa) => rsa.private.d.as_bytes(),
226 #[cfg(all(feature = "alloc", feature = "ecdsa"))]
227 Self::SkEcdsaSha2NistP256(sk) => sk.key_handle(),
228 #[cfg(feature = "alloc")]
229 Self::SkEd25519(sk) => sk.key_handle(),
230 #[cfg(feature = "alloc")]
231 Self::Other(key) => key.private.as_ref(),
232 };
233
234 let mut n = 0u32;
235
236 for chunk in bytes.chunks_exact(4) {
237 n ^= u32::from_be_bytes(chunk.try_into().expect("not 4 bytes"));
238 }
239
240 n
241 }
242
243 pub fn decode_as(reader: &mut impl Reader, algorithm: Algorithm) -> Result<Self> {
245 match algorithm {
246 #[cfg(feature = "alloc")]
247 Algorithm::Dsa => DsaKeypair::decode(reader).map(Self::Dsa),
248 #[cfg(feature = "ecdsa")]
249 Algorithm::Ecdsa { curve } => match EcdsaKeypair::decode(reader)? {
250 keypair if keypair.curve() == curve => Ok(Self::Ecdsa(keypair)),
251 _ => Err(Error::AlgorithmUnknown),
252 },
253 Algorithm::Ed25519 => Ed25519Keypair::decode(reader).map(Self::Ed25519),
254 #[cfg(feature = "alloc")]
255 Algorithm::Rsa { .. } => RsaKeypair::decode(reader).map(Self::Rsa),
256 #[cfg(all(feature = "alloc", feature = "ecdsa"))]
257 Algorithm::SkEcdsaSha2NistP256 => {
258 SkEcdsaSha2NistP256::decode(reader).map(Self::SkEcdsaSha2NistP256)
259 }
260 #[cfg(feature = "alloc")]
261 Algorithm::SkEd25519 => SkEd25519::decode(reader).map(Self::SkEd25519),
262 #[cfg(feature = "alloc")]
263 algorithm @ Algorithm::Other(_) => {
264 OpaqueKeypair::decode_as(reader, algorithm).map(Self::Other)
265 }
266 #[allow(unreachable_patterns)]
267 _ => Err(Error::AlgorithmUnknown),
268 }
269 }
270}
271
272impl ConstantTimeEq for KeypairData {
273 fn ct_eq(&self, other: &Self) -> Choice {
274 match (self, other) {
276 #[cfg(feature = "alloc")]
277 (Self::Dsa(a), Self::Dsa(b)) => a.ct_eq(b),
278 #[cfg(feature = "ecdsa")]
279 (Self::Ecdsa(a), Self::Ecdsa(b)) => a.ct_eq(b),
280 (Self::Ed25519(a), Self::Ed25519(b)) => a.ct_eq(b),
281 #[cfg(feature = "alloc")]
282 (Self::Encrypted(a), Self::Encrypted(b)) => a.ct_eq(b),
283 #[cfg(feature = "alloc")]
284 (Self::Rsa(a), Self::Rsa(b)) => a.ct_eq(b),
285 #[cfg(all(feature = "alloc", feature = "ecdsa"))]
286 (Self::SkEcdsaSha2NistP256(a), Self::SkEcdsaSha2NistP256(b)) => {
287 Choice::from((a == b) as u8)
290 }
291 #[cfg(feature = "alloc")]
292 (Self::SkEd25519(a), Self::SkEd25519(b)) => {
293 Choice::from((a == b) as u8)
296 }
297 #[cfg(feature = "alloc")]
298 (Self::Other(a), Self::Other(b)) => a.ct_eq(b),
299 #[allow(unreachable_patterns)]
300 _ => Choice::from(0),
301 }
302 }
303}
304
305impl Eq for KeypairData {}
306
307impl PartialEq for KeypairData {
308 fn eq(&self, other: &Self) -> bool {
309 self.ct_eq(other).into()
310 }
311}
312
313impl Decode for KeypairData {
314 type Error = Error;
315
316 fn decode(reader: &mut impl Reader) -> Result<Self> {
317 let algorithm = Algorithm::decode(reader)?;
318 Self::decode_as(reader, algorithm)
319 }
320}
321
322impl Encode for KeypairData {
323 fn encoded_len(&self) -> encoding::Result<usize> {
324 let alg_len = self
325 .algorithm()
326 .ok()
327 .map(|alg| alg.encoded_len())
328 .transpose()?
329 .unwrap_or(0);
330
331 let key_len = match self {
332 #[cfg(feature = "alloc")]
333 Self::Dsa(key) => key.encoded_len()?,
334 #[cfg(feature = "ecdsa")]
335 Self::Ecdsa(key) => key.encoded_len()?,
336 Self::Ed25519(key) => key.encoded_len()?,
337 #[cfg(feature = "alloc")]
338 Self::Encrypted(ciphertext) => return Ok(ciphertext.len()),
339 #[cfg(feature = "alloc")]
340 Self::Rsa(key) => key.encoded_len()?,
341 #[cfg(all(feature = "alloc", feature = "ecdsa"))]
342 Self::SkEcdsaSha2NistP256(sk) => sk.encoded_len()?,
343 #[cfg(feature = "alloc")]
344 Self::SkEd25519(sk) => sk.encoded_len()?,
345 #[cfg(feature = "alloc")]
346 Self::Other(key) => key.encoded_len()?,
347 };
348
349 [alg_len, key_len].checked_sum()
350 }
351
352 fn encode(&self, writer: &mut impl Writer) -> encoding::Result<()> {
353 if let Ok(alg) = self.algorithm() {
354 alg.encode(writer)?;
355 }
356
357 match self {
358 #[cfg(feature = "alloc")]
359 Self::Dsa(key) => key.encode(writer)?,
360 #[cfg(feature = "ecdsa")]
361 Self::Ecdsa(key) => key.encode(writer)?,
362 Self::Ed25519(key) => key.encode(writer)?,
363 #[cfg(feature = "alloc")]
364 Self::Encrypted(ciphertext) => writer.write(ciphertext)?,
365 #[cfg(feature = "alloc")]
366 Self::Rsa(key) => key.encode(writer)?,
367 #[cfg(all(feature = "alloc", feature = "ecdsa"))]
368 Self::SkEcdsaSha2NistP256(sk) => sk.encode(writer)?,
369 #[cfg(feature = "alloc")]
370 Self::SkEd25519(sk) => sk.encode(writer)?,
371 #[cfg(feature = "alloc")]
372 Self::Other(key) => key.encode(writer)?,
373 }
374
375 Ok(())
376 }
377}
378
379impl TryFrom<&KeypairData> for public::KeyData {
380 type Error = Error;
381
382 fn try_from(keypair_data: &KeypairData) -> Result<public::KeyData> {
383 Ok(match keypair_data {
384 #[cfg(feature = "alloc")]
385 KeypairData::Dsa(dsa) => public::KeyData::Dsa(dsa.into()),
386 #[cfg(feature = "ecdsa")]
387 KeypairData::Ecdsa(ecdsa) => public::KeyData::Ecdsa(ecdsa.into()),
388 KeypairData::Ed25519(ed25519) => public::KeyData::Ed25519(ed25519.into()),
389 #[cfg(feature = "alloc")]
390 KeypairData::Encrypted(_) => return Err(Error::Encrypted),
391 #[cfg(feature = "alloc")]
392 KeypairData::Rsa(rsa) => public::KeyData::Rsa(rsa.into()),
393 #[cfg(all(feature = "alloc", feature = "ecdsa"))]
394 KeypairData::SkEcdsaSha2NistP256(sk) => {
395 public::KeyData::SkEcdsaSha2NistP256(sk.public().clone())
396 }
397 #[cfg(feature = "alloc")]
398 KeypairData::SkEd25519(sk) => public::KeyData::SkEd25519(sk.public().clone()),
399 #[cfg(feature = "alloc")]
400 KeypairData::Other(key) => public::KeyData::Other(key.into()),
401 })
402 }
403}
404
405#[cfg(feature = "alloc")]
406impl From<DsaKeypair> for KeypairData {
407 fn from(keypair: DsaKeypair) -> KeypairData {
408 Self::Dsa(keypair)
409 }
410}
411
412#[cfg(feature = "ecdsa")]
413impl From<EcdsaKeypair> for KeypairData {
414 fn from(keypair: EcdsaKeypair) -> KeypairData {
415 Self::Ecdsa(keypair)
416 }
417}
418
419impl From<Ed25519Keypair> for KeypairData {
420 fn from(keypair: Ed25519Keypair) -> KeypairData {
421 Self::Ed25519(keypair)
422 }
423}
424
425#[cfg(feature = "alloc")]
426impl From<RsaKeypair> for KeypairData {
427 fn from(keypair: RsaKeypair) -> KeypairData {
428 Self::Rsa(keypair)
429 }
430}
431
432#[cfg(all(feature = "alloc", feature = "ecdsa"))]
433impl From<SkEcdsaSha2NistP256> for KeypairData {
434 fn from(keypair: SkEcdsaSha2NistP256) -> KeypairData {
435 Self::SkEcdsaSha2NistP256(keypair)
436 }
437}
438
439#[cfg(feature = "alloc")]
440impl From<SkEd25519> for KeypairData {
441 fn from(keypair: SkEd25519) -> KeypairData {
442 Self::SkEd25519(keypair)
443 }
444}