Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 3 additions & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,9 @@ jobs:
test:
name: Test
runs-on: ubuntu-latest
strategy:
matrix:
toolchain:
- stable
steps:
- uses: actions/checkout@v4
- run: rustup update ${{ matrix.toolchain }} && rustup default ${{ matrix.toolchain }}
- run: rustup update stable && rustup default stable
- run: cargo build --verbose
- run: cargo test --verbose

Expand All @@ -28,7 +24,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: rustup update ${{ matrix.toolchain }} && rustup default ${{ matrix.toolchain }}
- run: rustup update stable && rustup default stable
- run: rustup component add clippy
- run: cargo clippy --all-targets --all-features -- -D warnings

Expand All @@ -37,6 +33,6 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: rustup update ${{ matrix.toolchain }} && rustup default ${{ matrix.toolchain }}
- run: rustup update stable && rustup default stable
- run: rustup component add rustfmt
- run: cargo fmt --all -- --check
20 changes: 7 additions & 13 deletions conversations/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ impl Context {
let remote_id = Inbox::inbox_identifier_for_key(remote_bundle.installation_key);
let payload_bytes = payloads
.into_iter()
.map(|p| p.to_envelope(remote_id.clone()))
.map(|p| p.into_envelope(remote_id.clone()))
.collect();

let convo_id = self.add_convo(Box::new(convo));
Expand All @@ -65,16 +65,13 @@ impl Context {
// Attach conversation_ids to Envelopes
Ok(payloads
.into_iter()
.map(|p| p.to_envelope(convo.remote_id()))
.map(|p| p.into_envelope(convo.remote_id()))
.collect())
}

// Decode bytes and send to protocol for processing.
pub fn handle_payload(&mut self, payload: &[u8]) -> Result<Option<ContentData>, ChatError> {
let env = match EnvelopeV1::decode(payload) {
Ok(v) => v,
Err(e) => return Err(e.into()),
};
let env = EnvelopeV1::decode(payload)?;

// TODO: Impl Conversation hinting
let convo_id = env.conversation_hint;
Expand Down Expand Up @@ -102,7 +99,7 @@ impl Context {
convo_id: ConversationId,
enc_payload: EncryptedPayload,
) -> Result<Option<ContentData>, ChatError> {
let Some(convo) = self.store.get_mut(&convo_id) else {
let Some(convo) = self.store.get_mut(convo_id) else {
return Err(ChatError::Protocol("convo id not found".into()));
};

Expand All @@ -115,21 +112,18 @@ impl Context {
}

fn add_convo(&mut self, convo: Box<dyn Convo>) -> ConversationIdOwned {
let convo_id = self.store.insert_convo(convo);

convo_id
self.store.insert_convo(convo)
}

// Returns a mutable reference to a Convo for a given ConvoId
fn get_convo_mut(&mut self, convo_id: ConversationId) -> Result<&mut dyn Convo, ChatError> {
self.store
.get_mut(&convo_id)
.get_mut(convo_id)
.ok_or_else(|| ChatError::NoConvo(convo_id.into()))
}
}

#[cfg(test)]

mod tests {
use super::*;
use crate::conversation::GroupTestConvo;
Expand All @@ -141,7 +135,7 @@ mod tests {
let new_convo = GroupTestConvo::new();
let convo_id = store.insert_convo(Box::new(new_convo));

let convo = store.get_mut(&convo_id).ok_or_else(|| 0);
let convo = store.get_mut(&convo_id).ok_or(0);
convo.unwrap();
}
}
7 changes: 5 additions & 2 deletions conversations/src/conversation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ pub type ConversationId<'a> = &'a str;
pub type ConversationIdOwned = Arc<str>;

pub trait Id: Debug {
fn id(&self) -> ConversationId;
fn id(&self) -> ConversationId<'_>;
}

pub trait Convo: Id + Debug {
Expand Down Expand Up @@ -54,14 +54,17 @@ impl ConversationStore {
Some(self.conversations.get_mut(id)?.as_mut())
}

#[allow(dead_code)]
pub fn conversation_ids(&self) -> Vec<ConversationIdOwned> {
self.conversations.keys().cloned().collect()
}
}

#[cfg(test)]
mod group_test;
mod privatev1;

use chat_proto::logoschat::encryption::EncryptedPayload;
pub use group_test::GroupTestConvo;
#[cfg(test)]
pub(crate) use group_test::GroupTestConvo;
pub use privatev1::PrivateV1Convo;
2 changes: 1 addition & 1 deletion conversations/src/conversation/group_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ impl GroupTestConvo {
}

impl Id for GroupTestConvo {
fn id(&self) -> ConversationId {
fn id(&self) -> ConversationId<'_> {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This elided lifetime here is not necessary.

Is this a specific style choice?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a style choice. The <'_> is actually required by the mismatched_lifetime_syntaxes lint (which is promoted to an error by -D warnings in CI). Without it, clippy fails.

Since ConversationId<'a> is a type alias for &'a str, using it without <'_> in fn id(&self) -> ConversationId hides the lifetime relationship with &self.

// implementation
"grouptest"
}
Expand Down
2 changes: 1 addition & 1 deletion conversations/src/conversation/privatev1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ impl PrivateV1Convo {
}

impl Id for PrivateV1Convo {
fn id(&self) -> ConversationId {
fn id(&self) -> ConversationId<'_> {
// TODO: implementation
"private_v1_convo_id"
}
Expand Down
4 changes: 2 additions & 2 deletions conversations/src/inbox.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
mod handler;
mod handshake;
mod inbox;
mod introduction;

pub use inbox::Inbox;
pub use handler::Inbox;
pub use introduction::Introduction;
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use blake2::{Blake2b512, Digest};
use chat_proto::logoschat::encryption::EncryptedPayload;
use hex;
use prost::Message;
use prost::bytes::Bytes;
use rand_core::OsRng;
Expand Down Expand Up @@ -29,7 +28,7 @@ pub struct Inbox {
ephemeral_keys: HashMap<String, StaticSecret>,
}

impl<'a> std::fmt::Debug for Inbox {
impl std::fmt::Debug for Inbox {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Inbox")
.field("ident", &self.ident)
Expand Down Expand Up @@ -61,7 +60,7 @@ impl Inbox {

PrekeyBundle {
identity_key: self.ident.public_key(),
signed_prekey: signed_prekey,
signed_prekey,
signature: [0u8; 64],
onetime_prekey: None,
}
Expand All @@ -83,7 +82,7 @@ impl Inbox {
};

let (seed_key, ephemeral_pub) =
InboxHandshake::perform_as_initiator(&self.ident.secret(), &pkb, &mut rng);
InboxHandshake::perform_as_initiator(self.ident.secret(), &pkb, &mut rng);

let mut convo = PrivateV1Convo::new_initiator(seed_key, remote_bundle.ephemeral_key);

Expand Down Expand Up @@ -218,7 +217,7 @@ impl Inbox {
fn lookup_ephemeral_key(&self, key: &str) -> Result<&StaticSecret, ChatError> {
self.ephemeral_keys
.get(key)
.ok_or_else(|| return ChatError::UnknownEphemeralKey())
.ok_or(ChatError::UnknownEphemeralKey())
}

pub fn inbox_identifier_for_key(pubkey: PublicKey) -> String {
Expand All @@ -228,7 +227,7 @@ impl Inbox {
}

impl Id for Inbox {
fn id(&self) -> ConversationId {
fn id(&self) -> ConversationId<'_> {
&self.local_convo_id
}
}
Expand Down
6 changes: 3 additions & 3 deletions conversations/src/inbox/handshake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,12 +85,12 @@ mod tests {
let mut rng = OsRng;

// Alice (initiator) generates her identity key
let alice_identity = StaticSecret::random_from_rng(&mut rng);
let alice_identity = StaticSecret::random_from_rng(rng);
let alice_identity_pub = PublicKey::from(&alice_identity);

// Bob (responder) generates his keys
let bob_identity = StaticSecret::random_from_rng(&mut rng);
let bob_signed_prekey = StaticSecret::random_from_rng(&mut rng);
let bob_identity = StaticSecret::random_from_rng(rng);
let bob_signed_prekey = StaticSecret::random_from_rng(rng);
let bob_signed_prekey_pub = PublicKey::from(&bob_signed_prekey);

// Create Bob's prekey bundle
Expand Down
8 changes: 4 additions & 4 deletions conversations/src/inbox/introduction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ impl From<PrekeyBundle> for Introduction {
}
}

impl Into<Vec<u8>> for Introduction {
fn into(self) -> Vec<u8> {
impl From<Introduction> for Vec<u8> {
fn from(val: Introduction) -> Self {
// TODO: avoid copies, via writing directly to slice
let link = format!(
"Bundle:{}:{}",
hex::encode(self.installation_key.as_bytes()),
hex::encode(self.ephemeral_key.as_bytes()),
hex::encode(val.installation_key.as_bytes()),
hex::encode(val.ephemeral_key.as_bytes()),
);

link.into_bytes()
Expand Down
1 change: 0 additions & 1 deletion conversations/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ pub use api::*;
mod tests {

use super::*;
use std::str::FromStr;

#[test]
fn test_ffi() {}
Expand Down
2 changes: 1 addition & 1 deletion conversations/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ pub(crate) struct AddressedEncryptedPayload {

impl AddressedEncryptedPayload {
// Wrap in an envelope and prepare for transmission
pub fn to_envelope(self, convo_id: String) -> AddressedEnvelope {
pub fn into_envelope(self, convo_id: String) -> AddressedEnvelope {
let envelope = proto::EnvelopeV1 {
// TODO: conversation_id should be obscured
conversation_hint: convo_id,
Expand Down
14 changes: 7 additions & 7 deletions crypto/src/x3dh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,17 +134,17 @@ mod tests {
let mut rng = OsRng;

// Alice (initiator) generates her identity key
let alice_identity = StaticSecret::random_from_rng(&mut rng);
let alice_identity = StaticSecret::random_from_rng(rng);
let alice_identity_pub = PublicKey::from(&alice_identity);

// Bob (responder) generates his keys
let bob_identity = StaticSecret::random_from_rng(&mut rng);
let bob_identity = StaticSecret::random_from_rng(rng);
let bob_identity_pub = PublicKey::from(&bob_identity);

let bob_signed_prekey = StaticSecret::random_from_rng(&mut rng);
let bob_signed_prekey = StaticSecret::random_from_rng(rng);
let bob_signed_prekey_pub = PublicKey::from(&bob_signed_prekey);

let bob_onetime_prekey = StaticSecret::random_from_rng(&mut rng);
let bob_onetime_prekey = StaticSecret::random_from_rng(rng);
let bob_onetime_prekey_pub = PublicKey::from(&bob_onetime_prekey);

// Create Bob's prekey bundle (with one-time prekey)
Expand Down Expand Up @@ -177,14 +177,14 @@ mod tests {
let mut rng = OsRng;

// Alice (initiator) generates her identity key
let alice_identity = StaticSecret::random_from_rng(&mut rng);
let alice_identity = StaticSecret::random_from_rng(rng);
let alice_identity_pub = PublicKey::from(&alice_identity);

// Bob (responder) generates his keys
let bob_identity = StaticSecret::random_from_rng(&mut rng);
let bob_identity = StaticSecret::random_from_rng(rng);
let bob_identity_pub = PublicKey::from(&bob_identity);

let bob_signed_prekey = StaticSecret::random_from_rng(&mut rng);
let bob_signed_prekey = StaticSecret::random_from_rng(rng);
let bob_signed_prekey_pub = PublicKey::from(&bob_signed_prekey);

// Create Bob's prekey bundle (without one-time prekey)
Expand Down
2 changes: 1 addition & 1 deletion double-ratchets/examples/double_ratchet_basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ fn main() {

let bob_dh = InstallationKeyPair::generate();

let mut alice: RatchetState = RatchetState::init_sender(shared_secret, bob_dh.public().clone());
let mut alice: RatchetState = RatchetState::init_sender(shared_secret, *bob_dh.public());
let mut bob: RatchetState = RatchetState::init_receiver(shared_secret, bob_dh);

let (ciphertext, header) = alice.encrypt_message(b"Hello Bob!");
Expand Down
2 changes: 1 addition & 1 deletion double-ratchets/examples/out_of_order_demo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ fn main() {

let shared_secret = [0x42u8; 32];
let bob_keypair = InstallationKeyPair::generate();
let bob_public = bob_keypair.public().clone();
let bob_public = *bob_keypair.public();

let conv_id = "out_of_order_conv";
let encryption_key = "super-secret-key-123!";
Expand Down
2 changes: 1 addition & 1 deletion double-ratchets/examples/serialization_demo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ fn main() {

let bob_dh = InstallationKeyPair::generate();

let mut alice: RatchetState = RatchetState::init_sender(shared_secret, bob_dh.public().clone());
let mut alice: RatchetState = RatchetState::init_sender(shared_secret, *bob_dh.public());
let mut bob: RatchetState = RatchetState::init_receiver(shared_secret, bob_dh);

let (ciphertext, header) = alice.encrypt_message(b"Hello Bob!");
Expand Down
2 changes: 1 addition & 1 deletion double-ratchets/examples/storage_demo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ fn run_conversation(alice_storage: &mut RatchetStorage, bob_storage: &mut Ratche
alice_storage,
conv_id,
shared_secret,
bob_keypair.public().clone(),
*bob_keypair.public(),
)
.unwrap();

Expand Down
6 changes: 3 additions & 3 deletions double-ratchets/src/reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,9 @@ mod tests {

#[test]
fn test_sequential_reads() {
let mut data = vec![0x01]; // version
data.extend_from_slice(&[0xAA; 32]); // 32-byte array
data.extend_from_slice(&[0x00, 0x00, 0x00, 0x10]); // u32 = 16
let mut data = vec![0x01]; // version
data.extend_from_slice(&[0xAA; 32]); // 32-byte array
data.extend_from_slice(&[0x00, 0x00, 0x00, 0x10]); // u32 = 16

let mut reader = Reader::new(&data);

Expand Down
8 changes: 4 additions & 4 deletions double-ratchets/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ impl<D: HkdfInfo> RatchetState<D> {
*chain = next_chain;

let header = Header {
dh_pub: self.dh_self.public().clone(),
dh_pub: *self.dh_self.public(),
msg_num: self.msg_send,
prev_chain_len: self.prev_chain_len,
};
Expand Down Expand Up @@ -481,7 +481,7 @@ mod tests {
let bob_keypair = InstallationKeyPair::generate();

// Alice initializes as sender, knowing Bob's public key
let alice = RatchetState::init_sender(shared_secret, bob_keypair.public().clone());
let alice = RatchetState::init_sender(shared_secret, *bob_keypair.public());

// Bob initializes as receiver with his private key
let bob = RatchetState::init_receiver(shared_secret, bob_keypair);
Expand Down Expand Up @@ -554,15 +554,15 @@ mod tests {
bob.decrypt_message(&ct, header).unwrap();

// Bob performs DH ratchet by trying to send
let old_bob_pub = bob.dh_self.public().clone();
let old_bob_pub = *bob.dh_self.public();
let (bob_ct, bob_header) = {
let mut b = bob.clone();
b.encrypt_message(b"reply")
};
assert_ne!(bob_header.dh_pub, old_bob_pub);

// Alice receives Bob's message with new DH pub → ratchets
let old_alice_pub = alice.dh_self.public().clone();
let old_alice_pub = *alice.dh_self.public();
let old_root = alice.root_key;

// Even if decrypt fails (wrong key), ratchet should happen
Expand Down
2 changes: 1 addition & 1 deletion double-ratchets/src/storage/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ mod tests {
fn create_test_state() -> (RatchetState, SharedSecret) {
let shared_secret = [0x42u8; 32];
let bob_keypair = InstallationKeyPair::generate();
let state = RatchetState::init_sender(shared_secret, bob_keypair.public().clone());
let state = RatchetState::init_sender(shared_secret, *bob_keypair.public());
(state, shared_secret)
}

Expand Down
Loading