1use std::fmt;
4use std::cmp::Ordering;
5use std::hash::Hasher;
6use std::time;
7
8#[cfg(test)]
9use quickcheck::{Arbitrary, Gen};
10
11use crate::Error;
12use crate::crypto::{mpi, hash::Hash, mem::Protected, KeyPair};
13use crate::packet::key::{
14 KeyParts,
15 KeyRole,
16 KeyRoleRT,
17 PublicParts,
18 SecretParts,
19 UnspecifiedParts,
20};
21use crate::packet::prelude::*;
22use crate::PublicKeyAlgorithm;
23use crate::HashAlgorithm;
24use crate::types::Timestamp;
25use crate::Result;
26use crate::crypto::Password;
27use crate::KeyID;
28use crate::Fingerprint;
29use crate::KeyHandle;
30use crate::policy::HashAlgoSecurity;
31
32#[derive(PartialEq, Eq, Hash)]
58pub struct Key6<P: KeyParts, R: KeyRole> {
59 pub(crate) common: Key4<P, R>,
60}
61
62impl<P, R> Clone for Key6<P, R>
70 where P: KeyParts, R: KeyRole
71{
72 fn clone(&self) -> Self {
73 Key6 {
74 common: self.common.clone(),
75 }
76 }
77}
78
79impl<P, R> fmt::Debug for Key6<P, R>
80where P: KeyParts,
81 R: KeyRole,
82{
83 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
84 f.debug_struct("Key6")
85 .field("fingerprint", &self.fingerprint())
86 .field("creation_time", &self.creation_time())
87 .field("pk_algo", &self.pk_algo())
88 .field("mpis", &self.mpis())
89 .field("secret", &self.optional_secret())
90 .finish()
91 }
92}
93
94impl<P, R> fmt::Display for Key6<P, R>
95where P: KeyParts,
96 R: KeyRole,
97{
98 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
99 write!(f, "{}", self.fingerprint())
100 }
101}
102
103impl<P, R> Key6<P, R>
104where P: KeyParts,
105 R: KeyRole,
106{
107 pub fn hash_algo_security(&self) -> HashAlgoSecurity {
133 HashAlgoSecurity::SecondPreImageResistance
134 }
135
136 pub fn public_cmp<PB, RB>(&self, b: &Key6<PB, RB>) -> Ordering
143 where PB: KeyParts,
144 RB: KeyRole,
145 {
146 self.mpis().cmp(b.mpis())
147 .then_with(|| self.creation_time().cmp(&b.creation_time()))
148 .then_with(|| self.pk_algo().cmp(&b.pk_algo()))
149 }
150
151 pub fn public_eq<PB, RB>(&self, b: &Key6<PB, RB>) -> bool
159 where PB: KeyParts,
160 RB: KeyRole,
161 {
162 self.public_cmp(b) == Ordering::Equal
163 }
164
165 pub fn public_hash<H>(&self, state: &mut H)
172 where H: Hasher
173 {
174 self.common.public_hash(state);
175 }
176}
177
178impl<P, R> Key6<P, R>
179where
180 P: KeyParts,
181 R: KeyRole,
182{
183 pub fn creation_time(&self) -> time::SystemTime {
185 self.common.creation_time()
186 }
187
188 pub(crate) fn creation_time_raw(&self) -> Timestamp {
193 self.common.creation_time_raw()
194 }
195
196 pub fn set_creation_time<T>(&mut self, timestamp: T)
208 -> Result<time::SystemTime>
209 where T: Into<time::SystemTime>
210 {
211 self.common.set_creation_time(timestamp)
212 }
213
214 pub fn pk_algo(&self) -> PublicKeyAlgorithm {
216 self.common.pk_algo()
217 }
218
219 pub fn set_pk_algo(&mut self, pk_algo: PublicKeyAlgorithm)
223 -> PublicKeyAlgorithm
224 {
225 self.common.set_pk_algo(pk_algo)
226 }
227
228 pub fn mpis(&self) -> &mpi::PublicKey {
230 self.common.mpis()
231 }
232
233 pub fn mpis_mut(&mut self) -> &mut mpi::PublicKey {
235 self.common.mpis_mut()
236 }
237
238 pub fn set_mpis(&mut self, mpis: mpi::PublicKey) -> mpi::PublicKey {
242 self.common.set_mpis(mpis)
243 }
244
245 pub fn has_secret(&self) -> bool {
247 self.common.has_secret()
248 }
249
250 pub fn has_unencrypted_secret(&self) -> bool {
256 self.common.has_unencrypted_secret()
257 }
258
259 pub fn optional_secret(&self) -> Option<&SecretKeyMaterial> {
261 self.common.optional_secret()
262 }
263
264 pub fn key_handle(&self) -> KeyHandle {
271 self.fingerprint().into()
272 }
273
274 pub fn fingerprint(&self) -> Fingerprint {
280 let fp = self.common.fingerprint.get_or_init(|| {
281 let mut h = HashAlgorithm::SHA256.context()
282 .expect("SHA256 is MTI for RFC9580")
283 .for_signature(6);
286
287 self.hash(&mut h).expect("v6 key hashing is infallible");
288
289 let mut digest = [0u8; 32];
290 let _ = h.digest(&mut digest);
291 Fingerprint::V6(digest)
292 });
293
294 debug_assert!(matches!(fp, Fingerprint::V6(_)));
301
302 fp.clone()
303 }
304
305 pub fn keyid(&self) -> KeyID {
311 self.fingerprint().into()
312 }
313
314 pub(crate) fn from_common(common: Key4<P, R>) -> Self {
317 Key6 { common }
318 }
319
320 pub(crate) fn make(creation_time: Timestamp,
325 pk_algo: PublicKeyAlgorithm,
326 mpis: mpi::PublicKey,
327 secret: Option<SecretKeyMaterial>)
328 -> Result<Self>
329 where
330 {
331 Ok(Key6 {
332 common: Key4::make(creation_time, pk_algo, mpis, secret)?,
333 })
334 }
335
336 pub(crate) fn role(&self) -> KeyRoleRT {
337 self.common.role()
338 }
339
340 pub(crate) fn set_role(&mut self, role: KeyRoleRT) {
341 self.common.set_role(role);
342 }
343}
344
345impl<R> Key6<key::PublicParts, R>
346where R: KeyRole,
347{
348 pub fn new<T>(creation_time: T, pk_algo: PublicKeyAlgorithm,
350 mpis: mpi::PublicKey)
351 -> Result<Self>
352 where T: Into<time::SystemTime>
353 {
354 Ok(Key6 {
355 common: Key4::new(creation_time, pk_algo, mpis)?,
356 })
357 }
358
359 pub fn import_public_x25519<T>(public_key: &[u8], ctime: T)
365 -> Result<Self>
366 where
367 T: Into<Option<time::SystemTime>>,
368 {
369 Ok(Key6 {
370 common: Key4::new(ctime.into().unwrap_or_else(crate::now),
371 PublicKeyAlgorithm::X25519,
372 mpi::PublicKey::X25519 {
373 u: public_key.try_into()?,
374 })?,
375 })
376 }
377
378 pub fn import_public_x448<T>(public_key: &[u8], ctime: T)
384 -> Result<Self>
385 where
386 T: Into<Option<time::SystemTime>>,
387 {
388 Ok(Key6 {
389 common: Key4::new(ctime.into().unwrap_or_else(crate::now),
390 PublicKeyAlgorithm::X448,
391 mpi::PublicKey::X448 {
392 u: Box::new(public_key.try_into()?),
393 })?,
394 })
395 }
396
397 pub fn import_public_ed25519<T>(public_key: &[u8], ctime: T) -> Result<Self>
403 where
404 T: Into<Option<time::SystemTime>>,
405 {
406 Ok(Key6 {
407 common: Key4::new(ctime.into().unwrap_or_else(crate::now),
408 PublicKeyAlgorithm::Ed25519,
409 mpi::PublicKey::Ed25519 {
410 a: public_key.try_into()?,
411 })?,
412 })
413 }
414
415 pub fn import_public_ed448<T>(public_key: &[u8], ctime: T) -> Result<Self>
421 where
422 T: Into<Option<time::SystemTime>>,
423 {
424 Ok(Key6 {
425 common: Key4::new(ctime.into().unwrap_or_else(crate::now),
426 PublicKeyAlgorithm::Ed448,
427 mpi::PublicKey::Ed448 {
428 a: Box::new(public_key.try_into()?),
429 })?,
430 })
431 }
432
433 pub fn import_public_rsa<T>(e: &[u8], n: &[u8], ctime: T)
440 -> Result<Self> where T: Into<Option<time::SystemTime>>
441 {
442 Ok(Key6 {
443 common: Key4::import_public_rsa(e, n, ctime)?,
444 })
445 }
446
447 pub fn import_public_mldsa65_ed25519<T>(
459 mldsa: &[u8], eddsa: &[u8], ctime: T)
460 -> Result<Self>
461 where
462 T: Into<Option<time::SystemTime>>
463 {
464 Ok(Key6 {
465 common: Key4::new(ctime.into().unwrap_or_else(crate::now),
466 PublicKeyAlgorithm::MLDSA65_Ed25519,
467 mpi::PublicKey::MLDSA65_Ed25519 {
468 eddsa: Box::new(eddsa.try_into()?),
469 mldsa: Box::new(mldsa.try_into()?),
470 })?,
471 })
472 }
473
474 pub fn import_public_mldsa87_ed448<T>(
486 mldsa: &[u8], eddsa: &[u8], ctime: T)
487 -> Result<Self>
488 where
489 T: Into<Option<time::SystemTime>>
490 {
491 Ok(Key6 {
492 common: Key4::new(ctime.into().unwrap_or_else(crate::now),
493 PublicKeyAlgorithm::MLDSA87_Ed448,
494 mpi::PublicKey::MLDSA87_Ed448 {
495 eddsa: Box::new(eddsa.try_into()?),
496 mldsa: Box::new(mldsa.try_into()?),
497 })?,
498 })
499 }
500
501 pub fn import_public_slhdsa128s<T>(public: &[u8], ctime: T)
509 -> Result<Self>
510 where
511 T: Into<Option<time::SystemTime>>
512 {
513 Ok(Key6 {
514 common: Key4::new(ctime.into().unwrap_or_else(crate::now),
515 PublicKeyAlgorithm::SLHDSA128s,
516 mpi::PublicKey::SLHDSA128s {
517 public: public.try_into()?,
518 })?,
519 })
520 }
521
522 pub fn import_public_slhdsa128f<T>(public: &[u8], ctime: T)
530 -> Result<Self>
531 where
532 T: Into<Option<time::SystemTime>>
533 {
534 Ok(Key6 {
535 common: Key4::new(ctime.into().unwrap_or_else(crate::now),
536 PublicKeyAlgorithm::SLHDSA128f,
537 mpi::PublicKey::SLHDSA128f {
538 public: public.try_into()?,
539 })?,
540 })
541 }
542
543 pub fn import_public_slhdsa256s<T>(public: &[u8], ctime: T)
551 -> Result<Self>
552 where
553 T: Into<Option<time::SystemTime>>
554 {
555 Ok(Key6 {
556 common: Key4::new(ctime.into().unwrap_or_else(crate::now),
557 PublicKeyAlgorithm::SLHDSA256s,
558 mpi::PublicKey::SLHDSA256s {
559 public: Box::new(public.try_into()?),
560 })?,
561 })
562 }
563
564 pub fn import_public_mlkem768_x25519<T>(mlkem: &[u8], ecdh: &[u8], ctime: T)
576 -> Result<Self>
577 where
578 T: Into<Option<time::SystemTime>>
579 {
580 Ok(Key6 {
581 common: Key4::new(ctime.into().unwrap_or_else(crate::now),
582 PublicKeyAlgorithm::MLKEM768_X25519,
583 mpi::PublicKey::MLKEM768_X25519 {
584 ecdh: Box::new(ecdh.try_into()?),
585 mlkem: Box::new(mlkem.try_into()?),
586 })?,
587 })
588 }
589
590 pub fn import_public_mlkem1024_x448<T>(mlkem: &[u8], ecdh: &[u8], ctime: T)
602 -> Result<Self>
603 where
604 T: Into<Option<time::SystemTime>>
605 {
606 Ok(Key6 {
607 common: Key4::new(ctime.into().unwrap_or_else(crate::now),
608 PublicKeyAlgorithm::MLKEM1024_X448,
609 mpi::PublicKey::MLKEM1024_X448 {
610 ecdh: Box::new(ecdh.try_into()?),
611 mlkem: Box::new(mlkem.try_into()?),
612 })?,
613 })
614 }
615}
616
617impl<R> Key6<SecretParts, R>
618where R: KeyRole,
619{
620 pub fn with_secret<T>(creation_time: T, pk_algo: PublicKeyAlgorithm,
623 mpis: mpi::PublicKey,
624 secret: SecretKeyMaterial)
625 -> Result<Self>
626 where T: Into<time::SystemTime>
627 {
628 Ok(Key6 {
629 common: Key4::with_secret(creation_time, pk_algo, mpis, secret)?,
630 })
631 }
632
633 pub fn import_secret_x25519<T>(private_key: &[u8],
642 ctime: T)
643 -> Result<Self>
644 where
645 T: Into<Option<std::time::SystemTime>>,
646 {
647 use crate::crypto::backend::{Backend, interface::Asymmetric};
648
649 let private_key = Protected::from(private_key);
650 let public_key = Backend::x25519_derive_public(&private_key)?;
651
652 Self::with_secret(
653 ctime.into().unwrap_or_else(crate::now),
654 PublicKeyAlgorithm::X25519,
655 mpi::PublicKey::X25519 {
656 u: public_key,
657 },
658 mpi::SecretKeyMaterial::X25519 {
659 x: private_key.into(),
660 }.into())
661 }
662
663 pub fn import_secret_x448<T>(private_key: &[u8],
672 ctime: T)
673 -> Result<Self>
674 where
675 T: Into<Option<std::time::SystemTime>>,
676 {
677 use crate::crypto::backend::{Backend, interface::Asymmetric};
678
679 let private_key = Protected::from(private_key);
680 let public_key = Backend::x448_derive_public(&private_key)?;
681
682 Self::with_secret(
683 ctime.into().unwrap_or_else(crate::now),
684 PublicKeyAlgorithm::X448,
685 mpi::PublicKey::X448 {
686 u: Box::new(public_key),
687 },
688 mpi::SecretKeyMaterial::X448 {
689 x: private_key.into(),
690 }.into())
691 }
692
693 pub fn import_secret_ed25519<T>(private_key: &[u8], ctime: T)
699 -> Result<Self>
700 where
701 T: Into<Option<time::SystemTime>>,
702 {
703 use crate::crypto::backend::{Backend, interface::Asymmetric};
704
705 let private_key = Protected::from(private_key);
706 let public_key = Backend::ed25519_derive_public(&private_key)?;
707
708 Self::with_secret(
709 ctime.into().unwrap_or_else(crate::now),
710 PublicKeyAlgorithm::Ed25519,
711 mpi::PublicKey::Ed25519 {
712 a: public_key,
713 },
714 mpi::SecretKeyMaterial::Ed25519 {
715 x: private_key.into(),
716 }.into())
717 }
718
719 pub fn import_secret_ed448<T>(private_key: &[u8], ctime: T)
725 -> Result<Self>
726 where
727 T: Into<Option<time::SystemTime>>,
728 {
729 use crate::crypto::backend::{Backend, interface::Asymmetric};
730
731 let private_key = Protected::from(private_key);
732 let public_key = Backend::ed448_derive_public(&private_key)?;
733
734 Self::with_secret(
735 ctime.into().unwrap_or_else(crate::now),
736 PublicKeyAlgorithm::Ed448,
737 mpi::PublicKey::Ed448 {
738 a: Box::new(public_key),
739 },
740 mpi::SecretKeyMaterial::Ed448 {
741 x: private_key.into(),
742 }.into())
743 }
744
745 pub fn into_keypair(self) -> Result<KeyPair> {
753 let (key, secret) = self.take_secret();
754 let secret = match secret {
755 SecretKeyMaterial::Unencrypted(secret) => secret,
756 SecretKeyMaterial::Encrypted(_) =>
757 return Err(Error::InvalidArgument(
758 "secret key material is encrypted".into()).into()),
759 };
760
761 KeyPair::new(key.role_into_unspecified().into(), secret)
762 }
763}
764
765macro_rules! impl_common_secret_functions_v6 {
766 ($t: ident) => {
767 impl<R> Key6<$t, R>
769 where R: KeyRole,
770 {
771 pub fn take_secret(mut self)
773 -> (Key6<PublicParts, R>, Option<SecretKeyMaterial>)
774 {
775 let old = std::mem::replace(&mut self.common.secret, None);
776 (self.parts_into_public(), old)
777 }
778
779 pub fn add_secret(mut self, secret: SecretKeyMaterial)
782 -> (Key6<SecretParts, R>, Option<SecretKeyMaterial>)
783 {
784 let old = std::mem::replace(&mut self.common.secret, Some(secret));
785 (self.parts_into_secret().expect("secret just set"), old)
786 }
787
788 pub fn steal_secret(&mut self) -> Option<SecretKeyMaterial>
790 {
791 std::mem::replace(&mut self.common.secret, None)
792 }
793 }
794 }
795}
796impl_common_secret_functions_v6!(PublicParts);
797impl_common_secret_functions_v6!(UnspecifiedParts);
798
799impl<R> Key6<SecretParts, R>
801where R: KeyRole,
802{
803 pub fn secret(&self) -> &SecretKeyMaterial {
805 self.common.secret()
806 }
807
808 pub fn secret_mut(&mut self) -> &mut SecretKeyMaterial {
810 self.common.secret_mut()
811 }
812
813 pub fn take_secret(mut self)
815 -> (Key6<PublicParts, R>, SecretKeyMaterial)
816 {
817 let old = std::mem::replace(&mut self.common.secret, None);
818 (self.parts_into_public(),
819 old.expect("Key<SecretParts, _> has a secret key material"))
820 }
821
822 pub fn add_secret(mut self, secret: SecretKeyMaterial)
826 -> (Key6<SecretParts, R>, SecretKeyMaterial)
827 {
828 let old = std::mem::replace(&mut self.common.secret, Some(secret));
829 (self.parts_into_secret().expect("secret just set"),
830 old.expect("Key<SecretParts, _> has a secret key material"))
831 }
832
833 pub fn decrypt_secret(self, password: &Password) -> Result<Self> {
848 let (key, mut secret) = self.take_secret();
849 let key = Key::V6(key);
851 secret.decrypt_in_place(&key, password)?;
852 let key = if let Key::V6(k) = key { k } else { unreachable!() };
853 Ok(key.add_secret(secret).0)
854 }
855
856 pub fn encrypt_secret(self, password: &Password)
871 -> Result<Key6<SecretParts, R>>
872 {
873 let (key, mut secret) = self.take_secret();
874 let key = Key::V6(key);
876 secret.encrypt_in_place(&key, password)?;
877 let key = if let Key::V6(k) = key { k } else { unreachable!() };
878 Ok(key.add_secret(secret).0)
879 }
880}
881
882impl<P, R> From<Key6<P, R>> for super::Key<P, R>
883where P: KeyParts,
884 R: KeyRole,
885{
886 fn from(p: Key6<P, R>) -> Self {
887 super::Key::V6(p)
888 }
889}
890
891#[cfg(test)]
892use crate::packet::key::{
893 PrimaryRole,
894 SubordinateRole,
895 UnspecifiedRole,
896};
897
898#[cfg(test)]
899impl Arbitrary for Key6<PublicParts, PrimaryRole> {
900 fn arbitrary(g: &mut Gen) -> Self {
901 Key6::from_common(Key4::arbitrary(g))
902 }
903}
904
905#[cfg(test)]
906impl Arbitrary for Key6<PublicParts, SubordinateRole> {
907 fn arbitrary(g: &mut Gen) -> Self {
908 Key6::from_common(Key4::arbitrary(g))
909 }
910}
911
912#[cfg(test)]
913impl Arbitrary for Key6<PublicParts, UnspecifiedRole> {
914 fn arbitrary(g: &mut Gen) -> Self {
915 Key6::from_common(Key4::arbitrary(g))
916 }
917}
918
919#[cfg(test)]
920impl Arbitrary for Key6<SecretParts, PrimaryRole> {
921 fn arbitrary(g: &mut Gen) -> Self {
922 Key6::from_common(Key4::arbitrary(g))
923 }
924}
925
926#[cfg(test)]
927impl Arbitrary for Key6<SecretParts, SubordinateRole> {
928 fn arbitrary(g: &mut Gen) -> Self {
929 Key6::from_common(Key4::arbitrary(g))
930 }
931}
932
933
934#[cfg(test)]
935mod tests {
936 use std::time::Duration;
937 use std::time::UNIX_EPOCH;
938
939 use crate::crypto::S2K;
940 use crate::packet::Key;
941 use crate::packet::key;
942 use crate::packet::Packet;
943 use super::*;
944 use crate::PacketPile;
945 use crate::serialize::Serialize;
946 use crate::types::*;
947 use crate::parse::Parse;
948
949 #[test]
950 fn primary_key_encrypt_decrypt() -> Result<()> {
951 key_encrypt_decrypt::<PrimaryRole>()
952 }
953
954 #[test]
955 fn subkey_encrypt_decrypt() -> Result<()> {
956 key_encrypt_decrypt::<SubordinateRole>()
957 }
958
959 fn key_encrypt_decrypt<R>() -> Result<()>
960 where
961 R: KeyRole + PartialEq,
962 {
963 let mut g = quickcheck::Gen::new(256);
964 let p: Password = Vec::<u8>::arbitrary(&mut g).into();
965
966 let check = |key: Key6<SecretParts, R>| -> Result<()> {
967 let key: Key<_, _> = key.into();
968 let encrypted = key.clone().encrypt_secret(&p)?;
969 let decrypted = encrypted.decrypt_secret(&p)?;
970 assert_eq!(key, decrypted);
971 Ok(())
972 };
973
974 use crate::types::Curve::*;
975 for curve in vec![NistP256, NistP384, NistP521, Ed25519] {
976 if ! curve.is_supported() {
977 eprintln!("Skipping unsupported {}", curve);
978 continue;
979 }
980
981 let key: Key6<_, R>
982 = Key6::generate_ecc(true, curve.clone())?;
983 check(key)?;
984 }
985
986 for bits in vec![2048, 3072] {
987 if ! PublicKeyAlgorithm::RSAEncryptSign.is_supported() {
988 eprintln!("Skipping unsupported RSA");
989 continue;
990 }
991
992 let key: Key6<_, R>
993 = Key6::generate_rsa(bits)?;
994 check(key)?;
995 }
996
997 Ok(())
998 }
999
1000 #[test]
1001 fn eq() {
1002 use crate::types::Curve::*;
1003
1004 for curve in vec![NistP256, NistP384, NistP521] {
1005 if ! curve.is_supported() {
1006 eprintln!("Skipping unsupported {}", curve);
1007 continue;
1008 }
1009
1010 let sign_key : Key6<_, key::UnspecifiedRole>
1011 = Key6::generate_ecc(true, curve.clone()).unwrap();
1012 let enc_key : Key6<_, key::UnspecifiedRole>
1013 = Key6::generate_ecc(false, curve).unwrap();
1014 let sign_clone = sign_key.clone();
1015 let enc_clone = enc_key.clone();
1016
1017 assert_eq!(sign_key, sign_clone);
1018 assert_eq!(enc_key, enc_clone);
1019 }
1020
1021 for bits in vec![1024, 2048, 3072, 4096] {
1022 if ! PublicKeyAlgorithm::RSAEncryptSign.is_supported() {
1023 eprintln!("Skipping unsupported RSA");
1024 continue;
1025 }
1026
1027 let key : Key6<_, key::UnspecifiedRole>
1028 = Key6::generate_rsa(bits).unwrap();
1029 let clone = key.clone();
1030 assert_eq!(key, clone);
1031 }
1032 }
1033
1034 #[test]
1035 fn generate_roundtrip() {
1036 use crate::types::Curve::*;
1037
1038 let keys = vec![NistP256, NistP384, NistP521].into_iter().flat_map(|cv|
1039 {
1040 if ! cv.is_supported() {
1041 eprintln!("Skipping unsupported {}", cv);
1042 return Vec::new();
1043 }
1044
1045 let sign_key : Key6<key::SecretParts, key::PrimaryRole>
1046 = Key6::generate_ecc(true, cv.clone()).unwrap();
1047 let enc_key = Key6::generate_ecc(false, cv).unwrap();
1048
1049 vec![sign_key, enc_key]
1050 }).chain(vec![1024, 2048, 3072, 4096].into_iter().filter_map(|b| {
1051 Key6::generate_rsa(b).ok()
1052 }));
1053
1054 for key in keys {
1055 let mut b = Vec::new();
1056 Packet::SecretKey(key.clone().into()).serialize(&mut b).unwrap();
1057
1058 let pp = PacketPile::from_bytes(&b).unwrap();
1059 if let Some(Packet::SecretKey(Key::V6(ref parsed_key))) =
1060 pp.path_ref(&[0])
1061 {
1062 assert_eq!(key.creation_time(), parsed_key.creation_time());
1063 assert_eq!(key.pk_algo(), parsed_key.pk_algo());
1064 assert_eq!(key.mpis(), parsed_key.mpis());
1065 assert_eq!(key.secret(), parsed_key.secret());
1066
1067 assert_eq!(&key, parsed_key);
1068 } else {
1069 panic!("bad packet: {:?}", pp.path_ref(&[0]));
1070 }
1071
1072 let mut b = Vec::new();
1073 let pk4 : Key6<PublicParts, PrimaryRole> = key.clone().into();
1074 Packet::PublicKey(pk4.into()).serialize(&mut b).unwrap();
1075
1076 let pp = PacketPile::from_bytes(&b).unwrap();
1077 if let Some(Packet::PublicKey(Key::V6(ref parsed_key))) =
1078 pp.path_ref(&[0])
1079 {
1080 assert!(! parsed_key.has_secret());
1081
1082 let key = key.take_secret().0;
1083 assert_eq!(&key, parsed_key);
1084 } else {
1085 panic!("bad packet: {:?}", pp.path_ref(&[0]));
1086 }
1087 }
1088 }
1089
1090 #[test]
1091 fn encryption_roundtrip() {
1092 use crate::crypto::SessionKey;
1093 use crate::types::Curve::*;
1094
1095 let keys = vec![NistP256, NistP384, NistP521].into_iter()
1096 .filter_map(|cv| {
1097 Key6::generate_ecc(false, cv).ok()
1098 }).chain(vec![1024, 2048, 3072, 4096].into_iter().filter_map(|b| {
1099 Key6::generate_rsa(b).ok()
1100 })).chain([
1101 (PublicKeyAlgorithm::MLKEM768_X25519, Key6::generate_mlkem768_x25519 as fn() -> Result<_>),
1102 (PublicKeyAlgorithm::MLKEM1024_X448, Key6::generate_mlkem1024_x448),
1103 ].into_iter().filter_map(|(algo, gen)| {
1104 if algo.is_supported() {
1105 Some(gen().expect(&format!("{} is supported", algo)))
1106 } else {
1107 None
1108 }
1109 }));
1110
1111 for key in keys.into_iter() {
1112 let key: Key<key::SecretParts, key::UnspecifiedRole> = key.into();
1113 let mut keypair = key.clone().into_keypair().unwrap();
1114 let cipher = SymmetricAlgorithm::AES256;
1115 let sk = SessionKey::new(cipher.key_size().unwrap()).unwrap();
1116
1117 let pkesk = PKESK6::for_recipient(&sk, &key).unwrap();
1118 let sk_ = pkesk.decrypt(&mut keypair, None)
1119 .expect("keypair should be able to decrypt PKESK");
1120 assert_eq!(sk, sk_);
1121
1122 let sk_ =
1123 pkesk.decrypt(&mut keypair, Some(cipher)).unwrap();
1124 assert_eq!(sk, sk_);
1125 }
1126 }
1127
1128 #[test]
1129 fn signature_roundtrip() {
1130 use crate::types::{Curve::*, SignatureType};
1131
1132 let keys = vec![NistP256, NistP384, NistP521].into_iter()
1133 .filter_map(|cv| {
1134 Key6::generate_ecc(true, cv).ok()
1135 }).chain(vec![1024, 2048, 3072, 4096].into_iter().filter_map(|b| {
1136 Key6::generate_rsa(b).ok()
1137 })).chain([
1138 (PublicKeyAlgorithm::MLDSA65_Ed25519, Key6::generate_mldsa65_ed25519 as fn() -> Result<_>),
1139 (PublicKeyAlgorithm::MLDSA87_Ed448, Key6::generate_mldsa87_ed448),
1140 (PublicKeyAlgorithm::SLHDSA128s, Key6::generate_slhdsa128s),
1141 (PublicKeyAlgorithm::SLHDSA128f, Key6::generate_slhdsa128f),
1142 (PublicKeyAlgorithm::SLHDSA256s, Key6::generate_slhdsa256s),
1143 ].into_iter().filter_map(|(algo, gen)| {
1144 if algo.is_supported() {
1145 Some(gen().expect(&format!("{} is supported", algo)))
1146 } else {
1147 None
1148 }
1149 }));
1150
1151 for key in keys.into_iter() {
1152 let key: Key<key::SecretParts, key::UnspecifiedRole> = key.into();
1153 let mut keypair = key.clone().into_keypair().unwrap();
1154 let hash = HashAlgorithm::default();
1155
1156 let ctx = hash.context().unwrap().for_signature(key.version());
1158 let sig = SignatureBuilder::new(SignatureType::Binary)
1159 .sign_hash(&mut keypair, ctx).unwrap();
1160
1161 let ctx = hash.context().unwrap().for_signature(key.version());
1163 sig.verify_hash(&key, ctx).unwrap();
1164 }
1165 }
1166
1167 #[test]
1168 fn secret_encryption_roundtrip() {
1169 use crate::types::Curve::*;
1170 use crate::types::SymmetricAlgorithm::*;
1171 use crate::types::AEADAlgorithm::*;
1172
1173 let keys = vec![NistP256, NistP384, NistP521].into_iter()
1174 .filter_map(|cv| -> Option<Key<key::SecretParts, key::PrimaryRole>> {
1175 Key6::generate_ecc(false, cv).map(Into::into).ok()
1176 }).chain(vec![1024, 2048, 3072, 4096].into_iter().filter_map(|b| {
1177 Key6::generate_rsa(b).map(Into::into).ok()
1178 }));
1179
1180 for key in keys {
1181 for (symm, aead) in [(AES128, None),
1182 (AES128, Some(OCB)),
1183 (AES256, Some(EAX))] {
1184 if ! aead.map(|a| a.is_supported()).unwrap_or(true) {
1185 continue;
1186 }
1187 assert!(! key.secret().is_encrypted());
1188
1189 let password = Password::from("foobarbaz");
1190 let mut encrypted_key = key.clone();
1191
1192 encrypted_key.secret_mut()
1193 .encrypt_in_place_with(&key, S2K::default(), symm, aead,
1194 &password).unwrap();
1195 assert!(encrypted_key.secret().is_encrypted());
1196
1197 encrypted_key.secret_mut()
1198 .decrypt_in_place(&key, &password).unwrap();
1199 assert!(! key.secret().is_encrypted());
1200 assert_eq!(key, encrypted_key);
1201 assert_eq!(key.secret(), encrypted_key.secret());
1202 }
1203 }
1204 }
1205
1206 #[test]
1207 fn encrypt_huge_plaintext() -> Result<()> {
1208 let sk = crate::crypto::SessionKey::new(256).unwrap();
1209
1210 if PublicKeyAlgorithm::RSAEncryptSign.is_supported() {
1211 let rsa2k: Key<SecretParts, UnspecifiedRole> =
1212 Key6::generate_rsa(2048)?.into();
1213 assert!(matches!(
1214 rsa2k.encrypt(&sk).unwrap_err().downcast().unwrap(),
1215 crate::Error::InvalidArgument(_)
1216 ));
1217 }
1218
1219 Ok(())
1220 }
1221
1222 #[test]
1223 fn issue_1016() {
1224 let mut g = quickcheck::Gen::new(256);
1229
1230 let mut key = Key6::<PublicParts, UnspecifiedRole>::arbitrary(&mut g);
1231 let fpr1 = key.fingerprint();
1232 if key.creation_time() == UNIX_EPOCH {
1233 key.set_creation_time(UNIX_EPOCH + Duration::new(1, 0)).expect("ok");
1234 } else {
1235 key.set_creation_time(UNIX_EPOCH).expect("ok");
1236 }
1237 assert_ne!(fpr1, key.fingerprint());
1238
1239 let mut key = Key6::<PublicParts, UnspecifiedRole>::arbitrary(&mut g);
1240 let fpr1 = key.fingerprint();
1241 key.set_pk_algo(PublicKeyAlgorithm::from(u8::from(key.pk_algo()) + 1));
1242 assert_ne!(fpr1, key.fingerprint());
1243
1244 let mut key = Key6::<PublicParts, UnspecifiedRole>::arbitrary(&mut g);
1245 let fpr1 = key.fingerprint();
1246 loop {
1247 let mpis2 = mpi::PublicKey::arbitrary(&mut g);
1248 if key.mpis() != &mpis2 {
1249 *key.mpis_mut() = mpis2;
1250 break;
1251 }
1252 }
1253 assert_ne!(fpr1, key.fingerprint());
1254
1255 let mut key = Key6::<PublicParts, UnspecifiedRole>::arbitrary(&mut g);
1256 let fpr1 = key.fingerprint();
1257 loop {
1258 let mpis2 = mpi::PublicKey::arbitrary(&mut g);
1259 if key.mpis() != &mpis2 {
1260 key.set_mpis(mpis2);
1261 break;
1262 }
1263 }
1264 assert_ne!(fpr1, key.fingerprint());
1265 }
1266
1267 #[test]
1270 fn ecc_support() -> Result<()> {
1271 for for_signing in [true, false] {
1272 for curve in Curve::variants()
1273 .filter(Curve::is_supported)
1274 {
1275 match curve {
1276 Curve::Cv25519 if for_signing => continue,
1277 Curve::Ed25519 if ! for_signing => continue,
1278 _ => (),
1279 }
1280
1281 eprintln!("curve {}, for signing {:?}", curve, for_signing);
1282 let key: Key<SecretParts, UnspecifiedRole> =
1283 Key6::generate_ecc(for_signing, curve.clone())?.into();
1284 let mut pair = key.into_keypair()?;
1285
1286 if for_signing {
1287 use crate::crypto::Signer;
1288 let hash = HashAlgorithm::default();
1289 let digest = hash.context()?
1290 .for_signature(pair.public().version())
1291 .into_digest()?;
1292 let sig = pair.sign(hash, &digest)?;
1293 pair.public().verify(&sig, hash, &digest)?;
1294 } else {
1295 use crate::crypto::{SessionKey, Decryptor};
1296 let sk = SessionKey::new(32).unwrap();
1297 let ciphertext = pair.public().encrypt(&sk)?;
1298 assert_eq!(pair.decrypt(&ciphertext, Some(sk.len()))?, sk);
1299 }
1300 }
1301 }
1302 Ok(())
1303 }
1304
1305 #[test]
1306 fn ecc_encoding() -> Result<()> {
1307 for for_signing in [true, false] {
1308 for curve in Curve::variants()
1309 .filter(Curve::is_supported)
1310 {
1311 match curve {
1312 Curve::Cv25519 if for_signing => continue,
1313 Curve::Ed25519 if ! for_signing => continue,
1314 _ => (),
1315 }
1316
1317 use crate::crypto::mpi::{Ciphertext, MPI, PublicKey};
1318 eprintln!("curve {}, for signing {:?}", curve, for_signing);
1319
1320 let key: Key<SecretParts, UnspecifiedRole> =
1321 Key6::generate_ecc(for_signing, curve.clone())?.into();
1322
1323 let uncompressed = |mpi: &MPI| mpi.value()[0] == 0x04;
1324
1325 match key.mpis() {
1326 PublicKey::X25519 { .. } if ! for_signing => (),
1327 PublicKey::X448 { .. } if ! for_signing => (),
1328 PublicKey::Ed25519 { .. } if for_signing => (),
1329 PublicKey::Ed448 { .. } if for_signing => (),
1330 PublicKey::ECDSA { curve: c, q } if for_signing => {
1331 assert!(c == &curve);
1332 assert!(c != &Curve::Ed25519);
1333 assert!(uncompressed(q));
1334 },
1335 PublicKey::ECDH { curve: c, q, .. } if ! for_signing => {
1336 assert!(c == &curve);
1337 assert!(c != &Curve::Cv25519);
1338 assert!(uncompressed(q));
1339
1340 use crate::crypto::SessionKey;
1341 let sk = SessionKey::new(32).unwrap();
1342 let ciphertext = key.encrypt(&sk)?;
1343 if let Ciphertext::ECDH { e, .. } = &ciphertext {
1344 assert!(uncompressed(e));
1345 } else {
1346 panic!("unexpected ciphertext: {:?}", ciphertext);
1347 }
1348 },
1349 mpi => unreachable!(
1350 "curve {}, mpi {:?}, for signing {:?}",
1351 curve, mpi, for_signing),
1352 }
1353 }
1354 }
1355 Ok(())
1356 }
1357
1358
1359 #[test]
1360 fn v6_key_fingerprint() -> Result<()> {
1361 let p = Packet::from_bytes("-----BEGIN PGP ARMORED FILE-----
1362
1363xjcGY4d/4xYAAAAtCSsGAQQB2kcPAQEHQPlNp7tI1gph5WdwamWH0DMZmbudiRoI
1364JC6thFQ9+JWj
1365=SgmS
1366-----END PGP ARMORED FILE-----")?;
1367 let k: &Key<PublicParts, PrimaryRole> = p.downcast_ref().unwrap();
1368 assert_eq!(k.fingerprint().to_string(),
1369 "4EADF309C6BC874AE04702451548F93F\
1370 96FA7A01D0A33B5AF7D4E379E0F9F8EE".to_string());
1371 Ok(())
1372 }
1373
1374 #[test]
1375 fn import_public_mldsa() -> Result<()> {
1376 if PublicKeyAlgorithm::MLDSA65_Ed25519.is_supported() {
1377 let key: Key6<SecretParts, UnspecifiedRole>
1378 = Key6::generate_mldsa65_ed25519()
1379 .expect("failed to generate MLDSA65 key, but it is supported.");
1380
1381 assert_eq!(key.pk_algo(), PublicKeyAlgorithm::MLDSA65_Ed25519);
1382 let creation_time = key.creation_time();
1383 let mpis = key.mpis();
1384 let crate::crypto::mpi::PublicKey::MLDSA65_Ed25519 {
1385 eddsa,
1386 mldsa,
1387 } = &mpis else {
1388 panic!("Key generate generated the wrong key");
1389 };
1390
1391 let imported_key = Key6::import_public_mldsa65_ed25519(
1392 &mldsa[..], &eddsa[..], creation_time)
1393 .expect("Can import key");
1394
1395 assert_eq!(key.parts_into_public(), imported_key);
1396 }
1397
1398 if PublicKeyAlgorithm::MLDSA87_Ed448.is_supported() {
1399 let key: Key6<SecretParts, UnspecifiedRole>
1400 = Key6::generate_mldsa87_ed448()
1401 .expect("failed to generate MLDSA87 key, but it is supported.");
1402
1403 assert_eq!(key.pk_algo(), PublicKeyAlgorithm::MLDSA87_Ed448);
1404 let creation_time = key.creation_time();
1405 let mpis = key.mpis();
1406 let crate::crypto::mpi::PublicKey::MLDSA87_Ed448 {
1407 eddsa,
1408 mldsa,
1409 } = &mpis else {
1410 panic!("Key generate generated the wrong key");
1411 };
1412
1413 let imported_key = Key6::import_public_mldsa87_ed448(
1414 &mldsa[..], &eddsa[..], creation_time)
1415 .expect("Can import key");
1416
1417 assert_eq!(key.parts_into_public(), imported_key);
1418 }
1419
1420 Ok(())
1421 }
1422
1423
1424 #[test]
1425 fn import_public_slhdsa() -> Result<()> {
1426 if PublicKeyAlgorithm::SLHDSA128s.is_supported() {
1427 let key: Key6<SecretParts, UnspecifiedRole>
1428 = Key6::generate_slhdsa128s()
1429 .expect("failed to generate SLHDSA128s key, but it is supported.");
1430
1431 assert_eq!(key.pk_algo(), PublicKeyAlgorithm::SLHDSA128s);
1432 let creation_time = key.creation_time();
1433 let mpis = key.mpis();
1434 let crate::crypto::mpi::PublicKey::SLHDSA128s {
1435 public,
1436 } = &mpis else {
1437 panic!("Key generate generated the wrong key");
1438 };
1439
1440 let imported_key = Key6::import_public_slhdsa128s(
1441 &public[..], creation_time)
1442 .expect("Can import key");
1443
1444 assert_eq!(key.parts_into_public(), imported_key);
1445 }
1446
1447 if PublicKeyAlgorithm::SLHDSA128f.is_supported() {
1448 let key: Key6<SecretParts, UnspecifiedRole>
1449 = Key6::generate_slhdsa128f()
1450 .expect("failed to generate SLHDSA128f key, but it is supported.");
1451
1452 assert_eq!(key.pk_algo(), PublicKeyAlgorithm::SLHDSA128f);
1453 let creation_time = key.creation_time();
1454 let mpis = key.mpis();
1455 let crate::crypto::mpi::PublicKey::SLHDSA128f {
1456 public,
1457 } = &mpis else {
1458 panic!("Key generate generated the wrong key");
1459 };
1460
1461 let imported_key = Key6::import_public_slhdsa128f(
1462 &public[..], creation_time)
1463 .expect("Can import key");
1464
1465 assert_eq!(key.parts_into_public(), imported_key);
1466 }
1467
1468 if PublicKeyAlgorithm::SLHDSA256s.is_supported() {
1469 let key: Key6<SecretParts, UnspecifiedRole>
1470 = Key6::generate_slhdsa256s()
1471 .expect("failed to generate SLHDSA256s key, but it is supported.");
1472
1473 assert_eq!(key.pk_algo(), PublicKeyAlgorithm::SLHDSA256s);
1474 let creation_time = key.creation_time();
1475 let mpis = key.mpis();
1476 let crate::crypto::mpi::PublicKey::SLHDSA256s {
1477 public,
1478 } = &mpis else {
1479 panic!("Key generate generated the wrong key");
1480 };
1481
1482 let imported_key = Key6::import_public_slhdsa256s(
1483 &public[..], creation_time)
1484 .expect("Can import key");
1485
1486 assert_eq!(key.parts_into_public(), imported_key);
1487 }
1488
1489 Ok(())
1490 }
1491
1492 #[test]
1493 fn import_public_mlkem() -> Result<()> {
1494 if PublicKeyAlgorithm::MLKEM768_X25519.is_supported() {
1495 let key: Key6<SecretParts, UnspecifiedRole>
1496 = Key6::generate_mlkem768_x25519()
1497 .expect("failed to generate ML-KEM768 key, but it is supported.");
1498
1499 assert_eq!(key.pk_algo(), PublicKeyAlgorithm::MLKEM768_X25519);
1500 let creation_time = key.creation_time();
1501 let mpis = key.mpis();
1502 let crate::crypto::mpi::PublicKey::MLKEM768_X25519 {
1503 ecdh,
1504 mlkem,
1505 } = &mpis else {
1506 panic!("Key generate generated the wrong key");
1507 };
1508
1509 let imported_key = Key6::import_public_mlkem768_x25519(
1510 &mlkem[..], &ecdh[..], creation_time)
1511 .expect("Can import key");
1512
1513 assert_eq!(key.parts_into_public(), imported_key);
1514 }
1515
1516 if PublicKeyAlgorithm::MLKEM1024_X448.is_supported() {
1517 let key: Key6<SecretParts, UnspecifiedRole>
1518 = Key6::generate_mlkem1024_x448()
1519 .expect("failed to generate ML-KEM1024 key, but it is supported.");
1520
1521 assert_eq!(key.pk_algo(), PublicKeyAlgorithm::MLKEM1024_X448);
1522 let creation_time = key.creation_time();
1523 let mpis = key.mpis();
1524 let crate::crypto::mpi::PublicKey::MLKEM1024_X448 {
1525 ecdh,
1526 mlkem,
1527 } = &mpis else {
1528 panic!("Key generate generated the wrong key");
1529 };
1530
1531 let imported_key = Key6::import_public_mlkem1024_x448(
1532 &mlkem[..], &ecdh[..], creation_time)
1533 .expect("Can import key");
1534
1535 assert_eq!(key.parts_into_public(), imported_key);
1536 }
1537
1538 Ok(())
1539 }
1540}