mirror of
https://github.com/darkrenaissance/darkfi.git
synced 2026-01-10 07:08:05 -05:00
tau: use digital signatures to verify tasks authenticity (per-workspace)
and fix configured workspaces keys format and manage write access based on those keys
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -7103,6 +7103,7 @@ dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
"rand 0.8.5",
|
||||
"ring 0.17.8",
|
||||
"serde",
|
||||
"signal-hook",
|
||||
"signal-hook-async-std",
|
||||
|
||||
@@ -32,6 +32,7 @@ sled = "0.34.7"
|
||||
blake3 = "1.5.1"
|
||||
crypto_box = { version = "0.9.1", features = ["std", "chacha20"] }
|
||||
rand = "0.8.5"
|
||||
ring = "0.17.8"
|
||||
|
||||
# Encoding and parsing
|
||||
bs58 = "0.5.1"
|
||||
@@ -62,4 +63,3 @@ structopt-toml = "0.5.1"
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
|
||||
@@ -24,8 +24,7 @@ use std::{
|
||||
};
|
||||
|
||||
use async_trait::async_trait;
|
||||
use crypto_box::ChaChaBox;
|
||||
use log::{debug, warn};
|
||||
use log::{debug, info, warn};
|
||||
use smol::lock::{Mutex, MutexGuard};
|
||||
use tinyjson::JsonValue;
|
||||
|
||||
@@ -46,9 +45,11 @@ use taud::{
|
||||
error::{to_json_result, TaudError, TaudResult},
|
||||
month_tasks::MonthTasks,
|
||||
task_info::{Comment, TaskInfo},
|
||||
util::{check_write_access, set_event},
|
||||
util::set_event,
|
||||
};
|
||||
|
||||
use crate::Workspace;
|
||||
|
||||
const DEFAULT_WORKSPACE: &str = "darkfi-dev";
|
||||
|
||||
pub struct JsonRpcInterface {
|
||||
@@ -56,9 +57,7 @@ pub struct JsonRpcInterface {
|
||||
notify_queue_sender: smol::channel::Sender<TaskInfo>,
|
||||
nickname: String,
|
||||
workspace: Mutex<String>,
|
||||
workspaces: Arc<HashMap<String, ChaChaBox>>,
|
||||
write: Option<String>,
|
||||
password: Option<String>,
|
||||
workspaces: Arc<HashMap<String, Workspace>>,
|
||||
p2p: net::P2pPtr,
|
||||
event_graph: EventGraphPtr,
|
||||
dnet_sub: JsonSubscriber,
|
||||
@@ -117,9 +116,7 @@ impl JsonRpcInterface {
|
||||
dataset_path: PathBuf,
|
||||
notify_queue_sender: smol::channel::Sender<TaskInfo>,
|
||||
nickname: String,
|
||||
workspaces: Arc<HashMap<String, ChaChaBox>>,
|
||||
write: Option<String>,
|
||||
password: Option<String>,
|
||||
workspaces: Arc<HashMap<String, Workspace>>,
|
||||
p2p: net::P2pPtr,
|
||||
event_graph: EventGraphPtr,
|
||||
dnet_sub: JsonSubscriber,
|
||||
@@ -132,8 +129,6 @@ impl JsonRpcInterface {
|
||||
workspace,
|
||||
workspaces,
|
||||
notify_queue_sender,
|
||||
write,
|
||||
password,
|
||||
p2p,
|
||||
event_graph,
|
||||
rpc_connections: Mutex::new(HashSet::new()),
|
||||
@@ -324,12 +319,14 @@ impl JsonRpcInterface {
|
||||
_ => return Err(TaudError::InvalidData("Invalid parameter \"created_at\"".to_string())),
|
||||
};
|
||||
|
||||
if !check_write_access(self.write.clone(), self.password.clone())? {
|
||||
let ws = self.workspace.lock().await.clone();
|
||||
if self.workspaces.get(&ws).unwrap().write_key.is_none() {
|
||||
info!("You don't have write access!");
|
||||
return Ok(JsonValue::Boolean(false))
|
||||
}
|
||||
|
||||
let mut new_task: TaskInfo = TaskInfo::new(
|
||||
self.workspace.lock().await.clone(),
|
||||
ws,
|
||||
params["title"].get::<String>().unwrap(),
|
||||
params["desc"].get::<String>().unwrap(),
|
||||
&self.nickname,
|
||||
@@ -401,12 +398,12 @@ impl JsonRpcInterface {
|
||||
return Err(TaudError::InvalidData("len of params should be 2".into()))
|
||||
}
|
||||
|
||||
if !check_write_access(self.write.clone(), self.password.clone())? {
|
||||
let ws = self.workspace.lock().await.clone();
|
||||
if self.workspaces.get(&ws).unwrap().write_key.is_none() {
|
||||
info!("You don't have write access!");
|
||||
return Ok(JsonValue::Boolean(false))
|
||||
}
|
||||
|
||||
let ws = self.workspace.lock().await.clone();
|
||||
|
||||
let task = self.check_params_for_modify(
|
||||
params[0].get::<String>().unwrap(),
|
||||
params[1].get::<HashMap<String, JsonValue>>().unwrap(),
|
||||
@@ -433,12 +430,12 @@ impl JsonRpcInterface {
|
||||
return Err(TaudError::InvalidData("len of params should be 2".into()))
|
||||
}
|
||||
|
||||
if !check_write_access(self.write.clone(), self.password.clone())? {
|
||||
return Ok(JsonValue::Boolean(false))
|
||||
}
|
||||
|
||||
let state = params[1].get::<String>().unwrap();
|
||||
let ws = self.workspace.lock().await.clone();
|
||||
if self.workspaces.get(&ws).unwrap().write_key.is_none() {
|
||||
info!("You don't have write access!");
|
||||
return Ok(JsonValue::Boolean(false))
|
||||
}
|
||||
|
||||
let mut task: TaskInfo =
|
||||
self.load_task_by_ref_id(params[0].get::<String>().unwrap(), ws)?;
|
||||
@@ -465,14 +462,15 @@ impl JsonRpcInterface {
|
||||
return Err(TaudError::InvalidData("len of params should be 2".into()))
|
||||
}
|
||||
|
||||
if !check_write_access(self.write.clone(), self.password.clone())? {
|
||||
return Ok(JsonValue::Boolean(false))
|
||||
}
|
||||
|
||||
let ref_id = params[0].get::<String>().unwrap();
|
||||
let comment_content = params[1].get::<String>().unwrap();
|
||||
|
||||
let ws = self.workspace.lock().await.clone();
|
||||
if self.workspaces.get(&ws).unwrap().write_key.is_none() {
|
||||
info!("You don't have write access!");
|
||||
return Ok(JsonValue::Boolean(false))
|
||||
}
|
||||
|
||||
let mut task: TaskInfo = self.load_task_by_ref_id(ref_id, ws)?;
|
||||
|
||||
task.set_comment(Comment::new(comment_content, &self.nickname));
|
||||
@@ -654,13 +652,13 @@ impl JsonRpcInterface {
|
||||
return Err(TaudError::InvalidData("Invalid path".into()))
|
||||
}
|
||||
|
||||
if !check_write_access(self.write.clone(), self.password.clone())? {
|
||||
return Ok(JsonValue::Boolean(false))
|
||||
}
|
||||
|
||||
let path = params[0].get::<String>().unwrap();
|
||||
let path = expand_path(path)?.join("exported_tasks");
|
||||
let ws = self.workspace.lock().await.clone();
|
||||
if self.workspaces.get(&ws).unwrap().write_key.is_none() {
|
||||
info!("You don't have write access!");
|
||||
return Ok(JsonValue::Boolean(false))
|
||||
}
|
||||
|
||||
let imported_tasks = MonthTasks::load_current_tasks(&path, ws.clone(), true)?;
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@ use futures::{select, FutureExt};
|
||||
use libc::mkfifo;
|
||||
use log::{debug, error, info};
|
||||
use rand::rngs::OsRng;
|
||||
use ring::signature::{Ed25519KeyPair, KeyPair, Signature, UnparsedPublicKey, ED25519};
|
||||
use smol::{fs, lock::RwLock, stream::StreamExt};
|
||||
use structopt_toml::StructOptToml;
|
||||
use tinyjson::JsonValue;
|
||||
@@ -54,7 +55,7 @@ use darkfi::{
|
||||
server::{listen_and_serve, RequestHandler},
|
||||
},
|
||||
system::{sleep, StoppableTask},
|
||||
util::path::expand_path,
|
||||
util::path::{expand_path, get_config_path},
|
||||
Error, Result,
|
||||
};
|
||||
|
||||
@@ -72,25 +73,21 @@ use crate::{
|
||||
settings::{Args, CONFIG_FILE, CONFIG_FILE_CONTENTS},
|
||||
};
|
||||
|
||||
fn get_workspaces(settings: &Args) -> Result<HashMap<String, ChaChaBox>> {
|
||||
let mut workspaces = HashMap::new();
|
||||
struct Workspace {
|
||||
read_key: ChaChaBox,
|
||||
write_key: Option<Ed25519KeyPair>,
|
||||
write_pubkey: UnparsedPublicKey<Vec<u8>>,
|
||||
}
|
||||
|
||||
for workspace in settings.workspaces.iter() {
|
||||
let workspace: Vec<&str> = workspace.split(':').collect();
|
||||
let (workspace, secret) = (workspace[0], workspace[1]);
|
||||
|
||||
let bytes: [u8; 32] = bs58::decode(secret)
|
||||
.into_vec()?
|
||||
.try_into()
|
||||
.map_err(|_| Error::ParseFailed("Parse secret key failed"))?;
|
||||
|
||||
let secret = crypto_box::SecretKey::from(bytes);
|
||||
let public = secret.public_key();
|
||||
let chacha_box = crypto_box::ChaChaBox::new(&public, &secret);
|
||||
workspaces.insert(workspace.to_string(), chacha_box);
|
||||
impl Workspace {
|
||||
fn new() -> Self {
|
||||
let secret_key = SecretKey::generate(&mut OsRng);
|
||||
Self {
|
||||
read_key: ChaChaBox::new(&secret_key.public_key(), &secret_key),
|
||||
write_key: None,
|
||||
write_pubkey: UnparsedPublicKey::new(&ED25519, vec![0]),
|
||||
}
|
||||
}
|
||||
|
||||
Ok(workspaces)
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
|
||||
@@ -98,16 +95,30 @@ pub struct EncryptedTask {
|
||||
payload: String,
|
||||
}
|
||||
|
||||
fn encrypt_task(
|
||||
task: &TaskInfo,
|
||||
chacha_box: &ChaChaBox,
|
||||
rng: &mut OsRng,
|
||||
) -> TaudResult<EncryptedTask> {
|
||||
debug!(target: "taud", "start encrypting task");
|
||||
#[derive(SerialEncodable, SerialDecodable)]
|
||||
struct SignedTask {
|
||||
task: Vec<u8>,
|
||||
signature: Vec<u8>,
|
||||
}
|
||||
|
||||
let nonce = ChaChaBox::generate_nonce(rng);
|
||||
let payload = &serialize(task)[..];
|
||||
let mut payload = chacha_box.encrypt(&nonce, payload)?;
|
||||
impl SignedTask {
|
||||
fn new(task: &TaskInfo, signature: Signature) -> Self {
|
||||
Self { task: serialize(task), signature: signature.as_ref().to_vec() }
|
||||
}
|
||||
}
|
||||
|
||||
/// Sign then encrypt a task
|
||||
fn encrypt_sign_task(task: &TaskInfo, workspace: &Workspace) -> TaudResult<EncryptedTask> {
|
||||
debug!(target: "taud", "start encrypting task");
|
||||
if workspace.write_key.is_none() {
|
||||
error!("You don't have write access")
|
||||
}
|
||||
let signature: Signature = workspace.write_key.as_ref().unwrap().sign(&serialize(task)[..]);
|
||||
let signed_task = SignedTask::new(task, signature);
|
||||
|
||||
let nonce = ChaChaBox::generate_nonce(&mut OsRng);
|
||||
let payload = &serialize(&signed_task)[..];
|
||||
let mut payload = workspace.read_key.encrypt(&nonce, payload)?;
|
||||
|
||||
let mut concat = vec![];
|
||||
concat.append(&mut nonce.as_slice().to_vec());
|
||||
@@ -118,7 +129,10 @@ fn encrypt_task(
|
||||
Ok(EncryptedTask { payload })
|
||||
}
|
||||
|
||||
fn try_decrypt_task(encrypt_task: &EncryptedTask, chacha_box: &ChaChaBox) -> TaudResult<TaskInfo> {
|
||||
fn try_decrypt_task(
|
||||
encrypt_task: &EncryptedTask,
|
||||
chacha_box: &ChaChaBox,
|
||||
) -> TaudResult<SignedTask> {
|
||||
debug!(target: "taud", "start decrypting task");
|
||||
|
||||
let bytes = match bs58::decode(&encrypt_task.payload).into_vec() {
|
||||
@@ -139,16 +153,114 @@ fn try_decrypt_task(encrypt_task: &EncryptedTask, chacha_box: &ChaChaBox) -> Tau
|
||||
// let nonce = encrypt_task.nonce.as_slice();
|
||||
let decrypted_task = chacha_box.decrypt(nonce, message)?;
|
||||
|
||||
let task = deserialize(&decrypted_task)?;
|
||||
let signed_task = deserialize(&decrypted_task)?;
|
||||
|
||||
Ok(task)
|
||||
Ok(signed_task)
|
||||
}
|
||||
|
||||
fn parse_configured_workspaces(data: &toml::Value) -> Result<HashMap<String, Workspace>> {
|
||||
let mut ret = HashMap::new();
|
||||
|
||||
let Some(table) = data.as_table() else { return Err(Error::ParseFailed("TOML not a map")) };
|
||||
let Some(workspace) = table.get("workspace") else { return Ok(ret) };
|
||||
let Some(workspace) = workspace.as_table() else {
|
||||
return Err(Error::ParseFailed("`workspace` not a map"))
|
||||
};
|
||||
|
||||
for (name, items) in workspace {
|
||||
let mut ws = Workspace::new();
|
||||
|
||||
if let Some(read_key) = items.get("read_key") {
|
||||
if let Some(read_key) = read_key.as_str() {
|
||||
let Ok(read_key_bytes) = bs58::decode(read_key).into_vec() else {
|
||||
return Err(Error::ParseFailed("Workspace secret not valid base58"))
|
||||
};
|
||||
|
||||
if read_key_bytes.len() != 32 {
|
||||
return Err(Error::ParseFailed("Workspace read_key not 32 bytes long"))
|
||||
}
|
||||
|
||||
let read_key_bytes: [u8; 32] = read_key_bytes.try_into().unwrap();
|
||||
let read_key = crypto_box::SecretKey::from(read_key_bytes);
|
||||
let public = read_key.public_key();
|
||||
ws.read_key = ChaChaBox::new(&public, &read_key);
|
||||
} else {
|
||||
return Err(Error::ParseFailed("Workspace read_key not a string"))
|
||||
}
|
||||
} else {
|
||||
return Err(Error::ParseFailed("Workspace read_key is not set"))
|
||||
}
|
||||
|
||||
if let Some(write_pubkey) = items.get("write_public_key") {
|
||||
if let Some(write_pubkey) = write_pubkey.as_str() {
|
||||
if !write_pubkey.is_empty() {
|
||||
info!("Found configured write_public_key for {} workspace", name);
|
||||
let write_pubkey = write_pubkey.to_string();
|
||||
let decoded_write_pubkey = bs58::decode(write_pubkey).into_vec().unwrap();
|
||||
ws.write_pubkey = UnparsedPublicKey::new(&ED25519, decoded_write_pubkey);
|
||||
}
|
||||
} else {
|
||||
return Err(Error::ParseFailed("Workspace write_public_key not a string"))
|
||||
}
|
||||
} else {
|
||||
return Err(Error::ParseFailed("Workspace write_public_key is not set"))
|
||||
}
|
||||
|
||||
if let Some(write_key) = items.get("write_key") {
|
||||
if let Some(write_key) = write_key.as_str() {
|
||||
if !write_key.is_empty() {
|
||||
info!("Found configured write_key for {} workspace", name);
|
||||
let write_key = write_key.to_string();
|
||||
let pkcs8_bytes = bs58::decode(write_key).into_vec().unwrap();
|
||||
let ed25519 = match Ed25519KeyPair::from_pkcs8(pkcs8_bytes.as_ref()) {
|
||||
Ok(key) => key,
|
||||
Err(e) => {
|
||||
error!("Failed parsing write_key: {}", e);
|
||||
return Err(Error::ParseFailed("Failed parsing write_key"))
|
||||
}
|
||||
};
|
||||
ws.write_key = Some(ed25519);
|
||||
}
|
||||
} else {
|
||||
return Err(Error::ParseFailed("Workspace write_key not a string"))
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(wrt_key) = ws.write_key.as_ref() {
|
||||
if wrt_key.public_key().as_ref() != ws.write_pubkey.as_ref() {
|
||||
error!("Wrong keypair for {} workspace, the workspace is not added!", name);
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
info!("Configured NaCl box for workspace {}", name);
|
||||
ret.insert(name.to_string(), ws);
|
||||
}
|
||||
|
||||
Ok(ret)
|
||||
}
|
||||
|
||||
async fn get_workspaces(settings: &Args) -> Result<HashMap<String, Workspace>> {
|
||||
let config_path = get_config_path(settings.config.clone(), CONFIG_FILE)?;
|
||||
let contents = fs::read_to_string(config_path).await?;
|
||||
let contents = match toml::from_str(&contents) {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
error!("Failed parsing TOML config: {}", e);
|
||||
return Err(Error::ParseFailed("Failed parsing TOML config"))
|
||||
}
|
||||
};
|
||||
|
||||
let workspaces = parse_configured_workspaces(&contents)?;
|
||||
|
||||
Ok(workspaces)
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
async fn start_sync_loop(
|
||||
event_graph: EventGraphPtr,
|
||||
broadcast_rcv: smol::channel::Receiver<TaskInfo>,
|
||||
workspaces: Arc<HashMap<String, ChaChaBox>>,
|
||||
workspaces: Arc<HashMap<String, Workspace>>,
|
||||
datastore_path: std::path::PathBuf,
|
||||
piped: bool,
|
||||
p2p: P2pPtr,
|
||||
@@ -164,8 +276,8 @@ async fn start_sync_loop(
|
||||
task_event = broadcast_rcv.recv().fuse() => {
|
||||
let tk = task_event.map_err(Error::from)?;
|
||||
if workspaces.contains_key(&tk.workspace) {
|
||||
let chacha_box = workspaces.get(&tk.workspace).unwrap();
|
||||
let encrypted_task = encrypt_task(&tk, chacha_box, &mut OsRng)?;
|
||||
let ws = workspaces.get(&tk.workspace).unwrap();
|
||||
let encrypted_task = encrypt_sign_task(&tk, ws)?;
|
||||
info!(target: "taud", "Send the task: ref: {}", tk.ref_id);
|
||||
// Build a DAG event and return it.
|
||||
let event = Event::new(
|
||||
@@ -183,9 +295,7 @@ async fn start_sync_loop(
|
||||
error!(target: "taud", "Failed inserting new event to DAG: {}", e);
|
||||
} else {
|
||||
// We sent this, so it should be considered seen.
|
||||
// TODO: should we save task on send or on receive?
|
||||
// on receive better because it's garanteed your event is out there
|
||||
// debug!("Marking event {} as seen", event_id);
|
||||
// debug!(target: "taud", "Marking event {} as seen", event_id);
|
||||
// seen.get().unwrap().insert(event_id.as_bytes(), &[]).unwrap();
|
||||
|
||||
// Otherwise, broadcast it
|
||||
@@ -219,22 +329,38 @@ async fn start_sync_loop(
|
||||
}
|
||||
}
|
||||
|
||||
/// Handel a received task, decrypt it, verify it, optionally write it
|
||||
/// to a named pipe and save it on disk.
|
||||
async fn on_receive_task(
|
||||
task: &EncryptedTask,
|
||||
enc_task: &EncryptedTask,
|
||||
datastore_path: &Path,
|
||||
workspaces: &HashMap<String, ChaChaBox>,
|
||||
workspaces: &HashMap<String, Workspace>,
|
||||
piped: bool,
|
||||
) -> TaudResult<()> {
|
||||
for (workspace, chacha_box) in workspaces.iter() {
|
||||
let task = try_decrypt_task(task, chacha_box);
|
||||
if let Err(e) = task {
|
||||
for (ws_name, workspace) in workspaces.iter() {
|
||||
let signed_task = try_decrypt_task(enc_task, &workspace.read_key);
|
||||
if let Err(e) = signed_task {
|
||||
debug!(target: "taud", "Unable to decrypt the task: {}", e);
|
||||
continue
|
||||
}
|
||||
|
||||
let mut task = task.unwrap();
|
||||
if workspace
|
||||
.write_pubkey
|
||||
.verify(&signed_task.as_ref().unwrap().task, &signed_task.as_ref().unwrap().signature)
|
||||
.is_err()
|
||||
{
|
||||
// *verified.lock().await = false;
|
||||
error!("Task is not verified: wrong write_public_key");
|
||||
error!("Task is not saved");
|
||||
continue
|
||||
}
|
||||
// else {
|
||||
// *verified.lock().await = true;
|
||||
// }
|
||||
|
||||
let mut task: TaskInfo = deserialize(&signed_task.unwrap().task)?;
|
||||
info!(target: "taud", "Save the task: ref: {}", task.ref_id);
|
||||
task.workspace.clone_from(workspace);
|
||||
task.workspace.clone_from(ws_name);
|
||||
if piped {
|
||||
// if we can't load the task then it's a new task.
|
||||
// otherwise it's a modification.
|
||||
@@ -338,7 +464,8 @@ async fn realmain(settings: Args, executor: Arc<smol::Executor<'static>>) -> Res
|
||||
return Ok(())
|
||||
}
|
||||
|
||||
let workspaces = Arc::new(get_workspaces(&settings)?);
|
||||
let workspaces = Arc::new(get_workspaces(&settings).await?);
|
||||
// let verified = Arc::new(Mutex::new(false));
|
||||
|
||||
if workspaces.is_empty() {
|
||||
error!(target: "taud", "Please add at least one workspace to the config file.");
|
||||
@@ -525,8 +652,6 @@ async fn realmain(settings: Args, executor: Arc<smol::Executor<'static>>) -> Res
|
||||
broadcast_snd,
|
||||
nickname.unwrap(),
|
||||
workspaces.clone(),
|
||||
settings.write,
|
||||
settings.password,
|
||||
p2p.clone(),
|
||||
event_graph.clone(),
|
||||
json_sub,
|
||||
|
||||
@@ -22,16 +22,12 @@ use std::{
|
||||
path::Path,
|
||||
};
|
||||
|
||||
use crypto_box::aead::Aead;
|
||||
use log::{debug, error};
|
||||
use log::debug;
|
||||
|
||||
use darkfi::{Error, Result};
|
||||
use rand::{distributions::Alphanumeric, rngs::OsRng, Rng};
|
||||
|
||||
use crate::{
|
||||
error::{TaudError, TaudResult},
|
||||
task_info::{TaskEvent, TaskInfo},
|
||||
};
|
||||
use crate::task_info::{TaskEvent, TaskInfo};
|
||||
|
||||
pub fn set_event(task_info: &mut TaskInfo, action: &str, author: &str, content: &str) {
|
||||
debug!(target: "tau", "TaskInfo::set_event()");
|
||||
@@ -47,49 +43,3 @@ pub fn pipe_write<P: AsRef<Path>>(path: P) -> Result<File> {
|
||||
pub fn gen_id(len: usize) -> String {
|
||||
OsRng.sample_iter(&Alphanumeric).take(len).map(char::from).collect()
|
||||
}
|
||||
|
||||
pub fn check_write_access(write: Option<String>, password: Option<String>) -> TaudResult<bool> {
|
||||
let secret = if write.is_some() {
|
||||
let scrt = write.clone().unwrap();
|
||||
let bytes: [u8; 32] = bs58::decode(scrt)
|
||||
.into_vec()
|
||||
.map_err(|_| {
|
||||
Error::ParseFailed("Parse secret key failed, couldn't decode into vector of bytes")
|
||||
})?
|
||||
.try_into()
|
||||
.map_err(|_| Error::ParseFailed("Parse secret key failed"))?;
|
||||
crypto_box::SecretKey::from(bytes)
|
||||
} else {
|
||||
crypto_box::SecretKey::generate(&mut OsRng)
|
||||
};
|
||||
|
||||
let public = secret.public_key();
|
||||
let chacha_box = crypto_box::ChaChaBox::new(&public, &secret);
|
||||
|
||||
if password.is_some() {
|
||||
let bytes = match bs58::decode(password.clone().unwrap()).into_vec() {
|
||||
Ok(v) => v,
|
||||
Err(_) => return Err(TaudError::DecryptionError("Error decoding payload".to_string())),
|
||||
};
|
||||
|
||||
if bytes.len() < 25 {
|
||||
return Err(TaudError::DecryptionError("Invalid bytes length".to_string()))
|
||||
}
|
||||
|
||||
// Try extracting the nonce
|
||||
let nonce = bytes[0..24].into();
|
||||
|
||||
// Take the remaining ciphertext
|
||||
let pswd = &bytes[24..];
|
||||
|
||||
if chacha_box.decrypt(nonce, pswd).is_err() {
|
||||
error!(target: "taud", "You don't have write access");
|
||||
return Ok(false);
|
||||
};
|
||||
} else {
|
||||
error!(target: "taud", "You don't have write access");
|
||||
return Ok(false);
|
||||
};
|
||||
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
@@ -17,8 +17,9 @@
|
||||
## Current display name
|
||||
#nickname = "NICKNAME"
|
||||
|
||||
## Workspaces
|
||||
workspaces = ["darkfi-dev:2bCqQTd8BJgeUzH7JQELZxjQuWS8aCmXZ9C6w7ktNS1v"]
|
||||
[workspace."darkfi-dev"]
|
||||
read_key = "2bCqQTd8BJgeUzH7JQELZxjQuWS8aCmXZ9C6w7ktNS1v"
|
||||
write_public_key = "Fgsc8tep4KX3Rb2drq8RxMyrHFWQ7wZaZPpF9F3GQYFG"
|
||||
|
||||
# P2P network settings
|
||||
[net]
|
||||
|
||||
Reference in New Issue
Block a user