pgp/
decrypt.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
//! Module dedicated to PGP decryption.
//!
//! This module exposes a simple function [`decrypt`] and its
//! associated [`Error`]s.

use std::io::Cursor;

use native::{Deserializable, Message, SignedSecretKey};

use crate::{utils::spawn_blocking, Error, Result};

/// Decrypts bytes using the given secret key and its passphrase.
pub async fn decrypt(
    skey: SignedSecretKey,
    passphrase: impl ToString,
    encrypted_bytes: Vec<u8>,
) -> Result<Vec<u8>> {
    let passphrase = passphrase.to_string();
    spawn_blocking(move || {
        let (msg, _) = Message::from_armor_single(Cursor::new(&encrypted_bytes))
            .map_err(Error::ImportMessageFromArmorError)?;
        let (decryptor, _) = msg
            .decrypt(|| passphrase, &[&skey])
            .map_err(Error::DecryptMessageError)?;
        let msgs = decryptor
            .collect::<native::errors::Result<Vec<_>>>()
            .map_err(Error::DecryptMessageError)?;
        let msg = msgs.into_iter().next().ok_or(Error::GetMessageEmptyError)?;
        let msg = msg.decompress().map_err(Error::DecompressMessageError)?;

        let plain_bytes = msg
            .get_content()
            .map_err(Error::GetMessageContentError)?
            .ok_or(Error::GetMessageContentEmptyError)?;

        Ok(plain_bytes)
    })
    .await?
}

#[cfg(test)]
mod tests {
    use crate::{decrypt, encrypt, gen_key_pair};

    #[tokio::test]
    async fn encrypt_then_decrypt() {
        let (alice_skey, alice_pkey) = gen_key_pair("alice@localhost", "").await.unwrap();
        let (bob_skey, bob_pkey) = gen_key_pair("bob@localhost", "").await.unwrap();
        let (carl_skey, _carl_pkey) = gen_key_pair("carl@localhost", "").await.unwrap();

        let msg = b"encrypted message".to_vec();
        let encrypted_msg = encrypt(vec![alice_pkey, bob_pkey], msg.clone())
            .await
            .unwrap();

        let alice_msg = decrypt(alice_skey, "", encrypted_msg.clone())
            .await
            .unwrap();
        assert_eq!(alice_msg, msg);

        let bob_msg = decrypt(bob_skey, "", encrypted_msg.clone()).await.unwrap();
        assert_eq!(bob_msg, msg);

        let carl_msg = decrypt(carl_skey, "", encrypted_msg.clone())
            .await
            .unwrap_err();
        assert!(matches!(
            carl_msg,
            super::Error::DecryptMessageError(native::errors::Error::MissingKey),
        ));
    }
}