pgp/
decrypt.rs

1//! # Decrypt
2//!
3//! Module dedicated to PGP decryption. This module exposes a simple
4//! function [`decrypt`] and its associated [`Error`]s.
5
6use std::io::Cursor;
7
8use crate::{
9    native::{self, Deserializable, Message, SignedSecretKey},
10    utils::spawn_blocking,
11    Error, Result,
12};
13
14/// Decrypts bytes using the given secret key and its passphrase.
15pub async fn decrypt(
16    skey: SignedSecretKey,
17    passphrase: impl ToString,
18    encrypted_bytes: Vec<u8>,
19) -> Result<Vec<u8>> {
20    let passphrase = passphrase.to_string();
21    spawn_blocking(move || {
22        let (msg, _) = Message::from_armor_single(Cursor::new(&encrypted_bytes))
23            .map_err(Error::ImportMessageFromArmorError)?;
24        let (decryptor, _) = msg
25            .decrypt(|| passphrase, &[&skey])
26            .map_err(Error::DecryptMessageError)?;
27        let msgs = decryptor
28            .collect::<native::errors::Result<Vec<_>>>()
29            .map_err(Error::DecryptMessageError)?;
30        let msg = msgs.into_iter().next().ok_or(Error::GetMessageEmptyError)?;
31        let msg = msg.decompress().map_err(Error::DecompressMessageError)?;
32
33        let plain_bytes = msg
34            .get_content()
35            .map_err(Error::GetMessageContentError)?
36            .ok_or(Error::GetMessageContentEmptyError)?;
37
38        Ok(plain_bytes)
39    })
40    .await?
41}
42
43#[cfg(test)]
44mod tests {
45    #[cfg(feature = "async-std")]
46    use async_std::test;
47    #[cfg(feature = "tokio")]
48    use tokio::test;
49
50    use crate::{decrypt, encrypt, gen_key_pair, native};
51
52    #[test_log::test(test)]
53    async fn encrypt_then_decrypt() {
54        let (alice_skey, alice_pkey) = gen_key_pair("alice@localhost", "").await.unwrap();
55        let (bob_skey, bob_pkey) = gen_key_pair("bob@localhost", "").await.unwrap();
56        let (carl_skey, _carl_pkey) = gen_key_pair("carl@localhost", "").await.unwrap();
57
58        let msg = b"encrypted message".to_vec();
59        let encrypted_msg = encrypt(vec![alice_pkey, bob_pkey], msg.clone())
60            .await
61            .unwrap();
62
63        let alice_msg = decrypt(alice_skey, "", encrypted_msg.clone())
64            .await
65            .unwrap();
66        assert_eq!(alice_msg, msg);
67
68        let bob_msg = decrypt(bob_skey, "", encrypted_msg.clone()).await.unwrap();
69        assert_eq!(bob_msg, msg);
70
71        let carl_msg = decrypt(carl_skey, "", encrypted_msg.clone())
72            .await
73            .unwrap_err();
74        assert!(matches!(
75            carl_msg,
76            super::Error::DecryptMessageError(native::errors::Error::MissingKey),
77        ));
78    }
79}