encrypted msg + online reporting + refactor

This commit is contained in:
JMARyA 2025-04-30 09:35:21 +02:00
parent 125d50530d
commit a567214f58
19 changed files with 318 additions and 304 deletions

View file

@ -1,17 +1,6 @@
use age::{Recipient, secrecy::ExposeSecret};
use based::auth::{Sessions, User};
use minisign::PublicKey;
use owl::{Deserialize, Serialize};
use owl::{prelude::*, query, save, set_global_db};
use rumqttc::{AsyncClient, Event, EventLoop, MqttOptions, Packet, Transport};
use std::io::{Read, Seek};
use std::time::Duration;
use std::{
io::{BufReader, Cursor},
net::SocketAddr,
path::PathBuf,
str::FromStr,
};
use tokio::time::sleep;
#[derive(Deserialize, Serialize)]
@ -57,7 +46,11 @@ pub fn mqtt_connect(machine_id: &str, mqtt: &str) -> (rumqttc::AsyncClient, rumq
AsyncClient::new(mqttoptions, 10)
}
pub async fn run_event_loop(mut eventloop: EventLoop) {
pub async fn run_event_loop<F, Fut>(mut eventloop: EventLoop, handle_payload: F)
where
F: Fn(String, Vec<u8>) -> Fut + Send + Sync + 'static,
Fut: std::future::Future<Output = ()> + Send + 'static,
{
log::info!("Handling MQTT events");
loop {
match eventloop.poll().await {
@ -65,9 +58,9 @@ pub async fn run_event_loop(mut eventloop: EventLoop) {
log::trace!("Incoming = {:?}", incoming);
match incoming {
Packet::Publish(publish) => {
log::info!("Got payload with size {}", publish.size());
let s = publish.payload;
// TODO : client decryption here
println!("got payload {}", String::from_utf8(s.to_vec()).unwrap());
tokio::spawn(handle_payload(publish.topic, s.to_vec()));
}
_ => {}
}
@ -83,103 +76,19 @@ pub async fn run_event_loop(mut eventloop: EventLoop) {
}
}
pub struct Identity {
pub age: age::x25519::Identity,
pub sign: minisign::KeyPair,
#[derive(Deserialize, Serialize)]
pub struct Result {
pub ok: u32,
}
fn save_parts(part1: &[u8], part2: &[u8]) -> Vec<u8> {
let mut vec = Vec::new();
let offset = part1.len() as u32; // assume it fits into u32
vec.extend_from_slice(&offset.to_le_bytes()); // or to_be_bytes() for big-endian
vec.extend_from_slice(part1);
vec.extend_from_slice(part2);
vec
}
fn load_parts(data: &[u8]) -> (Vec<u8>, Vec<u8>) {
let offset_bytes: [u8; 4] = data[..4].try_into().unwrap();
let offset = u32::from_le_bytes(offset_bytes) as usize;
let part1 = data[4..4 + offset].to_vec();
let part2 = data[4 + offset..].to_vec();
(part1, part2)
}
impl Identity {
pub fn new() -> Self {
let age = age::x25519::Identity::generate();
let sign = minisign::KeyPair::generate_encrypted_keypair(Some(String::new())).unwrap();
Self { age, sign }
impl Result {
#[allow(non_snake_case)]
pub fn Ok() -> Self {
Self { ok: 1 }
}
pub fn public(&self) -> (String, String) {
(self.pub_key_age(), self.pub_key_sign())
}
pub fn pub_key_age(&self) -> String {
self.age.to_public().to_string()
}
pub fn pub_key_sign(&self) -> String {
self.sign.pk.to_box().unwrap().to_string()
}
pub fn save(&self, dir: &PathBuf) {
let age_key = self.age.to_string();
std::fs::write(dir.join("age.key"), age_key.expose_secret().to_string()).unwrap();
let kbx = self.sign.sk.to_box(None).unwrap();
std::fs::write(dir.join("sign.key"), kbx.into_string()).unwrap();
log::info!("Saved identity to {dir:?}");
}
pub fn try_load(dir: &PathBuf) -> Option<Self> {
let age =
age::x25519::Identity::from_str(&std::fs::read_to_string(dir.join("age.key")).ok()?)
.unwrap();
let kbx = minisign::SecretKeyBox::from_string(
&std::fs::read_to_string(dir.join("sign.key")).ok()?,
)
.unwrap();
let sign = kbx.into_secret_key(Some(String::new())).unwrap();
let pk = minisign::PublicKey::from_secret_key(&sign).ok()?;
let kp = minisign::KeyPair { pk: pk, sk: sign };
log::info!("Loaded identity from {dir:?}");
Some(Self { age, sign: kp })
}
pub fn encrypt(&self, data: &[u8], recipient: &impl Recipient) -> Vec<u8> {
let signed =
minisign::sign(None, &self.sign.sk, data, Some("mynameisanubis"), None).unwrap();
let signed = save_parts(&signed.to_bytes(), data);
let enc = age::encrypt(recipient, &signed).unwrap();
enc
}
pub fn decrypt(&self, data: &[u8], pk: &PublicKey) -> Option<Vec<u8>> {
let dec = age::decrypt(&self.age, data).unwrap();
let (sig, data) = load_parts(&dec);
let sign_box =
minisign::SignatureBox::from_string(&String::from_utf8(sig).unwrap()).unwrap();
if minisign::verify(
pk,
&sign_box,
BufReader::new(Cursor::new(data.clone())),
true,
false,
false,
)
.is_ok()
{
return Some(data);
}
None
#[allow(non_snake_case)]
pub fn Err() -> Self {
Self { ok: 0 }
}
}