Kaynağa Gözat

bin/ircd: channel/contact metadata encryption

Dastan-glitch 4 yıl önce
ebeveyn
işleme
b4f7a420c4
3 değiştirilmiş dosya ile 98 ekleme ve 55 silme
  1. 66 1
      bin/ircd/src/crypto.rs
  2. 2 9
      bin/ircd/src/protocol_privmsg.rs
  3. 30 45
      bin/ircd/src/server.rs

+ 66 - 1
bin/ircd/src/crypto.rs

@@ -1,9 +1,12 @@
 use crypto_box::aead::Aead;
+use fxhash::FxHashMap;
 use rand::rngs::OsRng;
 
+use crate::{privmsg::Privmsg, settings::ChannelInfo, MAXIMUM_LENGTH_OF_NICKNAME};
+
 /// Try decrypting a message given a NaCl box and a base58 string.
 /// The format we're using is nonce+ciphertext, where nonce is 24 bytes.
-pub fn try_decrypt_message(salt_box: &crypto_box::Box, ciphertext: &str) -> Option<String> {
+fn try_decrypt_message(salt_box: &crypto_box::Box, ciphertext: &str) -> Option<String> {
     let bytes = match bs58::decode(ciphertext).into_vec() {
         Ok(v) => v,
         Err(_) => return None,
@@ -41,3 +44,65 @@ pub fn encrypt_message(salt_box: &crypto_box::Box, plaintext: &str) -> String {
 
     bs58::encode(concat).into_string()
 }
+/// Decrypt PrivMsg target
+pub fn decrypt_target(
+    privmsg: &mut Privmsg,
+    configured_chans: FxHashMap<String, ChannelInfo>,
+    configured_contacts: FxHashMap<String, crypto_box::Box>,
+) {
+    for chan_name in configured_chans.keys() {
+        let chan_info = configured_chans.get(chan_name).unwrap();
+        if !chan_info.joined {
+            continue
+        }
+
+        let salt_box = chan_info.salt_box.clone();
+        if salt_box.is_some() {
+            let decrypted_target = try_decrypt_message(&salt_box.unwrap(), &privmsg.target);
+            if decrypted_target.is_none() {
+                continue
+            }
+
+            let target = decrypted_target.unwrap();
+            if chan_name.to_string() == target {
+                privmsg.target = target;
+            }
+        }
+    }
+
+    for contact in configured_contacts.keys() {
+        let salt_box = configured_contacts.get(contact).unwrap();
+        let decrypted_target = try_decrypt_message(&salt_box, &privmsg.target);
+        if decrypted_target.is_none() {
+            continue
+        }
+
+        let target = decrypted_target.unwrap();
+        if contact.to_string() == target {
+            privmsg.target = target;
+        }
+    }
+}
+
+/// Decrypt PrivMsg nickname and message
+pub fn decrypt_privmsg(salt_box: &crypto_box::Box, privmsg: &mut Privmsg) {
+    let decrypted_nick = try_decrypt_message(&salt_box.clone(), &privmsg.nickname);
+    let decrypted_msg = try_decrypt_message(&salt_box.clone(), &privmsg.message);
+
+    if decrypted_nick.is_none() | decrypted_msg.is_none() {
+        return
+    }
+
+    privmsg.nickname = decrypted_nick.unwrap();
+    if privmsg.nickname.len() > MAXIMUM_LENGTH_OF_NICKNAME {
+        privmsg.nickname = privmsg.nickname[..MAXIMUM_LENGTH_OF_NICKNAME].to_string();
+    }
+    privmsg.message = decrypted_msg.unwrap();
+}
+
+/// Encrypt PrivMsg
+pub fn encrypt_privmsg(salt_box: &crypto_box::Box, privmsg: &mut Privmsg) {
+    privmsg.nickname = encrypt_message(salt_box, &privmsg.nickname);
+    privmsg.target = encrypt_message(salt_box, &privmsg.target);
+    privmsg.message = encrypt_message(salt_box, &privmsg.message);
+}

+ 2 - 9
bin/ircd/src/protocol_privmsg.rs

@@ -7,10 +7,7 @@ use ringbuffer::{RingBufferExt, RingBufferWrite};
 
 use darkfi::{net, Result};
 
-use crate::{
-    privmsg::{Privmsg, PrivmsgsBuffer, SeenMsgIds},
-    MAXIMUM_LENGTH_OF_NICKNAME,
-};
+use crate::privmsg::{Privmsg, PrivmsgsBuffer, SeenMsgIds};
 
 pub struct ProtocolPrivmsg {
     jobsman: net::ProtocolJobsManagerPtr,
@@ -61,11 +58,7 @@ impl ProtocolPrivmsg {
 
         loop {
             let msg = self.msg_sub.receive().await?;
-            let mut msg = (*msg).to_owned();
-
-            if msg.nickname.len() > MAXIMUM_LENGTH_OF_NICKNAME {
-                msg.nickname = msg.nickname[..MAXIMUM_LENGTH_OF_NICKNAME].to_string();
-            }
+            let msg = (*msg).to_owned();
 
             {
                 let msg_ids = &mut self.msg_ids.lock().await;

+ 30 - 45
bin/ircd/src/server.rs

@@ -9,7 +9,7 @@ use ringbuffer::{RingBufferExt, RingBufferWrite};
 use darkfi::{net::P2pPtr, system::SubscriberPtr, Error, Result};
 
 use crate::{
-    crypto::{encrypt_message, try_decrypt_message},
+    crypto::{decrypt_privmsg, decrypt_target, encrypt_privmsg},
     privmsg::{Privmsg, PrivmsgsBuffer, SeenMsgIds},
     ChannelInfo, MAXIMUM_LENGTH_OF_MESSAGE, MAXIMUM_LENGTH_OF_NICKNAME,
 };
@@ -182,9 +182,18 @@ impl<C: AsyncRead + AsyncWrite + Send + Unpin + 'static> IrcServerConnection<C>
                     return Err(Error::MalformedPacket)
                 }
 
-                let mut message = line[substr_idx + 1..].to_string();
+                let message = line[substr_idx + 1..].to_string();
+
                 info!("(Plain) PRIVMSG {} :{}", target, message);
 
+                let random_id = OsRng.next_u64();
+                let mut privmsg = Privmsg {
+                    id: random_id,
+                    nickname: self.nickname.clone(),
+                    target: target.to_string().clone(),
+                    message,
+                };
+
                 if target.starts_with('#') {
                     if !self.configured_chans.contains_key(target) {
                         return Ok(())
@@ -196,22 +205,19 @@ impl<C: AsyncRead + AsyncWrite + Send + Unpin + 'static> IrcServerConnection<C>
                         return Ok(())
                     }
 
-                    message = if let Some(salt_box) = &channel_info.salt_box {
-                        let encrypted = encrypt_message(salt_box, &message);
-                        info!("(Encrypted) PRIVMSG {} :{}", target, encrypted);
-                        encrypted
-                    } else {
-                        message.to_string()
-                    };
+                    if let Some(salt_box) = &channel_info.salt_box {
+                        encrypt_privmsg(salt_box, &mut privmsg);
+                        info!("(Encrypted) PRIVMSG: {:?}", privmsg);
+                    }
                 } else {
                     // If we have a configured secret for this nick, we encrypt the message.
                     if let Some(salt_box) = self.configured_contacts.get(target) {
-                        message = encrypt_message(salt_box, &message);
-                        info!("(Encrypted) PRIVMSG {} :{}", target, message);
+                        encrypt_privmsg(salt_box, &mut privmsg);
+                        info!("(Encrypted) PRIVMSG: {:?}", privmsg);
                     }
                 }
 
-                self.on_receive_privmsg(&message, target).await?;
+                self.on_receive_privmsg(privmsg).await?;
             }
             "CAP" => {
                 self.is_cap_end = false;
@@ -359,25 +365,16 @@ impl<C: AsyncRead + AsyncWrite + Send + Unpin + 'static> IrcServerConnection<C>
         Ok(())
     }
 
-    async fn on_receive_privmsg(&mut self, message: &str, target: &str) -> Result<()> {
-        let random_id = OsRng.next_u64();
-
-        let protocol_msg = Privmsg {
-            id: random_id,
-            nickname: self.nickname.clone(),
-            target: target.to_string(),
-            message: message.to_string(),
-        };
-
+    async fn on_receive_privmsg(&mut self, privmsg: Privmsg) -> Result<()> {
         {
-            (*self.seen_msg_ids.lock().await).push(random_id);
-            (*self.privmsgs_buffer.lock().await).push(protocol_msg.clone())
+            (*self.seen_msg_ids.lock().await).push(privmsg.id);
+            (*self.privmsgs_buffer.lock().await).push(privmsg.clone())
         }
 
-        self.senders.notify_with_exclude(protocol_msg.clone(), &[self.subscriber_id]).await;
+        self.senders.notify_with_exclude(privmsg.clone(), &[self.subscriber_id]).await;
 
-        debug!(target: "ircd", "PRIVMSG to be sent: {:?}", protocol_msg);
-        self.p2p.broadcast(protocol_msg).await?;
+        debug!(target: "ircd", "PRIVMSG to be sent: {:?}", privmsg);
+        self.p2p.broadcast(privmsg).await?;
 
         Ok(())
     }
@@ -423,6 +420,7 @@ impl<C: AsyncRead + AsyncWrite + Send + Unpin + 'static> IrcServerConnection<C>
         info!("Received msg from P2p network: {:?}", msg);
 
         let mut msg = msg.clone();
+        decrypt_target(&mut msg, self.configured_chans.clone(), self.configured_contacts.clone());
 
         if msg.target.starts_with('#') {
             // Try to potentially decrypt the incoming message.
@@ -435,16 +433,8 @@ impl<C: AsyncRead + AsyncWrite + Send + Unpin + 'static> IrcServerConnection<C>
                 return Ok(())
             }
 
-            let salt_box = chan_info.salt_box.clone();
-
-            if salt_box.is_some() {
-                let decrypted_msg = try_decrypt_message(&salt_box.unwrap(), &msg.message);
-
-                if decrypted_msg.is_none() {
-                    return Ok(())
-                }
-
-                msg.message = decrypted_msg.unwrap();
+            if let Some(salt_box) = &chan_info.salt_box {
+                decrypt_privmsg(salt_box, &mut msg);
                 info!("Decrypted received message: {:?}", msg);
             }
 
@@ -456,16 +446,11 @@ impl<C: AsyncRead + AsyncWrite + Send + Unpin + 'static> IrcServerConnection<C>
             self.reply(&msg.to_irc_msg()).await?;
             return Ok(())
         } else {
-            if self.is_cap_end &&
-                self.is_nick_init &&
-                (self.nickname == msg.target || self.nickname == msg.nickname)
-            {
+            if self.is_cap_end && self.is_nick_init && self.nickname == msg.target {
                 if self.configured_contacts.contains_key(&msg.target) {
                     let salt_box = self.configured_contacts.get(&msg.target).unwrap();
-                    if let Some(decrypted) = try_decrypt_message(&salt_box, &msg.message) {
-                        msg.message = decrypted;
-                        info!("Decrypted received message: {:?}", msg);
-                    }
+                    decrypt_privmsg(salt_box, &mut msg);
+                    info!("Decrypted received message: {:?}", msg);
                 }
 
                 self.reply(&msg.to_irc_msg()).await?;