use thiserror::Error;
#[cfg(doc)]
use super::EstablishedEcies;
use crate::{Curve25519PublicKey, KeyError, base64_decode, base64_encode};
#[derive(Debug, Error)]
pub enum MessageDecodeError {
#[error("The initial message is missing the | separator")]
MissingSeparator,
#[error("The embedded ephemeral Curve25519 key could not have been decoded: {0:?}")]
KeyError(#[from] KeyError),
#[error("The ciphertext could not have been decoded from a base64 string: {0:?}")]
Base64(#[from] base64::DecodeError),
}
#[derive(Debug, PartialEq, Eq)]
pub struct InitialMessage {
pub public_key: Curve25519PublicKey,
pub ciphertext: Vec<u8>,
}
impl InitialMessage {
pub fn encode(&self) -> String {
let ciphertext = base64_encode(&self.ciphertext);
let key = self.public_key.to_base64();
format!("{ciphertext}|{key}")
}
pub fn decode(message: &str) -> Result<Self, MessageDecodeError> {
match message.split_once('|') {
Some((ciphertext, key)) => {
let public_key = Curve25519PublicKey::from_base64(key)?;
let ciphertext = base64_decode(ciphertext)?;
Ok(Self { ciphertext, public_key })
}
None => Err(MessageDecodeError::MissingSeparator),
}
}
}
#[derive(Debug)]
pub struct Message {
pub ciphertext: Vec<u8>,
}
impl Message {
pub fn encode(&self) -> String {
base64_encode(&self.ciphertext)
}
pub fn decode(message: &str) -> Result<Self, MessageDecodeError> {
Ok(Self { ciphertext: base64_decode(message)? })
}
}
#[cfg(test)]
mod test {
use super::*;
const INITIAL_MESSAGE: &str = "3On7QFJyLQMAErua9K/yIOcJALvuMYax1AW0iWgf64AwtSMZXwAA012Q|9yA/CX8pJKF02Prd75ZyBQHg3fGTVVGDNl86q1z17Us";
const MESSAGE: &str = "ZmtSLdzMcyjC5eV6L8xBI6amsq7gDNbCjz1W5OjX4Z8W";
const PUBLIC_KEY: &str = "9yA/CX8pJKF02Prd75ZyBQHg3fGTVVGDNl86q1z17Us";
#[test]
fn initial_message() {
let message = InitialMessage::decode(INITIAL_MESSAGE)
.expect("We should be able to decode our known-valid initial message");
assert_eq!(
message.public_key.to_base64(),
PUBLIC_KEY,
"The decoded public key should match the expected one"
);
let encoded = message.encode();
assert_eq!(INITIAL_MESSAGE, encoded);
}
#[test]
fn message() {
let message = Message::decode(MESSAGE)
.expect("We should be able to decode our known-valid initial message");
let encoded = message.encode();
assert_eq!(MESSAGE, encoded);
}
}