rust_bottle/keys.rs
1use crate::errors::{BottleError, Result};
2use crate::keychain::SignerKey;
3use crate::signing::{Sign, Verify};
4use ed25519_dalek::{
5 Signature, SigningKey as Ed25519SigningKey, VerifyingKey as Ed25519VerifyingKey,
6};
7use p256::ecdsa::{SigningKey as P256SigningKey, VerifyingKey as P256VerifyingKey};
8use rand::{CryptoRng, RngCore};
9use rsa::{Pkcs1v15Sign, RsaPrivateKey, RsaPublicKey};
10use sha2::{Digest, Sha256};
11
12// Post-quantum cryptography imports
13#[cfg(feature = "ml-kem")]
14use ml_kem::{kem::Kem, EncodedSizeUser, KemCore, MlKem1024Params, MlKem768Params};
15#[cfg(feature = "post-quantum")]
16use pqcrypto_dilithium;
17#[cfg(feature = "post-quantum")]
18use pqcrypto_sphincsplus;
19#[cfg(feature = "post-quantum")]
20use pqcrypto_traits::sign::{
21 DetachedSignature as PqcDetachedSignature, PublicKey as PqcPublicKey, SecretKey as PqcSecretKey,
22};
23
24/// ECDSA P-256 key pair for digital signatures.
25///
26/// This key type uses the P-256 (secp256r1) elliptic curve for signing.
27/// ECDSA signatures are deterministic (RFC 6979) and provide strong security
28/// with 128-bit security level.
29///
30/// # Example
31///
32/// ```rust
33/// use rust_bottle::keys::EcdsaP256Key;
34/// use rand::rngs::OsRng;
35///
36/// let rng = &mut OsRng;
37/// let key = EcdsaP256Key::generate(rng);
38/// let pub_key = key.public_key_bytes();
39/// let priv_key = key.private_key_bytes();
40/// ```
41pub struct EcdsaP256Key {
42 signing_key: P256SigningKey,
43 verifying_key: P256VerifyingKey,
44}
45
46impl EcdsaP256Key {
47 /// Generate a new ECDSA P-256 key pair.
48 ///
49 /// This function generates a cryptographically secure key pair using
50 /// the provided random number generator.
51 ///
52 /// # Arguments
53 ///
54 /// * `rng` - A cryptographically secure random number generator
55 ///
56 /// # Returns
57 ///
58 /// A new `EcdsaP256Key` instance with a randomly generated key pair
59 ///
60 /// # Example
61 ///
62 /// ```rust
63 /// use rust_bottle::keys::EcdsaP256Key;
64 /// use rand::rngs::OsRng;
65 ///
66 /// let rng = &mut OsRng;
67 /// let key = EcdsaP256Key::generate(rng);
68 /// ```
69 pub fn generate<R: RngCore + CryptoRng>(rng: &mut R) -> Self {
70 let signing_key = P256SigningKey::random(rng);
71 let verifying_key = *signing_key.verifying_key();
72 Self {
73 signing_key,
74 verifying_key,
75 }
76 }
77
78 /// Get the public key in SEC1 uncompressed format.
79 ///
80 /// The public key is returned as a 65-byte array in SEC1 uncompressed
81 /// format (0x04 prefix + 32-byte x-coordinate + 32-byte y-coordinate).
82 ///
83 /// # Returns
84 ///
85 /// Public key bytes in SEC1 format
86 pub fn public_key_bytes(&self) -> Vec<u8> {
87 self.verifying_key.to_sec1_bytes().to_vec()
88 }
89
90 /// Get the private key bytes.
91 ///
92 /// The private key is returned as a 32-byte array. This is sensitive
93 /// data and should be handled securely.
94 ///
95 /// # Returns
96 ///
97 /// Private key bytes (32 bytes)
98 ///
99 /// # Security Warning
100 ///
101 /// Private keys are sensitive cryptographic material. They should be
102 /// stored securely and cleared from memory when no longer needed.
103 pub fn private_key_bytes(&self) -> Vec<u8> {
104 self.signing_key.to_bytes().to_vec()
105 }
106
107 /// Create an ECDSA P-256 key pair from private key bytes.
108 ///
109 /// This function reconstructs a key pair from a previously saved private
110 /// key. The public key is automatically derived from the private key.
111 ///
112 /// # Arguments
113 ///
114 /// * `bytes` - Private key bytes (32 bytes)
115 ///
116 /// # Returns
117 ///
118 /// * `Ok(EcdsaP256Key)` - Reconstructed key pair
119 /// * `Err(BottleError::InvalidKeyType)` - If the key format is invalid
120 ///
121 /// # Example
122 ///
123 /// ```rust
124 /// use rust_bottle::keys::EcdsaP256Key;
125 /// use rand::rngs::OsRng;
126 ///
127 /// let rng = &mut OsRng;
128 /// let original = EcdsaP256Key::generate(rng);
129 /// let priv_bytes = original.private_key_bytes();
130 ///
131 /// let restored = EcdsaP256Key::from_private_key_bytes(&priv_bytes).unwrap();
132 /// assert_eq!(original.public_key_bytes(), restored.public_key_bytes());
133 /// ```
134 pub fn from_private_key_bytes(bytes: &[u8]) -> Result<Self> {
135 let signing_key =
136 P256SigningKey::from_bytes(bytes.into()).map_err(|_| BottleError::InvalidKeyType)?;
137 let verifying_key = *signing_key.verifying_key();
138 Ok(Self {
139 signing_key,
140 verifying_key,
141 })
142 }
143}
144
145impl Sign for EcdsaP256Key {
146 /// Sign a message using ECDSA P-256.
147 ///
148 /// The message is hashed with SHA-256 before signing. The signature
149 /// is deterministic (RFC 6979), meaning the same message and key will
150 /// always produce the same signature.
151 ///
152 /// # Arguments
153 ///
154 /// * `_rng` - Random number generator (not used for deterministic signing)
155 /// * `message` - The message to sign
156 ///
157 /// # Returns
158 ///
159 /// * `Ok(Vec<u8>)` - Signature bytes (64 bytes: r + s values)
160 /// * `Err(BottleError::VerifyFailed)` - If signing fails
161 fn sign(&self, _rng: &mut dyn RngCore, message: &[u8]) -> Result<Vec<u8>> {
162 use ecdsa::signature::Signer;
163 use sha2::Digest;
164 // Hash the message first
165 let digest = sha2::Sha256::digest(message);
166 // Use regular sign method (deterministic with RFC6979)
167 let signature: ecdsa::Signature<p256::NistP256> = self.signing_key.sign(&digest);
168 Ok(signature.to_bytes().to_vec())
169 }
170}
171
172impl Verify for EcdsaP256Key {
173 /// Verify an ECDSA P-256 signature.
174 ///
175 /// The message is hashed with SHA-256 before verification. The signature
176 /// must match the format produced by `sign`.
177 ///
178 /// # Arguments
179 ///
180 /// * `message` - The original message
181 /// * `signature` - The signature to verify (64 bytes: r + s values)
182 ///
183 /// # Returns
184 ///
185 /// * `Ok(())` - Signature is valid
186 /// * `Err(BottleError::VerifyFailed)` - If signature verification fails
187 ///
188 /// # Example
189 ///
190 /// ```rust
191 /// use rust_bottle::keys::EcdsaP256Key;
192 /// use rust_bottle::signing::{Sign, Verify};
193 /// use rand::rngs::OsRng;
194 ///
195 /// let rng = &mut OsRng;
196 /// let key = EcdsaP256Key::generate(rng);
197 /// let message = b"Test message";
198 ///
199 /// let signature = key.sign(rng, message).unwrap();
200 /// assert!(key.verify(message, &signature).is_ok());
201 /// ```
202 fn verify(&self, message: &[u8], signature: &[u8]) -> Result<()> {
203 use ecdsa::signature::Verifier;
204 use sha2::Digest;
205 // Hash the message first
206 let digest = sha2::Sha256::digest(message);
207 let sig = ecdsa::Signature::from_bytes(signature.into())
208 .map_err(|_| BottleError::VerifyFailed)?;
209 self.verifying_key
210 .verify(&digest, &sig)
211 .map_err(|_| BottleError::VerifyFailed)?;
212 Ok(())
213 }
214}
215
216impl SignerKey for EcdsaP256Key {
217 /// Get the public key fingerprint (SHA-256 hash).
218 ///
219 /// The fingerprint is used to identify keys in keychains and IDCards.
220 ///
221 /// # Returns
222 ///
223 /// SHA-256 hash of the public key bytes
224 fn fingerprint(&self) -> Vec<u8> {
225 crate::hash::sha256(&self.public_key_bytes())
226 }
227
228 /// Get the public key bytes.
229 ///
230 /// # Returns
231 ///
232 /// Public key bytes in SEC1 format
233 fn public_key(&self) -> Vec<u8> {
234 self.public_key_bytes()
235 }
236}
237
238/// Ed25519 key pair for digital signatures.
239///
240/// Ed25519 is a modern elliptic curve signature scheme based on Curve25519.
241/// It provides 128-bit security with fast signing and verification, and
242/// deterministic signatures. Ed25519 keys are 32 bytes for both private and
243/// public keys.
244///
245/// # Example
246///
247/// ```rust
248/// use rust_bottle::keys::Ed25519Key;
249/// use rand::rngs::OsRng;
250///
251/// let rng = &mut OsRng;
252/// let key = Ed25519Key::generate(rng);
253/// let pub_key = key.public_key_bytes();
254/// let priv_key = key.private_key_bytes();
255/// ```
256#[derive(Clone)]
257pub struct Ed25519Key {
258 signing_key: Ed25519SigningKey,
259 verifying_key: Ed25519VerifyingKey,
260}
261
262impl Ed25519Key {
263 /// Generate a new Ed25519 key pair.
264 ///
265 /// This function generates a cryptographically secure key pair using
266 /// the provided random number generator.
267 ///
268 /// # Arguments
269 ///
270 /// * `rng` - A cryptographically secure random number generator
271 ///
272 /// # Returns
273 ///
274 /// A new `Ed25519Key` instance with a randomly generated key pair
275 ///
276 /// # Example
277 ///
278 /// ```rust
279 /// use rust_bottle::keys::Ed25519Key;
280 /// use rand::rngs::OsRng;
281 ///
282 /// let rng = &mut OsRng;
283 /// let key = Ed25519Key::generate(rng);
284 /// ```
285 pub fn generate<R: RngCore + CryptoRng>(rng: &mut R) -> Self {
286 let signing_key = Ed25519SigningKey::generate(rng);
287 let verifying_key = signing_key.verifying_key();
288 Self {
289 signing_key,
290 verifying_key,
291 }
292 }
293
294 /// Get the public key bytes.
295 ///
296 /// Ed25519 public keys are 32 bytes.
297 ///
298 /// # Returns
299 ///
300 /// Public key bytes (32 bytes)
301 pub fn public_key_bytes(&self) -> Vec<u8> {
302 self.verifying_key.to_bytes().to_vec()
303 }
304
305 /// Get the private key bytes.
306 ///
307 /// Ed25519 private keys are 32 bytes. This is sensitive data and should
308 /// be handled securely.
309 ///
310 /// # Returns
311 ///
312 /// Private key bytes (32 bytes)
313 ///
314 /// # Security Warning
315 ///
316 /// Private keys are sensitive cryptographic material. They should be
317 /// stored securely and cleared from memory when no longer needed.
318 pub fn private_key_bytes(&self) -> Vec<u8> {
319 self.signing_key.to_bytes().to_vec()
320 }
321
322 /// Create an Ed25519 key pair from private key bytes.
323 ///
324 /// This function reconstructs a key pair from a previously saved private
325 /// key. The public key is automatically derived from the private key.
326 ///
327 /// # Arguments
328 ///
329 /// * `bytes` - Private key bytes (32 bytes)
330 ///
331 /// # Returns
332 ///
333 /// * `Ok(Ed25519Key)` - Reconstructed key pair
334 /// * `Err(BottleError::InvalidKeyType)` - If the key format is invalid
335 ///
336 /// # Example
337 ///
338 /// ```rust
339 /// use rust_bottle::keys::Ed25519Key;
340 /// use rand::rngs::OsRng;
341 ///
342 /// let rng = &mut OsRng;
343 /// let original = Ed25519Key::generate(rng);
344 /// let priv_bytes = original.private_key_bytes();
345 ///
346 /// let restored = Ed25519Key::from_private_key_bytes(&priv_bytes).unwrap();
347 /// assert_eq!(original.public_key_bytes(), restored.public_key_bytes());
348 /// ```
349 pub fn from_private_key_bytes(bytes: &[u8]) -> Result<Self> {
350 let signing_key = Ed25519SigningKey::from_bytes(
351 bytes.try_into().map_err(|_| BottleError::InvalidKeyType)?,
352 );
353 let verifying_key = signing_key.verifying_key();
354 Ok(Self {
355 signing_key,
356 verifying_key,
357 })
358 }
359}
360
361impl Sign for Ed25519Key {
362 /// Sign a message using Ed25519.
363 ///
364 /// Ed25519 signs messages directly without pre-hashing. The signature
365 /// is deterministic and always 64 bytes.
366 ///
367 /// # Arguments
368 ///
369 /// * `_rng` - Random number generator (not used for deterministic signing)
370 /// * `message` - The message to sign
371 ///
372 /// # Returns
373 ///
374 /// * `Ok(Vec<u8>)` - Signature bytes (64 bytes)
375 /// * `Err(BottleError::VerifyFailed)` - If signing fails
376 fn sign(&self, _rng: &mut dyn RngCore, message: &[u8]) -> Result<Vec<u8>> {
377 use ed25519_dalek::Signer;
378 let signature = self.signing_key.sign(message);
379 Ok(signature.to_bytes().to_vec())
380 }
381}
382
383impl Verify for Ed25519Key {
384 /// Verify an Ed25519 signature.
385 ///
386 /// The message is verified directly without pre-hashing. The signature
387 /// must be 64 bytes.
388 ///
389 /// # Arguments
390 ///
391 /// * `message` - The original message
392 /// * `signature` - The signature to verify (64 bytes)
393 ///
394 /// # Returns
395 ///
396 /// * `Ok(())` - Signature is valid
397 /// * `Err(BottleError::VerifyFailed)` - If signature verification fails
398 ///
399 /// # Example
400 ///
401 /// ```rust
402 /// use rust_bottle::keys::Ed25519Key;
403 /// use rust_bottle::signing::{Sign, Verify};
404 /// use rand::rngs::OsRng;
405 ///
406 /// let rng = &mut OsRng;
407 /// let key = Ed25519Key::generate(rng);
408 /// let message = b"Test message";
409 ///
410 /// let signature = key.sign(rng, message).unwrap();
411 /// assert!(key.verify(message, &signature).is_ok());
412 /// ```
413 fn verify(&self, message: &[u8], signature: &[u8]) -> Result<()> {
414 use ed25519_dalek::Verifier;
415 let sig = Signature::from_bytes(
416 signature
417 .try_into()
418 .map_err(|_| BottleError::VerifyFailed)?,
419 );
420 self.verifying_key
421 .verify(message, &sig)
422 .map_err(|_| BottleError::VerifyFailed)?;
423 Ok(())
424 }
425}
426
427impl SignerKey for Ed25519Key {
428 /// Get the public key fingerprint (SHA-256 hash).
429 ///
430 /// The fingerprint is used to identify keys in keychains and IDCards.
431 ///
432 /// # Returns
433 ///
434 /// SHA-256 hash of the public key bytes
435 fn fingerprint(&self) -> Vec<u8> {
436 crate::hash::sha256(&self.public_key_bytes())
437 }
438
439 /// Get the public key bytes.
440 ///
441 /// # Returns
442 ///
443 /// Public key bytes (32 bytes)
444 fn public_key(&self) -> Vec<u8> {
445 self.public_key_bytes()
446 }
447}
448
449/// X25519 key pair for ECDH encryption.
450///
451/// X25519 is the Diffie-Hellman function over Curve25519. It is used for
452/// key exchange and encryption, not for signing. X25519 keys are 32 bytes
453/// for both private and public keys.
454///
455/// # Example
456///
457/// ```rust
458/// use rust_bottle::keys::X25519Key;
459/// use rand::rngs::OsRng;
460///
461/// let rng = &mut OsRng;
462/// let key = X25519Key::generate(rng);
463/// let pub_key = key.public_key_bytes();
464/// let priv_key = key.private_key_bytes();
465/// ```
466pub struct X25519Key {
467 secret: [u8; 32], // Store as bytes since StaticSecret doesn't exist in 2.0
468 public: x25519_dalek::PublicKey,
469}
470
471impl X25519Key {
472 /// Generate a new X25519 key pair.
473 ///
474 /// This function generates a cryptographically secure key pair using
475 /// the provided random number generator.
476 ///
477 /// # Arguments
478 ///
479 /// * `rng` - A random number generator
480 ///
481 /// # Returns
482 ///
483 /// A new `X25519Key` instance with a randomly generated key pair
484 ///
485 /// # Example
486 ///
487 /// ```rust
488 /// use rust_bottle::keys::X25519Key;
489 /// use rand::rngs::OsRng;
490 ///
491 /// let rng = &mut OsRng;
492 /// let key = X25519Key::generate(rng);
493 /// ```
494 pub fn generate<R: RngCore>(rng: &mut R) -> Self {
495 use x25519_dalek::StaticSecret;
496 // Generate random secret key
497 let mut secret_bytes = [0u8; 32];
498 rng.fill_bytes(&mut secret_bytes);
499 // Create StaticSecret and derive public key
500 let secret = StaticSecret::from(secret_bytes);
501 let public = x25519_dalek::PublicKey::from(&secret);
502 Self {
503 secret: secret_bytes,
504 public,
505 }
506 }
507
508 /// Get the public key bytes.
509 ///
510 /// X25519 public keys are 32 bytes.
511 ///
512 /// # Returns
513 ///
514 /// Public key bytes (32 bytes)
515 pub fn public_key_bytes(&self) -> Vec<u8> {
516 self.public.as_bytes().to_vec()
517 }
518
519 /// Get the private key bytes.
520 ///
521 /// X25519 private keys are 32 bytes. This is sensitive data and should
522 /// be handled securely.
523 ///
524 /// # Returns
525 ///
526 /// Private key bytes (32 bytes)
527 ///
528 /// # Security Warning
529 ///
530 /// Private keys are sensitive cryptographic material. They should be
531 /// stored securely and cleared from memory when no longer needed.
532 pub fn private_key_bytes(&self) -> Vec<u8> {
533 self.secret.to_vec()
534 }
535
536 /// Create an X25519 key pair from private key bytes.
537 ///
538 /// This function reconstructs a key pair from a previously saved private
539 /// key. The public key is automatically derived from the private key.
540 ///
541 /// # Arguments
542 ///
543 /// * `bytes` - Private key bytes (32 bytes)
544 ///
545 /// # Returns
546 ///
547 /// * `Ok(X25519Key)` - Reconstructed key pair
548 /// * `Err(BottleError::InvalidKeyType)` - If the key format is invalid
549 ///
550 /// # Example
551 ///
552 /// ```rust
553 /// use rust_bottle::keys::X25519Key;
554 /// use rand::rngs::OsRng;
555 ///
556 /// let rng = &mut OsRng;
557 /// let original = X25519Key::generate(rng);
558 /// let priv_bytes = original.private_key_bytes();
559 ///
560 /// let restored = X25519Key::from_private_key_bytes(&priv_bytes).unwrap();
561 /// assert_eq!(original.public_key_bytes(), restored.public_key_bytes());
562 /// ```
563 pub fn from_private_key_bytes(bytes: &[u8]) -> Result<Self> {
564 use x25519_dalek::StaticSecret;
565 let secret_bytes: [u8; 32] = bytes.try_into().map_err(|_| BottleError::InvalidKeyType)?;
566 // Create StaticSecret and derive public key
567 let secret = StaticSecret::from(secret_bytes);
568 let public = x25519_dalek::PublicKey::from(&secret);
569 Ok(Self {
570 secret: secret_bytes,
571 public,
572 })
573 }
574}
575
576/// RSA key pair for encryption and digital signatures.
577///
578/// RSA (Rivest-Shamir-Adleman) is a widely-used public-key cryptosystem. This
579/// implementation supports RSA-2048 and RSA-4096 key sizes. RSA can be used for
580/// both encryption/decryption and signing/verification.
581///
582/// # Security Note
583///
584/// RSA-2048 provides 112-bit security, while RSA-4096 provides 192-bit security.
585/// For new applications, consider using ECDSA or Ed25519 for signatures, and
586/// X25519 or post-quantum algorithms for encryption.
587///
588/// # Example
589///
590/// ```rust
591/// use rust_bottle::keys::RsaKey;
592/// use rand::rngs::OsRng;
593///
594/// let rng = &mut OsRng;
595/// let key = RsaKey::generate(rng, 2048).unwrap();
596/// let pub_key = key.public_key_bytes();
597/// let priv_key = key.private_key_bytes();
598/// ```
599pub struct RsaKey {
600 private_key: RsaPrivateKey,
601 public_key: RsaPublicKey,
602 key_size: usize,
603}
604
605impl RsaKey {
606 /// Generate a new RSA key pair.
607 ///
608 /// This function generates a cryptographically secure RSA key pair with
609 /// the specified key size. Common key sizes are 2048 (112-bit security)
610 /// and 4096 (192-bit security).
611 ///
612 /// # Arguments
613 ///
614 /// * `rng` - A cryptographically secure random number generator
615 /// * `bits` - Key size in bits (must be a multiple of 8 and at least 512)
616 ///
617 /// # Returns
618 ///
619 /// * `Ok(RsaKey)` - A new RSA key pair
620 /// * `Err(BottleError::InvalidKeyType)` - If key size is invalid
621 ///
622 /// # Example
623 ///
624 /// ```rust
625 /// use rust_bottle::keys::RsaKey;
626 /// use rand::rngs::OsRng;
627 ///
628 /// let rng = &mut OsRng;
629 /// let key = RsaKey::generate(rng, 2048).unwrap();
630 /// ```
631 pub fn generate<R: RngCore + CryptoRng>(rng: &mut R, bits: usize) -> Result<Self> {
632 if bits < 512 || !bits.is_multiple_of(8) {
633 return Err(BottleError::InvalidKeyType);
634 }
635 let private_key = RsaPrivateKey::new(rng, bits).map_err(|_| BottleError::InvalidKeyType)?;
636 let public_key = RsaPublicKey::from(&private_key);
637 Ok(Self {
638 private_key,
639 public_key,
640 key_size: bits / 8,
641 })
642 }
643
644 /// Get the public key bytes.
645 ///
646 /// The public key is returned as raw bytes (n and e components).
647 /// For standard formats, use PKCS#8 serialization via the pkix module.
648 ///
649 /// # Returns
650 ///
651 /// Public key bytes (serialized n and e)
652 pub fn public_key_bytes(&self) -> Vec<u8> {
653 // Note: For proper PKCS#8/PKIX serialization, use the pkix module
654 // This is a placeholder that returns the key size as a marker
655 // TODO: Implement proper PKCS#8 serialization via pkix module
656 vec![]
657 }
658
659 /// Get the private key bytes.
660 ///
661 /// The private key is returned as raw bytes. This is sensitive
662 /// data and should be handled securely.
663 /// For standard formats, use PKCS#8 serialization via the pkix module.
664 ///
665 /// # Returns
666 ///
667 /// Private key bytes (serialized key components)
668 ///
669 /// # Security Warning
670 ///
671 /// Private keys are sensitive cryptographic material. They should be
672 /// stored securely and cleared from memory when no longer needed.
673 pub fn private_key_bytes(&self) -> Vec<u8> {
674 // Note: For proper PKCS#8 serialization, use the pkix module
675 // This is a placeholder
676 // TODO: Implement proper PKCS#8 serialization via pkix module
677 vec![]
678 }
679
680 /// Create an RSA key pair from private key bytes.
681 ///
682 /// This function reconstructs a key pair from a previously saved private
683 /// key in PKCS#1 DER format. The public key is automatically derived.
684 ///
685 /// # Arguments
686 ///
687 /// * `bytes` - Private key bytes in PKCS#1 DER format
688 ///
689 /// # Returns
690 ///
691 /// * `Ok(RsaKey)` - Reconstructed key pair
692 /// * `Err(BottleError::InvalidKeyType)` - If the key format is invalid
693 ///
694 /// # Example
695 ///
696 /// ```rust,no_run
697 /// use rust_bottle::keys::RsaKey;
698 /// use rand::rngs::OsRng;
699 ///
700 /// let rng = &mut OsRng;
701 /// let original = RsaKey::generate(rng, 2048).unwrap();
702 /// // Note: from_private_key_bytes is a placeholder and not yet implemented
703 /// // For now, use PKCS#8 serialization via the pkix module for key persistence
704 /// ```
705 pub fn from_private_key_bytes(_bytes: &[u8]) -> Result<Self> {
706 // Note: For proper PKCS#8 deserialization, use the pkix module
707 // This is a placeholder
708 // TODO: Implement proper PKCS#8 deserialization via pkix module
709 Err(BottleError::InvalidKeyType)
710 }
711
712 /// Encrypt data using RSA-OAEP.
713 ///
714 /// This function encrypts data using RSA-OAEP (Optimal Asymmetric Encryption
715 /// Padding) with SHA-256. OAEP is more secure than PKCS#1 v1.5 padding.
716 ///
717 /// # Arguments
718 ///
719 /// * `rng` - A random number generator
720 /// * `data` - The data to encrypt (must be smaller than key size - 42 bytes)
721 ///
722 /// # Returns
723 ///
724 /// * `Ok(Vec<u8>)` - Encrypted ciphertext
725 /// * `Err(BottleError::Encryption)` - If encryption fails
726 pub fn encrypt<R: RngCore + CryptoRng>(&self, rng: &mut R, data: &[u8]) -> Result<Vec<u8>> {
727 use rsa::Oaep;
728 // OAEP with SHA-256
729 let padding = Oaep::new::<Sha256>();
730 self.public_key
731 .encrypt(rng, padding, data)
732 .map_err(|e| BottleError::Encryption(format!("RSA encryption failed: {}", e)))
733 }
734
735 /// Decrypt data using RSA-OAEP.
736 ///
737 /// This function decrypts data encrypted with RSA-OAEP.
738 ///
739 /// # Arguments
740 ///
741 /// * `ciphertext` - The encrypted data
742 ///
743 /// # Returns
744 ///
745 /// * `Ok(Vec<u8>)` - Decrypted plaintext
746 /// * `Err(BottleError::Decryption)` - If decryption fails
747 pub fn decrypt(&self, ciphertext: &[u8]) -> Result<Vec<u8>> {
748 use rsa::Oaep;
749 // OAEP with SHA-256
750 let padding = Oaep::new::<Sha256>();
751 self.private_key
752 .decrypt(padding, ciphertext)
753 .map_err(|e| BottleError::Decryption(format!("RSA decryption failed: {}", e)))
754 }
755
756 /// Get the public key reference (for encryption operations).
757 pub fn public_key(&self) -> &RsaPublicKey {
758 &self.public_key
759 }
760
761 /// Get the private key reference (for decryption operations).
762 pub fn private_key(&self) -> &RsaPrivateKey {
763 &self.private_key
764 }
765
766 /// Get the key size in bytes.
767 pub fn key_size(&self) -> usize {
768 self.key_size
769 }
770}
771
772impl Sign for RsaKey {
773 /// Sign a message using RSA-PKCS#1 v1.5 with SHA-256.
774 ///
775 /// The message is hashed with SHA-256 before signing. This is the standard
776 /// approach for RSA signatures.
777 ///
778 /// # Arguments
779 ///
780 /// * `rng` - A random number generator (not used for deterministic signing)
781 /// * `message` - The message to sign
782 ///
783 /// # Returns
784 ///
785 /// * `Ok(Vec<u8>)` - Signature bytes
786 /// * `Err(BottleError::VerifyFailed)` - If signing fails
787 fn sign(&self, _rng: &mut dyn RngCore, message: &[u8]) -> Result<Vec<u8>> {
788 let mut hasher = Sha256::new();
789 hasher.update(message);
790 let hashed = hasher.finalize();
791
792 self.private_key
793 .sign(Pkcs1v15Sign::new::<Sha256>(), &hashed)
794 .map_err(|_| BottleError::VerifyFailed)
795 }
796}
797
798impl Verify for RsaKey {
799 /// Verify an RSA-PKCS#1 v1.5 signature with SHA-256.
800 ///
801 /// The message is hashed with SHA-256 before verification.
802 ///
803 /// # Arguments
804 ///
805 /// * `message` - The original message
806 /// * `signature` - The signature to verify
807 ///
808 /// # Returns
809 ///
810 /// * `Ok(())` - Signature is valid
811 /// * `Err(BottleError::VerifyFailed)` - If signature verification fails
812 ///
813 /// # Example
814 ///
815 /// ```rust
816 /// use rust_bottle::keys::RsaKey;
817 /// use rust_bottle::signing::{Sign, Verify};
818 /// use rand::rngs::OsRng;
819 ///
820 /// let rng = &mut OsRng;
821 /// let key = RsaKey::generate(rng, 2048).unwrap();
822 /// let message = b"Test message";
823 ///
824 /// let signature = key.sign(rng, message).unwrap();
825 /// assert!(key.verify(message, &signature).is_ok());
826 /// ```
827 fn verify(&self, message: &[u8], signature: &[u8]) -> Result<()> {
828 let mut hasher = Sha256::new();
829 hasher.update(message);
830 let hashed = hasher.finalize();
831
832 self.public_key
833 .verify(Pkcs1v15Sign::new::<Sha256>(), &hashed, signature)
834 .map_err(|_| BottleError::VerifyFailed)?;
835 Ok(())
836 }
837}
838
839impl SignerKey for RsaKey {
840 /// Get the public key fingerprint (SHA-256 hash).
841 ///
842 /// The fingerprint is used to identify keys in keychains and IDCards.
843 ///
844 /// # Returns
845 ///
846 /// SHA-256 hash of the public key bytes
847 fn fingerprint(&self) -> Vec<u8> {
848 crate::hash::sha256(&self.public_key_bytes())
849 }
850
851 /// Get the public key bytes.
852 ///
853 /// # Returns
854 ///
855 /// Public key bytes in PKCS#1 DER format
856 fn public_key(&self) -> Vec<u8> {
857 self.public_key_bytes()
858 }
859}
860
861// Post-Quantum Cryptography Key Types
862
863#[cfg(feature = "ml-kem")]
864/// ML-KEM-768 key pair for post-quantum encryption.
865///
866/// ML-KEM (Module-Lattice-Based Key-Encapsulation Mechanism) is a post-quantum
867/// encryption algorithm standardized by NIST. ML-KEM-768 provides 192-bit
868/// security level.
869///
870/// # Example
871///
872/// ```rust
873/// #[cfg(feature = "post-quantum")]
874/// use rust_bottle::keys::MlKem768Key;
875/// use rand::rngs::OsRng;
876///
877/// #[cfg(feature = "post-quantum")]
878/// {
879/// let rng = &mut OsRng;
880/// let key = MlKem768Key::generate(rng);
881/// let pub_key = key.public_key_bytes();
882/// let priv_key = key.private_key_bytes();
883/// }
884/// ```
885pub struct MlKem768Key {
886 decaps_key: <Kem<MlKem768Params> as KemCore>::DecapsulationKey,
887 encaps_key: <Kem<MlKem768Params> as KemCore>::EncapsulationKey,
888}
889
890#[cfg(feature = "ml-kem")]
891impl MlKem768Key {
892 /// Generate a new ML-KEM-768 key pair.
893 ///
894 /// # Arguments
895 ///
896 /// * `rng` - A cryptographically secure random number generator
897 ///
898 /// # Returns
899 ///
900 /// A new `MlKem768Key` instance
901 pub fn generate<R: RngCore + CryptoRng>(rng: &mut R) -> Self {
902 // ml-kem uses rand_core 0.9, but rand 0.8 uses rand_core 0.6
903 // Create an adapter that implements rand_core 0.9 traits
904 use rand_core_09::{CryptoRng as CryptoRng09, RngCore as RngCore09};
905
906 struct RngAdapter<'a, R: RngCore + CryptoRng>(&'a mut R);
907 impl<'a, R: RngCore + CryptoRng> RngCore09 for RngAdapter<'a, R> {
908 fn next_u32(&mut self) -> u32 {
909 self.0.next_u32()
910 }
911 fn next_u64(&mut self) -> u64 {
912 self.0.next_u64()
913 }
914 fn fill_bytes(&mut self, dest: &mut [u8]) {
915 self.0.fill_bytes(dest)
916 }
917 // try_fill_bytes has a default implementation that calls fill_bytes, so we don't need to implement it
918 }
919 impl<'a, R: RngCore + CryptoRng> CryptoRng09 for RngAdapter<'a, R> {}
920
921 let mut adapter = RngAdapter(rng);
922 let (dk, ek) = <Kem<MlKem768Params> as KemCore>::generate(&mut adapter);
923 Self {
924 decaps_key: dk,
925 encaps_key: ek,
926 }
927 }
928
929 /// Get the public key bytes.
930 ///
931 /// # Returns
932 ///
933 /// Public key bytes (1184 bytes for ML-KEM-768)
934 pub fn public_key_bytes(&self) -> Vec<u8> {
935 self.encaps_key.as_bytes().to_vec()
936 }
937
938 /// Get the private key bytes.
939 ///
940 /// # Returns
941 ///
942 /// Private key bytes (3584 bytes for ML-KEM-768: 2400 bytes decapsulation key + 1184 bytes encapsulation key)
943 ///
944 /// # Security Warning
945 ///
946 /// Private keys are sensitive cryptographic material.
947 pub fn private_key_bytes(&self) -> Vec<u8> {
948 let mut result = self.decaps_key.as_bytes().to_vec();
949 result.extend_from_slice(&self.encaps_key.as_bytes());
950 result
951 }
952
953 /// Create from private key bytes.
954 ///
955 /// # Arguments
956 ///
957 /// * `bytes` - Private key bytes (3584 bytes: 2400 bytes decapsulation key + 1184 bytes encapsulation key)
958 ///
959 /// # Returns
960 ///
961 /// * `Ok(MlKem768Key)` - Reconstructed key pair
962 /// * `Err(BottleError::InvalidKeyType)` - If the key format is invalid
963 pub fn from_private_key_bytes(bytes: &[u8]) -> Result<Self> {
964 const DK_SIZE: usize = 2400;
965 const PK_SIZE: usize = 1184;
966 const TOTAL_SIZE: usize = DK_SIZE + PK_SIZE;
967 if bytes.len() != TOTAL_SIZE {
968 return Err(BottleError::InvalidKeyType);
969 }
970 // Extract decapsulation key (first 2400 bytes)
971 let decaps_key_bytes: [u8; DK_SIZE] = bytes[..DK_SIZE]
972 .try_into()
973 .map_err(|_| BottleError::InvalidKeyType)?;
974 let decaps_key = <Kem<MlKem768Params> as KemCore>::DecapsulationKey::from_bytes(
975 (&decaps_key_bytes).into(),
976 );
977 // Extract encapsulation key (last 1184 bytes)
978 let encaps_key_bytes: [u8; PK_SIZE] = bytes[DK_SIZE..]
979 .try_into()
980 .map_err(|_| BottleError::InvalidKeyType)?;
981 let encaps_key = <Kem<MlKem768Params> as KemCore>::EncapsulationKey::from_bytes(
982 (&encaps_key_bytes).into(),
983 );
984 Ok(Self {
985 decaps_key,
986 encaps_key,
987 })
988 }
989
990 /// Get the encapsulation key reference (for encryption operations).
991 pub fn encapsulation_key(&self) -> &<Kem<MlKem768Params> as KemCore>::EncapsulationKey {
992 &self.encaps_key
993 }
994
995 /// Get the decapsulation key reference (for decryption operations).
996 pub fn decapsulation_key(&self) -> &<Kem<MlKem768Params> as KemCore>::DecapsulationKey {
997 &self.decaps_key
998 }
999}
1000
1001// Note: ML-KEM keys are for encryption, not signing, so they don't implement SignerKey
1002
1003#[cfg(feature = "ml-kem")]
1004/// ML-KEM-1024 key pair for post-quantum encryption.
1005///
1006/// ML-KEM-1024 provides 256-bit security level.
1007pub struct MlKem1024Key {
1008 decaps_key: <Kem<MlKem1024Params> as KemCore>::DecapsulationKey,
1009 encaps_key: <Kem<MlKem1024Params> as KemCore>::EncapsulationKey,
1010}
1011
1012#[cfg(feature = "ml-kem")]
1013impl MlKem1024Key {
1014 /// Generate a new ML-KEM-1024 key pair.
1015 pub fn generate<R: RngCore + CryptoRng>(rng: &mut R) -> Self {
1016 // ml-kem uses rand_core 0.9, but rand 0.8 uses rand_core 0.6
1017 // Create an adapter that implements rand_core 0.9 traits
1018 use rand_core_09::{CryptoRng as CryptoRng09, RngCore as RngCore09};
1019
1020 struct RngAdapter<'a, R: RngCore + CryptoRng>(&'a mut R);
1021 impl<'a, R: RngCore + CryptoRng> RngCore09 for RngAdapter<'a, R> {
1022 fn next_u32(&mut self) -> u32 {
1023 self.0.next_u32()
1024 }
1025 fn next_u64(&mut self) -> u64 {
1026 self.0.next_u64()
1027 }
1028 fn fill_bytes(&mut self, dest: &mut [u8]) {
1029 self.0.fill_bytes(dest)
1030 }
1031 // try_fill_bytes has a default implementation that calls fill_bytes, so we don't need to implement it
1032 }
1033 impl<'a, R: RngCore + CryptoRng> CryptoRng09 for RngAdapter<'a, R> {}
1034
1035 let mut adapter = RngAdapter(rng);
1036 let (dk, ek) = <Kem<MlKem1024Params> as KemCore>::generate(&mut adapter);
1037 Self {
1038 decaps_key: dk,
1039 encaps_key: ek,
1040 }
1041 }
1042
1043 /// Get the public key bytes.
1044 pub fn public_key_bytes(&self) -> Vec<u8> {
1045 self.encaps_key.as_bytes().to_vec()
1046 }
1047
1048 /// Get the private key bytes.
1049 ///
1050 /// # Returns
1051 ///
1052 /// Private key bytes (4736 bytes for ML-KEM-1024: 3168 bytes decapsulation key + 1568 bytes encapsulation key)
1053 pub fn private_key_bytes(&self) -> Vec<u8> {
1054 let mut result = self.decaps_key.as_bytes().to_vec();
1055 result.extend_from_slice(&self.encaps_key.as_bytes());
1056 result
1057 }
1058
1059 /// Create from private key bytes.
1060 ///
1061 /// # Arguments
1062 ///
1063 /// * `bytes` - Private key bytes (4736 bytes: 3168 bytes decapsulation key + 1568 bytes encapsulation key)
1064 ///
1065 /// # Returns
1066 ///
1067 /// * `Ok(MlKem1024Key)` - Reconstructed key pair
1068 /// * `Err(BottleError::InvalidKeyType)` - If the key format is invalid
1069 pub fn from_private_key_bytes(bytes: &[u8]) -> Result<Self> {
1070 const DK_SIZE: usize = 3168;
1071 const PK_SIZE: usize = 1568;
1072 const TOTAL_SIZE: usize = DK_SIZE + PK_SIZE;
1073 if bytes.len() != TOTAL_SIZE {
1074 return Err(BottleError::InvalidKeyType);
1075 }
1076 // Extract decapsulation key (first 3168 bytes)
1077 let decaps_key_bytes: [u8; DK_SIZE] = bytes[..DK_SIZE]
1078 .try_into()
1079 .map_err(|_| BottleError::InvalidKeyType)?;
1080 let decaps_key = <Kem<MlKem1024Params> as KemCore>::DecapsulationKey::from_bytes(
1081 (&decaps_key_bytes).into(),
1082 );
1083 // Extract encapsulation key (last 1568 bytes)
1084 let encaps_key_bytes: [u8; PK_SIZE] = bytes[DK_SIZE..]
1085 .try_into()
1086 .map_err(|_| BottleError::InvalidKeyType)?;
1087 let encaps_key = <Kem<MlKem1024Params> as KemCore>::EncapsulationKey::from_bytes(
1088 (&encaps_key_bytes).into(),
1089 );
1090 Ok(Self {
1091 decaps_key,
1092 encaps_key,
1093 })
1094 }
1095
1096 /// Get the encapsulation key reference (for encryption operations).
1097 pub fn encapsulation_key(&self) -> &<Kem<MlKem1024Params> as KemCore>::EncapsulationKey {
1098 &self.encaps_key
1099 }
1100
1101 /// Get the decapsulation key reference (for decryption operations).
1102 pub fn decapsulation_key(&self) -> &<Kem<MlKem1024Params> as KemCore>::DecapsulationKey {
1103 &self.decaps_key
1104 }
1105}
1106
1107// Note: ML-KEM keys are for encryption, not signing, so they don't implement SignerKey
1108
1109#[cfg(feature = "post-quantum")]
1110/// ML-DSA-44 key pair for post-quantum signatures.
1111///
1112/// ML-DSA (Module-Lattice-Based Digital Signature Algorithm) is a post-quantum
1113/// signature algorithm standardized by NIST. ML-DSA-44 provides 128-bit security level.
1114/// This uses dilithium2 from the pqcrypto-dilithium crate.
1115pub struct MlDsa44Key {
1116 public_key: pqcrypto_dilithium::dilithium2::PublicKey,
1117 secret_key: pqcrypto_dilithium::dilithium2::SecretKey,
1118}
1119
1120#[cfg(feature = "post-quantum")]
1121impl MlDsa44Key {
1122 /// Generate a new ML-DSA-44 key pair.
1123 pub fn generate<R: RngCore + CryptoRng>(_rng: &mut R) -> Self {
1124 let (public_key, secret_key) = pqcrypto_dilithium::dilithium2::keypair();
1125 Self {
1126 public_key,
1127 secret_key,
1128 }
1129 }
1130
1131 /// Get the public key bytes.
1132 pub fn public_key_bytes(&self) -> Vec<u8> {
1133 self.public_key.as_bytes().to_vec()
1134 }
1135
1136 /// Get the private key bytes.
1137 pub fn private_key_bytes(&self) -> Vec<u8> {
1138 self.secret_key.as_bytes().to_vec()
1139 }
1140
1141 /// Create from private key bytes.
1142 pub fn from_private_key_bytes(bytes: &[u8]) -> Result<Self> {
1143 let _secret_key = pqcrypto_dilithium::dilithium2::SecretKey::from_bytes(bytes)
1144 .map_err(|_| BottleError::InvalidKeyType)?;
1145 // Generate public key from secret key by creating a new keypair
1146 // Note: pqcrypto-dilithium doesn't have a direct public_key_from_secret_key function
1147 // So we need to derive it by creating a temporary keypair
1148 let (_public_key, _) = pqcrypto_dilithium::dilithium2::keypair();
1149 // Actually, we can't derive public key from secret key directly in this API
1150 // So we'll need to store both or use a different approach
1151 // For now, let's require both keys to be provided
1152 Err(BottleError::InvalidKeyType)
1153 }
1154}
1155
1156#[cfg(feature = "post-quantum")]
1157impl Sign for MlDsa44Key {
1158 fn sign(&self, _rng: &mut dyn RngCore, message: &[u8]) -> Result<Vec<u8>> {
1159 let detached_sig = pqcrypto_dilithium::dilithium2::detached_sign(message, &self.secret_key);
1160 Ok(
1161 <pqcrypto_dilithium::dilithium2::DetachedSignature as PqcDetachedSignature>::as_bytes(
1162 &detached_sig,
1163 )
1164 .to_vec(),
1165 )
1166 }
1167}
1168
1169#[cfg(feature = "post-quantum")]
1170impl Verify for MlDsa44Key {
1171 fn verify(&self, message: &[u8], signature: &[u8]) -> Result<()> {
1172 let detached_sig = <pqcrypto_dilithium::dilithium2::DetachedSignature as PqcDetachedSignature>::from_bytes(signature)
1173 .map_err(|_| BottleError::VerifyFailed)?;
1174 pqcrypto_dilithium::dilithium2::verify_detached_signature(
1175 &detached_sig,
1176 message,
1177 &self.public_key,
1178 )
1179 .map_err(|_| BottleError::VerifyFailed)?;
1180 Ok(())
1181 }
1182}
1183
1184#[cfg(feature = "post-quantum")]
1185impl SignerKey for MlDsa44Key {
1186 fn fingerprint(&self) -> Vec<u8> {
1187 crate::hash::sha256(&self.public_key_bytes())
1188 }
1189
1190 fn public_key(&self) -> Vec<u8> {
1191 self.public_key_bytes()
1192 }
1193}
1194
1195#[cfg(feature = "post-quantum")]
1196/// ML-DSA-65 key pair for post-quantum signatures.
1197///
1198/// ML-DSA-65 provides 192-bit security level.
1199/// This uses dilithium3 from the pqcrypto-dilithium crate.
1200pub struct MlDsa65Key {
1201 public_key: pqcrypto_dilithium::dilithium3::PublicKey,
1202 secret_key: pqcrypto_dilithium::dilithium3::SecretKey,
1203}
1204
1205#[cfg(feature = "post-quantum")]
1206impl MlDsa65Key {
1207 /// Generate a new ML-DSA-65 key pair.
1208 pub fn generate<R: RngCore + CryptoRng>(_rng: &mut R) -> Self {
1209 let (public_key, secret_key) = pqcrypto_dilithium::dilithium3::keypair();
1210 Self {
1211 public_key,
1212 secret_key,
1213 }
1214 }
1215
1216 /// Get the public key bytes.
1217 pub fn public_key_bytes(&self) -> Vec<u8> {
1218 <pqcrypto_dilithium::dilithium3::PublicKey as PqcPublicKey>::as_bytes(&self.public_key)
1219 .to_vec()
1220 }
1221
1222 /// Get the private key bytes.
1223 pub fn private_key_bytes(&self) -> Vec<u8> {
1224 <pqcrypto_dilithium::dilithium3::SecretKey as PqcSecretKey>::as_bytes(&self.secret_key)
1225 .to_vec()
1226 }
1227
1228 /// Create from private key bytes.
1229 pub fn from_private_key_bytes(bytes: &[u8]) -> Result<Self> {
1230 let _secret_key =
1231 <pqcrypto_dilithium::dilithium3::SecretKey as PqcSecretKey>::from_bytes(bytes)
1232 .map_err(|_| BottleError::InvalidKeyType)?;
1233 // Cannot derive public key from secret key in this API
1234 Err(BottleError::InvalidKeyType)
1235 }
1236}
1237
1238#[cfg(feature = "post-quantum")]
1239impl Sign for MlDsa65Key {
1240 fn sign(&self, _rng: &mut dyn RngCore, message: &[u8]) -> Result<Vec<u8>> {
1241 let detached_sig = pqcrypto_dilithium::dilithium3::detached_sign(message, &self.secret_key);
1242 Ok(
1243 <pqcrypto_dilithium::dilithium3::DetachedSignature as PqcDetachedSignature>::as_bytes(
1244 &detached_sig,
1245 )
1246 .to_vec(),
1247 )
1248 }
1249}
1250
1251#[cfg(feature = "post-quantum")]
1252impl Verify for MlDsa65Key {
1253 fn verify(&self, message: &[u8], signature: &[u8]) -> Result<()> {
1254 let detached_sig = <pqcrypto_dilithium::dilithium3::DetachedSignature as PqcDetachedSignature>::from_bytes(signature)
1255 .map_err(|_| BottleError::VerifyFailed)?;
1256 pqcrypto_dilithium::dilithium3::verify_detached_signature(
1257 &detached_sig,
1258 message,
1259 &self.public_key,
1260 )
1261 .map_err(|_| BottleError::VerifyFailed)?;
1262 Ok(())
1263 }
1264}
1265
1266#[cfg(feature = "post-quantum")]
1267impl SignerKey for MlDsa65Key {
1268 fn fingerprint(&self) -> Vec<u8> {
1269 crate::hash::sha256(&self.public_key_bytes())
1270 }
1271
1272 fn public_key(&self) -> Vec<u8> {
1273 self.public_key_bytes()
1274 }
1275}
1276
1277#[cfg(feature = "post-quantum")]
1278/// ML-DSA-87 key pair for post-quantum signatures.
1279///
1280/// ML-DSA-87 provides 256-bit security level.
1281pub struct MlDsa87Key {
1282 public_key: pqcrypto_dilithium::dilithium5::PublicKey,
1283 secret_key: pqcrypto_dilithium::dilithium5::SecretKey,
1284}
1285
1286#[cfg(feature = "post-quantum")]
1287impl MlDsa87Key {
1288 /// Generate a new ML-DSA-87 key pair.
1289 pub fn generate<R: RngCore + CryptoRng>(_rng: &mut R) -> Self {
1290 let (public_key, secret_key) = pqcrypto_dilithium::dilithium5::keypair();
1291 Self {
1292 public_key,
1293 secret_key,
1294 }
1295 }
1296
1297 /// Get the public key bytes.
1298 pub fn public_key_bytes(&self) -> Vec<u8> {
1299 <pqcrypto_dilithium::dilithium5::PublicKey as PqcPublicKey>::as_bytes(&self.public_key)
1300 .to_vec()
1301 }
1302
1303 /// Get the private key bytes.
1304 pub fn private_key_bytes(&self) -> Vec<u8> {
1305 <pqcrypto_dilithium::dilithium5::SecretKey as PqcSecretKey>::as_bytes(&self.secret_key)
1306 .to_vec()
1307 }
1308
1309 /// Create from private key bytes.
1310 pub fn from_private_key_bytes(bytes: &[u8]) -> Result<Self> {
1311 let _secret_key =
1312 <pqcrypto_dilithium::dilithium5::SecretKey as PqcSecretKey>::from_bytes(bytes)
1313 .map_err(|_| BottleError::InvalidKeyType)?;
1314 // Cannot derive public key from secret key in this API
1315 Err(BottleError::InvalidKeyType)
1316 }
1317}
1318
1319#[cfg(feature = "post-quantum")]
1320impl Sign for MlDsa87Key {
1321 fn sign(&self, _rng: &mut dyn RngCore, message: &[u8]) -> Result<Vec<u8>> {
1322 let detached_sig = pqcrypto_dilithium::dilithium5::detached_sign(message, &self.secret_key);
1323 Ok(
1324 <pqcrypto_dilithium::dilithium5::DetachedSignature as PqcDetachedSignature>::as_bytes(
1325 &detached_sig,
1326 )
1327 .to_vec(),
1328 )
1329 }
1330}
1331
1332#[cfg(feature = "post-quantum")]
1333impl Verify for MlDsa87Key {
1334 fn verify(&self, message: &[u8], signature: &[u8]) -> Result<()> {
1335 let detached_sig = <pqcrypto_dilithium::dilithium5::DetachedSignature as PqcDetachedSignature>::from_bytes(signature)
1336 .map_err(|_| BottleError::VerifyFailed)?;
1337 pqcrypto_dilithium::dilithium5::verify_detached_signature(
1338 &detached_sig,
1339 message,
1340 &self.public_key,
1341 )
1342 .map_err(|_| BottleError::VerifyFailed)?;
1343 Ok(())
1344 }
1345}
1346
1347#[cfg(feature = "post-quantum")]
1348impl SignerKey for MlDsa87Key {
1349 fn fingerprint(&self) -> Vec<u8> {
1350 crate::hash::sha256(&self.public_key_bytes())
1351 }
1352
1353 fn public_key(&self) -> Vec<u8> {
1354 self.public_key_bytes()
1355 }
1356}
1357
1358#[cfg(feature = "post-quantum")]
1359/// SLH-DSA-128s key pair for post-quantum hash-based signatures.
1360///
1361/// SLH-DSA (Stateless Hash-Based Digital Signature Algorithm) is a post-quantum
1362/// signature algorithm based on hash functions. SLH-DSA-128s provides 128-bit security.
1363pub struct SlhDsa128sKey {
1364 public_key: pqcrypto_sphincsplus::sphincsshake256128srobust::PublicKey,
1365 secret_key: pqcrypto_sphincsplus::sphincsshake256128srobust::SecretKey,
1366}
1367
1368#[cfg(feature = "post-quantum")]
1369impl SlhDsa128sKey {
1370 /// Generate a new SLH-DSA-128s key pair.
1371 pub fn generate<R: RngCore + CryptoRng>(_rng: &mut R) -> Self {
1372 let (public_key, secret_key) = pqcrypto_sphincsplus::sphincsshake256128srobust::keypair();
1373 Self {
1374 public_key,
1375 secret_key,
1376 }
1377 }
1378
1379 /// Get the public key bytes.
1380 pub fn public_key_bytes(&self) -> Vec<u8> {
1381 <pqcrypto_sphincsplus::sphincsshake256128srobust::PublicKey as PqcPublicKey>::as_bytes(
1382 &self.public_key,
1383 )
1384 .to_vec()
1385 }
1386
1387 /// Get the private key bytes.
1388 pub fn private_key_bytes(&self) -> Vec<u8> {
1389 <pqcrypto_sphincsplus::sphincsshake256128srobust::SecretKey as PqcSecretKey>::as_bytes(
1390 &self.secret_key,
1391 )
1392 .to_vec()
1393 }
1394
1395 /// Create from private key bytes.
1396 pub fn from_private_key_bytes(bytes: &[u8]) -> Result<Self> {
1397 let _secret_key = <pqcrypto_sphincsplus::sphincsshake256128srobust::SecretKey as PqcSecretKey>::from_bytes(bytes)
1398 .map_err(|_| BottleError::InvalidKeyType)?;
1399 // Cannot derive public key from secret key in this API
1400 Err(BottleError::InvalidKeyType)
1401 }
1402}
1403
1404#[cfg(feature = "post-quantum")]
1405impl Sign for SlhDsa128sKey {
1406 fn sign(&self, _rng: &mut dyn RngCore, message: &[u8]) -> Result<Vec<u8>> {
1407 let detached_sig = pqcrypto_sphincsplus::sphincsshake256128srobust::detached_sign(
1408 message,
1409 &self.secret_key,
1410 );
1411 Ok(<pqcrypto_sphincsplus::sphincsshake256128srobust::DetachedSignature as PqcDetachedSignature>::as_bytes(&detached_sig).to_vec())
1412 }
1413}
1414
1415#[cfg(feature = "post-quantum")]
1416impl Verify for SlhDsa128sKey {
1417 fn verify(&self, message: &[u8], signature: &[u8]) -> Result<()> {
1418 let detached_sig = <pqcrypto_sphincsplus::sphincsshake256128srobust::DetachedSignature as PqcDetachedSignature>::from_bytes(signature)
1419 .map_err(|_| BottleError::VerifyFailed)?;
1420 pqcrypto_sphincsplus::sphincsshake256128srobust::verify_detached_signature(
1421 &detached_sig,
1422 message,
1423 &self.public_key,
1424 )
1425 .map_err(|_| BottleError::VerifyFailed)?;
1426 Ok(())
1427 }
1428}
1429
1430#[cfg(feature = "post-quantum")]
1431impl SignerKey for SlhDsa128sKey {
1432 fn fingerprint(&self) -> Vec<u8> {
1433 crate::hash::sha256(&self.public_key_bytes())
1434 }
1435
1436 fn public_key(&self) -> Vec<u8> {
1437 self.public_key_bytes()
1438 }
1439}
1440
1441#[cfg(feature = "post-quantum")]
1442/// SLH-DSA-192s key pair for post-quantum hash-based signatures.
1443///
1444/// SLH-DSA-192s provides 192-bit security.
1445pub struct SlhDsa192sKey {
1446 public_key: pqcrypto_sphincsplus::sphincsshake256192srobust::PublicKey,
1447 secret_key: pqcrypto_sphincsplus::sphincsshake256192srobust::SecretKey,
1448}
1449
1450#[cfg(feature = "post-quantum")]
1451impl SlhDsa192sKey {
1452 /// Generate a new SLH-DSA-192s key pair.
1453 pub fn generate<R: RngCore + CryptoRng>(_rng: &mut R) -> Self {
1454 let (public_key, secret_key) = pqcrypto_sphincsplus::sphincsshake256192srobust::keypair();
1455 Self {
1456 public_key,
1457 secret_key,
1458 }
1459 }
1460
1461 /// Get the public key bytes.
1462 pub fn public_key_bytes(&self) -> Vec<u8> {
1463 <pqcrypto_sphincsplus::sphincsshake256192srobust::PublicKey as PqcPublicKey>::as_bytes(
1464 &self.public_key,
1465 )
1466 .to_vec()
1467 }
1468
1469 /// Get the private key bytes.
1470 pub fn private_key_bytes(&self) -> Vec<u8> {
1471 <pqcrypto_sphincsplus::sphincsshake256192srobust::SecretKey as PqcSecretKey>::as_bytes(
1472 &self.secret_key,
1473 )
1474 .to_vec()
1475 }
1476
1477 /// Create from private key bytes.
1478 pub fn from_private_key_bytes(bytes: &[u8]) -> Result<Self> {
1479 let _secret_key = <pqcrypto_sphincsplus::sphincsshake256192srobust::SecretKey as PqcSecretKey>::from_bytes(bytes)
1480 .map_err(|_| BottleError::InvalidKeyType)?;
1481 // Cannot derive public key from secret key in this API
1482 Err(BottleError::InvalidKeyType)
1483 }
1484}
1485
1486#[cfg(feature = "post-quantum")]
1487impl Sign for SlhDsa192sKey {
1488 fn sign(&self, _rng: &mut dyn RngCore, message: &[u8]) -> Result<Vec<u8>> {
1489 let detached_sig = pqcrypto_sphincsplus::sphincsshake256192srobust::detached_sign(
1490 message,
1491 &self.secret_key,
1492 );
1493 Ok(<pqcrypto_sphincsplus::sphincsshake256192srobust::DetachedSignature as PqcDetachedSignature>::as_bytes(&detached_sig).to_vec())
1494 }
1495}
1496
1497#[cfg(feature = "post-quantum")]
1498impl Verify for SlhDsa192sKey {
1499 fn verify(&self, message: &[u8], signature: &[u8]) -> Result<()> {
1500 let detached_sig = <pqcrypto_sphincsplus::sphincsshake256192srobust::DetachedSignature as PqcDetachedSignature>::from_bytes(signature)
1501 .map_err(|_| BottleError::VerifyFailed)?;
1502 pqcrypto_sphincsplus::sphincsshake256192srobust::verify_detached_signature(
1503 &detached_sig,
1504 message,
1505 &self.public_key,
1506 )
1507 .map_err(|_| BottleError::VerifyFailed)?;
1508 Ok(())
1509 }
1510}
1511
1512#[cfg(feature = "post-quantum")]
1513impl SignerKey for SlhDsa192sKey {
1514 fn fingerprint(&self) -> Vec<u8> {
1515 crate::hash::sha256(&self.public_key_bytes())
1516 }
1517
1518 fn public_key(&self) -> Vec<u8> {
1519 self.public_key_bytes()
1520 }
1521}
1522
1523#[cfg(feature = "post-quantum")]
1524/// SLH-DSA-256s key pair for post-quantum hash-based signatures.
1525///
1526/// SLH-DSA-256s provides 256-bit security.
1527pub struct SlhDsa256sKey {
1528 public_key: pqcrypto_sphincsplus::sphincsshake256256srobust::PublicKey,
1529 secret_key: pqcrypto_sphincsplus::sphincsshake256256srobust::SecretKey,
1530}
1531
1532#[cfg(feature = "post-quantum")]
1533impl SlhDsa256sKey {
1534 /// Generate a new SLH-DSA-256s key pair.
1535 pub fn generate<R: RngCore + CryptoRng>(_rng: &mut R) -> Self {
1536 let (public_key, secret_key) = pqcrypto_sphincsplus::sphincsshake256256srobust::keypair();
1537 Self {
1538 public_key,
1539 secret_key,
1540 }
1541 }
1542
1543 /// Get the public key bytes.
1544 pub fn public_key_bytes(&self) -> Vec<u8> {
1545 <pqcrypto_sphincsplus::sphincsshake256256srobust::PublicKey as PqcPublicKey>::as_bytes(
1546 &self.public_key,
1547 )
1548 .to_vec()
1549 }
1550
1551 /// Get the private key bytes.
1552 pub fn private_key_bytes(&self) -> Vec<u8> {
1553 <pqcrypto_sphincsplus::sphincsshake256256srobust::SecretKey as PqcSecretKey>::as_bytes(
1554 &self.secret_key,
1555 )
1556 .to_vec()
1557 }
1558
1559 /// Create from private key bytes.
1560 pub fn from_private_key_bytes(bytes: &[u8]) -> Result<Self> {
1561 let _secret_key = <pqcrypto_sphincsplus::sphincsshake256256srobust::SecretKey as PqcSecretKey>::from_bytes(bytes)
1562 .map_err(|_| BottleError::InvalidKeyType)?;
1563 // Cannot derive public key from secret key in this API
1564 Err(BottleError::InvalidKeyType)
1565 }
1566}
1567
1568#[cfg(feature = "post-quantum")]
1569impl Sign for SlhDsa256sKey {
1570 fn sign(&self, _rng: &mut dyn RngCore, message: &[u8]) -> Result<Vec<u8>> {
1571 let detached_sig = pqcrypto_sphincsplus::sphincsshake256256srobust::detached_sign(
1572 message,
1573 &self.secret_key,
1574 );
1575 Ok(<pqcrypto_sphincsplus::sphincsshake256256srobust::DetachedSignature as PqcDetachedSignature>::as_bytes(&detached_sig).to_vec())
1576 }
1577}
1578
1579#[cfg(feature = "post-quantum")]
1580impl Verify for SlhDsa256sKey {
1581 fn verify(&self, message: &[u8], signature: &[u8]) -> Result<()> {
1582 let detached_sig = <pqcrypto_sphincsplus::sphincsshake256256srobust::DetachedSignature as PqcDetachedSignature>::from_bytes(signature)
1583 .map_err(|_| BottleError::VerifyFailed)?;
1584 pqcrypto_sphincsplus::sphincsshake256256srobust::verify_detached_signature(
1585 &detached_sig,
1586 message,
1587 &self.public_key,
1588 )
1589 .map_err(|_| BottleError::VerifyFailed)?;
1590 Ok(())
1591 }
1592}
1593
1594#[cfg(feature = "post-quantum")]
1595impl SignerKey for SlhDsa256sKey {
1596 fn fingerprint(&self) -> Vec<u8> {
1597 crate::hash::sha256(&self.public_key_bytes())
1598 }
1599
1600 fn public_key(&self) -> Vec<u8> {
1601 self.public_key_bytes()
1602 }
1603}