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)
513 -> Result<Self>
514 where
515 T: Into<Option<time::SystemTime>>
516 {
517 Ok(Key6 {
518 common: Key4::new(ctime.into().unwrap_or_else(crate::now),
519 PublicKeyAlgorithm::SLHDSA128s,
520 mpi::PublicKey::SLHDSA128s {
521 public: public.try_into()?,
522 })?,
523 })
524 }
525
526 pub fn import_public_slhdsa128f<T>(public: &[u8], ctime: T)
538 -> Result<Self>
539 where
540 T: Into<Option<time::SystemTime>>
541 {
542 Ok(Key6 {
543 common: Key4::new(ctime.into().unwrap_or_else(crate::now),
544 PublicKeyAlgorithm::SLHDSA128f,
545 mpi::PublicKey::SLHDSA128f {
546 public: public.try_into()?,
547 })?,
548 })
549 }
550
551 pub fn import_public_slhdsa256s<T>(public: &[u8], ctime: T)
563 -> Result<Self>
564 where
565 T: Into<Option<time::SystemTime>>
566 {
567 Ok(Key6 {
568 common: Key4::new(ctime.into().unwrap_or_else(crate::now),
569 PublicKeyAlgorithm::SLHDSA256s,
570 mpi::PublicKey::SLHDSA256s {
571 public: Box::new(public.try_into()?),
572 })?,
573 })
574 }
575
576 pub fn import_public_mlkem768_x25519<T>(mlkem: &[u8], ecdh: &[u8], ctime: T)
588 -> Result<Self>
589 where
590 T: Into<Option<time::SystemTime>>
591 {
592 Ok(Key6 {
593 common: Key4::new(ctime.into().unwrap_or_else(crate::now),
594 PublicKeyAlgorithm::MLKEM768_X25519,
595 mpi::PublicKey::MLKEM768_X25519 {
596 ecdh: Box::new(ecdh.try_into()?),
597 mlkem: Box::new(mlkem.try_into()?),
598 })?,
599 })
600 }
601
602 pub fn import_public_mlkem1024_x448<T>(mlkem: &[u8], ecdh: &[u8], ctime: T)
614 -> Result<Self>
615 where
616 T: Into<Option<time::SystemTime>>
617 {
618 Ok(Key6 {
619 common: Key4::new(ctime.into().unwrap_or_else(crate::now),
620 PublicKeyAlgorithm::MLKEM1024_X448,
621 mpi::PublicKey::MLKEM1024_X448 {
622 ecdh: Box::new(ecdh.try_into()?),
623 mlkem: Box::new(mlkem.try_into()?),
624 })?,
625 })
626 }
627}
628
629impl<R> Key6<SecretParts, R>
630where R: KeyRole,
631{
632 pub fn with_secret<T>(creation_time: T, pk_algo: PublicKeyAlgorithm,
635 mpis: mpi::PublicKey,
636 secret: SecretKeyMaterial)
637 -> Result<Self>
638 where T: Into<time::SystemTime>
639 {
640 Ok(Key6 {
641 common: Key4::with_secret(creation_time, pk_algo, mpis, secret)?,
642 })
643 }
644
645 pub fn import_secret_x25519<T>(private_key: &[u8],
654 ctime: T)
655 -> Result<Self>
656 where
657 T: Into<Option<std::time::SystemTime>>,
658 {
659 use crate::crypto::backend::{Backend, interface::Asymmetric};
660
661 let private_key = Protected::from(private_key);
662 let public_key = Backend::x25519_derive_public(&private_key)?;
663
664 Self::with_secret(
665 ctime.into().unwrap_or_else(crate::now),
666 PublicKeyAlgorithm::X25519,
667 mpi::PublicKey::X25519 {
668 u: public_key,
669 },
670 mpi::SecretKeyMaterial::X25519 {
671 x: private_key.into(),
672 }.into())
673 }
674
675 pub fn import_secret_x448<T>(private_key: &[u8],
684 ctime: T)
685 -> Result<Self>
686 where
687 T: Into<Option<std::time::SystemTime>>,
688 {
689 use crate::crypto::backend::{Backend, interface::Asymmetric};
690
691 let private_key = Protected::from(private_key);
692 let public_key = Backend::x448_derive_public(&private_key)?;
693
694 Self::with_secret(
695 ctime.into().unwrap_or_else(crate::now),
696 PublicKeyAlgorithm::X448,
697 mpi::PublicKey::X448 {
698 u: Box::new(public_key),
699 },
700 mpi::SecretKeyMaterial::X448 {
701 x: private_key.into(),
702 }.into())
703 }
704
705 pub fn import_secret_ed25519<T>(private_key: &[u8], ctime: T)
711 -> Result<Self>
712 where
713 T: Into<Option<time::SystemTime>>,
714 {
715 use crate::crypto::backend::{Backend, interface::Asymmetric};
716
717 let private_key = Protected::from(private_key);
718 let public_key = Backend::ed25519_derive_public(&private_key)?;
719
720 Self::with_secret(
721 ctime.into().unwrap_or_else(crate::now),
722 PublicKeyAlgorithm::Ed25519,
723 mpi::PublicKey::Ed25519 {
724 a: public_key,
725 },
726 mpi::SecretKeyMaterial::Ed25519 {
727 x: private_key.into(),
728 }.into())
729 }
730
731 pub fn import_secret_ed448<T>(private_key: &[u8], ctime: T)
737 -> Result<Self>
738 where
739 T: Into<Option<time::SystemTime>>,
740 {
741 use crate::crypto::backend::{Backend, interface::Asymmetric};
742
743 let private_key = Protected::from(private_key);
744 let public_key = Backend::ed448_derive_public(&private_key)?;
745
746 Self::with_secret(
747 ctime.into().unwrap_or_else(crate::now),
748 PublicKeyAlgorithm::Ed448,
749 mpi::PublicKey::Ed448 {
750 a: Box::new(public_key),
751 },
752 mpi::SecretKeyMaterial::Ed448 {
753 x: private_key.into(),
754 }.into())
755 }
756
757 pub fn into_keypair(self) -> Result<KeyPair> {
765 let (key, secret) = self.take_secret();
766 let secret = match secret {
767 SecretKeyMaterial::Unencrypted(secret) => secret,
768 SecretKeyMaterial::Encrypted(_) =>
769 return Err(Error::InvalidArgument(
770 "secret key material is encrypted".into()).into()),
771 };
772
773 KeyPair::new(key.role_into_unspecified().into(), secret)
774 }
775}
776
777macro_rules! impl_common_secret_functions_v6 {
778 ($t: ident) => {
779 impl<R> Key6<$t, R>
781 where R: KeyRole,
782 {
783 pub fn take_secret(mut self)
785 -> (Key6<PublicParts, R>, Option<SecretKeyMaterial>)
786 {
787 let old = std::mem::replace(&mut self.common.secret, None);
788 (self.parts_into_public(), old)
789 }
790
791 pub fn add_secret(mut self, secret: SecretKeyMaterial)
794 -> (Key6<SecretParts, R>, Option<SecretKeyMaterial>)
795 {
796 let old = std::mem::replace(&mut self.common.secret, Some(secret));
797 (self.parts_into_secret().expect("secret just set"), old)
798 }
799
800 pub fn steal_secret(&mut self) -> Option<SecretKeyMaterial>
802 {
803 std::mem::replace(&mut self.common.secret, None)
804 }
805 }
806 }
807}
808impl_common_secret_functions_v6!(PublicParts);
809impl_common_secret_functions_v6!(UnspecifiedParts);
810
811impl<R> Key6<SecretParts, R>
813where R: KeyRole,
814{
815 pub fn secret(&self) -> &SecretKeyMaterial {
817 self.common.secret()
818 }
819
820 pub fn secret_mut(&mut self) -> &mut SecretKeyMaterial {
822 self.common.secret_mut()
823 }
824
825 pub fn take_secret(mut self)
827 -> (Key6<PublicParts, R>, SecretKeyMaterial)
828 {
829 let old = std::mem::replace(&mut self.common.secret, None);
830 (self.parts_into_public(),
831 old.expect("Key<SecretParts, _> has a secret key material"))
832 }
833
834 pub fn add_secret(mut self, secret: SecretKeyMaterial)
838 -> (Key6<SecretParts, R>, SecretKeyMaterial)
839 {
840 let old = std::mem::replace(&mut self.common.secret, Some(secret));
841 (self.parts_into_secret().expect("secret just set"),
842 old.expect("Key<SecretParts, _> has a secret key material"))
843 }
844
845 pub fn decrypt_secret(self, password: &Password) -> Result<Self> {
860 let (key, mut secret) = self.take_secret();
861 let key = Key::V6(key);
863 secret.decrypt_in_place(&key, password)?;
864 let key = if let Key::V6(k) = key { k } else { unreachable!() };
865 Ok(key.add_secret(secret).0)
866 }
867
868 pub fn encrypt_secret(self, password: &Password)
883 -> Result<Key6<SecretParts, R>>
884 {
885 let (key, mut secret) = self.take_secret();
886 let key = Key::V6(key);
888 secret.encrypt_in_place(&key, password)?;
889 let key = if let Key::V6(k) = key { k } else { unreachable!() };
890 Ok(key.add_secret(secret).0)
891 }
892}
893
894impl<P, R> From<Key6<P, R>> for super::Key<P, R>
895where P: KeyParts,
896 R: KeyRole,
897{
898 fn from(p: Key6<P, R>) -> Self {
899 super::Key::V6(p)
900 }
901}
902
903#[cfg(test)]
904use crate::packet::key::{
905 PrimaryRole,
906 SubordinateRole,
907 UnspecifiedRole,
908};
909
910#[cfg(test)]
911impl Arbitrary for Key6<PublicParts, PrimaryRole> {
912 fn arbitrary(g: &mut Gen) -> Self {
913 Key6::from_common(Key4::arbitrary(g))
914 }
915}
916
917#[cfg(test)]
918impl Arbitrary for Key6<PublicParts, SubordinateRole> {
919 fn arbitrary(g: &mut Gen) -> Self {
920 Key6::from_common(Key4::arbitrary(g))
921 }
922}
923
924#[cfg(test)]
925impl Arbitrary for Key6<PublicParts, UnspecifiedRole> {
926 fn arbitrary(g: &mut Gen) -> Self {
927 Key6::from_common(Key4::arbitrary(g))
928 }
929}
930
931#[cfg(test)]
932impl Arbitrary for Key6<SecretParts, PrimaryRole> {
933 fn arbitrary(g: &mut Gen) -> Self {
934 Key6::from_common(Key4::arbitrary(g))
935 }
936}
937
938#[cfg(test)]
939impl Arbitrary for Key6<SecretParts, SubordinateRole> {
940 fn arbitrary(g: &mut Gen) -> Self {
941 Key6::from_common(Key4::arbitrary(g))
942 }
943}
944
945
946#[cfg(test)]
947mod tests {
948 use std::time::Duration;
949 use std::time::UNIX_EPOCH;
950
951 use crate::crypto::S2K;
952 use crate::packet::Key;
953 use crate::packet::key;
954 use crate::packet::Packet;
955 use super::*;
956 use crate::PacketPile;
957 use crate::serialize::Serialize;
958 use crate::types::*;
959 use crate::parse::Parse;
960
961 #[test]
962 fn primary_key_encrypt_decrypt() -> Result<()> {
963 key_encrypt_decrypt::<PrimaryRole>()
964 }
965
966 #[test]
967 fn subkey_encrypt_decrypt() -> Result<()> {
968 key_encrypt_decrypt::<SubordinateRole>()
969 }
970
971 fn key_encrypt_decrypt<R>() -> Result<()>
972 where
973 R: KeyRole + PartialEq,
974 {
975 let mut g = quickcheck::Gen::new(256);
976 let p: Password = Vec::<u8>::arbitrary(&mut g).into();
977
978 let check = |key: Key6<SecretParts, R>| -> Result<()> {
979 let key: Key<_, _> = key.into();
980 let encrypted = key.clone().encrypt_secret(&p)?;
981 let decrypted = encrypted.decrypt_secret(&p)?;
982 assert_eq!(key, decrypted);
983 Ok(())
984 };
985
986 use crate::types::Curve::*;
987 for curve in vec![NistP256, NistP384, NistP521, Ed25519] {
988 if ! curve.is_supported() {
989 eprintln!("Skipping unsupported {}", curve);
990 continue;
991 }
992
993 let key: Key6<_, R>
994 = Key6::generate_ecc(true, curve.clone())?;
995 check(key)?;
996 }
997
998 for bits in vec![2048, 3072] {
999 if ! PublicKeyAlgorithm::RSAEncryptSign.is_supported() {
1000 eprintln!("Skipping unsupported RSA");
1001 continue;
1002 }
1003
1004 let key: Key6<_, R>
1005 = Key6::generate_rsa(bits)?;
1006 check(key)?;
1007 }
1008
1009 Ok(())
1010 }
1011
1012 #[test]
1013 fn eq() {
1014 use crate::types::Curve::*;
1015
1016 for curve in vec![NistP256, NistP384, NistP521] {
1017 if ! curve.is_supported() {
1018 eprintln!("Skipping unsupported {}", curve);
1019 continue;
1020 }
1021
1022 let sign_key : Key6<_, key::UnspecifiedRole>
1023 = Key6::generate_ecc(true, curve.clone()).unwrap();
1024 let enc_key : Key6<_, key::UnspecifiedRole>
1025 = Key6::generate_ecc(false, curve).unwrap();
1026 let sign_clone = sign_key.clone();
1027 let enc_clone = enc_key.clone();
1028
1029 assert_eq!(sign_key, sign_clone);
1030 assert_eq!(enc_key, enc_clone);
1031 }
1032
1033 for bits in vec![1024, 2048, 3072, 4096] {
1034 if ! PublicKeyAlgorithm::RSAEncryptSign.is_supported() {
1035 eprintln!("Skipping unsupported RSA");
1036 continue;
1037 }
1038
1039 let key : Key6<_, key::UnspecifiedRole>
1040 = Key6::generate_rsa(bits).unwrap();
1041 let clone = key.clone();
1042 assert_eq!(key, clone);
1043 }
1044 }
1045
1046 #[test]
1047 fn generate_roundtrip() {
1048 use crate::types::Curve::*;
1049
1050 let keys = vec![NistP256, NistP384, NistP521].into_iter().flat_map(|cv|
1051 {
1052 if ! cv.is_supported() {
1053 eprintln!("Skipping unsupported {}", cv);
1054 return Vec::new();
1055 }
1056
1057 let sign_key : Key6<key::SecretParts, key::PrimaryRole>
1058 = Key6::generate_ecc(true, cv.clone()).unwrap();
1059 let enc_key = Key6::generate_ecc(false, cv).unwrap();
1060
1061 vec![sign_key, enc_key]
1062 }).chain(vec![1024, 2048, 3072, 4096].into_iter().filter_map(|b| {
1063 Key6::generate_rsa(b).ok()
1064 }));
1065
1066 for key in keys {
1067 let mut b = Vec::new();
1068 Packet::SecretKey(key.clone().into()).serialize(&mut b).unwrap();
1069
1070 let pp = PacketPile::from_bytes(&b).unwrap();
1071 if let Some(Packet::SecretKey(Key::V6(ref parsed_key))) =
1072 pp.path_ref(&[0])
1073 {
1074 assert_eq!(key.creation_time(), parsed_key.creation_time());
1075 assert_eq!(key.pk_algo(), parsed_key.pk_algo());
1076 assert_eq!(key.mpis(), parsed_key.mpis());
1077 assert_eq!(key.secret(), parsed_key.secret());
1078
1079 assert_eq!(&key, parsed_key);
1080 } else {
1081 panic!("bad packet: {:?}", pp.path_ref(&[0]));
1082 }
1083
1084 let mut b = Vec::new();
1085 let pk4 : Key6<PublicParts, PrimaryRole> = key.clone().into();
1086 Packet::PublicKey(pk4.into()).serialize(&mut b).unwrap();
1087
1088 let pp = PacketPile::from_bytes(&b).unwrap();
1089 if let Some(Packet::PublicKey(Key::V6(ref parsed_key))) =
1090 pp.path_ref(&[0])
1091 {
1092 assert!(! parsed_key.has_secret());
1093
1094 let key = key.take_secret().0;
1095 assert_eq!(&key, parsed_key);
1096 } else {
1097 panic!("bad packet: {:?}", pp.path_ref(&[0]));
1098 }
1099 }
1100 }
1101
1102 #[test]
1103 fn encryption_roundtrip() {
1104 use crate::crypto::SessionKey;
1105 use crate::types::Curve::*;
1106
1107 let keys = vec![NistP256, NistP384, NistP521].into_iter()
1108 .filter_map(|cv| {
1109 Key6::generate_ecc(false, cv).ok()
1110 }).chain(vec![1024, 2048, 3072, 4096].into_iter().filter_map(|b| {
1111 Key6::generate_rsa(b).ok()
1112 })).chain([
1113 (PublicKeyAlgorithm::MLKEM768_X25519, Key6::generate_mlkem768_x25519 as fn() -> Result<_>),
1114 (PublicKeyAlgorithm::MLKEM1024_X448, Key6::generate_mlkem1024_x448),
1115 ].into_iter().filter_map(|(algo, gen)| {
1116 if algo.is_supported() {
1117 Some(gen().expect(&format!("{} is supported", algo)))
1118 } else {
1119 None
1120 }
1121 }));
1122
1123 for key in keys.into_iter() {
1124 let key: Key<key::SecretParts, key::UnspecifiedRole> = key.into();
1125 let mut keypair = key.clone().into_keypair().unwrap();
1126 let cipher = SymmetricAlgorithm::AES256;
1127 let sk = SessionKey::new(cipher.key_size().unwrap()).unwrap();
1128
1129 let pkesk = PKESK6::for_recipient(&sk, &key).unwrap();
1130 let sk_ = pkesk.decrypt(&mut keypair, None)
1131 .expect("keypair should be able to decrypt PKESK");
1132 assert_eq!(sk, sk_);
1133
1134 let sk_ =
1135 pkesk.decrypt(&mut keypair, Some(cipher)).unwrap();
1136 assert_eq!(sk, sk_);
1137 }
1138 }
1139
1140 #[test]
1141 fn signature_roundtrip() {
1142 use crate::types::{Curve::*, SignatureType};
1143
1144 let keys = vec![NistP256, NistP384, NistP521].into_iter()
1145 .filter_map(|cv| {
1146 Key6::generate_ecc(true, cv).ok()
1147 }).chain(vec![1024, 2048, 3072, 4096].into_iter().filter_map(|b| {
1148 Key6::generate_rsa(b).ok()
1149 })).chain([
1150 (PublicKeyAlgorithm::MLDSA65_Ed25519, Key6::generate_mldsa65_ed25519 as fn() -> Result<_>),
1151 (PublicKeyAlgorithm::MLDSA87_Ed448, Key6::generate_mldsa87_ed448),
1152 (PublicKeyAlgorithm::SLHDSA128s, Key6::generate_slhdsa128s),
1153 (PublicKeyAlgorithm::SLHDSA128f, Key6::generate_slhdsa128f),
1154 (PublicKeyAlgorithm::SLHDSA256s, Key6::generate_slhdsa256s),
1155 ].into_iter().filter_map(|(algo, gen)| {
1156 if algo.is_supported() {
1157 Some(gen().expect(&format!("{} is supported", algo)))
1158 } else {
1159 None
1160 }
1161 }));
1162
1163 for key in keys.into_iter() {
1164 let key: Key<key::SecretParts, key::UnspecifiedRole> = key.into();
1165 let mut keypair = key.clone().into_keypair().unwrap();
1166 let hash = HashAlgorithm::default();
1167
1168 let ctx = hash.context().unwrap().for_signature(key.version());
1170 let sig = SignatureBuilder::new(SignatureType::Binary)
1171 .sign_hash(&mut keypair, ctx).unwrap();
1172
1173 let ctx = hash.context().unwrap().for_signature(key.version());
1175 sig.verify_hash(&key, ctx).unwrap();
1176 }
1177 }
1178
1179 #[test]
1180 fn secret_encryption_roundtrip() {
1181 use crate::types::Curve::*;
1182 use crate::types::SymmetricAlgorithm::*;
1183 use crate::types::AEADAlgorithm::*;
1184
1185 let keys = vec![NistP256, NistP384, NistP521].into_iter()
1186 .filter_map(|cv| -> Option<Key<key::SecretParts, key::PrimaryRole>> {
1187 Key6::generate_ecc(false, cv).map(Into::into).ok()
1188 }).chain(vec![1024, 2048, 3072, 4096].into_iter().filter_map(|b| {
1189 Key6::generate_rsa(b).map(Into::into).ok()
1190 }));
1191
1192 for key in keys {
1193 for (symm, aead) in [(AES128, None),
1194 (AES128, Some(OCB)),
1195 (AES256, Some(EAX))] {
1196 if ! aead.map(|a| a.is_supported()).unwrap_or(true) {
1197 continue;
1198 }
1199 assert!(! key.secret().is_encrypted());
1200
1201 let password = Password::from("foobarbaz");
1202 let mut encrypted_key = key.clone();
1203
1204 encrypted_key.secret_mut()
1205 .encrypt_in_place_with(&key, S2K::default(), symm, aead,
1206 &password).unwrap();
1207 assert!(encrypted_key.secret().is_encrypted());
1208
1209 encrypted_key.secret_mut()
1210 .decrypt_in_place(&key, &password).unwrap();
1211 assert!(! key.secret().is_encrypted());
1212 assert_eq!(key, encrypted_key);
1213 assert_eq!(key.secret(), encrypted_key.secret());
1214 }
1215 }
1216 }
1217
1218 #[test]
1219 fn encrypt_huge_plaintext() -> Result<()> {
1220 let sk = crate::crypto::SessionKey::new(256).unwrap();
1221
1222 if PublicKeyAlgorithm::RSAEncryptSign.is_supported() {
1223 let rsa2k: Key<SecretParts, UnspecifiedRole> =
1224 Key6::generate_rsa(2048)?.into();
1225 assert!(matches!(
1226 rsa2k.encrypt(&sk).unwrap_err().downcast().unwrap(),
1227 crate::Error::InvalidArgument(_)
1228 ));
1229 }
1230
1231 Ok(())
1232 }
1233
1234 #[test]
1235 fn issue_1016() {
1236 let mut g = quickcheck::Gen::new(256);
1241
1242 let mut key = Key6::<PublicParts, UnspecifiedRole>::arbitrary(&mut g);
1243 let fpr1 = key.fingerprint();
1244 if key.creation_time() == UNIX_EPOCH {
1245 key.set_creation_time(UNIX_EPOCH + Duration::new(1, 0)).expect("ok");
1246 } else {
1247 key.set_creation_time(UNIX_EPOCH).expect("ok");
1248 }
1249 assert_ne!(fpr1, key.fingerprint());
1250
1251 let mut key = Key6::<PublicParts, UnspecifiedRole>::arbitrary(&mut g);
1252 let fpr1 = key.fingerprint();
1253 key.set_pk_algo(PublicKeyAlgorithm::from(u8::from(key.pk_algo()) + 1));
1254 assert_ne!(fpr1, key.fingerprint());
1255
1256 let mut key = Key6::<PublicParts, UnspecifiedRole>::arbitrary(&mut g);
1257 let fpr1 = key.fingerprint();
1258 loop {
1259 let mpis2 = mpi::PublicKey::arbitrary(&mut g);
1260 if key.mpis() != &mpis2 {
1261 *key.mpis_mut() = mpis2;
1262 break;
1263 }
1264 }
1265 assert_ne!(fpr1, key.fingerprint());
1266
1267 let mut key = Key6::<PublicParts, UnspecifiedRole>::arbitrary(&mut g);
1268 let fpr1 = key.fingerprint();
1269 loop {
1270 let mpis2 = mpi::PublicKey::arbitrary(&mut g);
1271 if key.mpis() != &mpis2 {
1272 key.set_mpis(mpis2);
1273 break;
1274 }
1275 }
1276 assert_ne!(fpr1, key.fingerprint());
1277 }
1278
1279 #[test]
1282 fn ecc_support() -> Result<()> {
1283 for for_signing in [true, false] {
1284 for curve in Curve::variants()
1285 .filter(Curve::is_supported)
1286 {
1287 match curve {
1288 Curve::Cv25519 if for_signing => continue,
1289 Curve::Ed25519 if ! for_signing => continue,
1290 _ => (),
1291 }
1292
1293 eprintln!("curve {}, for signing {:?}", curve, for_signing);
1294 let key: Key<SecretParts, UnspecifiedRole> =
1295 Key6::generate_ecc(for_signing, curve.clone())?.into();
1296 let mut pair = key.into_keypair()?;
1297
1298 if for_signing {
1299 use crate::crypto::Signer;
1300 let hash = HashAlgorithm::default();
1301 let digest = hash.context()?
1302 .for_signature(pair.public().version())
1303 .into_digest()?;
1304 let sig = pair.sign(hash, &digest)?;
1305 pair.public().verify(&sig, hash, &digest)?;
1306 } else {
1307 use crate::crypto::{SessionKey, Decryptor};
1308 let sk = SessionKey::new(32).unwrap();
1309 let ciphertext = pair.public().encrypt(&sk)?;
1310 assert_eq!(pair.decrypt(&ciphertext, Some(sk.len()))?, sk);
1311 }
1312 }
1313 }
1314 Ok(())
1315 }
1316
1317 #[test]
1318 fn ecc_encoding() -> Result<()> {
1319 for for_signing in [true, false] {
1320 for curve in Curve::variants()
1321 .filter(Curve::is_supported)
1322 {
1323 match curve {
1324 Curve::Cv25519 if for_signing => continue,
1325 Curve::Ed25519 if ! for_signing => continue,
1326 _ => (),
1327 }
1328
1329 use crate::crypto::mpi::{Ciphertext, MPI, PublicKey};
1330 eprintln!("curve {}, for signing {:?}", curve, for_signing);
1331
1332 let key: Key<SecretParts, UnspecifiedRole> =
1333 Key6::generate_ecc(for_signing, curve.clone())?.into();
1334
1335 let uncompressed = |mpi: &MPI| mpi.value()[0] == 0x04;
1336
1337 match key.mpis() {
1338 PublicKey::X25519 { .. } if ! for_signing => (),
1339 PublicKey::X448 { .. } if ! for_signing => (),
1340 PublicKey::Ed25519 { .. } if for_signing => (),
1341 PublicKey::Ed448 { .. } if for_signing => (),
1342 PublicKey::ECDSA { curve: c, q } if for_signing => {
1343 assert!(c == &curve);
1344 assert!(c != &Curve::Ed25519);
1345 assert!(uncompressed(q));
1346 },
1347 PublicKey::ECDH { curve: c, q, .. } if ! for_signing => {
1348 assert!(c == &curve);
1349 assert!(c != &Curve::Cv25519);
1350 assert!(uncompressed(q));
1351
1352 use crate::crypto::SessionKey;
1353 let sk = SessionKey::new(32).unwrap();
1354 let ciphertext = key.encrypt(&sk)?;
1355 if let Ciphertext::ECDH { e, .. } = &ciphertext {
1356 assert!(uncompressed(e));
1357 } else {
1358 panic!("unexpected ciphertext: {:?}", ciphertext);
1359 }
1360 },
1361 mpi => unreachable!(
1362 "curve {}, mpi {:?}, for signing {:?}",
1363 curve, mpi, for_signing),
1364 }
1365 }
1366 }
1367 Ok(())
1368 }
1369
1370
1371 #[test]
1372 fn v6_key_fingerprint() -> Result<()> {
1373 let p = Packet::from_bytes("-----BEGIN PGP ARMORED FILE-----
1374
1375xjcGY4d/4xYAAAAtCSsGAQQB2kcPAQEHQPlNp7tI1gph5WdwamWH0DMZmbudiRoI
1376JC6thFQ9+JWj
1377=SgmS
1378-----END PGP ARMORED FILE-----")?;
1379 let k: &Key<PublicParts, PrimaryRole> = p.downcast_ref().unwrap();
1380 assert_eq!(k.fingerprint().to_string(),
1381 "4EADF309C6BC874AE04702451548F93F\
1382 96FA7A01D0A33B5AF7D4E379E0F9F8EE".to_string());
1383 Ok(())
1384 }
1385
1386 #[test]
1387 fn import_public_mldsa() -> Result<()> {
1388 if PublicKeyAlgorithm::MLDSA65_Ed25519.is_supported() {
1389 let key: Key6<SecretParts, UnspecifiedRole>
1390 = Key6::generate_mldsa65_ed25519()
1391 .expect("failed to generate MLDSA65 key, but it is supported.");
1392
1393 assert_eq!(key.pk_algo(), PublicKeyAlgorithm::MLDSA65_Ed25519);
1394 let creation_time = key.creation_time();
1395 let mpis = key.mpis();
1396 let crate::crypto::mpi::PublicKey::MLDSA65_Ed25519 {
1397 eddsa,
1398 mldsa,
1399 } = &mpis else {
1400 panic!("Key generate generated the wrong key");
1401 };
1402
1403 let imported_key = Key6::import_public_mldsa65_ed25519(
1404 &mldsa[..], &eddsa[..], creation_time)
1405 .expect("Can import key");
1406
1407 assert_eq!(key.parts_into_public(), imported_key);
1408 }
1409
1410 if PublicKeyAlgorithm::MLDSA87_Ed448.is_supported() {
1411 let key: Key6<SecretParts, UnspecifiedRole>
1412 = Key6::generate_mldsa87_ed448()
1413 .expect("failed to generate MLDSA87 key, but it is supported.");
1414
1415 assert_eq!(key.pk_algo(), PublicKeyAlgorithm::MLDSA87_Ed448);
1416 let creation_time = key.creation_time();
1417 let mpis = key.mpis();
1418 let crate::crypto::mpi::PublicKey::MLDSA87_Ed448 {
1419 eddsa,
1420 mldsa,
1421 } = &mpis else {
1422 panic!("Key generate generated the wrong key");
1423 };
1424
1425 let imported_key = Key6::import_public_mldsa87_ed448(
1426 &mldsa[..], &eddsa[..], creation_time)
1427 .expect("Can import key");
1428
1429 assert_eq!(key.parts_into_public(), imported_key);
1430 }
1431
1432 Ok(())
1433 }
1434
1435
1436 #[test]
1437 fn import_public_slhdsa() -> Result<()> {
1438 if PublicKeyAlgorithm::SLHDSA128s.is_supported() {
1439 let key: Key6<SecretParts, UnspecifiedRole>
1440 = Key6::generate_slhdsa128s()
1441 .expect("failed to generate SLHDSA128s key, but it is supported.");
1442
1443 assert_eq!(key.pk_algo(), PublicKeyAlgorithm::SLHDSA128s);
1444 let creation_time = key.creation_time();
1445 let mpis = key.mpis();
1446 let crate::crypto::mpi::PublicKey::SLHDSA128s {
1447 public,
1448 } = &mpis else {
1449 panic!("Key generate generated the wrong key");
1450 };
1451
1452 let imported_key = Key6::import_public_slhdsa128s(
1453 &public[..], creation_time)
1454 .expect("Can import key");
1455
1456 assert_eq!(key.parts_into_public(), imported_key);
1457 }
1458
1459 if PublicKeyAlgorithm::SLHDSA128f.is_supported() {
1460 let key: Key6<SecretParts, UnspecifiedRole>
1461 = Key6::generate_slhdsa128f()
1462 .expect("failed to generate SLHDSA128f key, but it is supported.");
1463
1464 assert_eq!(key.pk_algo(), PublicKeyAlgorithm::SLHDSA128f);
1465 let creation_time = key.creation_time();
1466 let mpis = key.mpis();
1467 let crate::crypto::mpi::PublicKey::SLHDSA128f {
1468 public,
1469 } = &mpis else {
1470 panic!("Key generate generated the wrong key");
1471 };
1472
1473 let imported_key = Key6::import_public_slhdsa128f(
1474 &public[..], creation_time)
1475 .expect("Can import key");
1476
1477 assert_eq!(key.parts_into_public(), imported_key);
1478 }
1479
1480 if PublicKeyAlgorithm::SLHDSA256s.is_supported() {
1481 let key: Key6<SecretParts, UnspecifiedRole>
1482 = Key6::generate_slhdsa256s()
1483 .expect("failed to generate SLHDSA256s key, but it is supported.");
1484
1485 assert_eq!(key.pk_algo(), PublicKeyAlgorithm::SLHDSA256s);
1486 let creation_time = key.creation_time();
1487 let mpis = key.mpis();
1488 let crate::crypto::mpi::PublicKey::SLHDSA256s {
1489 public,
1490 } = &mpis else {
1491 panic!("Key generate generated the wrong key");
1492 };
1493
1494 let imported_key = Key6::import_public_slhdsa256s(
1495 &public[..], creation_time)
1496 .expect("Can import key");
1497
1498 assert_eq!(key.parts_into_public(), imported_key);
1499 }
1500
1501 Ok(())
1502 }
1503
1504 #[test]
1505 fn import_public_mlkem() -> Result<()> {
1506 if PublicKeyAlgorithm::MLKEM768_X25519.is_supported() {
1507 let key: Key6<SecretParts, UnspecifiedRole>
1508 = Key6::generate_mlkem768_x25519()
1509 .expect("failed to generate ML-KEM768 key, but it is supported.");
1510
1511 assert_eq!(key.pk_algo(), PublicKeyAlgorithm::MLKEM768_X25519);
1512 let creation_time = key.creation_time();
1513 let mpis = key.mpis();
1514 let crate::crypto::mpi::PublicKey::MLKEM768_X25519 {
1515 ecdh,
1516 mlkem,
1517 } = &mpis else {
1518 panic!("Key generate generated the wrong key");
1519 };
1520
1521 let imported_key = Key6::import_public_mlkem768_x25519(
1522 &mlkem[..], &ecdh[..], creation_time)
1523 .expect("Can import key");
1524
1525 assert_eq!(key.parts_into_public(), imported_key);
1526 }
1527
1528 if PublicKeyAlgorithm::MLKEM1024_X448.is_supported() {
1529 let key: Key6<SecretParts, UnspecifiedRole>
1530 = Key6::generate_mlkem1024_x448()
1531 .expect("failed to generate ML-KEM1024 key, but it is supported.");
1532
1533 assert_eq!(key.pk_algo(), PublicKeyAlgorithm::MLKEM1024_X448);
1534 let creation_time = key.creation_time();
1535 let mpis = key.mpis();
1536 let crate::crypto::mpi::PublicKey::MLKEM1024_X448 {
1537 ecdh,
1538 mlkem,
1539 } = &mpis else {
1540 panic!("Key generate generated the wrong key");
1541 };
1542
1543 let imported_key = Key6::import_public_mlkem1024_x448(
1544 &mlkem[..], &ecdh[..], creation_time)
1545 .expect("Can import key");
1546
1547 assert_eq!(key.parts_into_public(), imported_key);
1548 }
1549
1550 Ok(())
1551 }
1552}