瀏覽代碼

darkirc: Use bcrypt-2b for server password encryption

parazyd 2 年之前
父節點
當前提交
170654c423
共有 6 個文件被更改,包括 89 次插入4 次删除
  1. 24 0
      Cargo.lock
  2. 1 0
      bin/darkirc/Cargo.toml
  3. 31 0
      bin/darkirc/src/crypto/bcrypt.rs
  4. 3 0
      bin/darkirc/src/crypto/mod.rs
  5. 2 2
      bin/darkirc/src/irc/command.rs
  6. 28 2
      bin/darkirc/src/main.rs

+ 24 - 0
Cargo.lock

@@ -831,6 +831,19 @@ version = "1.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
 
+[[package]]
+name = "bcrypt"
+version = "0.15.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e65938ed058ef47d92cf8b346cc76ef48984572ade631927e9937b5ffc7662c7"
+dependencies = [
+ "base64 0.22.1",
+ "blowfish",
+ "getrandom 0.2.15",
+ "subtle",
+ "zeroize",
+]
+
 [[package]]
 name = "bincode"
 version = "1.3.3"
@@ -1004,6 +1017,16 @@ dependencies = [
  "piper",
 ]
 
+[[package]]
+name = "blowfish"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e412e2cd0f2b2d93e02543ceae7917b3c70331573df19ee046bcbc35e45e87d7"
+dependencies = [
+ "byteorder",
+ "cipher 0.4.4",
+]
+
 [[package]]
 name = "bounded-vec-deque"
 version = "0.1.1"
@@ -2210,6 +2233,7 @@ name = "darkirc"
 version = "0.5.0"
 dependencies = [
  "async-trait",
+ "bcrypt",
  "blake3 1.5.1",
  "bs58",
  "crypto_box",

+ 1 - 0
bin/darkirc/Cargo.toml

@@ -34,6 +34,7 @@ rustls-pemfile = "2.1.2"
 
 # Crypto
 blake3 = "1.5.1"
+bcrypt = "0.15.1"
 crypto_box = {version = "0.9.1", features = ["std", "chacha20"]}
 rand = "0.8.5"
 

+ 31 - 0
bin/darkirc/src/crypto/bcrypt.rs

@@ -0,0 +1,31 @@
+/* This file is part of DarkFi (https://dark.fi)
+ *
+ * Copyright (C) 2020-2024 Dyne.org foundation
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+use bcrypt::DEFAULT_COST;
+
+/// Salt used for the IRC server connection password
+pub const BCRYPT_PASSWORD_SALT: [u8; 16] = [
+    0x22, 0x23, 0xff, 0x41, 0x57, 0x47, 0x48, 0xfe, 0xde, 0xca, 0x1c, 0xd1, 0x94, 0xef, 0xcc, 0xaa,
+];
+
+/// Encrypt the given password with bcrypt-2b
+pub fn bcrypt_hash_password<P: AsRef<[u8]>>(password: P) -> String {
+    bcrypt::hash_with_salt(password, DEFAULT_COST, BCRYPT_PASSWORD_SALT)
+        .unwrap()
+        .format_for_version(bcrypt::Version::TwoB)
+}

+ 3 - 0
bin/darkirc/src/crypto/mod.rs

@@ -20,3 +20,6 @@
 
 /// ChaCha box, used for channel encryption, and optionally DM encryption.
 pub mod saltbox;
+
+/// bcrypt utilities
+pub mod bcrypt;

+ 2 - 2
bin/darkirc/src/irc/command.rs

@@ -32,7 +32,6 @@
 //! * `KILL`
 //! * `NOTICE`
 //! * `OPER`
-//! * `PASS`
 //! * `RESTART`
 //! * `SERVICE`
 //! * `SERVLIST`
@@ -62,6 +61,7 @@ use super::{
     server::MAX_NICK_LEN,
     IrcChannel, SERVER_NAME,
 };
+use crate::crypto::bcrypt::bcrypt_hash_password;
 
 impl Client {
     /// `ADMIN [<server>]`
@@ -622,7 +622,7 @@ impl Client {
             ))])
         };
 
-        if self.server.password == password.to_string() {
+        if self.server.password == bcrypt_hash_password(password) {
             self.is_pass_set.store(true, SeqCst);
         } else {
             error!("[IRC CLIENT] Password is not correct!");

+ 28 - 2
bin/darkirc/src/main.rs

@@ -15,7 +15,8 @@
  * You should have received a copy of the GNU Affero General Public License
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
-use std::{collections::HashSet, path::PathBuf, sync::Arc};
+
+use std::{collections::HashSet, io::Write, path::PathBuf, sync::Arc};
 
 use darkfi::{
     async_daemonize, cli_desc,
@@ -44,6 +45,7 @@ use irc::server::IrcServer;
 
 /// Cryptography utilities
 mod crypto;
+use crypto::bcrypt::bcrypt_hash_password;
 
 // RLN
 //mod rln;
@@ -116,10 +118,14 @@ struct Args {
     #[structopt(long, default_value = "10")]
     sync_timeout: u8,
 
-    /// IRC Password
+    /// IRC Password (Encrypted with bcrypt-2b)
     #[structopt(long)]
     pub password: Option<String>,
 
+    /// Encrypt a given password for the IRC server connection
+    #[structopt(long)]
+    encrypt_password: bool,
+
     /// replay_mode
     #[structopt(long)]
     replay_mode: bool,
@@ -209,6 +215,26 @@ async fn realmain(args: Args, ex: Arc<Executor<'static>>) -> Result<()> {
         return Ok(())
     }
 
+    if args.encrypt_password {
+        let mut pw = String::new();
+
+        print!("Enter password: ");
+        std::io::stdout().flush()?;
+        std::io::stdin().read_line(&mut pw)?;
+
+        if let Some('\n') = pw.chars().next_back() {
+            pw.pop();
+        }
+        if let Some('\r') = pw.chars().next_back() {
+            pw.pop();
+        }
+
+        println!("{}", bcrypt_hash_password(pw));
+        std::io::stdout().flush()?;
+
+        return Ok(())
+    }
+
     let replay_mode = args.replay_mode;
 
     info!("Initializing DarkIRC node");