Add encryption
- actually encrypt the body of a mail
This commit is contained in:
@@ -4,12 +4,14 @@
|
|||||||
// cryptographic functions
|
// cryptographic functions
|
||||||
//
|
//
|
||||||
|
|
||||||
|
use std::io::Write;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use anyhow;
|
use anyhow;
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use sequoia_openpgp::parse::{PacketParser, PacketParserResult, Parse};
|
use sequoia_openpgp::parse::{PacketParser, PacketParserResult, Parse};
|
||||||
use sequoia_openpgp::policy::StandardPolicy;
|
use sequoia_openpgp::policy::StandardPolicy;
|
||||||
|
use sequoia_openpgp::serialize::stream::{Message, Armorer, Encryptor, LiteralWriter};
|
||||||
use sequoia_openpgp::{Fingerprint, Cert, Packet};
|
use sequoia_openpgp::{Fingerprint, Cert, Packet};
|
||||||
use sequoia_openpgp::cert::raw::RawCertParser;
|
use sequoia_openpgp::cert::raw::RawCertParser;
|
||||||
use sequoia_cert_store::{Store, CertStore, LazyCert};
|
use sequoia_cert_store::{Store, CertStore, LazyCert};
|
||||||
@@ -20,6 +22,7 @@ use wot::{Depth, Path};
|
|||||||
use crate::types::errors::HuskError;
|
use crate::types::errors::HuskError;
|
||||||
use crate::types::husk_context::HuskContext;
|
use crate::types::husk_context::HuskContext;
|
||||||
use crate::types::introducer::Introducer;
|
use crate::types::introducer::Introducer;
|
||||||
|
use crate::types::recipient::Recipient;
|
||||||
|
|
||||||
pub fn get_local_trust_root(cert_store: &CertStore) -> anyhow::Result<Cert> {
|
pub fn get_local_trust_root(cert_store: &CertStore) -> anyhow::Result<Cert> {
|
||||||
|
|
||||||
@@ -155,6 +158,42 @@ pub fn is_encrypted(body: &Bytes) -> bool {
|
|||||||
false
|
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)]
|
#[cfg(test)]
|
||||||
pub mod tests {
|
pub mod tests {
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
|
|||||||
+11
-4
@@ -210,14 +210,21 @@ impl Daemon {
|
|||||||
// none -> accept
|
// none -> accept
|
||||||
// partial -> accept (later: split)
|
// partial -> accept (later: split)
|
||||||
// full -> encrypt
|
// full -> encrypt
|
||||||
// check mailbody
|
|
||||||
// is encrypted -> accept
|
|
||||||
// else -> encrypt
|
|
||||||
|
|
||||||
let protection = ProtectionPossibility::from(&context.mail);
|
let protection = ProtectionPossibility::from(&context.mail);
|
||||||
|
|
||||||
if protection == ProtectionPossibility::Full {
|
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")]
|
#[error("Cannot find local trust root")]
|
||||||
NoLocalTrustRoot,
|
NoLocalTrustRoot,
|
||||||
#[error("Cannot access cert store")]
|
#[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>>,
|
pub recipients: Vec<Recipient<'mc>>,
|
||||||
// header
|
// header
|
||||||
body: Vec<Bytes>,
|
body: Vec<Bytes>,
|
||||||
pub body_size: usize,
|
pub body_size: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'mc> MailContext<'mc> {
|
impl<'mc> MailContext<'mc> {
|
||||||
@@ -46,7 +46,7 @@ impl<'mc> MailContext<'mc> {
|
|||||||
recipient.certs = certs;
|
recipient.certs = certs;
|
||||||
|
|
||||||
self.recipients.push(recipient);
|
self.recipients.push(recipient);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user