Skip to content

Commit

Permalink
wip: add SecretExchange encode/decode
Browse files Browse the repository at this point in the history
Signed-off-by: Dhanuka Warusadura <dhanuka@gnome.org>
  • Loading branch information
warusadura committed May 15, 2024
1 parent 84c221a commit 6b1e08f
Showing 1 changed file with 45 additions and 25 deletions.
70 changes: 45 additions & 25 deletions server/src/daemon/secret_exchange.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// SecretExchange — Exchange secrets between processes in an unexposed way

// In this implementation the payload is a HashMap.
// In this implementation the payload is a String.
// Initial implementation uses a KeyFile.
// Secret components (key, iv, ...) are base64 encoded before transit.

Expand All @@ -20,24 +20,22 @@ pub struct SecretExchange {
}

impl SecretExchange {
pub fn secret_exchange_begin(&self) -> HashMap<&str, String> {
let mut exchange: HashMap<&str, String> = HashMap::new();
exchange.insert(PUBLIC, BASE64_STANDARD.encode(&self.public_key));
pub fn secret_exchange_begin(&self) -> String {
let map = HashMap::from([(PUBLIC, BASE64_STANDARD.encode(&self.public_key))]);

exchange
encode(&map)
}

pub fn secret_exchange_receive(
&self,
exchange_in: HashMap<&str, String>,
) -> Result<HashMap<&str, String>, base64::DecodeError> {
pub fn secret_exchange_receive(&self, exchange: String) -> Result<String, base64::DecodeError> {
let map = decode(&exchange);
let mut exchange_out: HashMap<&str, String> = HashMap::new();
let secret = exchange_in.get(SECRET);

let secret = map.get(SECRET);
if !secret.is_none() {
let secret = BASE64_STANDARD.decode(secret.unwrap())?;
let public_key = BASE64_STANDARD.decode(exchange_in.get(PUBLIC).unwrap())?;
let public_key = BASE64_STANDARD.decode(map.get(PUBLIC).unwrap())?;
let public_key = Key::new(public_key);
let iv = BASE64_STANDARD.decode(exchange_in.get(IV).unwrap())?;
let iv = BASE64_STANDARD.decode(map.get(IV).unwrap())?;

let aes_key = Key::generate_aes_key(&self.private_key, &public_key);
let secret = crypto::decrypt(secret, &aes_key, &iv).to_vec();
Expand All @@ -48,27 +46,28 @@ impl SecretExchange {
}
exchange_out.insert(PUBLIC, BASE64_STANDARD.encode(&self.public_key));

Ok(exchange_out)
Ok(encode(&exchange_out))
}

pub fn secret_exchange_send(
&self,
secret: &str,
exchange: HashMap<&str, String>,
) -> Result<HashMap<&str, String>, base64::DecodeError> {
let public_key = BASE64_STANDARD.decode(exchange.get(PUBLIC).unwrap())?;
let public_key = Key::new(public_key);
exchange: String,
) -> Result<String, base64::DecodeError> {
let map = decode(&exchange);

let public_key = Key::new(BASE64_STANDARD.decode(map.get(PUBLIC).unwrap())?);
let aes_key = Key::generate_aes_key(&self.private_key, &public_key);
let iv = crypto::generate_iv();
let secret = crypto::encrypt(secret, &aes_key, &iv);

let mut exchange: HashMap<&str, String> = HashMap::new();
exchange.insert(SECRET, BASE64_STANDARD.encode(secret));
exchange.insert(PUBLIC, BASE64_STANDARD.encode(&self.public_key));
exchange.insert(IV, BASE64_STANDARD.encode(iv));
let map = HashMap::from([
(PUBLIC, BASE64_STANDARD.encode(&self.public_key)),
(SECRET, BASE64_STANDARD.encode(secret)),
(IV, BASE64_STANDARD.encode(iv)),
]);

Ok(exchange)
Ok(encode(&map))
}

pub fn new() -> Self {
Expand All @@ -82,8 +81,29 @@ impl SecretExchange {
}
}

pub fn get_secret(exchange: HashMap<&str, String>) -> String {
exchange.get(SECRET).unwrap().to_owned()
fn encode(map: &HashMap<&str, String>) -> String {
map.iter()
.map(|(k, v)| format!("{}={}", k, v))
.collect::<Vec<_>>()
.join("\n")
}

fn decode(exchange: &String) -> HashMap<String, String> {
exchange
.split("\n")
.collect::<Vec<_>>()
.iter()
.map(|entry| {
let (key, value) = entry.split_once("=").unwrap();
(key.to_string(), value.to_string())
})
.collect::<HashMap<String, String>>()
}

pub fn get_secret(exchange: &String) -> String {
let map = decode(&exchange);

map.get(SECRET).unwrap().to_owned()
}

#[cfg(test)]
Expand All @@ -100,6 +120,6 @@ mod test {
let exchange = callee.secret_exchange_send(secret, exchange.unwrap());
let exchange = caller.secret_exchange_receive(exchange.unwrap());

assert_eq!(get_secret(exchange.unwrap()), secret);
assert_eq!(get_secret(&exchange.unwrap()), secret);
}
}

0 comments on commit 6b1e08f

Please sign in to comment.