Alias TTL renews only on authenticated actions (sending messages)

- Sending a message includes `from` fingerprint
- Server renews alias TTL on send (proves identity: you encrypted it)
- Polling/receiving does NOT renew (anyone can spam messages to you)
- Key registration does NOT renew (separate concern)

This prevents alias keepalive attacks where someone spams a user
just to keep their alias from expiring.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Siavash Sameni
2026-03-27 07:39:15 +04:00
parent bf67566b0c
commit 7fe6de0ba1
4 changed files with 32 additions and 3 deletions

View File

@@ -82,7 +82,7 @@ pub async fn run(recipient_fp: &str, message: &str, server_url: &str) -> Result<
let encoded = bincode::serialize(&wire_msg)
.context("failed to serialize wire message")?;
client.send_message(recipient_fp, &encoded).await?;
client.send_message(recipient_fp, Some(&our_pub.fingerprint.to_string()), &encoded).await?;
println!("Message sent to {}", recipient_fp);
Ok(())

View File

@@ -19,6 +19,7 @@ struct RegisterRequest {
#[derive(Serialize)]
struct SendRequest {
to: String,
from: Option<String>,
message: Vec<u8>,
}
@@ -93,12 +94,13 @@ impl ServerClient {
}
/// Send an encrypted message to the server for delivery.
pub async fn send_message(&self, to: &str, message: &[u8]) -> Result<()> {
pub async fn send_message(&self, to: &str, from: Option<&str>, message: &[u8]) -> Result<()> {
let to_clean: String = to.chars().filter(|c| c.is_ascii_hexdigit()).collect();
self.client
.post(format!("{}/v1/messages/send", self.base_url))
.json(&SendRequest {
to: to_clean,
from: from.map(|f| f.chars().filter(|c| c.is_ascii_hexdigit()).collect()),
message: message.to_vec(),
})
.send()

View File

@@ -369,7 +369,7 @@ impl App {
}
};
match client.send_message(&peer, &encoded).await {
match client.send_message(&peer, Some(&self.our_fp), &encoded).await {
Ok(_) => {
self.add_message(ChatLine {
sender: self.our_fp[..12].to_string(),