فهرست منبع

bin/ircd2: remove redundant code for parsing channels and contacts

ghassmo 3 سال پیش
والد
کامیت
8d927348c7
4فایلهای تغییر یافته به همراه153 افزوده شده و 294 حذف شده
  1. 20 29
      bin/ircd2/src/crypto.rs
  2. 49 51
      bin/ircd2/src/irc/client.rs
  3. 15 22
      bin/ircd2/src/irc/mod.rs
  4. 69 192
      bin/ircd2/src/settings.rs

+ 20 - 29
bin/ircd2/src/crypto.rs

@@ -1,10 +1,9 @@
-use std::fmt;
+use std::{collections::HashMap, fmt};
 
 use crypto_box::{
     aead::{Aead, AeadCore},
     SalsaBox,
 };
-use fxhash::FxHashMap;
 use rand::rngs::OsRng;
 
 use crate::{
@@ -65,59 +64,51 @@ pub fn encrypt(salt_box: &SalsaBox, plaintext: &str) -> String {
 
 /// Decrypt PrivMsg target
 pub fn decrypt_target(
-    contact: &mut String,
     privmsg: &mut PrivMsgEvent,
-    configured_chans: FxHashMap<String, ChannelInfo>,
-    configured_contacts: FxHashMap<String, ContactInfo>,
+    configured_chans: &HashMap<String, ChannelInfo>,
+    configured_contacts: &HashMap<String, ContactInfo>,
+    private_key: &Option<String>,
 ) {
-    for chan_name in configured_chans.keys() {
-        let chan_info = configured_chans.get(chan_name).unwrap();
+    for (name, chan_info) in configured_chans {
         if !chan_info.joined {
             continue
         }
 
-        let salt_box = chan_info.salt_box.clone();
+        let salt_box = chan_info.salt_box(&name).clone();
 
         if let Some(salt_box) = salt_box {
-            let decrypted_target = try_decrypt(&salt_box, &privmsg.target);
-            if decrypted_target.is_none() {
-                continue
-            }
-
-            let target = decrypted_target.unwrap();
-            if *chan_name == target {
-                privmsg.target = target;
+            if let Some(_) = try_decrypt(&salt_box, &privmsg.target) {
+                privmsg.target = name.clone();
                 return
             }
         }
     }
 
-    for cnt_name in configured_contacts.keys() {
-        let cnt_info = configured_contacts.get(cnt_name).unwrap();
+    if private_key.is_none() {
+        return
+    }
+
+    for (name, contact_info) in configured_contacts {
+        let salt_box = contact_info.salt_box(&private_key.as_ref().unwrap(), &name).clone();
 
-        let salt_box = cnt_info.salt_box.clone();
         if let Some(salt_box) = salt_box {
-            let decrypted_target = try_decrypt(&salt_box, &privmsg.target);
-            if decrypted_target.is_none() {
-                continue
+            if let Some(_) = try_decrypt(&salt_box, &privmsg.target) {
+                privmsg.target = name.clone();
+                return
             }
-
-            let target = decrypted_target.unwrap();
-            privmsg.target = target;
-            *contact = cnt_name.into();
-            return
         }
     }
 }
 
 /// Decrypt PrivMsg nickname and message
 pub fn decrypt_privmsg(salt_box: &SalsaBox, privmsg: &mut PrivMsgEvent) {
-    let decrypted_nick = try_decrypt(&salt_box.clone(), &privmsg.nick);
-    let decrypted_msg = try_decrypt(&salt_box.clone(), &privmsg.msg);
+    let decrypted_nick = try_decrypt(&salt_box, &privmsg.nick);
+    let decrypted_msg = try_decrypt(&salt_box, &privmsg.msg);
 
     if decrypted_nick.is_none() && decrypted_msg.is_none() {
         return
     }
+
     privmsg.nick = decrypted_nick.unwrap();
     privmsg.msg = decrypted_msg.unwrap();
 }

+ 49 - 51
bin/ircd2/src/irc/client.rs

@@ -51,8 +51,8 @@ impl<C: AsyncRead + AsyncWrite + Send + Unpin + 'static> IrcClient<C> {
 
             futures::select! {
                 // Process msg from View
-                msg = self.subscription.receive().fuse() => {
-                    if let Err(e) = self.process_msg(&msg).await {
+                mut msg = self.subscription.receive().fuse() => {
+                    if let Err(e) = self.process_msg(&mut msg).await {
                         error!("[CLIENT {}] Process msg: {}",  self.address, e);
                         break
                     }
@@ -75,32 +75,29 @@ impl<C: AsyncRead + AsyncWrite + Send + Unpin + 'static> IrcClient<C> {
         self.subscription.unsubscribe().await;
     }
 
-    pub async fn process_msg(&mut self, msg: &PrivMsgEvent) -> Result<()> {
+    pub async fn process_msg(&mut self, msg: &mut PrivMsgEvent) -> Result<()> {
         info!("[CLIENT {}] msg from View: {:?}", self.address, msg.to_string());
 
-        let mut msg = msg.clone();
-        let mut contact = String::new();
-
         decrypt_target(
-            &mut contact,
-            &mut msg,
-            self.irc_config.configured_chans.clone(),
-            self.irc_config.configured_contacts.clone(),
+            msg,
+            &self.irc_config.channels,
+            &self.irc_config.contacts,
+            &self.irc_config.private_key,
         );
 
         if msg.target.starts_with('#') {
             // Try to potentially decrypt the incoming message.
-            if !self.irc_config.configured_chans.contains_key(&msg.target) {
+            if !self.irc_config.channels.contains_key(&msg.target) {
                 return Ok(())
             }
 
-            let chan_info = self.irc_config.configured_chans.get_mut(&msg.target).unwrap();
+            let chan_info = self.irc_config.channels.get_mut(&msg.target).unwrap();
             if !chan_info.joined {
                 return Ok(())
             }
 
-            if let Some(salt_box) = &chan_info.salt_box {
-                decrypt_privmsg(salt_box, &mut msg);
+            if let Some(salt_box) = &chan_info.salt_box(&msg.target) {
+                decrypt_privmsg(salt_box, msg);
                 info!(
                     "[CLIENT {}] Decrypted received message: {:?}",
                     self.address,
@@ -114,24 +111,25 @@ impl<C: AsyncRead + AsyncWrite + Send + Unpin + 'static> IrcClient<C> {
             }
 
             self.reply(&msg.to_string()).await?;
-        } else if self.irc_config.is_cap_end && self.irc_config.is_nick_init {
-            if !self.irc_config.configured_contacts.contains_key(&contact) {
-                return Ok(())
-            }
+        } else if self.irc_config.private_key.is_some() {
+            if let Some(contact_info) = self.irc_config.contacts.get(&msg.target) {
+                let salt_box = &contact_info
+                    .salt_box(&self.irc_config.private_key.as_ref().unwrap(), &msg.target);
+
+                if salt_box.is_none() {
+                    return Ok(())
+                }
+
+                decrypt_privmsg(salt_box.as_ref().unwrap(), msg);
 
-            let contact_info = self.irc_config.configured_contacts.get(&contact).unwrap();
-            if let Some(salt_box) = &contact_info.salt_box {
-                decrypt_privmsg(salt_box, &mut msg);
-                // This is for /query
-                msg.nick = contact;
                 info!(
                     "[CLIENT {}] Decrypted received message: {:?}",
                     self.address,
                     msg.to_string()
                 );
-            }
 
-            self.reply(&msg.to_string()).await?;
+                self.reply(&msg.to_string()).await?;
+            }
         }
 
         Ok(())
@@ -200,8 +198,7 @@ impl<C: AsyncRead + AsyncWrite + Send + Unpin + 'static> IrcClient<C> {
 
             // join all channels
             self.on_receive_join(self.irc_config.auto_channels.clone()).await?;
-            self.on_receive_join(self.irc_config.configured_chans.keys().cloned().collect())
-                .await?;
+            self.on_receive_join(self.irc_config.channels.keys().cloned().collect()).await?;
 
             if *self.irc_config.capabilities.get("no-history").unwrap() {
                 return Ok(())
@@ -263,8 +260,8 @@ impl<C: AsyncRead + AsyncWrite + Send + Unpin + 'static> IrcClient<C> {
             let part_reply =
                 format!(":{}!anon@dark.fi PART {}\r\n", self.irc_config.nickname, chan);
             self.reply(&part_reply).await?;
-            if self.irc_config.configured_chans.contains_key(chan) {
-                let chan_info = self.irc_config.configured_chans.get_mut(chan).unwrap();
+            if self.irc_config.channels.contains_key(chan) {
+                let chan_info = self.irc_config.channels.get_mut(chan).unwrap();
                 chan_info.joined = false;
             }
         }
@@ -279,7 +276,7 @@ impl<C: AsyncRead + AsyncWrite + Send + Unpin + 'static> IrcClient<C> {
             }
 
             let topic = &line[substr_idx + 1..];
-            let chan_info = self.irc_config.configured_chans.get_mut(channel).unwrap();
+            let chan_info = self.irc_config.channels.get_mut(channel).unwrap();
             chan_info.topic = Some(topic.to_string());
 
             let topic_reply = format!(
@@ -289,7 +286,7 @@ impl<C: AsyncRead + AsyncWrite + Send + Unpin + 'static> IrcClient<C> {
             self.reply(&topic_reply).await?;
         } else {
             // Client is asking or the topic
-            let chan_info = self.irc_config.configured_chans.get(channel).unwrap();
+            let chan_info = self.irc_config.channels.get(channel).unwrap();
             let topic_reply = if let Some(topic) = &chan_info.topic {
                 format!(
                     "{} {} {} :{}\r\n",
@@ -401,8 +398,8 @@ impl<C: AsyncRead + AsyncWrite + Send + Unpin + 'static> IrcClient<C> {
             if !chan.starts_with('#') {
                 continue
             }
-            if self.irc_config.configured_chans.contains_key(chan) {
-                let chan_info = self.irc_config.configured_chans.get(chan).unwrap();
+            if self.irc_config.channels.contains_key(chan) {
+                let chan_info = self.irc_config.channels.get(chan).unwrap();
 
                 if chan_info.names.is_empty() {
                     return Ok(())
@@ -449,35 +446,36 @@ impl<C: AsyncRead + AsyncWrite + Send + Unpin + 'static> IrcClient<C> {
         };
 
         if target.starts_with('#') {
-            if !self.irc_config.configured_chans.contains_key(target) {
+            if !self.irc_config.channels.contains_key(target) {
                 return Ok(())
             }
 
-            let channel_info = self.irc_config.configured_chans.get(target).unwrap();
+            let channel_info = self.irc_config.channels.get(target).unwrap();
 
             if !channel_info.joined {
                 return Ok(())
             }
 
-            if let Some(salt_box) = &channel_info.salt_box {
+            if let Some(salt_box) = &channel_info.salt_box(&target) {
                 encrypt_privmsg(salt_box, &mut privmsg);
                 info!("[CLIENT {}] (Encrypted) PRIVMSG: {:?}", self.address, privmsg.to_string());
             }
-        } else {
-            if !self.irc_config.configured_contacts.contains_key(target) {
-                return Ok(())
-            }
-
-            let contact_info = self.irc_config.configured_contacts.get(target).unwrap();
-            if let Some(salt_box) = &contact_info.salt_box {
-                encrypt_privmsg(salt_box, &mut privmsg);
-                info!("[CLIENT {}] (Encrypted) PRIVMSG: {:?}", self.address, privmsg.to_string());
+        } else if self.irc_config.private_key.is_some() {
+            if let Some(contact_info) = self.irc_config.contacts.get(target) {
+                if let Some(salt_box) =
+                    &contact_info.salt_box(&self.irc_config.private_key.as_ref().unwrap(), target)
+                {
+                    encrypt_privmsg(salt_box, &mut privmsg);
+                    info!(
+                        "[CLIENT {}] (Encrypted) PRIVMSG: {:?}",
+                        self.address,
+                        privmsg.to_string()
+                    );
+                }
             }
         }
 
-        // Notify the server
         self.server_notifier.send((privmsg, self.subscription.get_id())).await?;
-
         Ok(())
     }
 
@@ -486,13 +484,13 @@ impl<C: AsyncRead + AsyncWrite + Send + Unpin + 'static> IrcClient<C> {
             if !chan.starts_with('#') {
                 continue
             }
-            if !self.irc_config.configured_chans.contains_key(chan) {
-                let mut chan_info = ChannelInfo::new()?;
+            if !self.irc_config.channels.contains_key(chan) {
+                let mut chan_info = ChannelInfo::new();
                 chan_info.topic = Some("n/a".to_string());
-                self.irc_config.configured_chans.insert(chan.to_string(), chan_info);
+                self.irc_config.channels.insert(chan.to_string(), chan_info);
             }
 
-            let chan_info = self.irc_config.configured_chans.get_mut(chan).unwrap();
+            let chan_info = self.irc_config.channels.get_mut(chan).unwrap();
             if chan_info.joined {
                 return Ok(())
             }

+ 15 - 22
bin/ircd2/src/irc/mod.rs

@@ -1,24 +1,16 @@
 use async_std::{net::TcpListener, sync::Arc};
-use std::{fs::File, net::SocketAddr};
+use std::{collections::HashMap, fs::File, net::SocketAddr};
 
 use async_executor::Executor;
 use futures::{io::BufReader, AsyncRead, AsyncReadExt, AsyncWrite};
 use futures_rustls::{rustls, TlsAcceptor};
-use fxhash::FxHashMap;
 use log::{error, info};
 
-use darkfi::{
-    system::SubscriberPtr,
-    util::path::{expand_path, get_config_path},
-    Error, Result,
-};
+use darkfi::{system::SubscriberPtr, util::path::expand_path, Error, Result};
 
 use crate::{
     privmsg::PrivMsgEvent,
-    settings::{
-        parse_configured_channels, parse_configured_contacts, Args, ChannelInfo, ContactInfo,
-        CONFIG_FILE,
-    },
+    settings::{Args, ChannelInfo, ContactInfo},
 };
 
 mod client;
@@ -37,28 +29,28 @@ pub struct IrcConfig {
     // user config
     pub nickname: String,
     pub password: String,
-    pub capabilities: FxHashMap<String, bool>,
+    pub private_key: Option<String>,
+    pub capabilities: HashMap<String, bool>,
 
     // channels and contacts
     pub auto_channels: Vec<String>,
-    pub configured_chans: FxHashMap<String, ChannelInfo>,
-    pub configured_contacts: FxHashMap<String, ContactInfo>,
+    pub channels: HashMap<String, ChannelInfo>,
+    pub contacts: HashMap<String, ContactInfo>,
 }
 
 impl IrcConfig {
     pub fn new(settings: &Args) -> Result<Self> {
         let password = settings.password.as_ref().unwrap_or(&String::new()).clone();
+        let private_key = settings.private_key.clone();
 
         let auto_channels = settings.autojoin.clone();
 
-        // Pick up channel settings from the TOML configuration
-        let cfg_path = get_config_path(settings.config.clone(), CONFIG_FILE)?;
-        let toml_contents = std::fs::read_to_string(cfg_path)?;
-        let configured_chans = parse_configured_channels(&toml_contents)?;
-        let configured_contacts = parse_configured_contacts(&toml_contents)?;
+        let channels = settings.channels.clone();
+        let contacts = settings.contacts.clone();
 
-        let mut capabilities = FxHashMap::default();
+        let mut capabilities = HashMap::new();
         capabilities.insert("no-history".to_string(), false);
+
         Ok(Self {
             is_nick_init: false,
             is_user_init: false,
@@ -68,8 +60,9 @@ impl IrcConfig {
             nickname: "anon".to_string(),
             password,
             auto_channels,
-            configured_chans,
-            configured_contacts,
+            channels,
+            contacts,
+            private_key,
             capabilities,
         })
     }

+ 69 - 192
bin/ircd2/src/settings.rs

@@ -1,10 +1,9 @@
 use crypto_box::SalsaBox;
-use fxhash::FxHashMap;
-use log::{info, warn};
-use serde::Deserialize;
+use log::error;
+use serde::{self, Deserialize, Serialize};
+use std::collections::HashMap;
 use structopt::StructOpt;
 use structopt_toml::StructOptToml;
-use toml::Value;
 use url::Url;
 
 use darkfi::{net::settings::SettingsOpt, Result};
@@ -26,7 +25,7 @@ pub enum RPL {
 }
 
 /// ircd cli
-#[derive(Clone, Debug, Deserialize, StructOpt, StructOptToml)]
+#[derive(Clone, Deserialize, StructOpt, StructOptToml)]
 #[serde(default)]
 #[structopt(name = "ircd")]
 pub struct Args {
@@ -64,6 +63,18 @@ pub struct Args {
     #[structopt(long)]
     pub password: Option<String>,
 
+    /// Channels
+    #[structopt(skip)]
+    pub channels: HashMap<String, ChannelInfo>,
+
+    /// Channels
+    #[structopt(skip)]
+    pub contacts: HashMap<String, ContactInfo>,
+
+    /// Private key
+    #[structopt(skip)]
+    pub private_key: Option<String>,
+
     #[structopt(flatten)]
     pub net: SettingsOpt,
 
@@ -72,15 +83,37 @@ pub struct Args {
     pub verbose: u8,
 }
 
-#[derive(Clone)]
+/// This struct holds information about preconfigured contacts.
+/// In the TOML configuration file, we can configure contacts as such:
+///
+/// ```toml
+/// [contact."nick"]
+/// pubkey = "7CkVuFgwTUpJn5Sv67Q3fyEDpa28yrSeL5Hg2GqQ4jfM"
+/// ```
+#[derive(Clone, Debug, Deserialize, Serialize)]
 pub struct ContactInfo {
-    /// Optional NaCl box for the channel, used for {en,de}cryption.
-    pub salt_box: Option<SalsaBox>,
+    pub pubkey: Option<String>,
 }
 
 impl ContactInfo {
-    pub fn new() -> Result<Self> {
-        Ok(Self { salt_box: None })
+    pub fn new() -> Self {
+        Self { pubkey: None }
+    }
+
+    pub fn salt_box(&self, private_key: &str, contact_name: &str) -> Option<SalsaBox> {
+        if let Ok(private) = parse_priv(private_key) {
+            if let Some(p) = &self.pubkey {
+                if let Ok(public) = parse_pub(&p) {
+                    return Some(SalsaBox::new(&public, &private))
+                } else {
+                    error!("Uncorrect public key in for contact {}", contact_name);
+                }
+            }
+        } else {
+            error!("Uncorrect Private key in config",);
+        }
+
+        None
     }
 }
 
@@ -97,206 +130,40 @@ impl ContactInfo {
 /// Having a topic set is useful if one wants to have a topic in the
 /// configured channel. It is not shared with others, but it is useful
 /// for personal reference.
-#[derive(Clone)]
+#[derive(Clone, Debug, Serialize, Deserialize)]
 pub struct ChannelInfo {
     /// Optional topic for the channel
     pub topic: Option<String>,
     /// Optional NaCl box for the channel, used for {en,de}cryption.
-    pub salt_box: Option<SalsaBox>,
+    pub secret: Option<String>,
     /// Flag indicates whether the user has joined the channel or not
+    #[serde(default, skip_serializing)]
     pub joined: bool,
     /// All nicknames which are visible on the channel
+    #[serde(default, skip_serializing)]
     pub names: Vec<String>,
 }
 
 impl ChannelInfo {
-    pub fn new() -> Result<Self> {
-        Ok(Self { topic: None, salt_box: None, joined: false, names: vec![] })
-    }
-}
-
-fn salt_box_from_shared_secret(s: &str) -> Result<SalsaBox> {
-    let bytes: [u8; 32] = bs58::decode(s).into_vec()?.try_into().unwrap();
-    let secret = crypto_box::SecretKey::from(bytes);
-    let public = secret.public_key();
-    Ok(SalsaBox::new(&public, &secret))
-}
-
-fn parse_priv_key(data: &str) -> Result<String> {
-    let mut pk = String::new();
-
-    let map = match toml::from_str(data)? {
-        Value::Table(m) => m,
-        _ => return Ok(pk),
-    };
-
-    if !map.contains_key("private_key") {
-        return Ok(pk)
-    }
-
-    if !map["private_key"].is_table() {
-        return Ok(pk)
-    }
-
-    let private_keys = map["private_key"].as_table().unwrap();
-
-    for prv_key in private_keys {
-        pk = prv_key.0.into();
-    }
-
-    info!("Found secret key in config, noted it down.");
-    Ok(pk)
-}
-
-/// Parse a TOML string for any configured contact list and return
-/// a map containing said configurations.
-///
-/// ```toml
-/// [contact."nick"]
-/// contact_pubkey = "7CkVuFgwTUpJn5Sv67Q3fyEDpa28yrSeL5Hg2GqQ4jfM"
-/// ```
-pub fn parse_configured_contacts(data: &str) -> Result<FxHashMap<String, ContactInfo>> {
-    let mut ret = FxHashMap::default();
-
-    let map = match toml::from_str(data) {
-        Ok(Value::Table(m)) => m,
-        _ => {
-            warn!("Invalid TOML string passed as argument to parse_configured_contacts()");
-            return Ok(ret)
-        }
-    };
-
-    if !map.contains_key("contact") {
-        return Ok(ret)
+    pub fn new() -> Self {
+        Self { topic: None, secret: None, joined: false, names: vec![] }
     }
 
-    if !map["contact"].is_table() {
-        warn!("TOML configuration contains a \"contact\" field, but it is not a table.");
-        return Ok(ret)
-    }
+    pub fn salt_box(&self, channel_name: &str) -> Option<SalsaBox> {
+        if let Some(s) = &self.secret {
+            let secret = parse_priv(s);
 
-    let contacts = map["contact"].as_table().unwrap();
-
-    // Our secret key for NaCl boxes.
-    let found_priv = match parse_priv_key(data) {
-        Ok(v) => v,
-        Err(_) => {
-            info!("Did not found private key in config, skipping contact configuration.");
-            return Ok(ret)
-        }
-    };
-
-    let bytes: [u8; 32] = match bs58::decode(found_priv).into_vec() {
-        Ok(v) => {
-            if v.len() != 32 {
-                warn!("Decoded base58 secret key string is not 32 bytes");
-                warn!("Skipping private contact configuration");
-                return Ok(ret)
+            if secret.is_err() {
+                error!("Uncorrect secret key for the channel {}", channel_name);
+                return None
             }
-            v.try_into().unwrap()
-        }
-        Err(e) => {
-            warn!("Failed to decode base58 secret key from string: {}", e);
-            warn!("Skipping private contact configuration");
-            return Ok(ret)
-        }
-    };
-
-    let secret = crypto_box::SecretKey::from(bytes);
-
-    for cnt in contacts {
-        info!("Found configuration for contact {}", cnt.0);
-        let mut contact_info = ContactInfo::new()?;
 
-        if !cnt.1.is_table() {
-            warn!("Config for contact {} isn't a TOML table", cnt.0);
-            continue
+            let secret = secret.unwrap();
+            let public = secret.public_key();
+            return Some(SalsaBox::new(&public, &secret))
         }
-
-        let table = cnt.1.as_table().unwrap();
-        if table.is_empty() {
-            warn!("Configuration for contact {} is empty.", cnt.0);
-            continue
-        }
-
-        // Build the NaCl box
-        if !table.contains_key("contact_pubkey") || !table["contact_pubkey"].is_str() {
-            warn!("Contact {} doesn't have `contact_pubkey` set or is not a string.", cnt.0);
-            continue
-        }
-
-        let pub_str = table["contact_pubkey"].as_str().unwrap();
-        let bytes: [u8; 32] = match bs58::decode(pub_str).into_vec() {
-            Ok(v) => {
-                if v.len() != 32 {
-                    warn!("Decoded base58 string is not 32 bytes");
-                    continue
-                }
-
-                v.try_into().unwrap()
-            }
-            Err(e) => {
-                warn!("Failed to decode base58 pubkey from string: {}", e);
-                continue
-            }
-        };
-
-        let public = crypto_box::PublicKey::from(bytes);
-        contact_info.salt_box = Some(SalsaBox::new(&public, &secret));
-        ret.insert(cnt.0.to_string(), contact_info);
-        info!("Instantiated NaCl box for contact {}", cnt.0);
+        None
     }
-
-    Ok(ret)
-}
-
-/// Parse a TOML string for any configured channels and return
-/// a map containing said configurations.
-///
-/// ```toml
-/// [channel."#memes"]
-/// secret = "7CkVuFgwTUpJn5Sv67Q3fyEDpa28yrSeL5Hg2GqQ4jfM"
-/// topic = "Dank Memes"
-/// ```
-pub fn parse_configured_channels(data: &str) -> Result<FxHashMap<String, ChannelInfo>> {
-    let mut ret = FxHashMap::default();
-
-    let map = match toml::from_str(data)? {
-        Value::Table(m) => m,
-        _ => return Ok(ret),
-    };
-
-    if !map.contains_key("channel") {
-        return Ok(ret)
-    }
-
-    if !map["channel"].is_table() {
-        return Ok(ret)
-    }
-
-    for chan in map["channel"].as_table().unwrap() {
-        info!("Found configuration for channel {}", chan.0);
-        let mut channel_info = ChannelInfo::new()?;
-
-        if chan.1.as_table().unwrap().contains_key("topic") {
-            let topic = chan.1["topic"].as_str().unwrap().to_string();
-            info!("Found topic for channel {}: {}", chan.0, topic);
-            channel_info.topic = Some(topic);
-        }
-
-        if chan.1.as_table().unwrap().contains_key("secret") {
-            // Build the NaCl box
-            if let Some(s) = chan.1["secret"].as_str() {
-                let salt_box = salt_box_from_shared_secret(s)?;
-                channel_info.salt_box = Some(salt_box);
-                info!("Instantiated NaCl box for channel {}", chan.0);
-            }
-        }
-
-        ret.insert(chan.0.to_string(), channel_info);
-    }
-
-    Ok(ret)
 }
 
 pub fn get_current_time() -> u64 {
@@ -308,3 +175,13 @@ pub fn get_current_time() -> u64 {
         .try_into()
         .unwrap()
 }
+
+fn parse_priv(key: &str) -> Result<crypto_box::SecretKey> {
+    let bytes: [u8; 32] = bs58::decode(key).into_vec()?.try_into().unwrap();
+    Ok(crypto_box::SecretKey::from(bytes))
+}
+
+fn parse_pub(key: &str) -> Result<crypto_box::PublicKey> {
+    let bytes: [u8; 32] = bs58::decode(key).into_vec()?.try_into().unwrap();
+    Ok(crypto_box::PublicKey::from(bytes))
+}