use async_trait::async_trait;
use didcomm_rs::Jwe;
use ed25519_dalek::{Keypair, PublicKey, SecretKey};
use rand_core::OsRng;
use vade::{VadePlugin, VadePluginResultValue};
use x25519_dalek::StaticSecret;
use crate::{
datatypes::{
BaseMessage, DidCommOptions, EncryptionKeyPair, EncryptionKeys, ExtendedMessage,
MessageDirection, ProtocolHandleOutput,
},
fill_message_id_and_timestamps, get_from_to_from_message,
keypair::{get_com_keypair, get_key_agreement_key},
message::{decrypt_message, encrypt_message},
protocol_handler::ProtocolHandler,
utils::{read_raw_message_from_db, vec_to_array, write_raw_message_to_db},
};
big_array! { BigArray; }
pub struct VadeDidComm {}
impl VadeDidComm {
pub fn new() -> Result<VadeDidComm, Box<dyn std::error::Error>> {
match env_logger::try_init() {
Ok(_) | Err(_) => (),
};
let vade_didcomm = VadeDidComm {};
Ok(vade_didcomm)
}
}
#[async_trait(?Send)]
impl VadePlugin for VadeDidComm {
async fn run_custom_function(
&mut self,
_method: &str,
function: &str,
_options: &str,
payload: &str,
) -> Result<VadePluginResultValue<Option<String>>, Box<dyn std::error::Error>> {
match function {
"create_keys" => {
let secret_key = StaticSecret::new(OsRng);
let pub_key = x25519_dalek::PublicKey::from(&secret_key);
let enc_key_pair = EncryptionKeyPair {
secret: secret_key.to_bytes(),
public: pub_key.to_bytes(),
};
Ok(VadePluginResultValue::Success(Some(serde_json::to_string(
&enc_key_pair,
)?)))
}
"query_didcomm_messages" => {
let mut message_values = payload.split('_');
let prefix = message_values.next().ok_or("Invalid message prefix")?;
let thid = message_values.next().ok_or("Invalid message thid")?;
let message_id = message_values.next().ok_or("Invalid message id")?;
let db_result = read_raw_message_from_db(prefix, thid, message_id)?;
let result = serde_json::to_string(&db_result)?;
Ok(VadePluginResultValue::Success(Some(result)))
}
_ => Ok(VadePluginResultValue::Ignored),
}
}
async fn didcomm_send(
&mut self,
options: &str,
message: &str,
) -> Result<VadePluginResultValue<Option<String>>, Box<dyn std::error::Error>> {
log::debug!("preparing DIDComm message for being sent");
let options_parsed = serde_json::from_str::<DidCommOptions>(options)?;
let message_with_id = fill_message_id_and_timestamps(message)?;
let mut protocol_result = match options_parsed.skip_protocol_handling {
None | Some(false) => {
ProtocolHandler::before_send(options, &message_with_id)?
}
_ => ProtocolHandleOutput {
direction: MessageDirection::Send,
encrypt: true,
protocol: "".to_string(),
metadata: "{}".to_string(),
message: message.to_owned(),
step: "".to_string(),
},
};
let message_raw = &message_with_id;
write_raw_message_to_db(message_raw)?;
let final_message: String;
if protocol_result.encrypt && !matches!(options_parsed.skip_message_packaging, Some(true)) {
let encryption_keys: EncryptionKeys;
if options_parsed.encryption_keys.is_some() {
encryption_keys = options_parsed
.encryption_keys
.ok_or("encryption_keys is missing in options parameter")?;
} else {
let parsed_message: BaseMessage = serde_json::from_str(message)?;
let from_to = get_from_to_from_message(&parsed_message)?;
let mut encoded_keypair = get_key_agreement_key(&from_to.from);
if encoded_keypair.is_err() {
encoded_keypair = get_com_keypair(&from_to.from, &from_to.to);
if encoded_keypair.is_err() {
return Err(Box::from("No keypair found"));
}
encoded_keypair = get_key_agreement_key(&encoded_keypair?.key_agreement_key);
}
let keypair = encoded_keypair?;
let secret_decoded = vec_to_array(hex::decode(keypair.secret_key)?)?;
let public_decoded = vec_to_array(hex::decode(keypair.target_pub_key)?)?;
let mut parsed_message: ExtendedMessage =
serde_json::from_str(&protocol_result.message)?;
log::debug!(
"adjusting from: {} to:{}",
keypair.key_agreement_key,
keypair.target_key_agreement_key
);
parsed_message.to = Some(vec![keypair.target_key_agreement_key]);
parsed_message.from = Some(keypair.key_agreement_key);
protocol_result.message = serde_json::to_string(&parsed_message)?;
encryption_keys = EncryptionKeys {
encryption_my_secret: StaticSecret::from(secret_decoded).to_bytes(),
encryption_others_public: Some(public_decoded),
};
}
let signing_keypair;
if let Some(signing_keys_input) = options_parsed.signing_keys {
let secret_key = SecretKey::from_bytes(
&signing_keys_input
.signing_my_secret
.ok_or("No signing secret key provided")?,
)?;
signing_keypair = Some(Keypair {
public: PublicKey::from(&secret_key),
secret: secret_key,
});
} else {
signing_keypair = None;
}
final_message = encrypt_message(
&protocol_result.message,
&encryption_keys.encryption_my_secret,
encryption_keys
.encryption_others_public
.as_ref()
.map(|v| v.to_vec()),
signing_keypair,
)?;
} else {
final_message = protocol_result.message;
}
let send_result = format!(
r#"{{
"message": {},
"messageRaw": {},
"metadata": {}
}}"#,
final_message, message_raw, protocol_result.metadata,
);
return Ok(VadePluginResultValue::Success(Some(send_result)));
}
async fn didcomm_receive(
&mut self,
options: &str,
message: &str,
) -> Result<VadePluginResultValue<Option<String>>, Box<dyn std::error::Error>> {
log::debug!("handling incoming DIDComm message");
let options_parsed = serde_json::from_str::<DidCommOptions>(options)?;
let parsed_message = serde_json::from_str::<Jwe>(message);
let decrypted: String;
if parsed_message.is_ok() && !matches!(options_parsed.skip_message_packaging, Some(true)) {
let decryption_keys: EncryptionKeys;
if options_parsed.encryption_keys.is_some() {
decryption_keys = options_parsed
.encryption_keys
.ok_or("encryption_keys is missing")?;
} else {
let parsed_message = parsed_message?;
let from = parsed_message
.protected
.unwrap_or_default()
.skid
.unwrap_or_default();
let recipient = &parsed_message.recipients.unwrap_or_default()[0];
let to = recipient.header.kid.as_ref().unwrap();
log::debug!("fetching kak for from: {} to: {}", to, from);
let mut encoded_keypair = get_key_agreement_key(to);
if encoded_keypair.is_err() {
log::debug!("fetching kak for {}", to);
encoded_keypair = get_com_keypair(to, &from);
if encoded_keypair.is_err() {
return Err(Box::from("No keypair found"));
}
}
let keypair = encoded_keypair?;
let mut target_pub_key = None;
if !keypair.target_pub_key.is_empty() {
target_pub_key = Some(vec_to_array(hex::decode(keypair.target_pub_key)?)?);
}
decryption_keys = EncryptionKeys {
encryption_my_secret: vec_to_array(hex::decode(keypair.secret_key)?)?,
encryption_others_public: target_pub_key,
};
}
let signing_others_public = options_parsed
.signing_keys
.map(|keys| keys.signing_others_public)
.flatten();
decrypted = decrypt_message(
message,
Some(&decryption_keys.encryption_my_secret),
decryption_keys
.encryption_others_public
.as_ref()
.map(|v| v.to_vec()),
signing_others_public.as_ref().map(|v| &v[..]),
)?;
} else {
decrypted = String::from(message);
}
let message_with_id = fill_message_id_and_timestamps(&decrypted)?;
write_raw_message_to_db(&message_with_id)?;
let protocol_result = match options_parsed.skip_protocol_handling {
None | Some(false) => {
ProtocolHandler::after_receive(options, &message_with_id)?
}
_ => ProtocolHandleOutput {
direction: MessageDirection::Receive,
encrypt: true,
protocol: "".to_string(),
metadata: "{}".to_string(),
message: message_with_id,
step: "".to_string(),
},
};
let receive_result = format!(
r#"{{
"message": {},
"metadata": {}
}}"#,
protocol_result.message, protocol_result.metadata,
);
return Ok(VadePluginResultValue::Success(Some(receive_result)));
}
}