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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
use anyhow::Result;
use gpgme::{Context as GpgmeContext, Protocol};
use thiserror::Error;
use super::raw;
use crate::crypto::{proto, IsContext, Key, Proto};
use crate::{Ciphertext, Plaintext, Recipients};
const PROTO: Protocol = Protocol::OpenPgp;
pub fn context() -> Result<Context, Err> {
Ok(Context::from(
gpgme::Context::from_protocol(PROTO).map_err(|err| Err::Context(err).into())?,
))
}
pub struct Context {
context: GpgmeContext,
}
impl Context {
pub fn from(context: GpgmeContext) -> Self {
Self { context }
}
}
impl IsContext for Context {
fn encrypt(&mut self, recipients: &Recipients, plaintext: Plaintext) -> Result<Ciphertext> {
let fingerprints: Vec<String> = recipients
.keys()
.iter()
.map(|key| key.fingerprint(false))
.collect();
let fingerprints: Vec<&str> = fingerprints.iter().map(|fp| fp.as_str()).collect();
raw::encrypt(&mut self.context, &fingerprints, plaintext)
}
fn decrypt(&mut self, ciphertext: Ciphertext) -> Result<Plaintext> {
raw::decrypt(&mut self.context, ciphertext)
}
fn can_decrypt(&mut self, ciphertext: Ciphertext) -> Result<bool> {
raw::can_decrypt(&mut self.context, ciphertext)
}
fn keys_public(&mut self) -> Result<Vec<Key>> {
Ok(raw::public_keys(&mut self.context)?
.into_iter()
.map(|key| {
Key::Gpg(proto::gpg::Key {
fingerprint: key.0,
user_ids: key.1,
})
})
.collect())
}
fn keys_private(&mut self) -> Result<Vec<Key>> {
Ok(raw::private_keys(&mut self.context)?
.into_iter()
.map(|key| {
Key::Gpg(proto::gpg::Key {
fingerprint: key.0,
user_ids: key.1,
})
})
.collect())
}
fn import_key(&mut self, key: &[u8]) -> Result<()> {
raw::import_key(&mut self.context, key)
}
fn export_key(&mut self, key: Key) -> Result<Vec<u8>> {
raw::export_key(&mut self.context, &key.fingerprint(false))
}
fn supports_proto(&self, proto: Proto) -> bool {
proto == Proto::Gpg
}
}
#[derive(Debug, Error)]
pub enum Err {
#[error("failed to obtain GPGME cryptography context")]
Context(#[source] gpgme::Error),
}