1use std::fmt;
4use std::cmp::Ordering;
5use std::convert::TryInto;
6use std::hash::Hasher;
7use std::time;
8
9#[cfg(test)]
10use quickcheck::{Arbitrary, Gen};
11
12use crate::Error;
13use crate::crypto::{mem::Protected, mpi, hash::Hash, KeyPair};
14use crate::packet;
15use crate::packet::prelude::*;
16use crate::PublicKeyAlgorithm;
17use crate::SymmetricAlgorithm;
18use crate::HashAlgorithm;
19use crate::types::{
20 Curve,
21 Timestamp,
22};
23use crate::Result;
24use crate::crypto::Password;
25use crate::KeyID;
26use crate::Fingerprint;
27use crate::KeyHandle;
28use crate::packet::key::{
29 self,
30 KeyParts,
31 KeyRole,
32 KeyRoleRT,
33 PublicParts,
34 SecretParts,
35 UnspecifiedParts,
36};
37use crate::policy::HashAlgoSecurity;
38
39
40pub struct Key4<P, R>
66 where P: KeyParts, R: KeyRole
67{
68 pub(crate) common: packet::Common,
70 pub(crate) creation_time: Timestamp,
72 pk_algo: PublicKeyAlgorithm,
74 mpis: mpi::PublicKey,
76 pub(crate) secret: Option<SecretKeyMaterial>,
78
79 pub(crate) fingerprint: std::sync::OnceLock<Fingerprint>,
80
81 role: KeyRoleRT,
83
84 p: std::marker::PhantomData<P>,
85 r: std::marker::PhantomData<R>,
86}
87
88impl<P, R> Clone for Key4<P, R>
96 where P: KeyParts, R: KeyRole
97{
98 fn clone(&self) -> Self {
99 Key4 {
100 common: self.common.clone(),
101 creation_time: self.creation_time.clone(),
102 pk_algo: self.pk_algo.clone(),
103 mpis: self.mpis.clone(),
104 secret: self.secret.clone(),
105 fingerprint: self.fingerprint.get()
106 .map(|fp| fp.clone().into())
107 .unwrap_or_default(),
108 role: self.role,
109 p: std::marker::PhantomData,
110 r: std::marker::PhantomData,
111 }
112 }
113}
114
115assert_send_and_sync!(Key4<P, R> where P: KeyParts, R: KeyRole);
116
117impl<P: KeyParts, R: KeyRole> PartialEq for Key4<P, R> {
118 fn eq(&self, other: &Key4<P, R>) -> bool {
119 self.creation_time == other.creation_time
120 && self.pk_algo == other.pk_algo
121 && self.mpis == other.mpis
122 && (! P::significant_secrets() || self.secret == other.secret)
123 }
124}
125
126impl<P: KeyParts, R: KeyRole> Eq for Key4<P, R> {}
127
128impl<P: KeyParts, R: KeyRole> std::hash::Hash for Key4<P, R> {
129 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
130 std::hash::Hash::hash(&self.creation_time, state);
131 std::hash::Hash::hash(&self.pk_algo, state);
132 std::hash::Hash::hash(&self.mpis, state);
133 if P::significant_secrets() {
134 std::hash::Hash::hash(&self.secret, state);
135 }
136 }
137}
138
139impl<P, R> fmt::Debug for Key4<P, R>
140 where P: key::KeyParts,
141 R: key::KeyRole,
142{
143 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
144 f.debug_struct("Key4")
145 .field("fingerprint", &self.fingerprint())
146 .field("creation_time", &self.creation_time)
147 .field("pk_algo", &self.pk_algo)
148 .field("mpis", &self.mpis)
149 .field("secret", &self.secret)
150 .finish()
151 }
152}
153
154impl<P, R> fmt::Display for Key4<P, R>
155 where P: key::KeyParts,
156 R: key::KeyRole,
157{
158 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
159 write!(f, "{}", self.fingerprint())
160 }
161}
162
163impl<P, R> Key4<P, R>
164 where P: key::KeyParts,
165 R: key::KeyRole,
166{
167 pub fn hash_algo_security(&self) -> HashAlgoSecurity {
193 HashAlgoSecurity::SecondPreImageResistance
194 }
195
196 pub fn public_cmp<PB, RB>(&self, b: &Key4<PB, RB>) -> Ordering
203 where PB: key::KeyParts,
204 RB: key::KeyRole,
205 {
206 self.mpis.cmp(&b.mpis)
207 .then_with(|| self.creation_time.cmp(&b.creation_time))
208 .then_with(|| self.pk_algo.cmp(&b.pk_algo))
209 }
210
211 pub fn public_eq<PB, RB>(&self, b: &Key4<PB, RB>) -> bool
219 where PB: key::KeyParts,
220 RB: key::KeyRole,
221 {
222 self.public_cmp(b) == Ordering::Equal
223 }
224
225 pub fn public_hash<H>(&self, state: &mut H)
232 where H: Hasher
233 {
234 use std::hash::Hash;
235
236 self.common.hash(state);
237 self.creation_time.hash(state);
238 self.pk_algo.hash(state);
239 Hash::hash(&self.mpis(), state);
240 }
241}
242
243impl<P, R> Key4<P, R>
244 where P: key::KeyParts,
245 R: key::KeyRole,
246{
247 pub fn creation_time(&self) -> time::SystemTime {
249 self.creation_time.into()
250 }
251
252 pub(crate) fn creation_time_raw(&self) -> Timestamp {
257 self.creation_time
258 }
259
260 pub fn set_creation_time<T>(&mut self, timestamp: T)
272 -> Result<time::SystemTime>
273 where T: Into<time::SystemTime>
274 {
275 self.fingerprint = Default::default();
277
278 Ok(std::mem::replace(&mut self.creation_time,
279 timestamp.into().try_into()?)
280 .into())
281 }
282
283 pub fn pk_algo(&self) -> PublicKeyAlgorithm {
285 self.pk_algo
286 }
287
288 pub fn set_pk_algo(&mut self, pk_algo: PublicKeyAlgorithm)
292 -> PublicKeyAlgorithm
293 {
294 self.fingerprint = Default::default();
296
297 ::std::mem::replace(&mut self.pk_algo, pk_algo)
298 }
299
300 pub fn mpis(&self) -> &mpi::PublicKey {
302 &self.mpis
303 }
304
305 pub fn mpis_mut(&mut self) -> &mut mpi::PublicKey {
307 self.fingerprint = Default::default();
309
310 &mut self.mpis
311 }
312
313 pub fn set_mpis(&mut self, mpis: mpi::PublicKey) -> mpi::PublicKey {
317 self.fingerprint = Default::default();
319
320 ::std::mem::replace(&mut self.mpis, mpis)
321 }
322
323 pub fn has_secret(&self) -> bool {
325 self.secret.is_some()
326 }
327
328 pub fn has_unencrypted_secret(&self) -> bool {
334 matches!(self.secret, Some(SecretKeyMaterial::Unencrypted { .. }))
335 }
336
337 pub fn optional_secret(&self) -> Option<&SecretKeyMaterial> {
339 self.secret.as_ref()
340 }
341
342 pub fn key_handle(&self) -> KeyHandle {
349 self.fingerprint().into()
350 }
351
352 pub fn fingerprint(&self) -> Fingerprint {
358 self.fingerprint.get_or_init(|| {
359 let mut h = HashAlgorithm::SHA1.context()
360 .expect("SHA1 is MTI for RFC4880")
361 .for_signature(4);
364
365 self.hash(&mut h).expect("v4 key hashing is infallible");
366
367 let mut digest = [0u8; 20];
368 let _ = h.digest(&mut digest);
369 Fingerprint::V4(digest)
370 }).clone()
371 }
372
373 pub fn keyid(&self) -> KeyID {
379 self.fingerprint().into()
380 }
381
382 pub(crate) fn make(creation_time: Timestamp,
387 pk_algo: PublicKeyAlgorithm,
388 mpis: mpi::PublicKey,
389 secret: Option<SecretKeyMaterial>)
390 -> Result<Self>
391 {
392 Ok(Key4 {
393 common: Default::default(),
394 creation_time,
395 pk_algo,
396 mpis,
397 secret,
398 fingerprint: Default::default(),
399 role: R::role(),
400 p: std::marker::PhantomData,
401 r: std::marker::PhantomData,
402 })
403 }
404
405 pub(crate) fn role(&self) -> KeyRoleRT {
406 self.role
407 }
408
409 pub(crate) fn set_role(&mut self, role: KeyRoleRT) {
410 self.role = role;
411 }
412}
413
414impl<R> Key4<key::PublicParts, R>
415 where R: key::KeyRole,
416{
417 pub fn new<T>(creation_time: T, pk_algo: PublicKeyAlgorithm,
419 mpis: mpi::PublicKey)
420 -> Result<Self>
421 where T: Into<time::SystemTime>
422 {
423 Ok(Key4 {
424 common: Default::default(),
425 creation_time: creation_time.into().try_into()?,
426 pk_algo,
427 mpis,
428 secret: None,
429 fingerprint: Default::default(),
430 role: R::role(),
431 p: std::marker::PhantomData,
432 r: std::marker::PhantomData,
433 })
434 }
435
436 pub fn import_public_cv25519<H, S, T>(public_key: &[u8],
444 hash: H, sym: S, ctime: T)
445 -> Result<Self> where H: Into<Option<HashAlgorithm>>,
446 S: Into<Option<SymmetricAlgorithm>>,
447 T: Into<Option<time::SystemTime>>
448 {
449 let mut point = Vec::from(public_key);
450 point.insert(0, 0x40);
451
452 use crate::crypto::ecdh;
453 Self::new(
454 ctime.into().unwrap_or_else(crate::now),
455 PublicKeyAlgorithm::ECDH,
456 mpi::PublicKey::ECDH {
457 curve: Curve::Cv25519,
458 hash: hash.into().unwrap_or_else(
459 || ecdh::default_ecdh_kdf_hash(&Curve::Cv25519)),
460 sym: sym.into().unwrap_or_else(
461 || ecdh::default_ecdh_kek_cipher(&Curve::Cv25519)),
462 q: mpi::MPI::new(&point),
463 })
464 }
465
466 pub fn import_public_x25519<T>(public_key: &[u8], ctime: T)
472 -> Result<Self>
473 where
474 T: Into<Option<time::SystemTime>>,
475 {
476 Ok(Key4::new(ctime.into().unwrap_or_else(crate::now),
477 PublicKeyAlgorithm::X25519,
478 mpi::PublicKey::X25519 {
479 u: public_key.try_into()?,
480 })?)
481 }
482
483 pub fn import_public_x448<T>(public_key: &[u8], ctime: T)
489 -> Result<Self>
490 where
491 T: Into<Option<time::SystemTime>>,
492 {
493 Ok(Key4::new(ctime.into().unwrap_or_else(crate::now),
494 PublicKeyAlgorithm::X448,
495 mpi::PublicKey::X448 {
496 u: Box::new(public_key.try_into()?),
497 })?)
498 }
499
500 pub fn import_public_ed25519<T>(public_key: &[u8], ctime: T) -> Result<Self>
506 where T: Into<Option<time::SystemTime>>
507 {
508 let mut point = Vec::from(public_key);
509 point.insert(0, 0x40);
510
511 Self::new(
512 ctime.into().unwrap_or_else(crate::now),
513 PublicKeyAlgorithm::EdDSA,
514 mpi::PublicKey::EdDSA {
515 curve: Curve::Ed25519,
516 q: mpi::MPI::new(&point),
517 })
518 }
519
520 pub fn import_public_ed448<T>(public_key: &[u8], ctime: T) -> Result<Self>
526 where
527 T: Into<Option<time::SystemTime>>,
528 {
529 Ok(Key4::new(ctime.into().unwrap_or_else(crate::now),
530 PublicKeyAlgorithm::Ed448,
531 mpi::PublicKey::Ed448 {
532 a: Box::new(public_key.try_into()?),
533 })?)
534 }
535
536 pub fn import_public_rsa<T>(e: &[u8], n: &[u8], ctime: T)
543 -> Result<Self> where T: Into<Option<time::SystemTime>>
544 {
545 Self::new(
546 ctime.into().unwrap_or_else(crate::now),
547 PublicKeyAlgorithm::RSAEncryptSign,
548 mpi::PublicKey::RSA {
549 e: mpi::MPI::new(e),
550 n: mpi::MPI::new(n),
551 })
552 }
553}
554
555impl<R> Key4<SecretParts, R>
556 where R: key::KeyRole,
557{
558 pub fn with_secret<T>(creation_time: T, pk_algo: PublicKeyAlgorithm,
561 mpis: mpi::PublicKey,
562 secret: SecretKeyMaterial)
563 -> Result<Self>
564 where T: Into<time::SystemTime>
565 {
566 Ok(Key4 {
567 common: Default::default(),
568 creation_time: creation_time.into().try_into()?,
569 pk_algo,
570 mpis,
571 secret: Some(secret),
572 fingerprint: Default::default(),
573 role: R::role(),
574 p: std::marker::PhantomData,
575 r: std::marker::PhantomData,
576 })
577 }
578
579 pub fn import_secret_cv25519<H, S, T>(private_key: &[u8],
590 hash: H, sym: S, ctime: T)
591 -> Result<Self> where H: Into<Option<HashAlgorithm>>,
592 S: Into<Option<SymmetricAlgorithm>>,
593 T: Into<Option<std::time::SystemTime>>
594 {
595 use crate::crypto::backend::{Backend, interface::Asymmetric};
596
597 let mut private_key = Protected::from(private_key);
598 let public_key = Backend::x25519_derive_public(&private_key)?;
599
600 Backend::x25519_clamp_secret(&mut private_key);
608
609 private_key.reverse();
617
618 use crate::crypto::ecdh;
619 Self::with_secret(
620 ctime.into().unwrap_or_else(crate::now),
621 PublicKeyAlgorithm::ECDH,
622 mpi::PublicKey::ECDH {
623 curve: Curve::Cv25519,
624 hash: hash.into().unwrap_or_else(
625 || ecdh::default_ecdh_kdf_hash(&Curve::Cv25519)),
626 sym: sym.into().unwrap_or_else(
627 || ecdh::default_ecdh_kek_cipher(&Curve::Cv25519)),
628 q: mpi::MPI::new_compressed_point(&public_key),
629 },
630 mpi::SecretKeyMaterial::ECDH {
631 scalar: private_key.into(),
632 }.into())
633 }
634
635 pub fn import_secret_ed25519<T>(private_key: &[u8], ctime: T)
640 -> Result<Self> where T: Into<Option<time::SystemTime>>
641 {
642 use crate::crypto::backend::{Backend, interface::Asymmetric};
643
644 let private_key = Protected::from(private_key);
645 let public_key = Backend::ed25519_derive_public(&private_key)?;
646
647 Self::with_secret(
648 ctime.into().unwrap_or_else(crate::now),
649 PublicKeyAlgorithm::EdDSA,
650 mpi::PublicKey::EdDSA {
651 curve: Curve::Ed25519,
652 q: mpi::MPI::new_compressed_point(&public_key),
653 },
654 mpi::SecretKeyMaterial::EdDSA {
655 scalar: private_key.into(),
656 }.into())
657 }
658
659 pub fn generate_ecc(for_signing: bool, curve: Curve) -> Result<Self> {
666 use crate::crypto::backend::{Backend, interface::Asymmetric};
667
668 let (pk_algo, public, secret) = match (curve, for_signing) {
669 (Curve::Ed25519, true) => {
670 let (secret, public) = Backend::ed25519_generate_key()?;
671
672 (
673 PublicKeyAlgorithm::EdDSA,
674 mpi::PublicKey::EdDSA {
675 curve: Curve::Ed25519,
676 q: mpi::MPI::new_compressed_point(&public),
677 },
678 mpi::SecretKeyMaterial::EdDSA {
679 scalar: secret.into(),
680 },
681 )
682 },
683
684 (Curve::Cv25519, false) => {
685 let (mut secret, public) = Backend::x25519_generate_key()?;
686
687 Backend::x25519_clamp_secret(&mut secret);
695
696 secret.reverse();
705
706 (
707 PublicKeyAlgorithm::ECDH,
708 mpi::PublicKey::ECDH {
709 curve: Curve::Cv25519,
710 q: mpi::MPI::new_compressed_point(&public),
711 hash: crate::crypto::ecdh::default_ecdh_kdf_hash(
712 &Curve::Cv25519),
713 sym: crate::crypto::ecdh::default_ecdh_kek_cipher(
714 &Curve::Cv25519),
715 },
716 mpi::SecretKeyMaterial::ECDH {
717 scalar: secret.into(),
718 },
719 )
720 },
721
722 (curve, for_signing) =>
723 Self::generate_ecc_backend(for_signing, curve)?,
724 };
725
726 Self::with_secret(crate::now(), pk_algo, public, secret.into())
727 }
728
729 pub fn generate_dsa(p_bits: usize) -> Result<Self> {
735 use crate::crypto::backend::{Backend, interface::Asymmetric};
736
737 let (p, q, g, y, x) = Backend::dsa_generate_key(p_bits)?;
738 let public_mpis = mpi::PublicKey::DSA { p, q, g, y };
739 let private_mpis = mpi::SecretKeyMaterial::DSA { x };
740
741 Self::with_secret(
742 crate::now(),
743 #[allow(deprecated)]
744 PublicKeyAlgorithm::DSA,
745 public_mpis,
746 private_mpis.into())
747 }
748
749 pub fn generate_elgamal(p_bits: usize) -> Result<Self> {
754 use crate::crypto::backend::{Backend, interface::Asymmetric};
755
756 let (p, g, y, x) = Backend::elgamal_generate_key(p_bits)?;
757 let public_mpis = mpi::PublicKey::ElGamal { p, g, y };
758 let private_mpis = mpi::SecretKeyMaterial::ElGamal { x };
759
760 Self::with_secret(
761 crate::now(),
762 #[allow(deprecated)]
763 PublicKeyAlgorithm::ElGamalEncrypt,
764 public_mpis,
765 private_mpis.into())
766 }
767
768 pub fn generate_x25519() -> Result<Self> {
770 use crate::crypto::backend::{Backend, interface::Asymmetric};
771
772 let (private, public) = Backend::x25519_generate_key()?;
773
774 Self::with_secret(
775 crate::now(),
776 PublicKeyAlgorithm::X25519,
777 mpi::PublicKey::X25519 {
778 u: public,
779 },
780 mpi::SecretKeyMaterial::X25519 {
781 x: private,
782 }.into())
783 }
784
785 pub fn generate_x448() -> Result<Self> {
787 use crate::crypto::backend::{Backend, interface::Asymmetric};
788
789 let (private, public) = Backend::x448_generate_key()?;
790
791 Self::with_secret(
792 crate::now(),
793 PublicKeyAlgorithm::X448,
794 mpi::PublicKey::X448 {
795 u: Box::new(public),
796 },
797 mpi::SecretKeyMaterial::X448 {
798 x: private,
799 }.into())
800 }
801
802 pub fn generate_ed25519() -> Result<Self> {
804 use crate::crypto::backend::{Backend, interface::Asymmetric};
805
806 let (private, public) = Backend::ed25519_generate_key()?;
807
808 Self::with_secret(
809 crate::now(),
810 PublicKeyAlgorithm::Ed25519,
811 mpi::PublicKey::Ed25519 {
812 a: public,
813 },
814 mpi::SecretKeyMaterial::Ed25519 {
815 x: private,
816 }.into())
817 }
818
819 pub fn generate_ed448() -> Result<Self> {
821 use crate::crypto::backend::{Backend, interface::Asymmetric};
822
823 let (private, public) = Backend::ed448_generate_key()?;
824
825 Self::with_secret(
826 crate::now(),
827 PublicKeyAlgorithm::Ed448,
828 mpi::PublicKey::Ed448 {
829 a: Box::new(public),
830 },
831 mpi::SecretKeyMaterial::Ed448 {
832 x: private,
833 }.into())
834 }
835
836 pub fn into_keypair(self) -> Result<KeyPair> {
844 let (key, secret) = self.take_secret();
845 let secret = match secret {
846 SecretKeyMaterial::Unencrypted(secret) => secret,
847 SecretKeyMaterial::Encrypted(_) =>
848 return Err(Error::InvalidArgument(
849 "secret key material is encrypted".into()).into()),
850 };
851
852 KeyPair::new(key.role_into_unspecified().into(), secret)
853 }
854}
855
856macro_rules! impl_common_secret_functions {
857 ($t: ident) => {
858 impl<R> Key4<$t, R>
860 where R: key::KeyRole,
861 {
862 pub fn take_secret(mut self)
864 -> (Key4<PublicParts, R>, Option<SecretKeyMaterial>)
865 {
866 let old = std::mem::replace(&mut self.secret, None);
867 (self.parts_into_public(), old)
868 }
869
870 pub fn add_secret(mut self, secret: SecretKeyMaterial)
873 -> (Key4<SecretParts, R>, Option<SecretKeyMaterial>)
874 {
875 let old = std::mem::replace(&mut self.secret, Some(secret));
876 (self.parts_into_secret().expect("secret just set"), old)
877 }
878
879 pub fn steal_secret(&mut self) -> Option<SecretKeyMaterial>
881 {
882 std::mem::replace(&mut self.secret, None)
883 }
884 }
885 }
886}
887impl_common_secret_functions!(PublicParts);
888impl_common_secret_functions!(UnspecifiedParts);
889
890impl<R> Key4<SecretParts, R>
892 where R: key::KeyRole,
893{
894 pub fn secret(&self) -> &SecretKeyMaterial {
896 self.secret.as_ref().expect("has secret")
897 }
898
899 pub fn secret_mut(&mut self) -> &mut SecretKeyMaterial {
901 self.secret.as_mut().expect("has secret")
902 }
903
904 pub fn take_secret(mut self)
906 -> (Key4<PublicParts, R>, SecretKeyMaterial)
907 {
908 let old = std::mem::replace(&mut self.secret, None);
909 (self.parts_into_public(),
910 old.expect("Key<SecretParts, _> has a secret key material"))
911 }
912
913 pub fn add_secret(mut self, secret: SecretKeyMaterial)
917 -> (Key4<SecretParts, R>, SecretKeyMaterial)
918 {
919 let old = std::mem::replace(&mut self.secret, Some(secret));
920 (self.parts_into_secret().expect("secret just set"),
921 old.expect("Key<SecretParts, _> has a secret key material"))
922 }
923
924 pub fn decrypt_secret(self, password: &Password) -> Result<Self> {
939 let (key, mut secret) = self.take_secret();
940 let key = Key::V4(key);
941 secret.decrypt_in_place(&key, password)?;
942 let key = if let Key::V4(k) = key { k } else { unreachable!() };
943 Ok(key.add_secret(secret).0)
944 }
945
946 pub fn encrypt_secret(self, password: &Password)
961 -> Result<Key4<SecretParts, R>>
962 {
963 let (key, mut secret) = self.take_secret();
964 let key = Key::V4(key);
965 secret.encrypt_in_place(&key, password)?;
966 let key = if let Key::V4(k) = key { k } else { unreachable!() };
967 Ok(key.add_secret(secret).0)
968 }
969}
970
971impl<P, R> From<Key4<P, R>> for super::Key<P, R>
972 where P: key::KeyParts,
973 R: key::KeyRole,
974{
975 fn from(p: Key4<P, R>) -> Self {
976 super::Key::V4(p)
977 }
978}
979
980#[cfg(test)]
981use crate::packet::key::{
982 PrimaryRole,
983 SubordinateRole,
984 UnspecifiedRole,
985};
986
987#[cfg(test)]
988impl Arbitrary for Key4<PublicParts, PrimaryRole> {
989 fn arbitrary(g: &mut Gen) -> Self {
990 Key4::<PublicParts, UnspecifiedRole>::arbitrary(g).into()
991 }
992}
993
994#[cfg(test)]
995impl Arbitrary for Key4<PublicParts, SubordinateRole> {
996 fn arbitrary(g: &mut Gen) -> Self {
997 Key4::<PublicParts, UnspecifiedRole>::arbitrary(g).into()
998 }
999}
1000
1001#[cfg(test)]
1002impl Arbitrary for Key4<PublicParts, UnspecifiedRole> {
1003 fn arbitrary(g: &mut Gen) -> Self {
1004 let mpis = mpi::PublicKey::arbitrary(g);
1005 Key4 {
1006 common: Arbitrary::arbitrary(g),
1007 creation_time: Arbitrary::arbitrary(g),
1008 pk_algo: mpis.algo()
1009 .expect("mpi::PublicKey::arbitrary only uses known algos"),
1010 mpis,
1011 secret: None,
1012 fingerprint: Default::default(),
1013 role: UnspecifiedRole::role(),
1014 p: std::marker::PhantomData,
1015 r: std::marker::PhantomData,
1016 }
1017 }
1018}
1019
1020#[cfg(test)]
1021impl Arbitrary for Key4<SecretParts, PrimaryRole> {
1022 fn arbitrary(g: &mut Gen) -> Self {
1023 Key4::<SecretParts, PrimaryRole>::arbitrary_secret_key(g)
1024 }
1025}
1026
1027#[cfg(test)]
1028impl Arbitrary for Key4<SecretParts, SubordinateRole> {
1029 fn arbitrary(g: &mut Gen) -> Self {
1030 Key4::<SecretParts, SubordinateRole>::arbitrary_secret_key(g)
1031 }
1032}
1033
1034#[cfg(test)]
1035impl<R> Key4<SecretParts, R>
1036where
1037 R: KeyRole,
1038 Key4::<PublicParts, R>: Arbitrary,
1039{
1040 fn arbitrary_secret_key(g: &mut Gen) -> Self {
1041 let key = Key::V4(Key4::<PublicParts, R>::arbitrary(g));
1042 let mut secret: SecretKeyMaterial =
1043 mpi::SecretKeyMaterial::arbitrary_for(g, key.pk_algo())
1044 .expect("only known algos used")
1045 .into();
1046
1047 if <bool>::arbitrary(g) {
1048 secret.encrypt_in_place(&key, &Password::from(Vec::arbitrary(g)))
1049 .unwrap();
1050 }
1051
1052 let key = if let Key::V4(k) = key { k } else { unreachable!() };
1053 Key4::<PublicParts, R>::add_secret(key, secret).0
1054 }
1055}
1056
1057#[cfg(test)]
1058mod tests {
1059 use std::time::Duration;
1060 use std::time::UNIX_EPOCH;
1061
1062 use crate::crypto::S2K;
1063 use crate::packet::Key;
1064 use crate::Cert;
1065 use crate::packet::pkesk::PKESK3;
1066 use crate::packet::key;
1067 use crate::packet::key::SecretKeyMaterial;
1068 use crate::packet::Packet;
1069 use super::*;
1070 use crate::PacketPile;
1071 use crate::serialize::Serialize;
1072 use crate::parse::Parse;
1073
1074 #[test]
1075 fn encrypted_rsa_key() {
1076 let cert = Cert::from_bytes(
1077 crate::tests::key("testy-new-encrypted-with-123.pgp")).unwrap();
1078 let key = cert.primary_key().key().clone();
1079 let (key, secret) = key.take_secret();
1080 let mut secret = secret.unwrap();
1081
1082 assert!(secret.is_encrypted());
1083 secret.decrypt_in_place(&key, &"123".into()).unwrap();
1084 assert!(!secret.is_encrypted());
1085 let (pair, _) = key.add_secret(secret);
1086 assert!(pair.has_unencrypted_secret());
1087
1088 match pair.secret() {
1089 SecretKeyMaterial::Unencrypted(ref u) => u.map(|mpis| match mpis {
1090 mpi::SecretKeyMaterial::RSA { .. } => (),
1091 _ => panic!(),
1092 }),
1093 _ => panic!(),
1094 }
1095 }
1096
1097 #[test]
1098 fn primary_key_encrypt_decrypt() -> Result<()> {
1099 key_encrypt_decrypt::<PrimaryRole>()
1100 }
1101
1102 #[test]
1103 fn subkey_encrypt_decrypt() -> Result<()> {
1104 key_encrypt_decrypt::<SubordinateRole>()
1105 }
1106
1107 fn key_encrypt_decrypt<R>() -> Result<()>
1108 where
1109 R: KeyRole + PartialEq,
1110 {
1111 let mut g = quickcheck::Gen::new(256);
1112 let p: Password = Vec::<u8>::arbitrary(&mut g).into();
1113
1114 let check = |key: Key4<SecretParts, R>| -> Result<()> {
1115 let key: Key<_, _> = key.into();
1116 let encrypted = key.clone().encrypt_secret(&p)?;
1117 let decrypted = encrypted.decrypt_secret(&p)?;
1118 assert_eq!(key, decrypted);
1119 Ok(())
1120 };
1121
1122 use crate::types::Curve::*;
1123 for curve in vec![NistP256, NistP384, NistP521, Ed25519] {
1124 if ! curve.is_supported() {
1125 eprintln!("Skipping unsupported {}", curve);
1126 continue;
1127 }
1128
1129 let key: Key4<_, R>
1130 = Key4::generate_ecc(true, curve.clone())?;
1131 check(key)?;
1132 }
1133
1134 for bits in vec![2048, 3072] {
1135 if ! PublicKeyAlgorithm::RSAEncryptSign.is_supported() {
1136 eprintln!("Skipping unsupported RSA");
1137 continue;
1138 }
1139
1140 let key: Key4<_, R>
1141 = Key4::generate_rsa(bits)?;
1142 check(key)?;
1143 }
1144
1145 Ok(())
1146 }
1147
1148 #[test]
1149 fn eq() {
1150 use crate::types::Curve::*;
1151
1152 for curve in vec![NistP256, NistP384, NistP521] {
1153 if ! curve.is_supported() {
1154 eprintln!("Skipping unsupported {}", curve);
1155 continue;
1156 }
1157
1158 let sign_key : Key4<_, key::UnspecifiedRole>
1159 = Key4::generate_ecc(true, curve.clone()).unwrap();
1160 let enc_key : Key4<_, key::UnspecifiedRole>
1161 = Key4::generate_ecc(false, curve).unwrap();
1162 let sign_clone = sign_key.clone();
1163 let enc_clone = enc_key.clone();
1164
1165 assert_eq!(sign_key, sign_clone);
1166 assert_eq!(enc_key, enc_clone);
1167 }
1168
1169 for bits in vec![1024, 2048, 3072, 4096] {
1170 if ! PublicKeyAlgorithm::RSAEncryptSign.is_supported() {
1171 eprintln!("Skipping unsupported RSA");
1172 continue;
1173 }
1174
1175 let key : Key4<_, key::UnspecifiedRole>
1176 = Key4::generate_rsa(bits).unwrap();
1177 let clone = key.clone();
1178 assert_eq!(key, clone);
1179 }
1180 }
1181
1182 #[test]
1183 fn generate_roundtrip() {
1184 use crate::types::Curve::*;
1185
1186 let keys = vec![NistP256, NistP384, NistP521].into_iter().flat_map(|cv|
1187 {
1188 if ! cv.is_supported() {
1189 eprintln!("Skipping unsupported {}", cv);
1190 return Vec::new();
1191 }
1192
1193 let sign_key : Key4<key::SecretParts, key::PrimaryRole>
1194 = Key4::generate_ecc(true, cv.clone()).unwrap();
1195 let enc_key = Key4::generate_ecc(false, cv).unwrap();
1196
1197 vec![sign_key, enc_key]
1198 }).chain(vec![1024, 2048, 3072, 4096].into_iter().filter_map(|b| {
1199 Key4::generate_rsa(b).ok()
1200 }));
1201
1202 for key in keys {
1203 let mut b = Vec::new();
1204 Packet::SecretKey(key.clone().into()).serialize(&mut b).unwrap();
1205
1206 let pp = PacketPile::from_bytes(&b).unwrap();
1207 if let Some(Packet::SecretKey(Key::V4(ref parsed_key))) =
1208 pp.path_ref(&[0])
1209 {
1210 assert_eq!(key.creation_time(), parsed_key.creation_time());
1211 assert_eq!(key.pk_algo(), parsed_key.pk_algo());
1212 assert_eq!(key.mpis(), parsed_key.mpis());
1213 assert_eq!(key.secret(), parsed_key.secret());
1214
1215 assert_eq!(&key, parsed_key);
1216 } else {
1217 panic!("bad packet: {:?}", pp.path_ref(&[0]));
1218 }
1219
1220 let mut b = Vec::new();
1221 let pk4 : Key4<PublicParts, PrimaryRole> = key.clone().into();
1222 Packet::PublicKey(pk4.into()).serialize(&mut b).unwrap();
1223
1224 let pp = PacketPile::from_bytes(&b).unwrap();
1225 if let Some(Packet::PublicKey(Key::V4(ref parsed_key))) =
1226 pp.path_ref(&[0])
1227 {
1228 assert!(! parsed_key.has_secret());
1229
1230 let key = key.take_secret().0;
1231 assert_eq!(&key, parsed_key);
1232 } else {
1233 panic!("bad packet: {:?}", pp.path_ref(&[0]));
1234 }
1235 }
1236 }
1237
1238 #[test]
1239 fn encryption_roundtrip() {
1240 use crate::crypto::SessionKey;
1241 use crate::types::Curve::*;
1242
1243 let keys = vec![NistP256, NistP384, NistP521].into_iter()
1244 .filter_map(|cv| {
1245 Key4::generate_ecc(false, cv).ok()
1246 }).chain(vec![1024, 2048, 3072, 4096].into_iter().filter_map(|b| {
1247 Key4::generate_rsa(b).ok()
1248 })).chain(vec![1024, 2048, 3072, 4096].into_iter().filter_map(|b| {
1249 Key4::generate_elgamal(b).ok()
1250 }));
1251
1252 for key in keys.into_iter() {
1253 let key: Key<key::SecretParts, key::UnspecifiedRole> = key.into();
1254 let mut keypair = key.clone().into_keypair().unwrap();
1255 let cipher = SymmetricAlgorithm::AES256;
1256 let sk = SessionKey::new(cipher.key_size().unwrap()).unwrap();
1257
1258 let pkesk = PKESK3::for_recipient(cipher, &sk, &key).unwrap();
1259 let (cipher_, sk_) = pkesk.decrypt(&mut keypair, None)
1260 .expect("keypair should be able to decrypt PKESK");
1261
1262 assert_eq!(cipher, cipher_);
1263 assert_eq!(sk, sk_);
1264
1265 let (cipher_, sk_) =
1266 pkesk.decrypt(&mut keypair, Some(cipher)).unwrap();
1267
1268 assert_eq!(cipher, cipher_);
1269 assert_eq!(sk, sk_);
1270 }
1271 }
1272
1273 #[test]
1274 fn secret_encryption_roundtrip() {
1275 use crate::types::Curve::*;
1276 use crate::types::SymmetricAlgorithm::*;
1277 use crate::types::AEADAlgorithm::*;
1278
1279 let keys = vec![NistP256, NistP384, NistP521].into_iter()
1280 .filter_map(|cv| -> Option<Key<key::SecretParts, key::PrimaryRole>> {
1281 Key4::generate_ecc(false, cv).map(Into::into).ok()
1282 }).chain(vec![1024, 2048, 3072, 4096].into_iter().filter_map(|b| {
1283 Key4::generate_rsa(b).map(Into::into).ok()
1284 }));
1285
1286 for key in keys {
1287 for (symm, aead) in [(AES128, None),
1288 (AES128, Some(OCB)),
1289 (AES256, Some(EAX))] {
1290 if ! aead.map(|a| a.is_supported()).unwrap_or(true) {
1291 continue;
1292 }
1293 assert!(! key.secret().is_encrypted());
1294
1295 let password = Password::from("foobarbaz");
1296 let mut encrypted_key = key.clone();
1297
1298 encrypted_key.secret_mut()
1299 .encrypt_in_place_with(&key, S2K::default(), symm, aead,
1300 &password).unwrap();
1301 assert!(encrypted_key.secret().is_encrypted());
1302
1303 encrypted_key.secret_mut()
1304 .decrypt_in_place(&key, &password).unwrap();
1305 assert!(! key.secret().is_encrypted());
1306 assert_eq!(key, encrypted_key);
1307 assert_eq!(key.secret(), encrypted_key.secret());
1308 }
1309 }
1310 }
1311
1312 #[test]
1313 fn import_cv25519() {
1314 use crate::crypto::{ecdh, mem, SessionKey};
1315 use self::mpi::{MPI, Ciphertext};
1316
1317 let ctime =
1319 time::UNIX_EPOCH + time::Duration::new(0x5c487129, 0);
1320 let public = b"\xed\x59\x0a\x15\x08\x95\xe9\x92\xd2\x2c\x14\x01\xb3\xe9\x3b\x7f\xff\xe6\x6f\x22\x65\xec\x69\xd9\xb8\xda\x24\x2c\x64\x84\x44\x11";
1321 let key : Key<_, key::UnspecifiedRole>
1322 = Key4::import_public_cv25519(&public[..],
1323 HashAlgorithm::SHA256,
1324 SymmetricAlgorithm::AES128,
1325 ctime).unwrap().into();
1326
1327 let eph_pubkey = MPI::new(&b"\x40\xda\x1c\x69\xc4\xe3\xb6\x9c\x6e\xd4\xc6\x69\x6c\x89\xc7\x09\xe9\xf8\x6a\xf1\xe3\x8d\xb6\xaa\xb5\xf7\x29\xae\xa6\xe7\xdd\xfe\x38"[..]);
1329 let ciphertext = Ciphertext::ECDH{
1330 e: eph_pubkey.clone(),
1331 key: Vec::from(&b"\x45\x8b\xd8\x4d\x88\xb3\xd2\x16\xb6\xc2\x3b\x99\x33\xd1\x23\x4b\x10\x15\x8e\x04\x16\xc5\x7c\x94\x88\xf6\x63\xf2\x68\x37\x08\x66\xfd\x5a\x7b\x40\x58\x21\x6b\x2c\xc0\xf4\xdc\x91\xd3\x48\xed\xc1"[..]).into_boxed_slice()
1332 };
1333 let shared_sec: mem::Protected = b"\x44\x0C\x99\x27\xF7\xD6\x1E\xAD\xD1\x1E\x9E\xC8\x22\x2C\x5D\x43\xCE\xB0\xE5\x45\x94\xEC\xAF\x67\xD9\x35\x1D\xA1\xA3\xA8\x10\x0B"[..].into();
1334
1335 let dek = b"\x09\x0D\xDC\x40\xC5\x71\x51\x88\xAC\xBD\x45\x56\xD4\x2A\xDF\x77\xCD\xF4\x82\xA2\x1B\x8F\x2E\x48\x3B\xCA\xBF\xD3\xE8\x6D\x0A\x7C\xDF\x10\xe6";
1337 let sk = SessionKey::from(Vec::from(&dek[..]));
1338
1339 let got_enc = ecdh::encrypt_wrap(&key.parts_into_public().role_into_subordinate(),
1341 &sk, eph_pubkey, &shared_sec)
1342 .unwrap();
1343
1344 assert_eq!(ciphertext, got_enc);
1345 }
1346
1347 #[test]
1348 fn import_cv25519_sec() -> Result<()> {
1349 use self::mpi::{MPI, Ciphertext};
1350
1351 let ctime =
1353 time::UNIX_EPOCH + time::Duration::new(0x5c487129, 0);
1354 let public = b"\xed\x59\x0a\x15\x08\x95\xe9\x92\xd2\x2c\x14\x01\xb3\xe9\x3b\x7f\xff\xe6\x6f\x22\x65\xec\x69\xd9\xb8\xda\x24\x2c\x64\x84\x44\x11";
1355 let secret = b"\xa0\x27\x13\x99\xc9\xe3\x2e\xd2\x47\xf6\xd6\x63\x9d\xe6\xec\xcb\x57\x0b\x92\xbb\x17\xfe\xb8\xf1\xc4\x1f\x06\x7c\x55\xfc\xdd\x58";
1356 let key: Key<_, UnspecifiedRole>
1357 = Key4::import_secret_cv25519(&secret[..],
1358 HashAlgorithm::SHA256,
1359 SymmetricAlgorithm::AES128,
1360 ctime).unwrap().into();
1361 match key.mpis() {
1362 self::mpi::PublicKey::ECDH{ ref q,.. } =>
1363 assert_eq!(&q.value()[1..], &public[..]),
1364 _ => unreachable!(),
1365 }
1366
1367 let eph_pubkey: &[u8; 33] = b"\x40\xda\x1c\x69\xc4\xe3\xb6\x9c\x6e\xd4\xc6\x69\x6c\x89\xc7\x09\xe9\xf8\x6a\xf1\xe3\x8d\xb6\xaa\xb5\xf7\x29\xae\xa6\xe7\xdd\xfe\x38";
1369 let ciphertext = Ciphertext::ECDH{
1370 e: MPI::new(&eph_pubkey[..]),
1371 key: Vec::from(&b"\x45\x8b\xd8\x4d\x88\xb3\xd2\x16\xb6\xc2\x3b\x99\x33\xd1\x23\x4b\x10\x15\x8e\x04\x16\xc5\x7c\x94\x88\xf6\x63\xf2\x68\x37\x08\x66\xfd\x5a\x7b\x40\x58\x21\x6b\x2c\xc0\xf4\xdc\x91\xd3\x48\xed\xc1"[..]).into_boxed_slice()
1372 };
1373 let pkesk =
1374 PKESK3::new(None, PublicKeyAlgorithm::ECDH, ciphertext)?;
1375
1376 let dek = b"\x0D\xDC\x40\xC5\x71\x51\x88\xAC\xBD\x45\x56\xD4\x2A\xDF\x77\xCD\xF4\x82\xA2\x1B\x8F\x2E\x48\x3B\xCA\xBF\xD3\xE8\x6D\x0A\x7C\xDF";
1378
1379 let key = key.parts_into_secret().unwrap();
1380 let mut keypair = key.into_keypair()?;
1381 let (sym, got_dek) = pkesk.decrypt(&mut keypair, None).unwrap();
1382
1383 assert_eq!(sym, SymmetricAlgorithm::AES256);
1384 assert_eq!(&dek[..], &got_dek[..]);
1385 Ok(())
1386 }
1387
1388 #[test]
1389 fn import_rsa() -> Result<()> {
1390 use crate::crypto::SessionKey;
1391 use self::mpi::{MPI, Ciphertext};
1392
1393 let ctime =
1395 time::UNIX_EPOCH + time::Duration::new(1548950502, 0);
1396 let d = b"\x14\xC4\x3A\x0C\x3A\x79\xA4\xF7\x63\x0D\x89\x93\x63\x8B\x56\x9C\x29\x2E\xCD\xCF\xBF\xB0\xEC\x66\x52\xC3\x70\x1B\x19\x21\x73\xDE\x8B\xAC\x0E\xF2\xE1\x28\x42\x66\x56\x55\x00\x3B\xFD\x50\xC4\x7C\xBC\x9D\xEB\x7D\xF4\x81\xFC\xC3\xBF\xF7\xFF\xD0\x41\x3E\x50\x3B\x5F\x5D\x5F\x56\x67\x5E\x00\xCE\xA4\x53\xB8\x59\xA0\x40\xC8\x96\x6D\x12\x09\x27\xBE\x1D\xF1\xC2\x68\xFC\xF0\x14\xD6\x52\x77\x07\xC8\x12\x36\x9C\x9A\x5C\xAF\x43\xCC\x95\x20\xBB\x0A\x44\x94\xDD\xB4\x4F\x45\x4E\x3A\x1A\x30\x0D\x66\x40\xAC\x68\xE8\xB0\xFD\xCD\x6C\x6B\x6C\xB5\xF7\xE4\x36\x95\xC2\x96\x98\xFD\xCA\x39\x6C\x1A\x2E\x55\xAD\xB6\xE0\xF8\x2C\xFF\xBC\xD3\x32\x15\x52\x39\xB3\x92\x35\xDB\x8B\x68\xAF\x2D\x4A\x6E\x64\xB8\x28\x63\xC4\x24\x94\x2D\xA9\xDB\x93\x56\xE3\xBC\xD0\xB6\x38\x84\x04\xA4\xC6\x18\x48\xFE\xB2\xF8\xE1\x60\x37\x52\x96\x41\xA5\x79\xF6\x3D\xB7\x2A\x71\x5B\x7A\x75\xBF\x7F\xA2\x5A\xC8\xA1\x38\xF2\x5A\xBD\x14\xFC\xAF\xB4\x54\x83\xA4\xBD\x49\xA2\x8B\x91\xB0\xE0\x4A\x1B\x21\x54\x07\x19\x70\x64\x7C\x3E\x9F\x8D\x8B\xE4\x70\xD1\xE7\xBE\x4E\x5C\xCE\xF1";
1397 let p = b"\xC8\x32\xD1\x17\x41\x4D\x8F\x37\x09\x18\x32\x4C\x4C\xF4\xA2\x15\x27\x43\x3D\xBB\xB5\xF6\x1F\xCF\xD2\xE4\x43\x61\x07\x0E\x9E\x35\x1F\x0A\x5D\xFB\x3A\x45\x74\x61\x73\x73\x7B\x5F\x1F\x87\xFB\x54\x8D\xA8\x85\x3E\xB0\xB7\xC7\xF5\xC9\x13\x99\x8D\x40\xE6\xA6\xD0\x71\x3A\xE3\x2D\x4A\xC3\xA3\xFF\xF7\x72\x82\x14\x52\xA4\xBA\x63\x0E\x17\xCA\xCA\x18\xC4\x3A\x40\x79\xF1\x86\xB3\x10\x4B\x9F\xB2\xAE\x2E\x13\x38\x8D\x2C\xF9\x88\x4C\x25\x53\xEF\xF9\xD1\x8B\x1A\x7C\xE7\xF6\x4B\x73\x51\x31\xFA\x44\x1D\x36\x65\x71\xDA\xFC\x6F";
1398 let q = b"\xCC\x30\xE9\xCC\xCB\x31\x28\xB5\x90\xFF\x06\x62\x42\x5B\x24\x0E\x00\xFE\xE2\x37\xC4\xAC\xBB\x3B\x8F\xF2\x0E\x3F\x78\xCF\x6B\x7C\xE8\x75\x57\x7C\x15\x9D\x1A\x66\xF2\x0A\xE5\xD3\x0B\xE7\x40\xF7\xE7\x00\xB6\x86\xB5\xD9\x20\x67\xE0\x4A\xC0\x90\xA4\x13\x4D\xC9\xB0\x12\xC5\xCD\x4C\xEB\xA1\x91\x2D\x43\x58\x6E\xB6\x75\xA0\x93\xF0\x5B\xC5\x31\xCA\xB7\xC6\x22\x0C\xD3\xEC\x84\xC5\x91\xA1\x5F\x2C\x8E\x07\x5D\xA1\x98\x67\xC5\x7A\x58\x16\x71\x3D\xED\x91\x03\x0D\xD4\x25\x07\x89\x9B\x33\x98\xA3\x70\xD9\xE7\xC8\x17\xA3\xD9";
1399
1400 let reference_key = Packet::from_bytes(b"\
1401-----BEGIN PGP PRIVATE KEY BLOCK-----
1402
1403xcLYBFxTG+YBCACfrr78JBmS/7rxsQg7y1IialuUqqbXmpMXz8mmd/tYKB1kymnK
1404kciCvYJ3CKq/3c3AlTlV7x4qKcXIL5XSuONdq9xHHpFyxjMJLAYMNn+PR6BgyLJG
1405J9MThBxELQGw7MEL+/7iFT6N92eu8PTyUnQwdDXA6JV5M49fbYCiG/2sCXSyVtJJ
1406DcQWkWQSZasC82PmFX4C/5QqunZ6nXRLkx79ErHwCzqO9GqY7rgPErmV0Hd2LXUt
1407AesCmSBFiR3Ole1MwNwp67hzQmFILqoBRKmJoEOfhjOiTCMET4SP7IE2pcpGKJyP
1408yJHwlfsG8SKTXBOsu9NUizX4HvSZ4ohXU6cXABEBAAEAB/0UxDoMOnmk92MNiZNj
1409i1acKS7Nz7+w7GZSw3AbGSFz3ousDvLhKEJmVlUAO/1QxHy8net99IH8w7/3/9BB
1410PlA7X11fVmdeAM6kU7hZoEDIlm0SCSe+HfHCaPzwFNZSdwfIEjacmlyvQ8yVILsK
1411RJTdtE9FTjoaMA1mQKxo6LD9zWxrbLX35DaVwpaY/co5bBouVa224Pgs/7zTMhVS
1412ObOSNduLaK8tSm5kuChjxCSULanbk1bjvNC2OIQEpMYYSP6y+OFgN1KWQaV59j23
1413KnFbenW/f6JayKE48lq9FPyvtFSDpL1JoouRsOBKGyFUBxlwZHw+n42L5HDR575O
1414XM7xBADIMtEXQU2PNwkYMkxM9KIVJ0M9u7X2H8/S5ENhBw6eNR8KXfs6RXRhc3N7
1415Xx+H+1SNqIU+sLfH9ckTmY1A5qbQcTrjLUrDo//3coIUUqS6Yw4XysoYxDpAefGG
1416sxBLn7KuLhM4jSz5iEwlU+/50YsafOf2S3NRMfpEHTZlcdr8bwQAzDDpzMsxKLWQ
1417/wZiQlskDgD+4jfErLs7j/IOP3jPa3zodVd8FZ0aZvIK5dML50D35wC2hrXZIGfg
1418SsCQpBNNybASxc1M66GRLUNYbrZ1oJPwW8UxyrfGIgzT7ITFkaFfLI4HXaGYZ8V6
1419WBZxPe2RAw3UJQeJmzOYo3DZ58gXo9kD/jLU2VpxpU/3BKrRO5AyvfMUKWlKXleT
1420pogdwcu0hHYntKr4mce7tBlRQRhtUv4dzRQ8OJ75oyvtl9mNfWaIOB/Jv5UOxeXh
1421jh20P23NClrtoM+5lYiaLEx0ZfD8xq85AKqrhMwcw4jH0lhJebTYOEeKrfD6SPbL
1422bzBv85X5WCw7RQ8=
1423=hd62
1424-----END PGP PRIVATE KEY BLOCK-----
1425")?;
1426
1427 let c = b"\x8A\x1A\xD4\x82\x91\x6B\xBF\xA1\x65\xD3\x82\x8C\x97\xAB\xD0\x91\xE4\xB4\xC4\x9D\x08\xD8\x8B\xB7\xE6\x13\x3F\x6F\x52\x14\xED\xC4\x77\xB7\x31\x00\xC1\x43\xF9\x62\x53\xBF\x21\x21\x52\x74\x35\xD8\xC7\xA2\x11\x89\xA5\xD5\x21\x98\x6D\x3C\x9F\xF0\xED\xDB\xD7\x0F\xAC\x3C\x15\x25\x34\x52\xC7\x7C\x82\x07\x5A\x99\xC1\xC6\xF6\xF2\x6D\x46\xC8\x56\x59\xE7\xC6\x34\x0C\xCA\x37\x70\xB4\x97\xDA\x18\x14\xC4\x03\x0A\xCB\xE5\x0C\x41\x43\x61\xBA\x32\xB6\x9A\xF3\xDF\x0C\xB0\xCE\xBD\xFE\x72\x6C\xCC\xC1\xE8\xF0\x05\x97\x61\xEA\x30\x10\xB9\x43\xC4\x9A\x41\xED\x72\x27\xA4\xD5\xE7\x08\x41\x6C\x57\x80\xF3\x64\xF0\x45\x70\x27\x36\xBD\x64\x59\x74\xCF\xCD\x39\xE6\xEB\x7C\x62\xC8\x38\x23\xF8\x4C\xB7\x30\x9F\xF1\x40\x4A\xE9\x72\x66\x99\xF7\x2A\x47\x1C\xE7\x12\x20\x58\xBA\x87\x00\xB8\xFC\x54\xBC\xA5\x1D\x7D\x8B\x50\xA4\x4B\xB3\xD7\x44\xC7\x68\x5E\x2D\xBB\xE9\x6E\xC4\xD0\x31\xB0\xD0\xB6\x02\xD1\x74\x6B\xC9\x3D\x19\x32\x3B\xF1\x0E\x74\xF6\x12\x13\xE6\x40\x8F\xA6\x97\xAD\x83\xB0\x84\xD6\xD9\xE5\x25\x8E\x57\x0B\x7A\x7B\xD0\x5C\x29\x96\xED\x29\xED";
1429 let ciphertext = Ciphertext::RSA{
1430 c: MPI::new(&c[..]),
1431 };
1432 let pkesk = PKESK3::new(None,
1433 PublicKeyAlgorithm::RSAEncryptSign,
1434 ciphertext).unwrap();
1435
1436 let dek = b"\xA5\x58\x3A\x04\x35\x8B\xC7\x3F\x4A\xEF\x0C\x5A\xEB\xED\x59\xCA\xFD\x96\xB5\x32\x23\x26\x0C\x91\x78\xD1\x31\x12\xF0\x41\x42\x9D";
1438 let sk = SessionKey::from(Vec::from(&dek[..]));
1439
1440 let test = |d: &[u8], p: &[u8], q: &[u8]| -> Result<()> {
1441 let key: key::SecretKey
1442 = Key4::import_secret_rsa(d, p, q, ctime)?.into();
1443 assert_eq!(Packet::from(key.clone()), reference_key);
1444 let mut decryptor = key.into_keypair()?;
1445 let got_sk = pkesk.decrypt(&mut decryptor, None).unwrap();
1446 assert_eq!(got_sk.1, sk);
1447 Ok(())
1448 };
1449
1450 test(d, p, q)?;
1451 test(d, q, p)?;
1452 Ok(())
1453 }
1454
1455 #[test]
1456 fn import_ed25519() {
1457 use crate::types::SignatureType;
1458 use crate::packet::signature::Signature4;
1459 use crate::packet::signature::subpacket::{
1460 Subpacket, SubpacketValue, SubpacketArea};
1461
1462 let ctime =
1464 time::UNIX_EPOCH + time::Duration::new(1548249630, 0);
1465 let q = b"\x57\x15\x45\x1B\x68\xA5\x13\xA2\x20\x0F\x71\x9D\xE3\x05\x3B\xED\xA2\x21\xDE\x61\x5A\xF5\x67\x45\xBB\x97\x99\x43\x53\x59\x7C\x3F";
1466 let key: key::PublicKey
1467 = Key4::import_public_ed25519(q, ctime).unwrap().into();
1468
1469 let mut hashed = SubpacketArea::default();
1470 let mut unhashed = SubpacketArea::default();
1471 let fpr = "D81A 5DC0 DEBF EE5F 9AC8 20EB 6769 5DB9 920D 4FAC"
1472 .parse().unwrap();
1473 let kid = "6769 5DB9 920D 4FAC".parse().unwrap();
1474 let ctime = 1549460479.into();
1475 let r = b"\x5A\xF9\xC7\x42\x70\x24\x73\xFF\x7F\x27\xF9\x20\x9D\x20\x0F\xE3\x8F\x71\x3C\x5F\x97\xFD\x60\x80\x39\x29\xC2\x14\xFD\xC2\x4D\x70";
1476 let s = b"\x6E\x68\x74\x11\x72\xF4\x9C\xE1\x99\x99\x1F\x67\xFC\x3A\x68\x33\xF9\x3F\x3A\xB9\x1A\xA5\x72\x4E\x78\xD4\x81\xCB\x7B\xA5\xE5\x0A";
1477
1478 hashed.add(Subpacket::new(SubpacketValue::IssuerFingerprint(fpr), false).unwrap()).unwrap();
1479 hashed.add(Subpacket::new(SubpacketValue::SignatureCreationTime(ctime), false).unwrap()).unwrap();
1480 unhashed.add(Subpacket::new(SubpacketValue::Issuer(kid), false).unwrap()).unwrap();
1481
1482 eprintln!("fpr: {}", key.fingerprint());
1483 let sig = Signature4::new(SignatureType::Binary, PublicKeyAlgorithm::EdDSA,
1484 HashAlgorithm::SHA256, hashed, unhashed,
1485 [0xa7,0x19],
1486 mpi::Signature::EdDSA{
1487 r: mpi::MPI::new(r), s: mpi::MPI::new(s)
1488 });
1489 let sig: Signature = sig.into();
1490 sig.verify_message(&key, b"Hello, World\n").unwrap();
1491 }
1492
1493 #[test]
1494 fn fingerprint_test() {
1495 let pile =
1496 PacketPile::from_bytes(crate::tests::key("public-key.pgp")).unwrap();
1497
1498 let mut pki = 0;
1500 let mut ski = 0;
1501
1502 let pks = [ "8F17777118A33DDA9BA48E62AACB3243630052D9" ];
1503 let sks = [ "C03FA6411B03AE12576461187223B56678E02528",
1504 "50E6D924308DBF223CFB510AC2B819056C652598",
1505 "2DC50AB55BE2F3B04C2D2CF8A3506AFB820ABD08"];
1506
1507 for p in pile.descendants() {
1508 if let &Packet::PublicKey(ref p) = p {
1509 let fp = p.fingerprint().to_hex();
1510 assert!(pki < pks.len());
1513 assert_eq!(fp, pks[pki]);
1514 pki += 1;
1515 }
1516
1517 if let &Packet::PublicSubkey(ref p) = p {
1518 let fp = p.fingerprint().to_hex();
1519 assert!(ski < sks.len());
1522 assert_eq!(fp, sks[ski]);
1523 ski += 1;
1524 }
1525 }
1526 assert!(pki == pks.len() && ski == sks.len());
1527 }
1528
1529 #[test]
1530 fn issue_617() -> Result<()> {
1531 use crate::serialize::MarshalInto;
1532 let p = Packet::from_bytes(&b"-----BEGIN PGP ARMORED FILE-----
1533
1534xcClBAAAAMUWBSuBBAAjAPDbS+Z6Ti+PouOV6c5Ypr3jn1w1Ih5GqikN5E29PGz+
1535CQMIoYc7R4YRiLr/ZJB/MW5M0kuuWyUirUKRkYCotB5omVE8fGtqW5wGCGf79Tzb
1536rKVmPl25CJdEabIfAOl0WwciipDx1tqNOOYEci/JWSbTEymEyCH9oQPObt2sdDxh
1537wLcBgsd/CVl3kuqiXFHNYDvWVBmUHeltS/J22Kfy/n1qD3CCBFooHGdc13KwtMLk
1538UPb5LTTqCk2ihQ7e+5u7EmueLUp1431HJiYa+olaPZ7caRNfQfggtHcfQOJdnWRJ
1539FN2nTDgLHX0cEOiMboZrS4S9xtjyVRLcRZcCIyeQF0Q889rq0lmxHG38XUeIj/3y
1540SJJNnZxmJtHNo+SZQ/gXhO9TzeeA6yQm2myQlRkXBtdQEz6mtznphWeWMkWApZpa
1541FwPoSAbbsLkNS/iNN2MDGAVYvezYn2QZ
1542=0cxs
1543-----END PGP ARMORED FILE-----"[..])?;
1544 let i: usize = 360;
1545 let mut buf = p.to_vec().unwrap();
1546 let bit = i.saturating_add(2 * 8) % (buf.len() * 8);
1549 buf[bit / 8] ^= 1 << (bit % 8);
1550 match Packet::from_bytes(&buf) {
1551 Ok(q) => {
1552 eprintln!("{:?}", p);
1553 eprintln!("{:?}", q);
1554 assert!(p != q);
1555 },
1556 Err(_) => unreachable!(),
1557 };
1558 Ok(())
1559 }
1560
1561 #[test]
1562 fn encrypt_huge_plaintext() -> Result<()> {
1563 let sk = crate::crypto::SessionKey::new(256).unwrap();
1564
1565 if PublicKeyAlgorithm::RSAEncryptSign.is_supported() {
1566 let rsa2k: Key<SecretParts, UnspecifiedRole> =
1567 Key4::generate_rsa(2048)?.into();
1568 assert!(matches!(
1569 rsa2k.encrypt(&sk).unwrap_err().downcast().unwrap(),
1570 crate::Error::InvalidArgument(_)
1571 ));
1572 }
1573
1574 if PublicKeyAlgorithm::ECDH.is_supported()
1575 && Curve::Cv25519.is_supported()
1576 {
1577 let cv25519: Key<SecretParts, UnspecifiedRole> =
1578 Key4::generate_ecc(false, Curve::Cv25519)?.into();
1579 assert!(matches!(
1580 cv25519.encrypt(&sk).unwrap_err().downcast().unwrap(),
1581 crate::Error::InvalidArgument(_)
1582 ));
1583 }
1584
1585 Ok(())
1586 }
1587
1588 #[test]
1589 fn cv25519_secret_is_reversed() -> Result<()> {
1590 use crate::crypto::backend::{Backend, interface::Asymmetric};
1591
1592 let (mut private_key, _) = Backend::x25519_generate_key()?;
1593 Backend::x25519_clamp_secret(&mut private_key);
1594
1595 let key: Key4<_, UnspecifiedRole> =
1596 Key4::import_secret_cv25519(&private_key, None, None, None)?;
1597 if let crate::packet::key::SecretKeyMaterial::Unencrypted(key) = key.secret() {
1598 key.map(|secret| {
1599 if let mpi::SecretKeyMaterial::ECDH { scalar } = secret {
1600 let scalar_reversed = private_key.iter().copied().rev().collect::<Vec<u8>>();
1601 let scalar_actual = &*scalar.value_padded(32);
1602 assert_eq!(scalar_actual, scalar_reversed);
1603 } else {
1604 unreachable!();
1605 }
1606 })
1607 } else {
1608 unreachable!();
1609 }
1610
1611 Ok(())
1612 }
1613
1614 #[test]
1615 fn ed25519_secret_is_not_reversed() {
1616 let private_key: &[u8] =
1617 &crate::crypto::SessionKey::new(32).unwrap();
1618 let key: Key4<_, UnspecifiedRole> = Key4::import_secret_ed25519(private_key, None).unwrap();
1619 if let crate::packet::key::SecretKeyMaterial::Unencrypted(key) = key.secret() {
1620 key.map(|secret| {
1621 if let mpi::SecretKeyMaterial::EdDSA { scalar } = secret {
1622 assert_eq!(&*scalar.value_padded(32), private_key);
1623 } else {
1624 unreachable!();
1625 }
1626 })
1627 } else {
1628 unreachable!();
1629 }
1630 }
1631
1632 #[test]
1633 fn issue_1016() {
1634 let mut g = quickcheck::Gen::new(256);
1639
1640 let mut key = Key4::<PublicParts, UnspecifiedRole>::arbitrary(&mut g);
1641 let fpr1 = key.fingerprint();
1642 if key.creation_time() == UNIX_EPOCH {
1643 key.set_creation_time(UNIX_EPOCH + Duration::new(1, 0)).expect("ok");
1644 } else {
1645 key.set_creation_time(UNIX_EPOCH).expect("ok");
1646 }
1647 assert_ne!(fpr1, key.fingerprint());
1648
1649 let mut key = Key4::<PublicParts, UnspecifiedRole>::arbitrary(&mut g);
1650 let fpr1 = key.fingerprint();
1651 key.set_pk_algo(PublicKeyAlgorithm::from(u8::from(key.pk_algo()) + 1));
1652 assert_ne!(fpr1, key.fingerprint());
1653
1654 let mut key = Key4::<PublicParts, UnspecifiedRole>::arbitrary(&mut g);
1655 let fpr1 = key.fingerprint();
1656 loop {
1657 let mpis2 = mpi::PublicKey::arbitrary(&mut g);
1658 if key.mpis() != &mpis2 {
1659 *key.mpis_mut() = mpis2;
1660 break;
1661 }
1662 }
1663 assert_ne!(fpr1, key.fingerprint());
1664
1665 let mut key = Key4::<PublicParts, UnspecifiedRole>::arbitrary(&mut g);
1666 let fpr1 = key.fingerprint();
1667 loop {
1668 let mpis2 = mpi::PublicKey::arbitrary(&mut g);
1669 if key.mpis() != &mpis2 {
1670 key.set_mpis(mpis2);
1671 break;
1672 }
1673 }
1674 assert_ne!(fpr1, key.fingerprint());
1675 }
1676
1677 #[test]
1680 fn ecc_support() -> Result<()> {
1681 for for_signing in [true, false] {
1682 for curve in Curve::variants()
1683 .filter(Curve::is_supported)
1684 {
1685 match curve {
1686 Curve::Cv25519 if for_signing => continue,
1687 Curve::Ed25519 if ! for_signing => continue,
1688 _ => (),
1689 }
1690
1691 eprintln!("curve {}, for signing {:?}", curve, for_signing);
1692 let key: Key<SecretParts, UnspecifiedRole> =
1693 Key4::generate_ecc(for_signing, curve.clone())?.into();
1694 let mut pair = key.into_keypair()?;
1695
1696 if for_signing {
1697 use crate::crypto::Signer;
1698 let hash = HashAlgorithm::default();
1699 let digest = hash.context()?
1700 .for_signature(pair.public().version())
1701 .into_digest()?;
1702 let sig = pair.sign(hash, &digest)?;
1703 pair.public().verify(&sig, hash, &digest)?;
1704 } else {
1705 use crate::crypto::{SessionKey, Decryptor};
1706 let sk = SessionKey::new(32).unwrap();
1707 let ciphertext = pair.public().encrypt(&sk)?;
1708 assert_eq!(pair.decrypt(&ciphertext, Some(sk.len()))?, sk);
1709 }
1710 }
1711 }
1712 Ok(())
1713 }
1714
1715 #[test]
1716 fn ecc_encoding() -> Result<()> {
1717 for for_signing in [true, false] {
1718 for curve in Curve::variants()
1719 .filter(Curve::is_supported)
1720 {
1721 match curve {
1722 Curve::Cv25519 if for_signing => continue,
1723 Curve::Ed25519 if ! for_signing => continue,
1724 _ => (),
1725 }
1726
1727 use crate::crypto::mpi::{Ciphertext, MPI, PublicKey};
1728 eprintln!("curve {}, for signing {:?}", curve, for_signing);
1729
1730 let key: Key<SecretParts, UnspecifiedRole> =
1731 Key4::generate_ecc(for_signing, curve.clone())?.into();
1732
1733 let compressed = |mpi: &MPI| mpi.value()[0] == 0x40;
1734 let uncompressed = |mpi: &MPI| mpi.value()[0] == 0x04;
1735
1736 match key.mpis() {
1737 PublicKey::ECDSA { curve: c, q } if for_signing => {
1738 assert!(c == &curve);
1739 assert!(uncompressed(q));
1740 },
1741 PublicKey::EdDSA { curve: c, q } if for_signing => {
1742 assert!(c == &curve);
1743 assert!(compressed(q));
1744 },
1745 PublicKey::ECDH { curve: c, q, .. } if ! for_signing => {
1746 assert!(c == &curve);
1747 if curve == Curve::Cv25519 {
1748 assert!(compressed(q));
1749 } else {
1750 assert!(uncompressed(q));
1751 }
1752
1753 use crate::crypto::SessionKey;
1754 let sk = SessionKey::new(32).unwrap();
1755 let ciphertext = key.encrypt(&sk)?;
1756 if let Ciphertext::ECDH { e, .. } = &ciphertext {
1757 if curve == Curve::Cv25519 {
1758 assert!(compressed(e));
1759 } else {
1760 assert!(uncompressed(e));
1761 }
1762 } else {
1763 panic!("unexpected ciphertext: {:?}", ciphertext);
1764 }
1765 },
1766 mpi => unreachable!(
1767 "curve {}, mpi {:?}, for signing {:?}",
1768 curve, mpi, for_signing),
1769 }
1770 }
1771 }
1772 Ok(())
1773 }
1774}