Skip to content

Commit

Permalink
Include the bot's public key in Delta Chat
Browse files Browse the repository at this point in the history
  • Loading branch information
Hocuri committed Jan 29, 2024
1 parent 598e2ef commit 3bbacb1
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 11 deletions.
62 changes: 57 additions & 5 deletions src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ use std::time::{Duration, Instant, SystemTime};

use anyhow::{bail, ensure, Context as _, Result};
use async_channel::{self as channel, Receiver, Sender};
use pgp::SignedPublicKey;
use ratelimit::Ratelimit;
use tokio::sync::{Mutex, Notify, RwLock};

use crate::chat::{get_chat_cnt, ChatId};
use crate::aheader::EncryptPreference;
use crate::chat::{get_chat_cnt, ChatId, ProtectionStatus};
use crate::config::Config;
use crate::constants::{DC_CHAT_ID_TRASH, DC_VERSION_STR};
use crate::contact::Contact;
Expand All @@ -22,6 +24,7 @@ use crate::events::{Event, EventEmitter, EventType, Events};
use crate::key::{load_self_public_key, load_self_secret_key, DcKey as _};
use crate::login_param::LoginParam;
use crate::message::{self, Message, MessageState, MsgId, Viewtype};
use crate::peerstate::{Peerstate, PeerstateKeyType};
use crate::quota::QuotaInfo;
use crate::scheduler::SchedulerState;
use crate::sql::Sql;
Expand Down Expand Up @@ -831,7 +834,7 @@ impl Context {
id
}
};
res += &format!("self_reporting_id {}\n", self_reporting_id);
res += &format!("self_reporting_id {}", self_reporting_id);

Ok(res)
}
Expand All @@ -844,8 +847,36 @@ impl Context {
pub async fn draft_self_report(&self) -> Result<ChatId> {
const SELF_REPORTING_BOT: &str = "[email protected]";

let contact = Contact::create(self, "Statistics bot", SELF_REPORTING_BOT).await?;
let chat_id = ChatId::create_for_contact(self, contact).await?;
let contact_id = Contact::create(self, "Statistics bot", SELF_REPORTING_BOT).await?;
let chat_id = ChatId::create_for_contact(self, contact_id).await?;

// We're including the bot's public key in Delta Chat
// so that the first message to the bot can directly be encrypted:
let public_key = SignedPublicKey::from_base64(
"xjMEZbfBlBYJKwYBBAHaRw8BAQdABpLWS2PUIGGo4pslVt4R8sylP5wZihmhf1DTDr3oCM\
PNHDxzZWxmX3JlcG9ydGluZ0B0ZXN0cnVuLm9yZz7CiwQQFggAMwIZAQUCZbfBlAIbAwQLCQgHBhUI\
CQoLAgMWAgEWIQTS2i16sHeYTckGn284K3M5Z4oohAAKCRA4K3M5Z4oohD8dAQCQV7CoH6UP4PD+Nq\
I4kW5tbbqdh2AnDROg60qotmLExAEAxDfd3QHAK9f8b9qQUbLmHIztCLxhEuVbWPBEYeVW0gvOOARl\
t8GUEgorBgEEAZdVAQUBAQdAMBUhYoAAcI625vGZqnM5maPX4sGJ7qvJxPAFILPy6AcDAQgHwngEGB\
YIACAFAmW3wZQCGwwWIQTS2i16sHeYTckGn284K3M5Z4oohAAKCRA4K3M5Z4oohPwCAQCvzk1ObIkj\
2GqsuIfaULlgdnfdZY8LNary425CEfHZDQD5AblXVrlMO1frdlc/Vo9z3pEeCrfYdD7ITD3/OeVoiQ\
4=",
)?;
let mut peerstate = Peerstate::from_public_key(
SELF_REPORTING_BOT,
0,
EncryptPreference::Mutual,
&public_key,
);
peerstate.set_verified(
PeerstateKeyType::PublicKey,
public_key.fingerprint(),
"".to_string(),
)?;
peerstate.save_to_db(&self.sql).await?;
chat_id
.set_protection(self, ProtectionStatus::Protected, time(), Some(contact_id))
.await?;

let mut msg = Message::new(Viewtype::Text);
msg.text = self.get_self_report().await?;
Expand Down Expand Up @@ -1125,8 +1156,9 @@ mod tests {
use crate::constants::Chattype;
use crate::contact::ContactId;
use crate::message::{Message, Viewtype};
use crate::mimeparser::SystemMessage;
use crate::receive_imf::receive_imf;
use crate::test_utils::TestContext;
use crate::test_utils::{get_chat_msg, TestContext};
use crate::tools::create_outgoing_rfc724_mid;

#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
Expand Down Expand Up @@ -1665,4 +1697,24 @@ mod tests {

Ok(())
}

#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn test_draft_self_report() -> Result<()> {
let alice = TestContext::new_alice().await;

let chat_id = alice.draft_self_report().await?;
let msg = get_chat_msg(&alice, chat_id, 0, 1).await;
assert_eq!(msg.get_info_type(), SystemMessage::ChatProtectionEnabled);

let chat = Chat::load_from_db(&alice, chat_id).await?;
assert!(chat.is_protected());

let mut draft = chat_id.get_draft(&alice).await?.unwrap();
assert!(draft.text.starts_with("core_version"));

// Test that sending into the protected chat works:
let sent = alice.send_msg(chat_id, &mut draft).await;

Ok(())
}
}
27 changes: 21 additions & 6 deletions src/peerstate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,13 +92,28 @@ pub struct Peerstate {
impl Peerstate {
/// Creates a peerstate from the `Autocrypt` header.
pub fn from_header(header: &Aheader, message_time: i64) -> Self {
Self::from_public_key(
&header.addr,
message_time,
header.prefer_encrypt,
&header.public_key,
)
}

/// Creates a peerstate from the given public key.
pub fn from_public_key(
addr: &str,
last_seen: i64,
prefer_encrypt: EncryptPreference,
public_key: &SignedPublicKey,
) -> Self {
Peerstate {
addr: header.addr.clone(),
last_seen: message_time,
last_seen_autocrypt: message_time,
prefer_encrypt: header.prefer_encrypt,
public_key: Some(header.public_key.clone()),
public_key_fingerprint: Some(header.public_key.fingerprint()),
addr: addr.to_string(),
last_seen,
last_seen_autocrypt: last_seen,
prefer_encrypt,
public_key: Some(public_key.clone()),
public_key_fingerprint: Some(public_key.fingerprint()),
gossip_key: None,
gossip_key_fingerprint: None,
gossip_timestamp: 0,
Expand Down

0 comments on commit 3bbacb1

Please sign in to comment.