|
|
@ -23,7 +23,6 @@ use std::{
|
|
|
|
collections::{hash_map::DefaultHasher, BTreeMap},
|
|
|
|
collections::{hash_map::DefaultHasher, BTreeMap},
|
|
|
|
future::Future,
|
|
|
|
future::Future,
|
|
|
|
hash::{Hash, Hasher},
|
|
|
|
hash::{Hash, Hasher},
|
|
|
|
pin::Pin,
|
|
|
|
|
|
|
|
sync::{Arc, Mutex},
|
|
|
|
sync::{Arc, Mutex},
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
@ -38,6 +37,8 @@ use melib::{
|
|
|
|
parser::BytesExt,
|
|
|
|
parser::BytesExt,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
use super::AttachmentBoxFuture;
|
|
|
|
|
|
|
|
|
|
|
|
pub async fn decrypt(raw: Vec<u8>) -> Result<(melib_pgp::DecryptionMetadata, Vec<u8>)> {
|
|
|
|
pub async fn decrypt(raw: Vec<u8>) -> Result<(melib_pgp::DecryptionMetadata, Vec<u8>)> {
|
|
|
|
let mut ctx = Context::new()?;
|
|
|
|
let mut ctx = Context::new()?;
|
|
|
|
let cipher = ctx.new_data_mem(&raw)?;
|
|
|
|
let cipher = ctx.new_data_mem(&raw)?;
|
|
|
@ -88,31 +89,47 @@ pub fn sign_filter(
|
|
|
|
Box::pin(async move {
|
|
|
|
Box::pin(async move {
|
|
|
|
if let Some(default_key) = default_key {
|
|
|
|
if let Some(default_key) = default_key {
|
|
|
|
let mut ctx = Context::new()?;
|
|
|
|
let mut ctx = Context::new()?;
|
|
|
|
let data = ctx.new_data_mem(&melib_pgp::convert_attachment_to_rfc_spec(
|
|
|
|
ctx.set_auto_key_locate(LocateKey::LOCAL)?;
|
|
|
|
a.into_raw().as_bytes(),
|
|
|
|
let keys = ctx.keylist(false, Some(default_key.clone()))?.await?;
|
|
|
|
))?;
|
|
|
|
if keys.is_empty() {
|
|
|
|
let sig_attachment = Attachment::new(
|
|
|
|
return Err(Error::new(format!(
|
|
|
|
ContentType::PGPSignature,
|
|
|
|
"Could not locate sign key with ID `{}`",
|
|
|
|
Default::default(),
|
|
|
|
default_key
|
|
|
|
ctx.sign(sign_keys, data)?.await?,
|
|
|
|
)));
|
|
|
|
);
|
|
|
|
}
|
|
|
|
let a: AttachmentBuilder = a.into();
|
|
|
|
sign_keys.extend(keys);
|
|
|
|
let parts = vec![a, sig_attachment.into()];
|
|
|
|
}
|
|
|
|
let boundary = ContentType::make_boundary(&parts);
|
|
|
|
if sign_keys.is_empty() {
|
|
|
|
Ok(Attachment::new(
|
|
|
|
return Err(Error::new(
|
|
|
|
ContentType::Multipart {
|
|
|
|
"No key was selected for signing; please select one.",
|
|
|
|
boundary: boundary.into_bytes(),
|
|
|
|
));
|
|
|
|
kind: MultipartType::Signed,
|
|
|
|
}
|
|
|
|
parts: parts.into_iter().map(|a| a.into()).collect::<Vec<_>>(),
|
|
|
|
let a: Attachment = a.into();
|
|
|
|
parameters: vec![],
|
|
|
|
let mut ctx = Context::new()?;
|
|
|
|
},
|
|
|
|
let data = ctx.new_data_mem(&melib_pgp::convert_attachment_to_rfc_spec(
|
|
|
|
Default::default(),
|
|
|
|
a.into_raw().as_bytes(),
|
|
|
|
vec![],
|
|
|
|
))?;
|
|
|
|
)
|
|
|
|
let sig_attachment = Attachment::new(
|
|
|
|
.into())
|
|
|
|
ContentType::PGPSignature,
|
|
|
|
})
|
|
|
|
Default::default(),
|
|
|
|
},
|
|
|
|
ctx.sign(sign_keys, data)?.await?,
|
|
|
|
)
|
|
|
|
);
|
|
|
|
|
|
|
|
let a: AttachmentBuilder = a.into();
|
|
|
|
|
|
|
|
let parts = vec![a, sig_attachment.into()];
|
|
|
|
|
|
|
|
let boundary = ContentType::make_boundary(&parts);
|
|
|
|
|
|
|
|
Ok(Attachment::new(
|
|
|
|
|
|
|
|
ContentType::Multipart {
|
|
|
|
|
|
|
|
boundary: boundary.into_bytes(),
|
|
|
|
|
|
|
|
kind: MultipartType::Signed,
|
|
|
|
|
|
|
|
parts: parts.into_iter().map(|a| a.into()).collect::<Vec<_>>(),
|
|
|
|
|
|
|
|
parameters: vec![],
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
Default::default(),
|
|
|
|
|
|
|
|
vec![],
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
.into())
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub fn encrypt_filter(
|
|
|
|
pub fn encrypt_filter(
|
|
|
@ -166,37 +183,62 @@ pub fn encrypt_filter(
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if let Some(encrypt_for_self) = encrypt_for_self {
|
|
|
|
if let Some(encrypt_for_self) = encrypt_for_self {
|
|
|
|
let mut ctx = Context::new()?;
|
|
|
|
let mut ctx = Context::new()?;
|
|
|
|
let data = ctx.new_data_mem(
|
|
|
|
ctx.set_auto_key_locate(LocateKey::LOCAL)?;
|
|
|
|
a.into_raw().as_bytes()
|
|
|
|
let keys = ctx
|
|
|
|
)?;
|
|
|
|
.keylist(false, Some(encrypt_for_self.to_string()))?
|
|
|
|
|
|
|
|
.await?;
|
|
|
|
let sig_attachment = {
|
|
|
|
if keys.is_empty() {
|
|
|
|
let mut a = Attachment::new(
|
|
|
|
return Err(Error::new(format!(
|
|
|
|
ContentType::OctetStream { name: None, parameters: vec![] },
|
|
|
|
"Could not locate personal encryption key for address `{}`",
|
|
|
|
Default::default(),
|
|
|
|
encrypt_for_self
|
|
|
|
ctx.encrypt(sign_keys, encrypt_keys, data)?.await?,
|
|
|
|
)));
|
|
|
|
);
|
|
|
|
}
|
|
|
|
a.content_disposition = ContentDisposition::from(br#"attachment; filename="msg.asc""#);
|
|
|
|
for key in keys {
|
|
|
|
a
|
|
|
|
if !encrypt_keys.contains(&key) {
|
|
|
|
};
|
|
|
|
encrypt_keys.push(key);
|
|
|
|
let mut a: AttachmentBuilder = AttachmentBuilder::new(b"Version: 1\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
let a: Attachment = a.into();
|
|
|
|
|
|
|
|
log::trace!(
|
|
|
|
|
|
|
|
"main attachment is {:?} sign_keys = {:?} encrypt_keys = {:?}",
|
|
|
|
|
|
|
|
&a,
|
|
|
|
|
|
|
|
&sign_keys,
|
|
|
|
|
|
|
|
&encrypt_keys
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
let mut ctx = Context::new()?;
|
|
|
|
|
|
|
|
let data = ctx.new_data_mem(a.into_raw().as_bytes())?;
|
|
|
|
|
|
|
|
|
|
|
|
a.set_content_type_from_bytes(b"application/pgp-encrypted");
|
|
|
|
let enc_attachment = {
|
|
|
|
a.set_content_disposition(ContentDisposition::from(b"attachment"));
|
|
|
|
let mut a = Attachment::new(
|
|
|
|
let parts = vec![a, sig_attachment.into()];
|
|
|
|
ContentType::OctetStream {
|
|
|
|
let boundary = ContentType::make_boundary(&parts);
|
|
|
|
name: None,
|
|
|
|
Ok(Attachment::new(
|
|
|
|
|
|
|
|
ContentType::Multipart {
|
|
|
|
|
|
|
|
boundary: boundary.into_bytes(),
|
|
|
|
|
|
|
|
kind: MultipartType::Encrypted,
|
|
|
|
|
|
|
|
parts: parts.into_iter().map(|a| a.into()).collect::<Vec<_>>(),
|
|
|
|
|
|
|
|
parameters: vec![],
|
|
|
|
parameters: vec![],
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Default::default(),
|
|
|
|
Default::default(),
|
|
|
|
vec![],
|
|
|
|
ctx.encrypt(sign_keys, encrypt_keys, data)?.await?,
|
|
|
|
)
|
|
|
|
);
|
|
|
|
.into())
|
|
|
|
a.content_disposition =
|
|
|
|
})
|
|
|
|
ContentDisposition::from(br#"attachment; filename="msg.asc""#);
|
|
|
|
},
|
|
|
|
a
|
|
|
|
)
|
|
|
|
};
|
|
|
|
|
|
|
|
let mut a: AttachmentBuilder = AttachmentBuilder::new(b"Version: 1\n");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
a.set_content_type_from_bytes(b"application/pgp-encrypted");
|
|
|
|
|
|
|
|
a.set_content_disposition(ContentDisposition::from(b"attachment"));
|
|
|
|
|
|
|
|
let parts = vec![a, enc_attachment.into()];
|
|
|
|
|
|
|
|
let boundary = ContentType::make_boundary(&parts);
|
|
|
|
|
|
|
|
Ok(Attachment::new(
|
|
|
|
|
|
|
|
ContentType::Multipart {
|
|
|
|
|
|
|
|
boundary: boundary.into_bytes(),
|
|
|
|
|
|
|
|
kind: MultipartType::Encrypted,
|
|
|
|
|
|
|
|
parts: parts.into_iter().map(|a| a.into()).collect::<Vec<_>>(),
|
|
|
|
|
|
|
|
parameters: vec![],
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
Default::default(),
|
|
|
|
|
|
|
|
vec![],
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
.into())
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|