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
448impl<R> Key6<SecretParts, R>
449where R: KeyRole,
450{
451 pub fn with_secret<T>(creation_time: T, pk_algo: PublicKeyAlgorithm,
454 mpis: mpi::PublicKey,
455 secret: SecretKeyMaterial)
456 -> Result<Self>
457 where T: Into<time::SystemTime>
458 {
459 Ok(Key6 {
460 common: Key4::with_secret(creation_time, pk_algo, mpis, secret)?,
461 })
462 }
463
464 pub fn import_secret_x25519<T>(private_key: &[u8],
473 ctime: T)
474 -> Result<Self>
475 where
476 T: Into<Option<std::time::SystemTime>>,
477 {
478 use crate::crypto::backend::{Backend, interface::Asymmetric};
479
480 let private_key = Protected::from(private_key);
481 let public_key = Backend::x25519_derive_public(&private_key)?;
482
483 Self::with_secret(
484 ctime.into().unwrap_or_else(crate::now),
485 PublicKeyAlgorithm::X25519,
486 mpi::PublicKey::X25519 {
487 u: public_key,
488 },
489 mpi::SecretKeyMaterial::X25519 {
490 x: private_key.into(),
491 }.into())
492 }
493
494 pub fn import_secret_x448<T>(private_key: &[u8],
503 ctime: T)
504 -> Result<Self>
505 where
506 T: Into<Option<std::time::SystemTime>>,
507 {
508 use crate::crypto::backend::{Backend, interface::Asymmetric};
509
510 let private_key = Protected::from(private_key);
511 let public_key = Backend::x448_derive_public(&private_key)?;
512
513 Self::with_secret(
514 ctime.into().unwrap_or_else(crate::now),
515 PublicKeyAlgorithm::X448,
516 mpi::PublicKey::X448 {
517 u: Box::new(public_key),
518 },
519 mpi::SecretKeyMaterial::X448 {
520 x: private_key.into(),
521 }.into())
522 }
523
524 pub fn import_secret_ed25519<T>(private_key: &[u8], ctime: T)
530 -> Result<Self>
531 where
532 T: Into<Option<time::SystemTime>>,
533 {
534 use crate::crypto::backend::{Backend, interface::Asymmetric};
535
536 let private_key = Protected::from(private_key);
537 let public_key = Backend::ed25519_derive_public(&private_key)?;
538
539 Self::with_secret(
540 ctime.into().unwrap_or_else(crate::now),
541 PublicKeyAlgorithm::Ed25519,
542 mpi::PublicKey::Ed25519 {
543 a: public_key,
544 },
545 mpi::SecretKeyMaterial::Ed25519 {
546 x: private_key.into(),
547 }.into())
548 }
549
550 pub fn import_secret_ed448<T>(private_key: &[u8], ctime: T)
556 -> Result<Self>
557 where
558 T: Into<Option<time::SystemTime>>,
559 {
560 use crate::crypto::backend::{Backend, interface::Asymmetric};
561
562 let private_key = Protected::from(private_key);
563 let public_key = Backend::ed448_derive_public(&private_key)?;
564
565 Self::with_secret(
566 ctime.into().unwrap_or_else(crate::now),
567 PublicKeyAlgorithm::Ed448,
568 mpi::PublicKey::Ed448 {
569 a: Box::new(public_key),
570 },
571 mpi::SecretKeyMaterial::Ed448 {
572 x: private_key.into(),
573 }.into())
574 }
575
576 pub fn into_keypair(self) -> Result<KeyPair> {
584 let (key, secret) = self.take_secret();
585 let secret = match secret {
586 SecretKeyMaterial::Unencrypted(secret) => secret,
587 SecretKeyMaterial::Encrypted(_) =>
588 return Err(Error::InvalidArgument(
589 "secret key material is encrypted".into()).into()),
590 };
591
592 KeyPair::new(key.role_into_unspecified().into(), secret)
593 }
594}
595
596macro_rules! impl_common_secret_functions_v6 {
597 ($t: ident) => {
598 impl<R> Key6<$t, R>
600 where R: KeyRole,
601 {
602 pub fn take_secret(mut self)
604 -> (Key6<PublicParts, R>, Option<SecretKeyMaterial>)
605 {
606 let old = std::mem::replace(&mut self.common.secret, None);
607 (self.parts_into_public(), old)
608 }
609
610 pub fn add_secret(mut self, secret: SecretKeyMaterial)
613 -> (Key6<SecretParts, R>, Option<SecretKeyMaterial>)
614 {
615 let old = std::mem::replace(&mut self.common.secret, Some(secret));
616 (self.parts_into_secret().expect("secret just set"), old)
617 }
618
619 pub fn steal_secret(&mut self) -> Option<SecretKeyMaterial>
621 {
622 std::mem::replace(&mut self.common.secret, None)
623 }
624 }
625 }
626}
627impl_common_secret_functions_v6!(PublicParts);
628impl_common_secret_functions_v6!(UnspecifiedParts);
629
630impl<R> Key6<SecretParts, R>
632where R: KeyRole,
633{
634 pub fn secret(&self) -> &SecretKeyMaterial {
636 self.common.secret()
637 }
638
639 pub fn secret_mut(&mut self) -> &mut SecretKeyMaterial {
641 self.common.secret_mut()
642 }
643
644 pub fn take_secret(mut self)
646 -> (Key6<PublicParts, R>, SecretKeyMaterial)
647 {
648 let old = std::mem::replace(&mut self.common.secret, None);
649 (self.parts_into_public(),
650 old.expect("Key<SecretParts, _> has a secret key material"))
651 }
652
653 pub fn add_secret(mut self, secret: SecretKeyMaterial)
657 -> (Key6<SecretParts, R>, SecretKeyMaterial)
658 {
659 let old = std::mem::replace(&mut self.common.secret, Some(secret));
660 (self.parts_into_secret().expect("secret just set"),
661 old.expect("Key<SecretParts, _> has a secret key material"))
662 }
663
664 pub fn decrypt_secret(self, password: &Password) -> Result<Self> {
679 let (key, mut secret) = self.take_secret();
680 let key = Key::V6(key);
682 secret.decrypt_in_place(&key, password)?;
683 let key = if let Key::V6(k) = key { k } else { unreachable!() };
684 Ok(key.add_secret(secret).0)
685 }
686
687 pub fn encrypt_secret(self, password: &Password)
702 -> Result<Key6<SecretParts, R>>
703 {
704 let (key, mut secret) = self.take_secret();
705 let key = Key::V6(key);
707 secret.encrypt_in_place(&key, password)?;
708 let key = if let Key::V6(k) = key { k } else { unreachable!() };
709 Ok(key.add_secret(secret).0)
710 }
711}
712
713impl<P, R> From<Key6<P, R>> for super::Key<P, R>
714where P: KeyParts,
715 R: KeyRole,
716{
717 fn from(p: Key6<P, R>) -> Self {
718 super::Key::V6(p)
719 }
720}
721
722#[cfg(test)]
723use crate::packet::key::{
724 PrimaryRole,
725 SubordinateRole,
726 UnspecifiedRole,
727};
728
729#[cfg(test)]
730impl Arbitrary for Key6<PublicParts, PrimaryRole> {
731 fn arbitrary(g: &mut Gen) -> Self {
732 Key6::from_common(Key4::arbitrary(g))
733 }
734}
735
736#[cfg(test)]
737impl Arbitrary for Key6<PublicParts, SubordinateRole> {
738 fn arbitrary(g: &mut Gen) -> Self {
739 Key6::from_common(Key4::arbitrary(g))
740 }
741}
742
743#[cfg(test)]
744impl Arbitrary for Key6<PublicParts, UnspecifiedRole> {
745 fn arbitrary(g: &mut Gen) -> Self {
746 Key6::from_common(Key4::arbitrary(g))
747 }
748}
749
750#[cfg(test)]
751impl Arbitrary for Key6<SecretParts, PrimaryRole> {
752 fn arbitrary(g: &mut Gen) -> Self {
753 Key6::from_common(Key4::arbitrary(g))
754 }
755}
756
757#[cfg(test)]
758impl Arbitrary for Key6<SecretParts, SubordinateRole> {
759 fn arbitrary(g: &mut Gen) -> Self {
760 Key6::from_common(Key4::arbitrary(g))
761 }
762}
763
764
765#[cfg(test)]
766mod tests {
767 use std::time::Duration;
768 use std::time::UNIX_EPOCH;
769
770 use crate::crypto::S2K;
771 use crate::packet::Key;
772 use crate::packet::key;
773 use crate::packet::Packet;
774 use super::*;
775 use crate::PacketPile;
776 use crate::serialize::Serialize;
777 use crate::types::*;
778 use crate::parse::Parse;
779
780 #[test]
781 fn primary_key_encrypt_decrypt() -> Result<()> {
782 key_encrypt_decrypt::<PrimaryRole>()
783 }
784
785 #[test]
786 fn subkey_encrypt_decrypt() -> Result<()> {
787 key_encrypt_decrypt::<SubordinateRole>()
788 }
789
790 fn key_encrypt_decrypt<R>() -> Result<()>
791 where
792 R: KeyRole + PartialEq,
793 {
794 let mut g = quickcheck::Gen::new(256);
795 let p: Password = Vec::<u8>::arbitrary(&mut g).into();
796
797 let check = |key: Key6<SecretParts, R>| -> Result<()> {
798 let key: Key<_, _> = key.into();
799 let encrypted = key.clone().encrypt_secret(&p)?;
800 let decrypted = encrypted.decrypt_secret(&p)?;
801 assert_eq!(key, decrypted);
802 Ok(())
803 };
804
805 use crate::types::Curve::*;
806 for curve in vec![NistP256, NistP384, NistP521, Ed25519] {
807 if ! curve.is_supported() {
808 eprintln!("Skipping unsupported {}", curve);
809 continue;
810 }
811
812 let key: Key6<_, R>
813 = Key6::generate_ecc(true, curve.clone())?;
814 check(key)?;
815 }
816
817 for bits in vec![2048, 3072] {
818 if ! PublicKeyAlgorithm::RSAEncryptSign.is_supported() {
819 eprintln!("Skipping unsupported RSA");
820 continue;
821 }
822
823 let key: Key6<_, R>
824 = Key6::generate_rsa(bits)?;
825 check(key)?;
826 }
827
828 Ok(())
829 }
830
831 #[test]
832 fn eq() {
833 use crate::types::Curve::*;
834
835 for curve in vec![NistP256, NistP384, NistP521] {
836 if ! curve.is_supported() {
837 eprintln!("Skipping unsupported {}", curve);
838 continue;
839 }
840
841 let sign_key : Key6<_, key::UnspecifiedRole>
842 = Key6::generate_ecc(true, curve.clone()).unwrap();
843 let enc_key : Key6<_, key::UnspecifiedRole>
844 = Key6::generate_ecc(false, curve).unwrap();
845 let sign_clone = sign_key.clone();
846 let enc_clone = enc_key.clone();
847
848 assert_eq!(sign_key, sign_clone);
849 assert_eq!(enc_key, enc_clone);
850 }
851
852 for bits in vec![1024, 2048, 3072, 4096] {
853 if ! PublicKeyAlgorithm::RSAEncryptSign.is_supported() {
854 eprintln!("Skipping unsupported RSA");
855 continue;
856 }
857
858 let key : Key6<_, key::UnspecifiedRole>
859 = Key6::generate_rsa(bits).unwrap();
860 let clone = key.clone();
861 assert_eq!(key, clone);
862 }
863 }
864
865 #[test]
866 fn generate_roundtrip() {
867 use crate::types::Curve::*;
868
869 let keys = vec![NistP256, NistP384, NistP521].into_iter().flat_map(|cv|
870 {
871 if ! cv.is_supported() {
872 eprintln!("Skipping unsupported {}", cv);
873 return Vec::new();
874 }
875
876 let sign_key : Key6<key::SecretParts, key::PrimaryRole>
877 = Key6::generate_ecc(true, cv.clone()).unwrap();
878 let enc_key = Key6::generate_ecc(false, cv).unwrap();
879
880 vec![sign_key, enc_key]
881 }).chain(vec![1024, 2048, 3072, 4096].into_iter().filter_map(|b| {
882 Key6::generate_rsa(b).ok()
883 }));
884
885 for key in keys {
886 let mut b = Vec::new();
887 Packet::SecretKey(key.clone().into()).serialize(&mut b).unwrap();
888
889 let pp = PacketPile::from_bytes(&b).unwrap();
890 if let Some(Packet::SecretKey(Key::V6(ref parsed_key))) =
891 pp.path_ref(&[0])
892 {
893 assert_eq!(key.creation_time(), parsed_key.creation_time());
894 assert_eq!(key.pk_algo(), parsed_key.pk_algo());
895 assert_eq!(key.mpis(), parsed_key.mpis());
896 assert_eq!(key.secret(), parsed_key.secret());
897
898 assert_eq!(&key, parsed_key);
899 } else {
900 panic!("bad packet: {:?}", pp.path_ref(&[0]));
901 }
902
903 let mut b = Vec::new();
904 let pk4 : Key6<PublicParts, PrimaryRole> = key.clone().into();
905 Packet::PublicKey(pk4.into()).serialize(&mut b).unwrap();
906
907 let pp = PacketPile::from_bytes(&b).unwrap();
908 if let Some(Packet::PublicKey(Key::V6(ref parsed_key))) =
909 pp.path_ref(&[0])
910 {
911 assert!(! parsed_key.has_secret());
912
913 let key = key.take_secret().0;
914 assert_eq!(&key, parsed_key);
915 } else {
916 panic!("bad packet: {:?}", pp.path_ref(&[0]));
917 }
918 }
919 }
920
921 #[test]
922 fn encryption_roundtrip() {
923 use crate::crypto::SessionKey;
924 use crate::types::Curve::*;
925
926 let keys = vec![NistP256, NistP384, NistP521].into_iter()
927 .filter_map(|cv| {
928 Key6::generate_ecc(false, cv).ok()
929 }).chain(vec![1024, 2048, 3072, 4096].into_iter().filter_map(|b| {
930 Key6::generate_rsa(b).ok()
931 }));
932
933 for key in keys.into_iter() {
934 let key: Key<key::SecretParts, key::UnspecifiedRole> = key.into();
935 let mut keypair = key.clone().into_keypair().unwrap();
936 let cipher = SymmetricAlgorithm::AES256;
937 let sk = SessionKey::new(cipher.key_size().unwrap()).unwrap();
938
939 let pkesk = PKESK6::for_recipient(&sk, &key).unwrap();
940 let sk_ = pkesk.decrypt(&mut keypair, None)
941 .expect("keypair should be able to decrypt PKESK");
942 assert_eq!(sk, sk_);
943
944 let sk_ =
945 pkesk.decrypt(&mut keypair, Some(cipher)).unwrap();
946 assert_eq!(sk, sk_);
947 }
948 }
949
950 #[test]
951 fn secret_encryption_roundtrip() {
952 use crate::types::Curve::*;
953 use crate::types::SymmetricAlgorithm::*;
954 use crate::types::AEADAlgorithm::*;
955
956 let keys = vec![NistP256, NistP384, NistP521].into_iter()
957 .filter_map(|cv| -> Option<Key<key::SecretParts, key::PrimaryRole>> {
958 Key6::generate_ecc(false, cv).map(Into::into).ok()
959 }).chain(vec![1024, 2048, 3072, 4096].into_iter().filter_map(|b| {
960 Key6::generate_rsa(b).map(Into::into).ok()
961 }));
962
963 for key in keys {
964 for (symm, aead) in [(AES128, None),
965 (AES128, Some(OCB)),
966 (AES256, Some(EAX))] {
967 if ! aead.map(|a| a.is_supported()).unwrap_or(true) {
968 continue;
969 }
970 assert!(! key.secret().is_encrypted());
971
972 let password = Password::from("foobarbaz");
973 let mut encrypted_key = key.clone();
974
975 encrypted_key.secret_mut()
976 .encrypt_in_place_with(&key, S2K::default(), symm, aead,
977 &password).unwrap();
978 assert!(encrypted_key.secret().is_encrypted());
979
980 encrypted_key.secret_mut()
981 .decrypt_in_place(&key, &password).unwrap();
982 assert!(! key.secret().is_encrypted());
983 assert_eq!(key, encrypted_key);
984 assert_eq!(key.secret(), encrypted_key.secret());
985 }
986 }
987 }
988
989 #[test]
990 fn encrypt_huge_plaintext() -> Result<()> {
991 let sk = crate::crypto::SessionKey::new(256).unwrap();
992
993 if PublicKeyAlgorithm::RSAEncryptSign.is_supported() {
994 let rsa2k: Key<SecretParts, UnspecifiedRole> =
995 Key6::generate_rsa(2048)?.into();
996 assert!(matches!(
997 rsa2k.encrypt(&sk).unwrap_err().downcast().unwrap(),
998 crate::Error::InvalidArgument(_)
999 ));
1000 }
1001
1002 Ok(())
1003 }
1004
1005 #[test]
1006 fn issue_1016() {
1007 let mut g = quickcheck::Gen::new(256);
1012
1013 let mut key = Key6::<PublicParts, UnspecifiedRole>::arbitrary(&mut g);
1014 let fpr1 = key.fingerprint();
1015 if key.creation_time() == UNIX_EPOCH {
1016 key.set_creation_time(UNIX_EPOCH + Duration::new(1, 0)).expect("ok");
1017 } else {
1018 key.set_creation_time(UNIX_EPOCH).expect("ok");
1019 }
1020 assert_ne!(fpr1, key.fingerprint());
1021
1022 let mut key = Key6::<PublicParts, UnspecifiedRole>::arbitrary(&mut g);
1023 let fpr1 = key.fingerprint();
1024 key.set_pk_algo(PublicKeyAlgorithm::from(u8::from(key.pk_algo()) + 1));
1025 assert_ne!(fpr1, key.fingerprint());
1026
1027 let mut key = Key6::<PublicParts, UnspecifiedRole>::arbitrary(&mut g);
1028 let fpr1 = key.fingerprint();
1029 loop {
1030 let mpis2 = mpi::PublicKey::arbitrary(&mut g);
1031 if key.mpis() != &mpis2 {
1032 *key.mpis_mut() = mpis2;
1033 break;
1034 }
1035 }
1036 assert_ne!(fpr1, key.fingerprint());
1037
1038 let mut key = Key6::<PublicParts, UnspecifiedRole>::arbitrary(&mut g);
1039 let fpr1 = key.fingerprint();
1040 loop {
1041 let mpis2 = mpi::PublicKey::arbitrary(&mut g);
1042 if key.mpis() != &mpis2 {
1043 key.set_mpis(mpis2);
1044 break;
1045 }
1046 }
1047 assert_ne!(fpr1, key.fingerprint());
1048 }
1049
1050 #[test]
1053 fn ecc_support() -> Result<()> {
1054 for for_signing in [true, false] {
1055 for curve in Curve::variants()
1056 .filter(Curve::is_supported)
1057 {
1058 match curve {
1059 Curve::Cv25519 if for_signing => continue,
1060 Curve::Ed25519 if ! for_signing => continue,
1061 _ => (),
1062 }
1063
1064 eprintln!("curve {}, for signing {:?}", curve, for_signing);
1065 let key: Key<SecretParts, UnspecifiedRole> =
1066 Key6::generate_ecc(for_signing, curve.clone())?.into();
1067 let mut pair = key.into_keypair()?;
1068
1069 if for_signing {
1070 use crate::crypto::Signer;
1071 let hash = HashAlgorithm::default();
1072 let digest = hash.context()?
1073 .for_signature(pair.public().version())
1074 .into_digest()?;
1075 let sig = pair.sign(hash, &digest)?;
1076 pair.public().verify(&sig, hash, &digest)?;
1077 } else {
1078 use crate::crypto::{SessionKey, Decryptor};
1079 let sk = SessionKey::new(32).unwrap();
1080 let ciphertext = pair.public().encrypt(&sk)?;
1081 assert_eq!(pair.decrypt(&ciphertext, Some(sk.len()))?, sk);
1082 }
1083 }
1084 }
1085 Ok(())
1086 }
1087
1088 #[test]
1089 fn ecc_encoding() -> Result<()> {
1090 for for_signing in [true, false] {
1091 for curve in Curve::variants()
1092 .filter(Curve::is_supported)
1093 {
1094 match curve {
1095 Curve::Cv25519 if for_signing => continue,
1096 Curve::Ed25519 if ! for_signing => continue,
1097 _ => (),
1098 }
1099
1100 use crate::crypto::mpi::{Ciphertext, MPI, PublicKey};
1101 eprintln!("curve {}, for signing {:?}", curve, for_signing);
1102
1103 let key: Key<SecretParts, UnspecifiedRole> =
1104 Key6::generate_ecc(for_signing, curve.clone())?.into();
1105
1106 let uncompressed = |mpi: &MPI| mpi.value()[0] == 0x04;
1107
1108 match key.mpis() {
1109 PublicKey::X25519 { .. } if ! for_signing => (),
1110 PublicKey::X448 { .. } if ! for_signing => (),
1111 PublicKey::Ed25519 { .. } if for_signing => (),
1112 PublicKey::Ed448 { .. } if for_signing => (),
1113 PublicKey::ECDSA { curve: c, q } if for_signing => {
1114 assert!(c == &curve);
1115 assert!(c != &Curve::Ed25519);
1116 assert!(uncompressed(q));
1117 },
1118 PublicKey::ECDH { curve: c, q, .. } if ! for_signing => {
1119 assert!(c == &curve);
1120 assert!(c != &Curve::Cv25519);
1121 assert!(uncompressed(q));
1122
1123 use crate::crypto::SessionKey;
1124 let sk = SessionKey::new(32).unwrap();
1125 let ciphertext = key.encrypt(&sk)?;
1126 if let Ciphertext::ECDH { e, .. } = &ciphertext {
1127 assert!(uncompressed(e));
1128 } else {
1129 panic!("unexpected ciphertext: {:?}", ciphertext);
1130 }
1131 },
1132 mpi => unreachable!(
1133 "curve {}, mpi {:?}, for signing {:?}",
1134 curve, mpi, for_signing),
1135 }
1136 }
1137 }
1138 Ok(())
1139 }
1140
1141
1142 #[test]
1143 fn v6_key_fingerprint() -> Result<()> {
1144 let p = Packet::from_bytes("-----BEGIN PGP ARMORED FILE-----
1145
1146xjcGY4d/4xYAAAAtCSsGAQQB2kcPAQEHQPlNp7tI1gph5WdwamWH0DMZmbudiRoI
1147JC6thFQ9+JWj
1148=SgmS
1149-----END PGP ARMORED FILE-----")?;
1150 let k: &Key<PublicParts, PrimaryRole> = p.downcast_ref().unwrap();
1151 assert_eq!(k.fingerprint().to_string(),
1152 "4EADF309C6BC874AE04702451548F93F\
1153 96FA7A01D0A33B5AF7D4E379E0F9F8EE".to_string());
1154 Ok(())
1155 }
1156}