Add encryption
- actually encrypt the body of a mail
This commit is contained in:
@@ -4,12 +4,14 @@
|
||||
// cryptographic functions
|
||||
//
|
||||
|
||||
use std::io::Write;
|
||||
use std::sync::Arc;
|
||||
|
||||
use anyhow;
|
||||
use bytes::Bytes;
|
||||
use sequoia_openpgp::parse::{PacketParser, PacketParserResult, Parse};
|
||||
use sequoia_openpgp::policy::StandardPolicy;
|
||||
use sequoia_openpgp::serialize::stream::{Message, Armorer, Encryptor, LiteralWriter};
|
||||
use sequoia_openpgp::{Fingerprint, Cert, Packet};
|
||||
use sequoia_openpgp::cert::raw::RawCertParser;
|
||||
use sequoia_cert_store::{Store, CertStore, LazyCert};
|
||||
@@ -20,6 +22,7 @@ use wot::{Depth, Path};
|
||||
use crate::types::errors::HuskError;
|
||||
use crate::types::husk_context::HuskContext;
|
||||
use crate::types::introducer::Introducer;
|
||||
use crate::types::recipient::Recipient;
|
||||
|
||||
pub fn get_local_trust_root(cert_store: &CertStore) -> anyhow::Result<Cert> {
|
||||
|
||||
@@ -155,6 +158,42 @@ pub fn is_encrypted(body: &Bytes) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
pub fn encrypt(context: &HuskContext<'_>, body: &Bytes, recipients: &Vec<Recipient>)
|
||||
-> anyhow::Result<Bytes> {
|
||||
|
||||
let mut keys = Vec::new();
|
||||
|
||||
// XXX: handle the case where a certificate misses an encryption subkey
|
||||
for rcpt in recipients {
|
||||
if rcpt.can_encrypt() {
|
||||
for cert in &rcpt.certs {
|
||||
cert.with_policy(&context.policy, None)?
|
||||
.keys()
|
||||
.supported()
|
||||
.alive()
|
||||
.revoked(false)
|
||||
.for_transport_encryption()
|
||||
.for_each(|k| {
|
||||
keys.push(k);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
if keys.len() > 0 {
|
||||
let mut sink = Vec::new();
|
||||
let message = Message::new(&mut sink);
|
||||
let message = Armorer::new(message).build()?;
|
||||
let message = Encryptor::for_recipients(message, keys).build()?;
|
||||
let mut message = LiteralWriter::new(message).build()?;
|
||||
message.write_all(&body[..])?;
|
||||
message.finalize()?;
|
||||
|
||||
Ok(Bytes::from(sink))
|
||||
} else {
|
||||
Err(HuskError::NoEncryptionKeys.into())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod tests {
|
||||
use bytes::Bytes;
|
||||
|
||||
+11
-4
@@ -210,14 +210,21 @@ impl Daemon {
|
||||
// none -> accept
|
||||
// partial -> accept (later: split)
|
||||
// full -> encrypt
|
||||
// check mailbody
|
||||
// is encrypted -> accept
|
||||
// else -> encrypt
|
||||
|
||||
let protection = ProtectionPossibility::from(&context.mail);
|
||||
|
||||
if protection == ProtectionPossibility::Full {
|
||||
// encrypt
|
||||
// if an error occures the body is not exchanged
|
||||
match crypto::encrypt(&context, &body, &context.mail.recipients) {
|
||||
Ok(encrypted) => {
|
||||
if cx.actions.replace_body(&encrypted).await.is_err() {
|
||||
log::error!("Cannot exchange body");
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
log::error!("{}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-1
@@ -11,5 +11,7 @@ pub enum HuskError {
|
||||
#[error("Cannot find local trust root")]
|
||||
NoLocalTrustRoot,
|
||||
#[error("Cannot access cert store")]
|
||||
NoCertStore
|
||||
NoCertStore,
|
||||
#[error("No encryption keys found")]
|
||||
NoEncryptionKeys,
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ pub struct MailContext<'mc> {
|
||||
pub recipients: Vec<Recipient<'mc>>,
|
||||
// header
|
||||
body: Vec<Bytes>,
|
||||
pub body_size: usize,
|
||||
pub body_size: usize,
|
||||
}
|
||||
|
||||
impl<'mc> MailContext<'mc> {
|
||||
@@ -46,7 +46,7 @@ impl<'mc> MailContext<'mc> {
|
||||
recipient.certs = certs;
|
||||
|
||||
self.recipients.push(recipient);
|
||||
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user