1 //! Key-related functionality. 2 //! 3 //! # Data Types 4 //! 5 //! The main data type is the [`Key`] enum. This enum abstracts away 6 //! the differences between the key formats (the deprecated [version 7 //! 3], the current [version 4], and the proposed [version 5] 8 //! formats). Nevertheless, some functionality remains format 9 //! specific. For instance, the `Key` enum doesn't provide a 10 //! mechanism to generate keys. This functionality depends on the 11 //! format. 12 //! 13 //! This version of Sequoia only supports version 4 keys ([`Key4`]). 14 //! However, future versions may include limited support for version 3 15 //! keys to allow working with archived messages, and we intend to add 16 //! support for version 5 keys once the new version of the 17 //! specification has been finalized. 18 //! 19 //! OpenPGP specifies four different types of keys: [public keys], 20 //! [secret keys], [public subkeys], and [secret subkeys]. These are 21 //! all represented by the `Key` enum and the `Key4` struct using 22 //! marker types. We use marker types rather than an enum, to better 23 //! exploit the type checking. For instance, type-specific methods 24 //! like [`Key::secret`] are only exposed for those types that 25 //! actually support them. See the documentation for [`Key`] for an 26 //! explanation of how the markers work. 27 //! 28 //! The [`SecretKeyMaterial`] data type allows working with secret key 29 //! material directly. This enum has two variants: [`Unencrypted`], 30 //! and [`Encrypted`]. It is not normally necessary to use this data 31 //! structure directly. The primary functionality that is of interest 32 //! to most users is decrypting secret key material. This is usually 33 //! more conveniently done using [`Key::decrypt_secret`]. 34 //! 35 //! [`Key`]: ../enum.Key.html 36 //! [`Key4`]: struct.Key4.html 37 //! [version 3]: https://tools.ietf.org/html/rfc1991#section-6.6 38 //! [version 4]: https://tools.ietf.org/html/rfc4880#section-5.5.2 39 //! [version 5]: https://www.ietf.org/id/draft-ietf-openpgp-rfc4880bis-09.html#name-public-key-packet-formats 40 //! [public keys]: https://tools.ietf.org/html/rfc4880#section-5.5.1.1 41 //! [secret keys]: https://tools.ietf.org/html/rfc4880#section-5.5.1.3 42 //! [public subkeys]: https://tools.ietf.org/html/rfc4880#section-5.5.1.2 43 //! [secret subkeys]: https://tools.ietf.org/html/rfc4880#section-5.5.1.4 44 //! [`Key::secret`]: ../enum.Key.html#method.secret 45 //! [`SecretKeyMaterial`]: enum.SecretKeyMaterial.html 46 //! [`Unencrypted`]: struct.Unencrypted.html 47 //! [`Encrypted`]: struct.Encrypted.html 48 //! [`Key::decrypt_secret`]: ../enum.Key.html#method.decrypt_secret 49 //! 50 //! # Key Creation 51 //! 52 //! Use [`Key4::generate_rsa`] or [`Key4::generate_ecc`] to create a 53 //! new key. 54 //! 55 //! Existing key material can be turned into an OpenPGP key using 56 //! [`Key4::import_public_cv25519`], [`Key4::import_public_ed25519`], 57 //! [`Key4::import_public_rsa`], [`Key4::import_secret_cv25519`], 58 //! [`Key4::import_secret_ed25519`], and [`Key4::import_secret_rsa`]. 59 //! 60 //! Whether you create a new key or import existing key material, you 61 //! still need to create a binding signature, and, for signing keys, a 62 //! back signature for the key to be usable. 63 //! 64 //! [`Key4::generate_rsa`]: struct.Key4.html#method.generate_rsa 65 //! [`Key4::generate_ecc`]: struct.Key4.html#method.generate_ecc 66 //! [`Key4::import_public_cv25519`]: struct.Key4.html#method.import_public_cv25519 67 //! [`Key4::import_public_ed25519`]: struct.Key4.html#method.import_public_ed25519 68 //! [`Key4::import_public_rsa`]: struct.Key4.html#method.import_public_rsa 69 //! [`Key4::import_secret_cv25519`]: struct.Key4.html#method.import_secret_cv25519 70 //! [`Key4::import_secret_ed25519`]: struct.Key4.html#method.import_secret_ed25519 71 //! [`Key4::import_secret_rsa`]: struct.Key4.html#method.import_secret_rsa 72 //! 73 //! # In-Memory Protection of Secret Key Material 74 //! 75 //! Whether the secret key material is protected on disk or not, 76 //! Sequoia encrypts unencrypted secret key material ([`Unencrypted`]) 77 //! while it is memory. This helps protect against [heartbleed]-style 78 //! attacks where a buffer over-read allows an attacker to read from 79 //! the process's address space. This protection is less important 80 //! for Rust programs, which are memory safe. However, it is 81 //! essential when Sequoia is used via its FFI. 82 //! 83 //! See [`crypto::mem::Encrypted`] for details. 84 //! 85 //! [`Unencrypted`]: struct.Unencrypted.html 86 //! [heartbleed]: https://en.wikipedia.org/wiki/Heartbleed 87 //! [`crypto::mem::Encrypted`]: ../../crypto/mem/struct.Encrypted.html 88 89 use std::fmt; 90 use std::cmp::Ordering; 91 use std::convert::TryInto; 92 use std::time; 93 94 #[cfg(any(test, feature = "quickcheck"))] 95 use quickcheck::{Arbitrary, Gen}; 96 97 use crate::Error; 98 use crate::cert::prelude::*; 99 use crate::crypto::{self, mem, mpi, hash::Hash}; 100 use crate::packet; 101 use crate::packet::prelude::*; 102 use crate::PublicKeyAlgorithm; 103 use crate::SymmetricAlgorithm; 104 use crate::HashAlgorithm; 105 use crate::types::{Curve, Timestamp}; 106 use crate::crypto::S2K; 107 use crate::Result; 108 use crate::crypto::Password; 109 use crate::KeyID; 110 use crate::Fingerprint; 111 use crate::KeyHandle; 112 113 mod conversions; 114 115 /// A marker trait that captures whether a `Key` definitely contains 116 /// secret key material. 117 /// 118 /// A [`Key`] can be treated as if it only has public key material 119 /// ([`key::PublicParts`]) or also has secret key material 120 /// ([`key::SecretParts`]). For those cases where the type 121 /// information needs to be erased (e.g., interfaces like 122 /// [`Cert::keys`]), we provide the [`key::UnspecifiedParts`] marker. 123 /// 124 /// Even if a `Key` does not have the `SecretKey` marker, it may still 125 /// have secret key material. But, it will generally act as if it 126 /// didn't. In particular, when serializing a `Key` without the 127 /// `SecretKey` marker, secret key material will be ignored. See the 128 /// documentation for [`Key`] for a demonstration of this behavior. 129 /// 130 /// [`Cert::keys`]: ../../cert/struct.Cert.html#method.keys 131 /// [`Key`]: ../enum.Key.html 132 /// [`key::PublicParts`]: struct.PublicParts.html 133 /// [`key::SecretParts`]: struct.SecretParts.html 134 /// [`key::UnspecifiedParts`]: struct.UnspecifiedParts.html 135 pub trait KeyParts: fmt::Debug { 136 /// Converts a key with unspecified parts into this kind of key. 137 /// 138 /// This function is helpful when you need to convert a concrete 139 /// type into a generic type. Using `From` works, but requires 140 /// adding a type bound to the generic type, which is ugly and 141 /// invasive. 142 /// 143 /// Converting a key with [`key::PublicParts`] or 144 /// [`key::UnspecifiedParts`] will always succeed. However, 145 /// converting a key to one with [`key::SecretParts`] only 146 /// succeeds if the key actually contains secret key material. 147 /// 148 /// [`key::PublicParts`]: struct.PublicParts.html 149 /// [`key::UnspecifiedParts`]: struct.UnspecifiedParts.html 150 /// [`key::SecretParts`]: struct.SecretParts.html 151 /// 152 /// # Examples 153 /// 154 /// For a less construed example, refer to the [source code]: 155 /// 156 /// [source code]: https://gitlab.com/search?search=convert_key&project_id=4469613&search_code=true&repository_ref=master 157 /// 158 /// ``` 159 /// use sequoia_openpgp as openpgp; 160 /// use openpgp::Result; 161 /// # use openpgp::cert::prelude::*; 162 /// use openpgp::packet::prelude::*; 163 /// 164 /// fn f<P>(cert: &Cert, mut key: Key<P, key::UnspecifiedRole>) 165 /// -> Result<Key<P, key::UnspecifiedRole>> 166 /// where P: key::KeyParts 167 /// { 168 /// // ... 169 /// 170 /// # let criterium = true; 171 /// if criterium { 172 /// // Cert::primary_key's return type is concrete 173 /// // (Key<key::PublicParts, key::PrimaryRole>). We need to 174 /// // convert it to the generic type Key<P, key::UnspecifiedRole>. 175 /// // First, we "downcast" it to have unspecified parts and an 176 /// // unspecified role, then we use a method defined by the 177 /// // generic type to perform the conversion to the generic 178 /// // type P. 179 /// key = P::convert_key( 180 /// cert.primary_key().key().clone() 181 /// .parts_into_unspecified() 182 /// .role_into_unspecified())?; 183 /// } 184 /// # else { unreachable!() } 185 /// 186 /// // ... 187 /// 188 /// Ok(key) 189 /// } 190 /// # fn main() -> openpgp::Result<()> { 191 /// # let (cert, _) = 192 /// # CertBuilder::general_purpose(None, Some("alice@example.org")) 193 /// # .generate()?; 194 /// # f(&cert, cert.primary_key().key().clone().role_into_unspecified()).unwrap(); 195 /// # Ok(()) 196 /// # } 197 /// ``` convert_key<R: KeyRole>(key: Key<UnspecifiedParts, R>) -> Result<Key<Self, R>> where Self: Sized198 fn convert_key<R: KeyRole>(key: Key<UnspecifiedParts, R>) 199 -> Result<Key<Self, R>> 200 where Self: Sized; 201 202 /// Converts a key reference with unspecified parts into this kind 203 /// of key reference. 204 /// 205 /// This function is helpful when you need to convert a concrete 206 /// type into a generic type. Using `From` works, but requires 207 /// adding a type bound to the generic type, which is ugly and 208 /// invasive. 209 /// 210 /// Converting a key with [`key::PublicParts`] or 211 /// [`key::UnspecifiedParts`] will always succeed. However, 212 /// converting a key to one with [`key::SecretParts`] only 213 /// succeeds if the key actually contains secret key material. 214 /// 215 /// [`key::PublicParts`]: struct.PublicParts.html 216 /// [`key::UnspecifiedParts`]: struct.UnspecifiedParts.html 217 /// [`key::SecretParts`]: struct.SecretParts.html convert_key_ref<R: KeyRole>(key: &Key<UnspecifiedParts, R>) -> Result<&Key<Self, R>> where Self: Sized218 fn convert_key_ref<R: KeyRole>(key: &Key<UnspecifiedParts, R>) 219 -> Result<&Key<Self, R>> 220 where Self: Sized; 221 222 /// Converts a key bundle with unspecified parts into this kind of 223 /// key bundle. 224 /// 225 /// This function is helpful when you need to convert a concrete 226 /// type into a generic type. Using `From` works, but requires 227 /// adding a type bound to the generic type, which is ugly and 228 /// invasive. 229 /// 230 /// Converting a key bundle with [`key::PublicParts`] or 231 /// [`key::UnspecifiedParts`] will always succeed. However, 232 /// converting a key bundle to one with [`key::SecretParts`] only 233 /// succeeds if the key bundle actually contains secret key 234 /// material. 235 /// 236 /// [`key::PublicParts`]: struct.PublicParts.html 237 /// [`key::UnspecifiedParts`]: struct.UnspecifiedParts.html 238 /// [`key::SecretParts`]: struct.SecretParts.html convert_bundle<R: KeyRole>(bundle: KeyBundle<UnspecifiedParts, R>) -> Result<KeyBundle<Self, R>> where Self: Sized239 fn convert_bundle<R: KeyRole>(bundle: KeyBundle<UnspecifiedParts, R>) 240 -> Result<KeyBundle<Self, R>> 241 where Self: Sized; 242 243 /// Converts a key bundle reference with unspecified parts into 244 /// this kind of key bundle reference. 245 /// 246 /// This function is helpful when you need to convert a concrete 247 /// type into a generic type. Using `From` works, but requires 248 /// adding a type bound to the generic type, which is ugly and 249 /// invasive. 250 /// 251 /// Converting a key bundle with [`key::PublicParts`] or 252 /// [`key::UnspecifiedParts`] will always succeed. However, 253 /// converting a key bundle to one with [`key::SecretParts`] only 254 /// succeeds if the key bundle actually contains secret key 255 /// material. 256 /// 257 /// [`key::PublicParts`]: struct.PublicParts.html 258 /// [`key::UnspecifiedParts`]: struct.UnspecifiedParts.html 259 /// [`key::SecretParts`]: struct.SecretParts.html convert_bundle_ref<R: KeyRole>(bundle: &KeyBundle<UnspecifiedParts, R>) -> Result<&KeyBundle<Self, R>> where Self: Sized260 fn convert_bundle_ref<R: KeyRole>(bundle: &KeyBundle<UnspecifiedParts, R>) 261 -> Result<&KeyBundle<Self, R>> 262 where Self: Sized; 263 264 /// Converts a key amalgamation with unspecified parts into this 265 /// kind of key amalgamation. 266 /// 267 /// This function is helpful when you need to convert a concrete 268 /// type into a generic type. Using `From` works, but requires 269 /// adding a type bound to the generic type, which is ugly and 270 /// invasive. 271 /// 272 /// Converting a key amalgamation with [`key::PublicParts`] or 273 /// [`key::UnspecifiedParts`] will always succeed. However, 274 /// converting a key amalgamation to one with [`key::SecretParts`] 275 /// only succeeds if the key amalgamation actually contains secret 276 /// key material. 277 /// 278 /// [`key::PublicParts`]: struct.PublicParts.html 279 /// [`key::UnspecifiedParts`]: struct.UnspecifiedParts.html 280 /// [`key::SecretParts`]: struct.SecretParts.html convert_key_amalgamation<'a, R: KeyRole>( ka: ComponentAmalgamation<'a, Key<UnspecifiedParts, R>>) -> Result<ComponentAmalgamation<'a, Key<Self, R>>> where Self: Sized281 fn convert_key_amalgamation<'a, R: KeyRole>( 282 ka: ComponentAmalgamation<'a, Key<UnspecifiedParts, R>>) 283 -> Result<ComponentAmalgamation<'a, Key<Self, R>>> 284 where Self: Sized; 285 286 /// Converts a key amalgamation reference with unspecified parts 287 /// into this kind of key amalgamation reference. 288 /// 289 /// This function is helpful when you need to convert a concrete 290 /// type into a generic type. Using `From` works, but requires 291 /// adding a type bound to the generic type, which is ugly and 292 /// invasive. 293 /// 294 /// Converting a key amalgamation with [`key::PublicParts`] or 295 /// [`key::UnspecifiedParts`] will always succeed. However, 296 /// converting a key amalgamation to one with [`key::SecretParts`] 297 /// only succeeds if the key amalgamation actually contains secret 298 /// key material. 299 /// 300 /// [`key::PublicParts`]: struct.PublicParts.html 301 /// [`key::UnspecifiedParts`]: struct.UnspecifiedParts.html 302 /// [`key::SecretParts`]: struct.SecretParts.html convert_key_amalgamation_ref<'a, R: KeyRole>( ka: &'a ComponentAmalgamation<'a, Key<UnspecifiedParts, R>>) -> Result<&'a ComponentAmalgamation<'a, Key<Self, R>>> where Self: Sized303 fn convert_key_amalgamation_ref<'a, R: KeyRole>( 304 ka: &'a ComponentAmalgamation<'a, Key<UnspecifiedParts, R>>) 305 -> Result<&'a ComponentAmalgamation<'a, Key<Self, R>>> 306 where Self: Sized; 307 } 308 309 /// A marker trait that captures a `Key`'s role. 310 /// 311 /// A [`Key`] can either be a primary key ([`key::PrimaryRole`]) or a 312 /// subordinate key ([`key::SubordinateRole`]). For those cases where 313 /// the type information needs to be erased (e.g., interfaces like 314 /// [`Cert::keys`]), we provide the [`key::UnspecifiedRole`] marker. 315 /// 316 /// [`Key`]: ../enum.Key.html 317 /// [`key::PrimaryRole`]: struct.PrimaryRole.html 318 /// [`key::SubordinateRole`]: struct.SubordinateRole.html 319 /// [`Cert::keys`]: ../../cert/struct.Cert.html#method.keys 320 /// [`key::UnspecifiedRole`]: struct.UnspecifiedRole.html 321 pub trait KeyRole: fmt::Debug { 322 /// Converts a key with an unspecified role into this kind of key. 323 /// 324 /// This function is helpful when you need to convert a concrete 325 /// type into a generic type. Using `From` works, but requires 326 /// adding a type bound to the generic type, which is ugly and 327 /// invasive. 328 /// 329 /// # Examples 330 /// 331 /// ``` 332 /// use sequoia_openpgp as openpgp; 333 /// use openpgp::Result; 334 /// # use openpgp::cert::prelude::*; 335 /// use openpgp::packet::prelude::*; 336 /// 337 /// fn f<R>(cert: &Cert, mut key: Key<key::UnspecifiedParts, R>) 338 /// -> Result<Key<key::UnspecifiedParts, R>> 339 /// where R: key::KeyRole 340 /// { 341 /// // ... 342 /// 343 /// # let criterium = true; 344 /// if criterium { 345 /// // Cert::primary_key's return type is concrete 346 /// // (Key<key::PublicParts, key::PrimaryRole>). We need to 347 /// // convert it to the generic type Key<key::UnspecifiedParts, R>. 348 /// // First, we "downcast" it to have unspecified parts and an 349 /// // unspecified role, then we use a method defined by the 350 /// // generic type to perform the conversion to the generic 351 /// // type R. 352 /// key = R::convert_key( 353 /// cert.primary_key().key().clone() 354 /// .parts_into_unspecified() 355 /// .role_into_unspecified()); 356 /// } 357 /// # else { unreachable!() } 358 /// 359 /// // ... 360 /// 361 /// Ok(key) 362 /// } 363 /// # fn main() -> openpgp::Result<()> { 364 /// # let (cert, _) = 365 /// # CertBuilder::general_purpose(None, Some("alice@example.org")) 366 /// # .generate()?; 367 /// # f(&cert, cert.primary_key().key().clone().parts_into_unspecified()).unwrap(); 368 /// # Ok(()) 369 /// # } 370 /// ``` convert_key<P: KeyParts>(key: Key<P, UnspecifiedRole>) -> Key<P, Self> where Self: Sized371 fn convert_key<P: KeyParts>(key: Key<P, UnspecifiedRole>) 372 -> Key<P, Self> 373 where Self: Sized; 374 375 /// Converts a key reference with an unspecified role into this 376 /// kind of key reference. 377 /// 378 /// This function is helpful when you need to convert a concrete 379 /// type into a generic type. Using `From` works, but requires 380 /// adding a type bound to the generic type, which is ugly and 381 /// invasive. convert_key_ref<P: KeyParts>(key: &Key<P, UnspecifiedRole>) -> &Key<P, Self> where Self: Sized382 fn convert_key_ref<P: KeyParts>(key: &Key<P, UnspecifiedRole>) 383 -> &Key<P, Self> 384 where Self: Sized; 385 386 /// Converts a key bundle with an unspecified role into this kind 387 /// of key bundle. 388 /// 389 /// This function is helpful when you need to convert a concrete 390 /// type into a generic type. Using `From` works, but requires 391 /// adding a type bound to the generic type, which is ugly and 392 /// invasive. convert_bundle<P: KeyParts>(bundle: KeyBundle<P, UnspecifiedRole>) -> KeyBundle<P, Self> where Self: Sized393 fn convert_bundle<P: KeyParts>(bundle: KeyBundle<P, UnspecifiedRole>) 394 -> KeyBundle<P, Self> 395 where Self: Sized; 396 397 /// Converts a key bundle reference with an unspecified role into 398 /// this kind of key bundle reference. 399 /// 400 /// This function is helpful when you need to convert a concrete 401 /// type into a generic type. Using `From` works, but requires 402 /// adding a type bound to the generic type, which is ugly and 403 /// invasive. convert_bundle_ref<P: KeyParts>(bundle: &KeyBundle<P, UnspecifiedRole>) -> &KeyBundle<P, Self> where Self: Sized404 fn convert_bundle_ref<P: KeyParts>(bundle: &KeyBundle<P, UnspecifiedRole>) 405 -> &KeyBundle<P, Self> 406 where Self: Sized; 407 } 408 409 /// A marker that indicates that a `Key` should be treated like a 410 /// public key. 411 /// 412 /// Note: this doesn't indicate whether the data structure contains 413 /// secret key material; it indicates whether any secret key material 414 /// should be ignored. For instance, when exporting a key with the 415 /// `PublicParts` marker, secret key material will *not* be exported. 416 /// See the documentation for [`Key`] for a demonstration. 417 /// 418 /// Refer to [`KeyParts`] for details. 419 /// 420 /// [`Key`]: ../enum.Key.html 421 /// [`KeyParts`]: trait.KeyParts.html 422 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] 423 pub struct PublicParts; 424 impl KeyParts for PublicParts { convert_key<R: KeyRole>(key: Key<UnspecifiedParts, R>) -> Result<Key<Self, R>>425 fn convert_key<R: KeyRole>(key: Key<UnspecifiedParts, R>) 426 -> Result<Key<Self, R>> { 427 Ok(key.into()) 428 } 429 convert_key_ref<R: KeyRole>(key: &Key<UnspecifiedParts, R>) -> Result<&Key<Self, R>>430 fn convert_key_ref<R: KeyRole>(key: &Key<UnspecifiedParts, R>) 431 -> Result<&Key<Self, R>> { 432 Ok(key.into()) 433 } 434 convert_bundle<R: KeyRole>(bundle: KeyBundle<UnspecifiedParts, R>) -> Result<KeyBundle<Self, R>>435 fn convert_bundle<R: KeyRole>(bundle: KeyBundle<UnspecifiedParts, R>) 436 -> Result<KeyBundle<Self, R>> { 437 Ok(bundle.into()) 438 } 439 convert_bundle_ref<R: KeyRole>(bundle: &KeyBundle<UnspecifiedParts, R>) -> Result<&KeyBundle<Self, R>>440 fn convert_bundle_ref<R: KeyRole>(bundle: &KeyBundle<UnspecifiedParts, R>) 441 -> Result<&KeyBundle<Self, R>> { 442 Ok(bundle.into()) 443 } 444 convert_key_amalgamation<'a, R: KeyRole>( ka: ComponentAmalgamation<'a, Key<UnspecifiedParts, R>>) -> Result<ComponentAmalgamation<'a, Key<Self, R>>>445 fn convert_key_amalgamation<'a, R: KeyRole>( 446 ka: ComponentAmalgamation<'a, Key<UnspecifiedParts, R>>) 447 -> Result<ComponentAmalgamation<'a, Key<Self, R>>> { 448 Ok(ka.into()) 449 } 450 convert_key_amalgamation_ref<'a, R: KeyRole>( ka: &'a ComponentAmalgamation<'a, Key<UnspecifiedParts, R>>) -> Result<&'a ComponentAmalgamation<'a, Key<Self, R>>>451 fn convert_key_amalgamation_ref<'a, R: KeyRole>( 452 ka: &'a ComponentAmalgamation<'a, Key<UnspecifiedParts, R>>) 453 -> Result<&'a ComponentAmalgamation<'a, Key<Self, R>>> { 454 Ok(ka.into()) 455 } 456 } 457 458 /// A marker that indicates that a `Key` should be treated like a 459 /// secret key. 460 /// 461 /// Unlike the [`key::PublicParts`] marker, this marker asserts that 462 /// the [`Key`] contains secret key material. Because secret key 463 /// material is not protected by the self-signature, there is no 464 /// indication that the secret key material is actually valid. 465 /// 466 /// Refer to [`KeyParts`] for details. 467 /// 468 /// [`key::PublicParts`]: struct.PublicParts.html 469 /// [`Key`]: ../enum.Key.html 470 /// [`KeyParts`]: trait.KeyParts.html 471 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] 472 pub struct SecretParts; 473 impl KeyParts for SecretParts { convert_key<R: KeyRole>(key: Key<UnspecifiedParts, R>) -> Result<Key<Self, R>>474 fn convert_key<R: KeyRole>(key: Key<UnspecifiedParts, R>) 475 -> Result<Key<Self, R>>{ 476 key.try_into() 477 } 478 convert_key_ref<R: KeyRole>(key: &Key<UnspecifiedParts, R>) -> Result<&Key<Self, R>>479 fn convert_key_ref<R: KeyRole>(key: &Key<UnspecifiedParts, R>) 480 -> Result<&Key<Self, R>> { 481 key.try_into() 482 } 483 convert_bundle<R: KeyRole>(bundle: KeyBundle<UnspecifiedParts, R>) -> Result<KeyBundle<Self, R>>484 fn convert_bundle<R: KeyRole>(bundle: KeyBundle<UnspecifiedParts, R>) 485 -> Result<KeyBundle<Self, R>> { 486 bundle.try_into() 487 } 488 convert_bundle_ref<R: KeyRole>(bundle: &KeyBundle<UnspecifiedParts, R>) -> Result<&KeyBundle<Self, R>>489 fn convert_bundle_ref<R: KeyRole>(bundle: &KeyBundle<UnspecifiedParts, R>) 490 -> Result<&KeyBundle<Self, R>> { 491 bundle.try_into() 492 } 493 convert_key_amalgamation<'a, R: KeyRole>( ka: ComponentAmalgamation<'a, Key<UnspecifiedParts, R>>) -> Result<ComponentAmalgamation<'a, Key<Self, R>>>494 fn convert_key_amalgamation<'a, R: KeyRole>( 495 ka: ComponentAmalgamation<'a, Key<UnspecifiedParts, R>>) 496 -> Result<ComponentAmalgamation<'a, Key<Self, R>>> { 497 ka.try_into() 498 } 499 convert_key_amalgamation_ref<'a, R: KeyRole>( ka: &'a ComponentAmalgamation<'a, Key<UnspecifiedParts, R>>) -> Result<&'a ComponentAmalgamation<'a, Key<Self, R>>>500 fn convert_key_amalgamation_ref<'a, R: KeyRole>( 501 ka: &'a ComponentAmalgamation<'a, Key<UnspecifiedParts, R>>) 502 -> Result<&'a ComponentAmalgamation<'a, Key<Self, R>>> { 503 ka.try_into() 504 } 505 } 506 507 /// A marker that indicates that a `Key`'s parts are unspecified. 508 /// 509 /// Neither public key-specific nor secret key-specific operations are 510 /// allowed on these types of keys. For instance, it is not possible 511 /// to export a key with the `UnspecifiedParts` marker, because it is 512 /// unclear how to treat any secret key material. To export such a 513 /// key, you need to first change the marker to [`key::PublicParts`] 514 /// or [`key::SecretParts`]. 515 /// 516 /// This marker is used when it is necessary to erase the type. For 517 /// instance, we need to do this when mixing [`Key`]s with different 518 /// markers in the same collection. See [`Cert::keys`] for an 519 /// example. 520 /// 521 /// Refer to [`KeyParts`] for details. 522 /// 523 /// [`key::PublicParts`]: struct.PublicParts.html 524 /// [`key::SecretParts`]: struct.SecretParts.html 525 /// [`KeyParts`]: trait.KeyParts.html 526 /// [`Key`]: ../enum.Key.html 527 /// [`Cert::keys`]: ../../struct.Cert.html#method.keys 528 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] 529 pub struct UnspecifiedParts; 530 impl KeyParts for UnspecifiedParts { convert_key<R: KeyRole>(key: Key<UnspecifiedParts, R>) -> Result<Key<Self, R>>531 fn convert_key<R: KeyRole>(key: Key<UnspecifiedParts, R>) 532 -> Result<Key<Self, R>> { 533 Ok(key) 534 } 535 convert_key_ref<R: KeyRole>(key: &Key<UnspecifiedParts, R>) -> Result<&Key<Self, R>>536 fn convert_key_ref<R: KeyRole>(key: &Key<UnspecifiedParts, R>) 537 -> Result<&Key<Self, R>> { 538 Ok(key) 539 } 540 convert_bundle<R: KeyRole>(bundle: KeyBundle<UnspecifiedParts, R>) -> Result<KeyBundle<Self, R>>541 fn convert_bundle<R: KeyRole>(bundle: KeyBundle<UnspecifiedParts, R>) 542 -> Result<KeyBundle<Self, R>> { 543 Ok(bundle) 544 } 545 convert_bundle_ref<R: KeyRole>(bundle: &KeyBundle<UnspecifiedParts, R>) -> Result<&KeyBundle<Self, R>>546 fn convert_bundle_ref<R: KeyRole>(bundle: &KeyBundle<UnspecifiedParts, R>) 547 -> Result<&KeyBundle<Self, R>> { 548 Ok(bundle) 549 } 550 convert_key_amalgamation<'a, R: KeyRole>( ka: ComponentAmalgamation<'a, Key<UnspecifiedParts, R>>) -> Result<ComponentAmalgamation<'a, Key<UnspecifiedParts, R>>>551 fn convert_key_amalgamation<'a, R: KeyRole>( 552 ka: ComponentAmalgamation<'a, Key<UnspecifiedParts, R>>) 553 -> Result<ComponentAmalgamation<'a, Key<UnspecifiedParts, R>>> { 554 Ok(ka.into()) 555 } 556 convert_key_amalgamation_ref<'a, R: KeyRole>( ka: &'a ComponentAmalgamation<'a, Key<UnspecifiedParts, R>>) -> Result<&'a ComponentAmalgamation<'a, Key<Self, R>>>557 fn convert_key_amalgamation_ref<'a, R: KeyRole>( 558 ka: &'a ComponentAmalgamation<'a, Key<UnspecifiedParts, R>>) 559 -> Result<&'a ComponentAmalgamation<'a, Key<Self, R>>> { 560 Ok(ka.into()) 561 } 562 } 563 564 /// A marker that indicates the `Key` should be treated like a primary key. 565 /// 566 /// Refer to [`KeyRole`] for details. 567 /// 568 /// [`KeyRole`]: trait.KeyRole.html 569 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] 570 pub struct PrimaryRole; 571 impl KeyRole for PrimaryRole { convert_key<P: KeyParts>(key: Key<P, UnspecifiedRole>) -> Key<P, Self>572 fn convert_key<P: KeyParts>(key: Key<P, UnspecifiedRole>) 573 -> Key<P, Self> { 574 key.into() 575 } 576 convert_key_ref<P: KeyParts>(key: &Key<P, UnspecifiedRole>) -> &Key<P, Self>577 fn convert_key_ref<P: KeyParts>(key: &Key<P, UnspecifiedRole>) 578 -> &Key<P, Self> { 579 key.into() 580 } 581 convert_bundle<P: KeyParts>(bundle: KeyBundle<P, UnspecifiedRole>) -> KeyBundle<P, Self>582 fn convert_bundle<P: KeyParts>(bundle: KeyBundle<P, UnspecifiedRole>) 583 -> KeyBundle<P, Self> { 584 bundle.into() 585 } 586 convert_bundle_ref<P: KeyParts>(bundle: &KeyBundle<P, UnspecifiedRole>) -> &KeyBundle<P, Self>587 fn convert_bundle_ref<P: KeyParts>(bundle: &KeyBundle<P, UnspecifiedRole>) 588 -> &KeyBundle<P, Self> { 589 bundle.into() 590 } 591 } 592 593 /// A marker that indicates the `Key` should treated like a subkey. 594 /// 595 /// Refer to [`KeyRole`] for details. 596 /// 597 /// [`KeyRole`]: trait.KeyRole.html 598 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] 599 pub struct SubordinateRole; 600 impl KeyRole for SubordinateRole { convert_key<P: KeyParts>(key: Key<P, UnspecifiedRole>) -> Key<P, Self>601 fn convert_key<P: KeyParts>(key: Key<P, UnspecifiedRole>) 602 -> Key<P, Self> { 603 key.into() 604 } 605 convert_key_ref<P: KeyParts>(key: &Key<P, UnspecifiedRole>) -> &Key<P, Self>606 fn convert_key_ref<P: KeyParts>(key: &Key<P, UnspecifiedRole>) 607 -> &Key<P, Self> { 608 key.into() 609 } 610 convert_bundle<P: KeyParts>(bundle: KeyBundle<P, UnspecifiedRole>) -> KeyBundle<P, Self>611 fn convert_bundle<P: KeyParts>(bundle: KeyBundle<P, UnspecifiedRole>) 612 -> KeyBundle<P, Self> { 613 bundle.into() 614 } 615 convert_bundle_ref<P: KeyParts>(bundle: &KeyBundle<P, UnspecifiedRole>) -> &KeyBundle<P, Self>616 fn convert_bundle_ref<P: KeyParts>(bundle: &KeyBundle<P, UnspecifiedRole>) 617 -> &KeyBundle<P, Self> { 618 bundle.into() 619 } 620 } 621 622 /// A marker that indicates the `Key`'s role is unspecified. 623 /// 624 /// Neither primary key-specific nor subkey-specific operations are 625 /// allowed. To perform those operations, the marker first has to be 626 /// changed to either [`key::PrimaryRole`] or 627 /// [`key::SubordinateRole`], as appropriate. 628 /// 629 /// Refer to [`KeyRole`] for details. 630 /// 631 /// [`key::PrimaryRole`]: struct.PrimaryRole.html 632 /// [`key::SubordinateRole`]: struct.SubordinateRole.html 633 /// [`KeyRole`]: trait.KeyRole.html 634 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] 635 pub struct UnspecifiedRole; 636 impl KeyRole for UnspecifiedRole { convert_key<P: KeyParts>(key: Key<P, UnspecifiedRole>) -> Key<P, Self>637 fn convert_key<P: KeyParts>(key: Key<P, UnspecifiedRole>) 638 -> Key<P, Self> { 639 key 640 } 641 convert_key_ref<P: KeyParts>(key: &Key<P, UnspecifiedRole>) -> &Key<P, Self>642 fn convert_key_ref<P: KeyParts>(key: &Key<P, UnspecifiedRole>) 643 -> &Key<P, Self> { 644 key 645 } 646 convert_bundle<P: KeyParts>(bundle: KeyBundle<P, UnspecifiedRole>) -> KeyBundle<P, Self>647 fn convert_bundle<P: KeyParts>(bundle: KeyBundle<P, UnspecifiedRole>) 648 -> KeyBundle<P, Self> { 649 bundle 650 } 651 convert_bundle_ref<P: KeyParts>(bundle: &KeyBundle<P, UnspecifiedRole>) -> &KeyBundle<P, Self>652 fn convert_bundle_ref<P: KeyParts>(bundle: &KeyBundle<P, UnspecifiedRole>) 653 -> &KeyBundle<P, Self> { 654 bundle 655 } 656 } 657 658 /// A Public Key. 659 pub(crate) type PublicKey = Key<PublicParts, PrimaryRole>; 660 /// A Public Subkey. 661 pub(crate) type PublicSubkey = Key<PublicParts, SubordinateRole>; 662 /// A Secret Key. 663 pub(crate) type SecretKey = Key<SecretParts, PrimaryRole>; 664 /// A Secret Subkey. 665 pub(crate) type SecretSubkey = Key<SecretParts, SubordinateRole>; 666 667 /// A key with public parts, and an unspecified role 668 /// (`UnspecifiedRole`). 669 #[allow(dead_code)] 670 pub(crate) type UnspecifiedPublic = Key<PublicParts, UnspecifiedRole>; 671 /// A key with secret parts, and an unspecified role 672 /// (`UnspecifiedRole`). 673 pub(crate) type UnspecifiedSecret = Key<SecretParts, UnspecifiedRole>; 674 675 /// A primary key with unspecified parts (`UnspecifiedParts`). 676 #[allow(dead_code)] 677 pub(crate) type UnspecifiedPrimary = Key<UnspecifiedParts, PrimaryRole>; 678 /// A subkey key with unspecified parts (`UnspecifiedParts`). 679 #[allow(dead_code)] 680 pub(crate) type UnspecifiedSecondary = Key<UnspecifiedParts, SubordinateRole>; 681 682 /// A key whose parts and role are unspecified 683 /// (`UnspecifiedParts`, `UnspecifiedRole`). 684 #[allow(dead_code)] 685 pub(crate) type UnspecifiedKey = Key<UnspecifiedParts, UnspecifiedRole>; 686 687 688 /// Holds a public key, public subkey, private key or private subkey 689 /// packet. 690 /// 691 /// Use [`Key4::generate_rsa`] or [`Key4::generate_ecc`] to create a 692 /// new key. 693 /// 694 /// Existing key material can be turned into an OpenPGP key using 695 /// [`Key4::with_secret`], [`Key4::import_public_cv25519`], 696 /// [`Key4::import_public_ed25519`], [`Key4::import_public_rsa`], 697 /// [`Key4::import_secret_cv25519`], [`Key4::import_secret_ed25519`], 698 /// and [`Key4::import_secret_rsa`]. 699 /// 700 /// Whether you create a new key or import existing key material, you 701 /// still need to create a binding signature, and, for signing keys, a 702 /// back signature before integrating the key into a certificate. 703 /// 704 /// Normally, you won't directly use `Key4`, but [`Key`], which is a 705 /// relatively thin wrapper around `Key4`. 706 /// 707 /// See [Section 5.5 of RFC 4880] and [the documentation for `Key`] 708 /// for more details. 709 /// 710 /// [`Key4::with_secret`]: #method.with_secret 711 /// [`Key4::generate_rsa`]: #method.generate_rsa 712 /// [`Key4::generate_ecc`]: #method.generate_ecc 713 /// [`Key4::import_public_cv25519`]: #method.import_public_cv25519 714 /// [`Key4::import_public_ed25519`]: #method.import_public_ed25519 715 /// [`Key4::import_public_rsa`]: #method.import_public_rsa 716 /// [`Key4::import_secret_cv25519`]: #method.import_secret_cv25519 717 /// [`Key4::import_secret_ed25519`]: #method.import_secret_ed25519 718 /// [`Key4::import_secret_rsa`]: #method.import_secret_rsa 719 /// [Section 5.5 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-5.5 720 /// [the documentation for `Key`]: ../enum.Key.html 721 /// [`Key`]: ../enum.Key.html 722 #[derive(Clone)] 723 pub struct Key4<P, R> 724 where P: KeyParts, R: KeyRole 725 { 726 /// CTB packet header fields. 727 pub(crate) common: packet::Common, 728 /// When the key was created. 729 creation_time: Timestamp, 730 /// Public key algorithm of this signature. 731 pk_algo: PublicKeyAlgorithm, 732 /// Public key MPIs. 733 mpis: mpi::PublicKey, 734 /// Optional secret part of the key. 735 secret: Option<SecretKeyMaterial>, 736 737 p: std::marker::PhantomData<P>, 738 r: std::marker::PhantomData<R>, 739 } 740 741 impl<P: KeyParts, R: KeyRole> PartialEq for Key4<P, R> { eq(&self, other: &Key4<P, R>) -> bool742 fn eq(&self, other: &Key4<P, R>) -> bool { 743 self.creation_time == other.creation_time 744 && self.pk_algo == other.pk_algo 745 && self.mpis == other.mpis 746 && self.secret == other.secret 747 } 748 } 749 750 impl<P: KeyParts, R: KeyRole> Eq for Key4<P, R> {} 751 752 impl<P: KeyParts, R: KeyRole> std::hash::Hash for Key4<P, R> { hash<H: std::hash::Hasher>(&self, state: &mut H)753 fn hash<H: std::hash::Hasher>(&self, state: &mut H) { 754 std::hash::Hash::hash(&self.creation_time, state); 755 std::hash::Hash::hash(&self.pk_algo, state); 756 std::hash::Hash::hash(&self.mpis, state); 757 std::hash::Hash::hash(&self.secret, state); 758 } 759 } 760 761 impl<P, R> fmt::Debug for Key4<P, R> 762 where P: key::KeyParts, 763 R: key::KeyRole, 764 { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result765 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 766 f.debug_struct("Key4") 767 .field("fingerprint", &self.fingerprint()) 768 .field("creation_time", &self.creation_time) 769 .field("pk_algo", &self.pk_algo) 770 .field("mpis", &self.mpis) 771 .field("secret", &self.secret) 772 .finish() 773 } 774 } 775 776 impl<P, R> fmt::Display for Key4<P, R> 777 where P: key::KeyParts, 778 R: key::KeyRole, 779 { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result780 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 781 write!(f, "{}", self.fingerprint()) 782 } 783 } 784 785 impl<P, R> Key4<P, R> 786 where P: key::KeyParts, 787 R: key::KeyRole, 788 { 789 /// Compares the public bits of two keys. 790 /// 791 /// This returns `Ordering::Equal` if the public MPIs, creation 792 /// time, and algorithm of the two `Key4`s match. This does not 793 /// consider the packets' encodings, packets' tags or their secret 794 /// key material. public_cmp<PB, RB>(&self, b: &Key4<PB, RB>) -> Ordering where PB: key::KeyParts, RB: key::KeyRole,795 pub fn public_cmp<PB, RB>(&self, b: &Key4<PB, RB>) -> Ordering 796 where PB: key::KeyParts, 797 RB: key::KeyRole, 798 { 799 match self.mpis.cmp(&b.mpis) { 800 Ordering::Equal => (), 801 o => return o, 802 } 803 804 match self.creation_time.cmp(&b.creation_time) { 805 Ordering::Equal => (), 806 o => return o, 807 } 808 809 self.pk_algo.cmp(&b.pk_algo) 810 } 811 812 /// Tests whether two keys are equal modulo their secret key 813 /// material. 814 /// 815 /// This returns true if the public MPIs, creation time and 816 /// algorithm of the two `Key4`s match. This does not consider 817 /// the packets' encodings, packets' tags or their secret key 818 /// material. public_eq<PB, RB>(&self, b: &Key4<PB, RB>) -> bool where PB: key::KeyParts, RB: key::KeyRole,819 pub fn public_eq<PB, RB>(&self, b: &Key4<PB, RB>) -> bool 820 where PB: key::KeyParts, 821 RB: key::KeyRole, 822 { 823 self.public_cmp(b) == Ordering::Equal 824 } 825 } 826 827 impl<R> Key4<key::PublicParts, R> 828 where R: key::KeyRole, 829 { 830 /// Creates an OpenPGP public key from the specified key material. new<T>(creation_time: T, pk_algo: PublicKeyAlgorithm, mpis: mpi::PublicKey) -> Result<Self> where T: Into<time::SystemTime>831 pub fn new<T>(creation_time: T, pk_algo: PublicKeyAlgorithm, 832 mpis: mpi::PublicKey) 833 -> Result<Self> 834 where T: Into<time::SystemTime> 835 { 836 Ok(Key4 { 837 common: Default::default(), 838 creation_time: creation_time.into().try_into()?, 839 pk_algo, 840 mpis, 841 secret: None, 842 p: std::marker::PhantomData, 843 r: std::marker::PhantomData, 844 }) 845 } 846 847 /// Creates an OpenPGP public key packet from existing X25519 key 848 /// material. 849 /// 850 /// The ECDH key will use hash algorithm `hash` and symmetric 851 /// algorithm `sym`. If one or both are `None` secure defaults 852 /// will be used. The key will have its creation date set to 853 /// `ctime` or the current time if `None` is given. import_public_cv25519<H, S, T>(public_key: &[u8], hash: H, sym: S, ctime: T) -> Result<Self> where H: Into<Option<HashAlgorithm>>, S: Into<Option<SymmetricAlgorithm>>, T: Into<Option<time::SystemTime>>854 pub fn import_public_cv25519<H, S, T>(public_key: &[u8], 855 hash: H, sym: S, ctime: T) 856 -> Result<Self> where H: Into<Option<HashAlgorithm>>, 857 S: Into<Option<SymmetricAlgorithm>>, 858 T: Into<Option<time::SystemTime>> 859 { 860 let mut point = Vec::from(public_key); 861 point.insert(0, 0x40); 862 863 Self::new( 864 ctime.into().unwrap_or_else(time::SystemTime::now), 865 PublicKeyAlgorithm::ECDH, 866 mpi::PublicKey::ECDH { 867 curve: Curve::Cv25519, 868 hash: hash.into().unwrap_or(HashAlgorithm::SHA512), 869 sym: sym.into().unwrap_or(SymmetricAlgorithm::AES256), 870 q: mpi::MPI::new(&point), 871 }) 872 } 873 874 /// Creates an OpenPGP public key packet from existing Ed25519 key 875 /// material. 876 /// 877 /// The ECDH key will use hash algorithm `hash` and symmetric 878 /// algorithm `sym`. If one or both are `None` secure defaults 879 /// will be used. The key will have its creation date set to 880 /// `ctime` or the current time if `None` is given. import_public_ed25519<T>(public_key: &[u8], ctime: T) -> Result<Self> where T: Into<Option<time::SystemTime>>881 pub fn import_public_ed25519<T>(public_key: &[u8], ctime: T) -> Result<Self> 882 where T: Into<Option<time::SystemTime>> 883 { 884 let mut point = Vec::from(public_key); 885 point.insert(0, 0x40); 886 887 Self::new( 888 ctime.into().unwrap_or_else(time::SystemTime::now), 889 PublicKeyAlgorithm::EdDSA, 890 mpi::PublicKey::EdDSA { 891 curve: Curve::Ed25519, 892 q: mpi::MPI::new(&point), 893 }) 894 } 895 896 /// Creates an OpenPGP public key packet from existing RSA key 897 /// material. 898 /// 899 /// The RSA key will use the public exponent `e` and the modulo 900 /// `n`. The key will have its creation date set to `ctime` or the 901 /// current time if `None` is given. import_public_rsa<T>(e: &[u8], n: &[u8], ctime: T) -> Result<Self> where T: Into<Option<time::SystemTime>>902 pub fn import_public_rsa<T>(e: &[u8], n: &[u8], ctime: T) 903 -> Result<Self> where T: Into<Option<time::SystemTime>> 904 { 905 Self::new( 906 ctime.into().unwrap_or_else(time::SystemTime::now), 907 PublicKeyAlgorithm::RSAEncryptSign, 908 mpi::PublicKey::RSA { 909 e: mpi::MPI::new(e), 910 n: mpi::MPI::new(n), 911 }) 912 } 913 } 914 915 impl<R> Key4<SecretParts, R> 916 where R: key::KeyRole, 917 { 918 /// Creates an OpenPGP key packet from the specified secret key 919 /// material. with_secret<T>(creation_time: T, pk_algo: PublicKeyAlgorithm, mpis: mpi::PublicKey, secret: SecretKeyMaterial) -> Result<Self> where T: Into<time::SystemTime>920 pub fn with_secret<T>(creation_time: T, pk_algo: PublicKeyAlgorithm, 921 mpis: mpi::PublicKey, 922 secret: SecretKeyMaterial) 923 -> Result<Self> 924 where T: Into<time::SystemTime> 925 { 926 Ok(Key4 { 927 common: Default::default(), 928 creation_time: creation_time.into().try_into()?, 929 pk_algo, 930 mpis, 931 secret: Some(secret), 932 p: std::marker::PhantomData, 933 r: std::marker::PhantomData, 934 }) 935 } 936 } 937 938 impl<P, R> Key4<P, R> 939 where P: key::KeyParts, 940 R: key::KeyRole, 941 { 942 /// Gets the `Key`'s creation time. creation_time(&self) -> time::SystemTime943 pub fn creation_time(&self) -> time::SystemTime { 944 self.creation_time.into() 945 } 946 947 /// Sets the `Key`'s creation time. 948 /// 949 /// `timestamp` is converted to OpenPGP's internal format, 950 /// [`Timestamp`]: a 32-bit quantity containing the number of 951 /// seconds since the Unix epoch. 952 /// 953 /// `timestamp` is silently rounded to match the internal 954 /// resolution. An error is returned if `timestamp` is out of 955 /// range. 956 /// 957 /// [`Timestamp`]: ../../types/struct.Timestamp.html set_creation_time<T>(&mut self, timestamp: T) -> Result<time::SystemTime> where T: Into<time::SystemTime>958 pub fn set_creation_time<T>(&mut self, timestamp: T) 959 -> Result<time::SystemTime> 960 where T: Into<time::SystemTime> 961 { 962 Ok(std::mem::replace(&mut self.creation_time, 963 timestamp.into().try_into()?) 964 .into()) 965 } 966 967 /// Gets the public key algorithm. pk_algo(&self) -> PublicKeyAlgorithm968 pub fn pk_algo(&self) -> PublicKeyAlgorithm { 969 self.pk_algo 970 } 971 972 /// Sets the public key algorithm. 973 /// 974 /// Returns the old public key algorithm. set_pk_algo(&mut self, pk_algo: PublicKeyAlgorithm) -> PublicKeyAlgorithm975 pub fn set_pk_algo(&mut self, pk_algo: PublicKeyAlgorithm) 976 -> PublicKeyAlgorithm 977 { 978 ::std::mem::replace(&mut self.pk_algo, pk_algo) 979 } 980 981 /// Returns a reference to the `Key`'s MPIs. mpis(&self) -> &mpi::PublicKey982 pub fn mpis(&self) -> &mpi::PublicKey { 983 &self.mpis 984 } 985 986 /// Returns a mutable reference to the `Key`'s MPIs. mpis_mut(&mut self) -> &mut mpi::PublicKey987 pub fn mpis_mut(&mut self) -> &mut mpi::PublicKey { 988 &mut self.mpis 989 } 990 991 /// Sets the `Key`'s MPIs. 992 /// 993 /// This function returns the old MPIs, if any. set_mpis(&mut self, mpis: mpi::PublicKey) -> mpi::PublicKey994 pub fn set_mpis(&mut self, mpis: mpi::PublicKey) -> mpi::PublicKey { 995 ::std::mem::replace(&mut self.mpis, mpis) 996 } 997 998 /// Returns whether the `Key` contains secret key material. has_secret(&self) -> bool999 pub fn has_secret(&self) -> bool { 1000 self.secret.is_some() 1001 } 1002 1003 /// Returns whether the `Key` contains unencrypted secret key 1004 /// material. 1005 /// 1006 /// This returns false if the `Key` doesn't contain any secret key 1007 /// material. has_unencrypted_secret(&self) -> bool1008 pub fn has_unencrypted_secret(&self) -> bool { 1009 match self.secret { 1010 Some(SecretKeyMaterial::Unencrypted { .. }) => true, 1011 _ => false, 1012 } 1013 } 1014 1015 /// Returns `Key`'s secret key material, if any. optional_secret(&self) -> Option<&SecretKeyMaterial>1016 pub fn optional_secret(&self) -> Option<&SecretKeyMaterial> { 1017 self.secret.as_ref() 1018 } 1019 1020 /// Computes and returns the `Key`'s `Fingerprint` and returns it as 1021 /// a `KeyHandle`. 1022 /// 1023 /// See [Section 12.2 of RFC 4880]. 1024 /// 1025 /// [Section 12.2 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-12.2 key_handle(&self) -> KeyHandle1026 pub fn key_handle(&self) -> KeyHandle { 1027 self.fingerprint().into() 1028 } 1029 1030 /// Computes and returns the `Key`'s `Fingerprint`. 1031 /// 1032 /// See [Section 12.2 of RFC 4880]. 1033 /// 1034 /// [Section 12.2 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-12.2 fingerprint(&self) -> Fingerprint1035 pub fn fingerprint(&self) -> Fingerprint { 1036 let mut h = HashAlgorithm::SHA1.context().unwrap(); 1037 1038 self.hash(&mut h); 1039 1040 let mut digest = vec![0u8; h.digest_size()]; 1041 h.digest(&mut digest); 1042 Fingerprint::from_bytes(digest.as_slice()) 1043 } 1044 1045 /// Computes and returns the `Key`'s `Key ID`. 1046 /// 1047 /// See [Section 12.2 of RFC 4880]. 1048 /// 1049 /// [Section 12.2 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-12.2 keyid(&self) -> KeyID1050 pub fn keyid(&self) -> KeyID { 1051 self.fingerprint().into() 1052 } 1053 } 1054 1055 macro_rules! impl_common_secret_functions { 1056 ($t: ident) => { 1057 /// Secret key material handling. 1058 impl<R> Key4<$t, R> 1059 where R: key::KeyRole, 1060 { 1061 /// Takes the `Key`'s `SecretKeyMaterial`, if any. 1062 pub fn take_secret(mut self) 1063 -> (Key4<PublicParts, R>, Option<SecretKeyMaterial>) 1064 { 1065 let old = std::mem::replace(&mut self.secret, None); 1066 (self.parts_into_public(), old) 1067 } 1068 1069 /// Adds the secret key material to the `Key`, returning 1070 /// the old secret key material, if any. 1071 pub fn add_secret(mut self, secret: SecretKeyMaterial) 1072 -> (Key4<SecretParts, R>, Option<SecretKeyMaterial>) 1073 { 1074 let old = std::mem::replace(&mut self.secret, Some(secret)); 1075 (self.parts_into_secret().expect("secret just set"), old) 1076 } 1077 } 1078 } 1079 } 1080 impl_common_secret_functions!(PublicParts); 1081 impl_common_secret_functions!(UnspecifiedParts); 1082 1083 /// Secret key handling. 1084 impl<R> Key4<SecretParts, R> 1085 where R: key::KeyRole, 1086 { 1087 /// Gets the `Key`'s `SecretKeyMaterial`. secret(&self) -> &SecretKeyMaterial1088 pub fn secret(&self) -> &SecretKeyMaterial { 1089 self.secret.as_ref().expect("has secret") 1090 } 1091 1092 /// Gets a mutable reference to the `Key`'s `SecretKeyMaterial`. secret_mut(&mut self) -> &mut SecretKeyMaterial1093 pub fn secret_mut(&mut self) -> &mut SecretKeyMaterial { 1094 self.secret.as_mut().expect("has secret") 1095 } 1096 1097 /// Takes the `Key`'s `SecretKeyMaterial`. take_secret(mut self) -> (Key4<PublicParts, R>, SecretKeyMaterial)1098 pub fn take_secret(mut self) 1099 -> (Key4<PublicParts, R>, SecretKeyMaterial) 1100 { 1101 let old = std::mem::replace(&mut self.secret, None); 1102 (self.parts_into_public(), 1103 old.expect("Key<SecretParts, _> has a secret key material")) 1104 } 1105 1106 /// Adds `SecretKeyMaterial` to the `Key`. 1107 /// 1108 /// This function returns the old secret key material, if any. add_secret(mut self, secret: SecretKeyMaterial) -> (Key4<SecretParts, R>, SecretKeyMaterial)1109 pub fn add_secret(mut self, secret: SecretKeyMaterial) 1110 -> (Key4<SecretParts, R>, SecretKeyMaterial) 1111 { 1112 let old = std::mem::replace(&mut self.secret, Some(secret)); 1113 (self.parts_into_secret().expect("secret just set"), 1114 old.expect("Key<SecretParts, _> has a secret key material")) 1115 } 1116 1117 /// Decrypts the secret key material using `password`. 1118 /// 1119 /// In OpenPGP, secret key material can be [protected with a 1120 /// password]. The password is usually hardened using a [KDF]. 1121 /// 1122 /// Refer to the documentation of [`Key::decrypt_secret`] for 1123 /// details. 1124 /// 1125 /// This function returns an error if the secret key material is 1126 /// not encrypted or the password is incorrect. 1127 /// 1128 /// [protected with a password]: https://tools.ietf.org/html/rfc4880#section-5.5.3 1129 /// [KDF]: https://tools.ietf.org/html/rfc4880#section-3.7 1130 /// [`Key::decrypt_secret`]: ../enum.Key.html#method.decrypt_secret decrypt_secret(mut self, password: &Password) -> Result<Self>1131 pub fn decrypt_secret(mut self, password: &Password) -> Result<Self> { 1132 let pk_algo = self.pk_algo; 1133 self.secret_mut().decrypt_in_place(pk_algo, password)?; 1134 Ok(self) 1135 } 1136 1137 /// Encrypts the secret key material using `password`. 1138 /// 1139 /// In OpenPGP, secret key material can be [protected with a 1140 /// password]. The password is usually hardened using a [KDF]. 1141 /// 1142 /// Refer to the documentation of [`Key::encrypt_secret`] for 1143 /// details. 1144 /// 1145 /// This returns an error if the secret key material is already 1146 /// encrypted. 1147 /// 1148 /// [protected with a password]: https://tools.ietf.org/html/rfc4880#section-5.5.3 1149 /// [KDF]: https://tools.ietf.org/html/rfc4880#section-3.7 1150 /// [`Key::encrypt_secret`]: ../enum.Key.html#method.encrypt_secret encrypt_secret(mut self, password: &Password) -> Result<Key4<SecretParts, R>>1151 pub fn encrypt_secret(mut self, password: &Password) 1152 -> Result<Key4<SecretParts, R>> 1153 { 1154 self.secret_mut().encrypt_in_place(password)?; 1155 Ok(self) 1156 } 1157 } 1158 1159 impl<P, R> From<Key4<P, R>> for super::Key<P, R> 1160 where P: key::KeyParts, 1161 R: key::KeyRole, 1162 { from(p: Key4<P, R>) -> Self1163 fn from(p: Key4<P, R>) -> Self { 1164 super::Key::V4(p) 1165 } 1166 } 1167 1168 /// Holds secret key material. 1169 /// 1170 /// This type allows postponing the decryption of the secret key 1171 /// material until it is actually needed. 1172 /// 1173 /// If the secret key material is not encrypted with a password, then 1174 /// we encrypt it in memory. This helps protect against 1175 /// [heartbleed]-style attacks where a buffer over-read allows an 1176 /// attacker to read from the process's address space. This 1177 /// protection is less important for Rust programs, which are memory 1178 /// safe. However, it is essential when Sequoia is used via its FFI. 1179 /// 1180 /// See [`crypto::mem::Encrypted`] for details. 1181 /// 1182 /// [`Unencrypted`]: struct.Unencrypted.html 1183 /// [heartbleed]: https://en.wikipedia.org/wiki/Heartbleed 1184 /// [`crypto::mem::Encrypted`]: ../../crypto/mem/struct.Encrypted.html 1185 #[derive(PartialEq, Eq, Hash, Clone, Debug)] 1186 pub enum SecretKeyMaterial { 1187 /// Unencrypted secret key. Can be used as-is. 1188 Unencrypted(Unencrypted), 1189 /// The secret key is encrypted with a password. 1190 Encrypted(Encrypted), 1191 } 1192 1193 impl From<mpi::SecretKeyMaterial> for SecretKeyMaterial { from(mpis: mpi::SecretKeyMaterial) -> Self1194 fn from(mpis: mpi::SecretKeyMaterial) -> Self { 1195 SecretKeyMaterial::Unencrypted(mpis.into()) 1196 } 1197 } 1198 1199 impl From<Unencrypted> for SecretKeyMaterial { from(key: Unencrypted) -> Self1200 fn from(key: Unencrypted) -> Self { 1201 SecretKeyMaterial::Unencrypted(key) 1202 } 1203 } 1204 1205 impl From<Encrypted> for SecretKeyMaterial { from(key: Encrypted) -> Self1206 fn from(key: Encrypted) -> Self { 1207 SecretKeyMaterial::Encrypted(key) 1208 } 1209 } 1210 1211 impl SecretKeyMaterial { 1212 /// Decrypts the secret key material using `password`. 1213 /// 1214 /// The `SecretKeyMaterial` type does not know what kind of key it 1215 /// contains. So, in order to know how many MPIs to parse, the 1216 /// public key algorithm needs to be provided explicitly. 1217 /// 1218 /// This returns an error if the secret key material is not 1219 /// encrypted or the password is incorrect. decrypt(mut self, pk_algo: PublicKeyAlgorithm, password: &Password) -> Result<Self>1220 pub fn decrypt(mut self, pk_algo: PublicKeyAlgorithm, 1221 password: &Password) 1222 -> Result<Self> 1223 { 1224 self.decrypt_in_place(pk_algo, password)?; 1225 Ok(self) 1226 } 1227 1228 /// Decrypts the secret key material using `password`. 1229 /// 1230 /// The `SecretKeyMaterial` type does not know what kind of key it 1231 /// contains. So, in order to know how many MPIs to parse, the 1232 /// public key algorithm needs to be provided explicitly. 1233 /// 1234 /// This returns an error if the secret key material is not 1235 /// encrypted or the password is incorrect. decrypt_in_place(&mut self, pk_algo: PublicKeyAlgorithm, password: &Password) -> Result<()>1236 pub fn decrypt_in_place(&mut self, pk_algo: PublicKeyAlgorithm, 1237 password: &Password) 1238 -> Result<()> 1239 { 1240 match self { 1241 SecretKeyMaterial::Encrypted(e) => { 1242 *self = e.decrypt(pk_algo, password)?.into(); 1243 Ok(()) 1244 } 1245 SecretKeyMaterial::Unencrypted(_) => 1246 Err(Error::InvalidArgument( 1247 "secret key is not encrypted".into()).into()), 1248 } 1249 } 1250 1251 /// Encrypts the secret key material using `password`. 1252 /// 1253 /// This returns an error if the secret key material is encrypted. 1254 /// 1255 /// See [`Unencrypted::encrypt`] for details. 1256 /// 1257 /// [`Unencrypted::encrypt`]: struct.Unencrypted.html#encrypt encrypt(mut self, password: &Password) -> Result<Self>1258 pub fn encrypt(mut self, password: &Password) -> Result<Self> { 1259 self.encrypt_in_place(password)?; 1260 Ok(self) 1261 } 1262 1263 /// Encrypts the secret key material using `password`. 1264 /// 1265 /// This returns an error if the secret key material is encrypted. 1266 /// 1267 /// See [`Unencrypted::encrypt`] for details. 1268 /// 1269 /// [`Unencrypted::encrypt`]: struct.Unencrypted.html#encrypt encrypt_in_place(&mut self, password: &Password) -> Result<()>1270 pub fn encrypt_in_place(&mut self, password: &Password) -> Result<()> { 1271 match self { 1272 SecretKeyMaterial::Unencrypted(ref u) => { 1273 *self = SecretKeyMaterial::Encrypted( 1274 u.encrypt(password)?.into()); 1275 Ok(()) 1276 } 1277 SecretKeyMaterial::Encrypted(_) => 1278 Err(Error::InvalidArgument( 1279 "secret key is encrypted".into()).into()), 1280 } 1281 } 1282 1283 /// Returns whether the secret key material is encrypted. is_encrypted(&self) -> bool1284 pub fn is_encrypted(&self) -> bool { 1285 match self { 1286 SecretKeyMaterial::Encrypted(_) => true, 1287 SecretKeyMaterial::Unencrypted(_) => false, 1288 } 1289 } 1290 } 1291 1292 /// Unencrypted secret key material. 1293 /// 1294 /// This data structure is used by the [`SecretKeyMaterial`] enum. 1295 /// 1296 /// Unlike an [`Encrypted`] key, this key an be used as-is. 1297 /// 1298 /// The secret key is encrypted in memory and only decrypted on 1299 /// demand. This helps protect against [heartbleed]-style 1300 /// attacks where a buffer over-read allows an attacker to read from 1301 /// the process's address space. This protection is less important 1302 /// for Rust programs, which are memory safe. However, it is 1303 /// essential when Sequoia is used via its FFI. 1304 /// 1305 /// See [`crypto::mem::Encrypted`] for details. 1306 /// 1307 /// [`SecretKeyMaterial`]: enum.SecretKeyMaterial.html 1308 /// [`Encrypted`]: struct.Encrypted.html 1309 /// [heartbleed]: https://en.wikipedia.org/wiki/Heartbleed 1310 /// [`crypto::mem::Encrypted`]: ../../crypto/mem/struct.Encrypted.html 1311 // Note: PartialEq, Eq, and Hash on mem::Encrypted does the right 1312 // thing. 1313 #[derive(Clone, Debug, PartialEq, Eq, Hash)] 1314 pub struct Unencrypted { 1315 /// MPIs of the secret key. 1316 mpis: mem::Encrypted, 1317 } 1318 1319 impl From<mpi::SecretKeyMaterial> for Unencrypted { from(mpis: mpi::SecretKeyMaterial) -> Self1320 fn from(mpis: mpi::SecretKeyMaterial) -> Self { 1321 use crate::serialize::Marshal; 1322 let mut plaintext = Vec::new(); 1323 // We need to store the type. 1324 plaintext.push( 1325 mpis.algo().unwrap_or(PublicKeyAlgorithm::Unknown(0)).into()); 1326 mpis.serialize(&mut plaintext) 1327 .expect("MPI serialization to vec failed"); 1328 Unencrypted { mpis: mem::Encrypted::new(plaintext.into()), } 1329 } 1330 } 1331 1332 impl Unencrypted { 1333 /// Maps the given function over the secret. map<F, T>(&self, mut fun: F) -> T where F: FnMut(&mpi::SecretKeyMaterial) -> T1334 pub fn map<F, T>(&self, mut fun: F) -> T 1335 where F: FnMut(&mpi::SecretKeyMaterial) -> T 1336 { 1337 self.mpis.map(|plaintext| { 1338 let algo: PublicKeyAlgorithm = plaintext[0].into(); 1339 let mpis = mpi::SecretKeyMaterial::parse(algo, &plaintext[1..]) 1340 .expect("Decrypted secret key is malformed"); 1341 fun(&mpis) 1342 }) 1343 } 1344 1345 /// Encrypts the secret key material using `password`. 1346 /// 1347 /// This encrypts the secret key material using an [AES 256] key 1348 /// derived from the `password` using the default [`s2k`] scheme. 1349 /// 1350 /// [AES 256]: ../../types/enum.SymmetricAlgorithm.html#variant.AES256 1351 /// [`s2k`]: ../../crypto/enum.S2K.html encrypt(&self, password: &Password) -> Result<Encrypted>1352 pub fn encrypt(&self, password: &Password) 1353 -> Result<Encrypted> 1354 { 1355 use std::io::Write; 1356 use crate::crypto::symmetric::Encryptor; 1357 1358 let s2k = S2K::default(); 1359 let algo = SymmetricAlgorithm::AES256; 1360 let key = s2k.derive_key(password, algo.key_size()?)?; 1361 1362 // Ciphertext is preceded by a random block. 1363 let mut trash = vec![0u8; algo.block_size()?]; 1364 crypto::random(&mut trash); 1365 1366 let mut esk = Vec::new(); 1367 { 1368 let mut encryptor = Encryptor::new(algo, &key, &mut esk)?; 1369 encryptor.write_all(&trash)?; 1370 self.map(|mpis| mpis.serialize_chksumd(&mut encryptor))?; 1371 } 1372 1373 Ok(Encrypted::new(s2k, algo, esk.into_boxed_slice())) 1374 } 1375 } 1376 1377 /// Secret key material encrypted with a password. 1378 /// 1379 /// This data structure is used by the [`SecretKeyMaterial`] enum. 1380 /// 1381 /// [`SecretKeyMaterial`]: enum.SecretKeyMaterial.html 1382 #[derive(Clone, Debug)] 1383 pub struct Encrypted { 1384 /// Key derivation mechanism to use. 1385 s2k: S2K, 1386 /// Symmetric algorithm used to encrypt the secret key material. 1387 algo: SymmetricAlgorithm, 1388 /// Encrypted MPIs prefixed with the IV. 1389 /// 1390 /// If we recognized the S2K object during parsing, we can 1391 /// successfully parse the data into S2K, IV, and ciphertext. 1392 /// However, if we do not recognize the S2K type, we do not know 1393 /// how large its parameters are, so we cannot cleanly parse it, 1394 /// and have to accept that the S2K's body bleeds into the rest of 1395 /// the data. 1396 ciphertext: std::result::Result<Box<[u8]>, // IV + ciphertext. 1397 Box<[u8]>>, // S2K body + IV + ciphertext. 1398 } 1399 1400 // Because the S2K and ciphertext cannot be cleanly separated at parse 1401 // time, we need to carefully compare and hash encrypted key packets. 1402 1403 impl PartialEq for Encrypted { eq(&self, other: &Encrypted) -> bool1404 fn eq(&self, other: &Encrypted) -> bool { 1405 self.algo == other.algo 1406 // Treat S2K and ciphertext as opaque blob. 1407 && { 1408 // XXX: This would be nicer without the allocations. 1409 use crate::serialize::MarshalInto; 1410 let mut a = self.s2k.to_vec().unwrap(); 1411 let mut b = other.s2k.to_vec().unwrap(); 1412 a.extend_from_slice(self.raw_ciphertext()); 1413 b.extend_from_slice(other.raw_ciphertext()); 1414 a == b 1415 } 1416 } 1417 } 1418 1419 impl Eq for Encrypted {} 1420 1421 impl std::hash::Hash for Encrypted { hash<H: std::hash::Hasher>(&self, state: &mut H)1422 fn hash<H: std::hash::Hasher>(&self, state: &mut H) { 1423 self.algo.hash(state); 1424 // Treat S2K and ciphertext as opaque blob. 1425 // XXX: This would be nicer without the allocations. 1426 use crate::serialize::MarshalInto; 1427 let mut a = self.s2k.to_vec().unwrap(); 1428 a.extend_from_slice(self.raw_ciphertext()); 1429 a.hash(state); 1430 } 1431 } 1432 1433 impl Encrypted { 1434 /// Creates a new encrypted key object. new(s2k: S2K, algo: SymmetricAlgorithm, ciphertext: Box<[u8]>) -> Self1435 pub fn new(s2k: S2K, algo: SymmetricAlgorithm, ciphertext: Box<[u8]>) 1436 -> Self 1437 { 1438 Self::new_raw(s2k, algo, Ok(ciphertext)) 1439 } 1440 1441 /// Creates a new encrypted key object. new_raw(s2k: S2K, algo: SymmetricAlgorithm, ciphertext: std::result::Result<Box<[u8]>, Box<[u8]>>) -> Self1442 pub(crate) fn new_raw(s2k: S2K, algo: SymmetricAlgorithm, 1443 ciphertext: std::result::Result<Box<[u8]>, 1444 Box<[u8]>>) 1445 -> Self 1446 { 1447 Encrypted { s2k, algo, ciphertext } 1448 } 1449 1450 /// Returns the key derivation mechanism. s2k(&self) -> &S2K1451 pub fn s2k(&self) -> &S2K { 1452 &self.s2k 1453 } 1454 1455 /// Returns the symmetric algorithm used to encrypt the secret 1456 /// key material. algo(&self) -> SymmetricAlgorithm1457 pub fn algo(&self) -> SymmetricAlgorithm { 1458 self.algo 1459 } 1460 1461 /// Returns the encrypted secret key material. 1462 /// 1463 /// If the [`S2K`] mechanism is not supported by Sequoia, this 1464 /// function will fail. Note that the information is not lost, 1465 /// but stored in the packet. If the packet is serialized again, 1466 /// it is written out. 1467 /// 1468 /// [`S2K`]: ../../crypto/enum.S2K.html ciphertext(&self) -> Result<&[u8]>1469 pub fn ciphertext(&self) -> Result<&[u8]> { 1470 self.ciphertext 1471 .as_ref() 1472 .map(|ciphertext| &ciphertext[..]) 1473 .map_err(|_| Error::MalformedPacket( 1474 format!("Unknown S2K: {:?}", self.s2k)).into()) 1475 } 1476 1477 /// Returns the encrypted secret key material, possibly including 1478 /// the body of the S2K object. raw_ciphertext(&self) -> &[u8]1479 pub(crate) fn raw_ciphertext(&self) -> &[u8] { 1480 match self.ciphertext.as_ref() { 1481 Ok(ciphertext) => &ciphertext[..], 1482 Err(s2k_ciphertext) => &s2k_ciphertext[..], 1483 } 1484 } 1485 1486 /// Decrypts the secret key material using `password`. 1487 /// 1488 /// The `Encrypted` key does not know what kind of key it is, so 1489 /// the public key algorithm is needed to parse the correct number 1490 /// of MPIs. decrypt(&self, pk_algo: PublicKeyAlgorithm, password: &Password) -> Result<Unencrypted>1491 pub fn decrypt(&self, pk_algo: PublicKeyAlgorithm, password: &Password) 1492 -> Result<Unencrypted> 1493 { 1494 use std::io::{Cursor, Read}; 1495 use crate::crypto::symmetric::Decryptor; 1496 1497 let key = self.s2k.derive_key(password, self.algo.key_size()?)?; 1498 let cur = Cursor::new(self.ciphertext()?); 1499 let mut dec = Decryptor::new(self.algo, &key, cur)?; 1500 1501 // Consume the first block. 1502 let mut trash = vec![0u8; self.algo.block_size()?]; 1503 dec.read_exact(&mut trash)?; 1504 1505 mpi::SecretKeyMaterial::parse_chksumd(pk_algo, &mut dec).map(|m| m.into()) 1506 } 1507 } 1508 1509 #[cfg(any(test, feature = "quickcheck"))] 1510 impl<P, R> Arbitrary for super::Key<P, R> 1511 where P: KeyParts, P: Clone, 1512 R: KeyRole, R: Clone, 1513 Key4<P, R>: Arbitrary, 1514 { arbitrary<G: Gen>(g: &mut G) -> Self1515 fn arbitrary<G: Gen>(g: &mut G) -> Self { 1516 Key4::arbitrary(g).into() 1517 } 1518 } 1519 1520 #[cfg(any(test, feature = "quickcheck"))] 1521 impl Arbitrary for Key4<PublicParts, UnspecifiedRole> { arbitrary<G: Gen>(g: &mut G) -> Self1522 fn arbitrary<G: Gen>(g: &mut G) -> Self { 1523 let mpis = mpi::PublicKey::arbitrary(g); 1524 Key4 { 1525 common: Arbitrary::arbitrary(g), 1526 creation_time: Arbitrary::arbitrary(g), 1527 pk_algo: mpis.algo() 1528 .expect("mpi::PublicKey::arbitrary only uses known algos"), 1529 mpis, 1530 secret: None, 1531 p: std::marker::PhantomData, 1532 r: std::marker::PhantomData, 1533 } 1534 } 1535 } 1536 1537 #[cfg(any(test, feature = "quickcheck"))] 1538 impl Arbitrary for Key4<SecretParts, UnspecifiedRole> { arbitrary<G: Gen>(g: &mut G) -> Self1539 fn arbitrary<G: Gen>(g: &mut G) -> Self { 1540 use rand::Rng; 1541 use PublicKeyAlgorithm::*; 1542 use mpi::MPI; 1543 1544 let key = Key4::arbitrary(g); 1545 let mut secret: SecretKeyMaterial = match key.pk_algo() { 1546 RSAEncryptSign => mpi::SecretKeyMaterial::RSA { 1547 d: MPI::arbitrary(g).into(), 1548 p: MPI::arbitrary(g).into(), 1549 q: MPI::arbitrary(g).into(), 1550 u: MPI::arbitrary(g).into(), 1551 }, 1552 1553 DSA => mpi::SecretKeyMaterial::DSA { 1554 x: MPI::arbitrary(g).into(), 1555 }, 1556 1557 ElGamalEncrypt => mpi::SecretKeyMaterial::ElGamal { 1558 x: MPI::arbitrary(g).into(), 1559 }, 1560 1561 EdDSA => mpi::SecretKeyMaterial::EdDSA { 1562 scalar: MPI::arbitrary(g).into(), 1563 }, 1564 1565 ECDSA => mpi::SecretKeyMaterial::ECDSA { 1566 scalar: MPI::arbitrary(g).into(), 1567 }, 1568 1569 ECDH => mpi::SecretKeyMaterial::ECDH { 1570 scalar: MPI::arbitrary(g).into(), 1571 }, 1572 1573 _ => unreachable!("only valid algos, normalizes to these values"), 1574 }.into(); 1575 1576 if g.gen() { 1577 secret.encrypt_in_place(&Password::from(Vec::arbitrary(g))) 1578 .unwrap(); 1579 } 1580 1581 Key4::<PublicParts, UnspecifiedRole>::add_secret(key, secret).0 1582 } 1583 } 1584 1585 #[cfg(test)] 1586 mod tests { 1587 use crate::packet::Key; 1588 use crate::Cert; 1589 use crate::packet::pkesk::PKESK3; 1590 use crate::packet::key; 1591 use crate::packet::key::SecretKeyMaterial; 1592 use crate::packet::Packet; 1593 use super::*; 1594 use crate::PacketPile; 1595 use crate::serialize::Serialize; 1596 use crate::parse::Parse; 1597 1598 #[test] encrypted_rsa_key()1599 fn encrypted_rsa_key() { 1600 let cert = Cert::from_bytes( 1601 crate::tests::key("testy-new-encrypted-with-123.pgp")).unwrap(); 1602 let mut pair = cert.primary_key().key().clone(); 1603 let pk_algo = pair.pk_algo(); 1604 let secret = pair.secret.as_mut().unwrap(); 1605 1606 assert!(secret.is_encrypted()); 1607 secret.decrypt_in_place(pk_algo, &"123".into()).unwrap(); 1608 assert!(!secret.is_encrypted()); 1609 1610 match secret { 1611 SecretKeyMaterial::Unencrypted(ref u) => u.map(|mpis| match mpis { 1612 mpi::SecretKeyMaterial::RSA { .. } => (), 1613 _ => panic!(), 1614 }), 1615 _ => panic!(), 1616 } 1617 } 1618 1619 #[test] eq()1620 fn eq() { 1621 use crate::types::Curve::*; 1622 1623 for curve in vec![NistP256, NistP384, NistP521] { 1624 let sign_key : Key4<_, key::UnspecifiedRole> 1625 = Key4::generate_ecc(true, curve.clone()).unwrap(); 1626 let enc_key : Key4<_, key::UnspecifiedRole> 1627 = Key4::generate_ecc(false, curve).unwrap(); 1628 let sign_clone = sign_key.clone(); 1629 let enc_clone = enc_key.clone(); 1630 1631 assert_eq!(sign_key, sign_clone); 1632 assert_eq!(enc_key, enc_clone); 1633 } 1634 1635 for bits in vec![1024, 2048, 3072, 4096] { 1636 let key : Key4<_, key::UnspecifiedRole> 1637 = Key4::generate_rsa(bits).unwrap(); 1638 let clone = key.clone(); 1639 assert_eq!(key, clone); 1640 } 1641 } 1642 1643 #[test] roundtrip()1644 fn roundtrip() { 1645 use crate::types::Curve::*; 1646 1647 let keys = vec![NistP256, NistP384, NistP521].into_iter().flat_map(|cv| 1648 { 1649 let sign_key : Key4<key::SecretParts, key::PrimaryRole> 1650 = Key4::generate_ecc(true, cv.clone()).unwrap(); 1651 let enc_key = Key4::generate_ecc(false, cv).unwrap(); 1652 1653 vec![sign_key, enc_key] 1654 }).chain(vec![1024, 2048, 3072, 4096].into_iter().map(|b| { 1655 Key4::generate_rsa(b).unwrap() 1656 })); 1657 1658 for key in keys { 1659 let mut b = Vec::new(); 1660 Packet::SecretKey(key.clone().into()).serialize(&mut b).unwrap(); 1661 1662 let pp = PacketPile::from_bytes(&b).unwrap(); 1663 if let Some(Packet::SecretKey(Key::V4(ref parsed_key))) = 1664 pp.path_ref(&[0]) 1665 { 1666 assert_eq!(key.creation_time, parsed_key.creation_time); 1667 assert_eq!(key.pk_algo, parsed_key.pk_algo); 1668 assert_eq!(key.mpis, parsed_key.mpis); 1669 assert_eq!(key.secret, parsed_key.secret); 1670 1671 assert_eq!(&key, parsed_key); 1672 } else { 1673 panic!("bad packet: {:?}", pp.path_ref(&[0])); 1674 } 1675 1676 let mut b = Vec::new(); 1677 let pk4 : Key4<PublicParts, PrimaryRole> = key.clone().into(); 1678 Packet::PublicKey(pk4.into()).serialize(&mut b).unwrap(); 1679 1680 let pp = PacketPile::from_bytes(&b).unwrap(); 1681 if let Some(Packet::PublicKey(Key::V4(ref parsed_key))) = 1682 pp.path_ref(&[0]) 1683 { 1684 assert!(! parsed_key.has_secret()); 1685 1686 let key = key.take_secret().0; 1687 assert_eq!(&key, parsed_key); 1688 } else { 1689 panic!("bad packet: {:?}", pp.path_ref(&[0])); 1690 } 1691 } 1692 } 1693 1694 #[test] encryption_roundtrip()1695 fn encryption_roundtrip() { 1696 use crate::crypto::SessionKey; 1697 use crate::types::Curve::*; 1698 1699 let keys = vec![NistP256, NistP384, NistP521].into_iter().map(|cv| { 1700 Key4::generate_ecc(false, cv).unwrap() 1701 }).chain(vec![1024, 2048, 3072, 4096].into_iter().map(|b| { 1702 Key4::generate_rsa(b).unwrap() 1703 })); 1704 1705 for key in keys.into_iter() { 1706 let key: Key<key::SecretParts, key::UnspecifiedRole> = key.into(); 1707 let mut keypair = key.clone().into_keypair().unwrap(); 1708 let cipher = SymmetricAlgorithm::AES256; 1709 let sk = SessionKey::new(cipher.key_size().unwrap()); 1710 1711 let pkesk = PKESK3::for_recipient(cipher, &sk, &key).unwrap(); 1712 let (cipher_, sk_) = pkesk.decrypt(&mut keypair, None).unwrap(); 1713 1714 assert_eq!(cipher, cipher_); 1715 assert_eq!(sk, sk_); 1716 1717 let (cipher_, sk_) = 1718 pkesk.decrypt(&mut keypair, Some(cipher)).unwrap(); 1719 1720 assert_eq!(cipher, cipher_); 1721 assert_eq!(sk, sk_); 1722 } 1723 } 1724 1725 #[test] secret_encryption_roundtrip()1726 fn secret_encryption_roundtrip() { 1727 use crate::types::Curve::*; 1728 1729 let keys = vec![NistP256, NistP384, NistP521].into_iter().map(|cv| { 1730 let k : Key4<key::SecretParts, key::PrimaryRole> 1731 = Key4::generate_ecc(false, cv).unwrap(); 1732 k 1733 }).chain(vec![1024, 2048, 3072, 4096].into_iter().map(|b| { 1734 Key4::generate_rsa(b).unwrap() 1735 })); 1736 1737 for key in keys { 1738 assert!(! key.secret().is_encrypted()); 1739 1740 let password = Password::from("foobarbaz"); 1741 let mut encrypted_key = key.clone(); 1742 1743 encrypted_key.secret_mut().encrypt_in_place(&password).unwrap(); 1744 assert!(encrypted_key.secret().is_encrypted()); 1745 1746 encrypted_key.secret_mut() 1747 .decrypt_in_place(key.pk_algo, &password).unwrap(); 1748 assert!(! key.secret().is_encrypted()); 1749 assert_eq!(key, encrypted_key); 1750 assert_eq!(key.secret(), encrypted_key.secret()); 1751 } 1752 } 1753 1754 #[test] import_cv25519()1755 fn import_cv25519() { 1756 use crate::crypto::{ecdh, mem, SessionKey}; 1757 use self::mpi::{MPI, Ciphertext}; 1758 1759 // X25519 key 1760 let ctime = 1761 time::UNIX_EPOCH + time::Duration::new(0x5c487129, 0); 1762 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"; 1763 let key : Key<_, key::UnspecifiedRole> 1764 = Key4::import_public_cv25519(&public[..], 1765 HashAlgorithm::SHA256, 1766 SymmetricAlgorithm::AES128, 1767 ctime).unwrap().into(); 1768 1769 // PKESK 1770 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"[..]); 1771 let ciphertext = Ciphertext::ECDH{ 1772 e: eph_pubkey.clone(), 1773 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() 1774 }; 1775 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(); 1776 1777 // Session key 1778 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"; 1779 let sk = SessionKey::from(Vec::from(&dek[..])); 1780 1781 // Expected 1782 let got_enc = ecdh::encrypt_wrap(&key.parts_into_public(), 1783 &sk, eph_pubkey, &shared_sec) 1784 .unwrap(); 1785 1786 assert_eq!(ciphertext, got_enc); 1787 } 1788 1789 #[test] import_cv25519_sec()1790 fn import_cv25519_sec() { 1791 use crate::crypto::ecdh; 1792 use self::mpi::{MPI, Ciphertext}; 1793 1794 // X25519 key 1795 let ctime = 1796 time::UNIX_EPOCH + time::Duration::new(0x5c487129, 0); 1797 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"; 1798 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"; 1799 let key: Key<_, UnspecifiedRole> 1800 = Key4::import_secret_cv25519(&secret[..], 1801 HashAlgorithm::SHA256, 1802 SymmetricAlgorithm::AES128, 1803 ctime).unwrap().into(); 1804 match key.mpis { 1805 self::mpi::PublicKey::ECDH{ ref q,.. } => 1806 assert_eq!(&q.value()[1..], &public[..]), 1807 _ => unreachable!(), 1808 } 1809 1810 // PKESK 1811 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"; 1812 let ciphertext = Ciphertext::ECDH{ 1813 e: MPI::new(&eph_pubkey[..]), 1814 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() 1815 }; 1816 1817 // Session key 1818 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"; 1819 1820 let key = key.parts_into_public(); 1821 let got_dek = match key.optional_secret() { 1822 Some(SecretKeyMaterial::Unencrypted(ref u)) => u.map(|mpis| { 1823 ecdh::decrypt(&key, mpis, &ciphertext) 1824 .unwrap() 1825 }), 1826 _ => unreachable!(), 1827 }; 1828 1829 assert_eq!(&dek[..], &got_dek[..]); 1830 } 1831 1832 #[test] import_rsa()1833 fn import_rsa() { 1834 use crate::crypto::SessionKey; 1835 use self::mpi::{MPI, Ciphertext}; 1836 1837 // RSA key 1838 let ctime = 1839 time::UNIX_EPOCH + time::Duration::new(1548950502, 0); 1840 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"; 1841 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"; 1842 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"; 1843 let key: key::SecretKey 1844 = Key4::import_secret_rsa(&d[..], &p[..], &q[..], ctime) 1845 .unwrap().into(); 1846 1847 // PKESK 1848 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"; 1849 let ciphertext = Ciphertext::RSA{ 1850 c: MPI::new(&c[..]), 1851 }; 1852 let pkesk = PKESK3::new(key.keyid(), PublicKeyAlgorithm::RSAEncryptSign, 1853 ciphertext).unwrap(); 1854 1855 // Session key 1856 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"; 1857 let sk = SessionKey::from(Vec::from(&dek[..])); 1858 1859 // Expected 1860 let mut decryptor = key.into_keypair().unwrap(); 1861 let got_sk = pkesk.decrypt(&mut decryptor, None).unwrap(); 1862 assert_eq!(got_sk.1, sk); 1863 } 1864 1865 #[test] import_ed25519()1866 fn import_ed25519() { 1867 use crate::types::SignatureType; 1868 use crate::packet::signature::Signature4; 1869 use crate::packet::signature::subpacket::{ 1870 Subpacket, SubpacketValue, SubpacketArea}; 1871 1872 // Ed25519 key 1873 let ctime = 1874 time::UNIX_EPOCH + time::Duration::new(1548249630, 0); 1875 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"; 1876 let key: key::PublicKey 1877 = Key4::import_public_ed25519(q, ctime).unwrap().into(); 1878 1879 let mut hashed = SubpacketArea::default(); 1880 let mut unhashed = SubpacketArea::default(); 1881 let fpr = "D81A 5DC0 DEBF EE5F 9AC8 20EB 6769 5DB9 920D 4FAC" 1882 .parse().unwrap(); 1883 let kid = "6769 5DB9 920D 4FAC".parse().unwrap(); 1884 let ctime = 1549460479.into(); 1885 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"; 1886 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"; 1887 1888 hashed.add(Subpacket::new(SubpacketValue::IssuerFingerprint(fpr), false).unwrap()).unwrap(); 1889 hashed.add(Subpacket::new(SubpacketValue::SignatureCreationTime(ctime), false).unwrap()).unwrap(); 1890 unhashed.add(Subpacket::new(SubpacketValue::Issuer(kid), false).unwrap()).unwrap(); 1891 1892 eprintln!("fpr: {}", key.fingerprint()); 1893 let sig = Signature4::new(SignatureType::Binary, PublicKeyAlgorithm::EdDSA, 1894 HashAlgorithm::SHA256, hashed, unhashed, 1895 [0xa7,0x19], 1896 mpi::Signature::EdDSA{ 1897 r: mpi::MPI::new(r), s: mpi::MPI::new(s) 1898 }); 1899 let sig: Signature = sig.into(); 1900 sig.verify_message(&key, b"Hello, World\n").unwrap(); 1901 } 1902 1903 #[test] fingerprint_test()1904 fn fingerprint_test() { 1905 let pile = 1906 PacketPile::from_bytes(crate::tests::key("public-key.gpg")).unwrap(); 1907 1908 // The blob contains a public key and a three subkeys. 1909 let mut pki = 0; 1910 let mut ski = 0; 1911 1912 let pks = [ "8F17 7771 18A3 3DDA 9BA4 8E62 AACB 3243 6300 52D9" ]; 1913 let sks = [ "C03F A641 1B03 AE12 5764 6118 7223 B566 78E0 2528", 1914 "50E6 D924 308D BF22 3CFB 510A C2B8 1905 6C65 2598", 1915 "2DC5 0AB5 5BE2 F3B0 4C2D 2CF8 A350 6AFB 820A BD08"]; 1916 1917 for p in pile.descendants() { 1918 if let &Packet::PublicKey(ref p) = p { 1919 let fp = p.fingerprint().to_string(); 1920 // eprintln!("PK: {:?}", fp); 1921 1922 assert!(pki < pks.len()); 1923 assert_eq!(fp, pks[pki]); 1924 pki += 1; 1925 } 1926 1927 if let &Packet::PublicSubkey(ref p) = p { 1928 let fp = p.fingerprint().to_string(); 1929 // eprintln!("SK: {:?}", fp); 1930 1931 assert!(ski < sks.len()); 1932 assert_eq!(fp, sks[ski]); 1933 ski += 1; 1934 } 1935 } 1936 assert!(pki == pks.len() && ski == sks.len()); 1937 } 1938 1939 #[test] encrypt_huge_plaintext() -> Result<()>1940 fn encrypt_huge_plaintext() -> Result<()> { 1941 let sk = crate::crypto::SessionKey::new(256); 1942 let rsa2k: Key<SecretParts, UnspecifiedRole> = 1943 Key4::generate_rsa(2048)?.into(); 1944 assert!(destructures_to!( 1945 crate::Error::InvalidArgument(_) = 1946 rsa2k.encrypt(&sk).unwrap_err().downcast().unwrap())); 1947 1948 let cv25519: Key<SecretParts, UnspecifiedRole> = 1949 Key4::generate_ecc(false, Curve::Cv25519)?.into(); 1950 assert!(destructures_to!( 1951 crate::Error::InvalidArgument(_) = 1952 cv25519.encrypt(&sk).unwrap_err().downcast().unwrap())); 1953 1954 Ok(()) 1955 } 1956 } 1957