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