mirror of
https://github.com/aljazceru/pubky-core.git
synced 2026-02-21 05:54:20 +01:00
refactor(pubky): move recovery_file code to pubky_common
This commit is contained in:
772
Cargo.lock
generated
772
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -5,13 +5,8 @@ edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.86"
|
||||
clap = "4.5.16"
|
||||
dialoguer = "0.11.0"
|
||||
dirs-next = "2.0.0"
|
||||
keyring = { version = "3.2.0", features = ["linux-native", "apple-native", "windows-native"] }
|
||||
keyring-search = "1.2.1"
|
||||
clap = { version = "4.5.16", features = ["derive"] }
|
||||
pubky = { version = "0.1.0", path = "../../../pubky" }
|
||||
pubky-common = { version = "0.1.0", path = "../../../pubky-common" }
|
||||
rpassword = "7.3.1"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
url = "2.5.2"
|
||||
|
||||
@@ -1,82 +1,40 @@
|
||||
// use std::io;
|
||||
|
||||
use anyhow::Result;
|
||||
// use clap::{App, Arg, SubCommand};
|
||||
// use dialoguer::{Input, Select};
|
||||
use clap::Parser;
|
||||
use std::path::PathBuf;
|
||||
use url::Url;
|
||||
|
||||
use keyring_search::{Limit, List, Search};
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(version, about, long_about = None)]
|
||||
struct Cli {
|
||||
/// Pubky Auth url
|
||||
url: Url,
|
||||
|
||||
// use keyring::Entry;
|
||||
// use pubky_common::crypto::Keypair;
|
||||
|
||||
const SERVICE_NAME: &str = "pubky";
|
||||
/// Path to a recovery_file of the Pubky you want to sign in with
|
||||
// #[arg(short, long, value_name = "FILE")]
|
||||
recovery_file: PathBuf,
|
||||
// /// Mutable data public key.
|
||||
// public_key: String,
|
||||
}
|
||||
|
||||
fn main() -> Result<()> {
|
||||
let result = Search::new().unwrap().by_service(SERVICE_NAME).unwrap();
|
||||
let cli = Cli::parse();
|
||||
|
||||
// let list: Vec<_> = result
|
||||
// .values()
|
||||
// .map(|v| {
|
||||
// dbg!(&v);
|
||||
// v.get("acct")
|
||||
// })
|
||||
// .filter(|acc| acc.is_some())
|
||||
// .collect();
|
||||
let url = cli.url;
|
||||
dbg!(url);
|
||||
|
||||
let list = List::list_credentials(&Search::new().unwrap().by_service(SERVICE_NAME), Limit::All);
|
||||
let recovery_file = std::fs::read(&cli.recovery_file)?;
|
||||
println!("Successfully opened recovery file");
|
||||
|
||||
dbg!(list);
|
||||
// // println!("Enter Pubky Auth URL to start the consent form:");
|
||||
// // let pubky_auth_url = rl.readline("> ")?;
|
||||
// // dbg!(pubky_auth_url);
|
||||
|
||||
// println!("Enter the alias for your keypair in your operating system secure storage:");
|
||||
// let mut name = String::new();
|
||||
// io::stdin().read_line(&mut name)?;
|
||||
// name = name.trim_end().to_lowercase();
|
||||
//
|
||||
// let entry = Entry::new(SERVICE_NAME, &name)?;
|
||||
//
|
||||
// let keypair = match entry.get_secret() {
|
||||
// Ok(secret_key) => {
|
||||
// let secret_key: &[u8; 32] = secret_key
|
||||
// .as_slice()
|
||||
// .try_into()
|
||||
// .expect("Invalid secret_key");
|
||||
// let keypair = Keypair::from_secret_key(&secret_key);
|
||||
//
|
||||
// println!("\nFound secret_key for Pubky {}", keypair.public_key());
|
||||
//
|
||||
// keypair
|
||||
// }
|
||||
// Err(error) => {
|
||||
// let keypair = Keypair::random();
|
||||
//
|
||||
// println!(
|
||||
// "\n{}\nGenerated new Pubky {}",
|
||||
// error.to_string(),
|
||||
// keypair.public_key()
|
||||
// );
|
||||
//
|
||||
// loop {
|
||||
// println!("\nStore the new Pubky keypair in operating system secure storage?[y/n]");
|
||||
// let mut choice = String::new();
|
||||
// io::stdin().read_line(&mut choice)?;
|
||||
//
|
||||
// match choice.as_str() {
|
||||
// "y\n" => {
|
||||
// entry.set_secret(&keypair.secret_key())?;
|
||||
//
|
||||
// break;
|
||||
// }
|
||||
// "n\n" => {
|
||||
// return Ok(());
|
||||
// }
|
||||
// _ => {}
|
||||
// };
|
||||
// }
|
||||
//
|
||||
// keypair
|
||||
// }
|
||||
// };
|
||||
// dbg!(keypair);
|
||||
println!("Enter your recovery_file's passphrase to confirm:");
|
||||
let passphrase = rpassword::read_password()?;
|
||||
|
||||
let keypair = pubky_common::recovery_file::decrypt_recovery_file(&recovery_file, &passphrase)?;
|
||||
|
||||
println!("Successfully decrypted recovery file...");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ rand = "0.8.5"
|
||||
thiserror = "1.0.60"
|
||||
postcard = { version = "1.0.8", features = ["alloc"] }
|
||||
crypto_secretbox = { version = "0.1.1", features = ["std"] }
|
||||
argon2 = { version = "0.5.3", features = ["std"] }
|
||||
|
||||
serde = { workspace = true, optional = true }
|
||||
|
||||
|
||||
@@ -2,5 +2,6 @@ pub mod auth;
|
||||
pub mod capabilities;
|
||||
pub mod crypto;
|
||||
pub mod namespaces;
|
||||
pub mod recovery_file;
|
||||
pub mod session;
|
||||
pub mod timestamp;
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
use argon2::Argon2;
|
||||
use pkarr::Keypair;
|
||||
use pubky_common::crypto::{decrypt, encrypt};
|
||||
|
||||
use crate::error::{Error, Result};
|
||||
use crate::crypto::{decrypt, encrypt};
|
||||
|
||||
static SPEC_NAME: &str = "recovery";
|
||||
static SPEC_LINE: &str = "pubky.org/recovery";
|
||||
|
||||
pub fn decrypt_recovery_file(recovery_file: &[u8], passphrase: &str) -> Result<Keypair> {
|
||||
pub fn decrypt_recovery_file(recovery_file: &[u8], passphrase: &str) -> Result<Keypair, Error> {
|
||||
let encryption_key = recovery_file_encryption_key_from_passphrase(passphrase)?;
|
||||
|
||||
let newline_index = recovery_file
|
||||
@@ -39,7 +38,7 @@ pub fn decrypt_recovery_file(recovery_file: &[u8], passphrase: &str) -> Result<K
|
||||
Ok(Keypair::from_secret_key(&secret_key))
|
||||
}
|
||||
|
||||
pub fn create_recovery_file(keypair: &Keypair, passphrase: &str) -> Result<Vec<u8>> {
|
||||
pub fn create_recovery_file(keypair: &Keypair, passphrase: &str) -> Result<Vec<u8>, Error> {
|
||||
let encryption_key = recovery_file_encryption_key_from_passphrase(passphrase)?;
|
||||
let secret_key = keypair.secret_key();
|
||||
|
||||
@@ -54,7 +53,7 @@ pub fn create_recovery_file(keypair: &Keypair, passphrase: &str) -> Result<Vec<u
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
fn recovery_file_encryption_key_from_passphrase(passphrase: &str) -> Result<[u8; 32]> {
|
||||
fn recovery_file_encryption_key_from_passphrase(passphrase: &str) -> Result<[u8; 32], Error> {
|
||||
let argon2id = Argon2::default();
|
||||
|
||||
let mut out = [0; 32];
|
||||
@@ -64,19 +63,39 @@ fn recovery_file_encryption_key_from_passphrase(passphrase: &str) -> Result<[u8;
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum Error {
|
||||
// === Recovery file ==
|
||||
#[error("Recovery file should start with a spec line, followed by a new line character")]
|
||||
RecoveryFileMissingSpecLine,
|
||||
|
||||
#[error("Recovery file should start with a spec line, followed by a new line character")]
|
||||
RecoveryFileVersionNotSupported,
|
||||
|
||||
#[error("Recovery file should contain an encrypted secret key after the new line character")]
|
||||
RecoverFileMissingEncryptedSecretKey,
|
||||
|
||||
#[error("Recovery file encrypted secret key should be 32 bytes, got {0}")]
|
||||
RecoverFileInvalidSecretKeyLength(usize),
|
||||
|
||||
#[error(transparent)]
|
||||
Argon(#[from] argon2::Error),
|
||||
|
||||
#[error(transparent)]
|
||||
Crypto(#[from] crate::crypto::Error),
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
use crate::PubkyClient;
|
||||
|
||||
#[test]
|
||||
fn encrypt_decrypt_recovery_file() {
|
||||
let passphrase = "very secure password";
|
||||
let keypair = Keypair::random();
|
||||
|
||||
let recovery_file = PubkyClient::create_recovery_file(&keypair, passphrase).unwrap();
|
||||
let recovered = PubkyClient::decrypt_recovery_file(&recovery_file, passphrase).unwrap();
|
||||
let recovery_file = create_recovery_file(&keypair, passphrase).unwrap();
|
||||
let recovered = decrypt_recovery_file(&recovery_file, passphrase).unwrap();
|
||||
|
||||
assert_eq!(recovered.public_key(), keypair.public_key());
|
||||
}
|
||||
@@ -17,7 +17,6 @@ url = "2.5.2"
|
||||
bytes = "^1.7.1"
|
||||
|
||||
pubky-common = { version = "0.1.0", path = "../pubky-common" }
|
||||
argon2 = { version = "0.5.3", features = ["std"] }
|
||||
|
||||
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
||||
pkarr = { workspace = true, features = ["async"] }
|
||||
|
||||
@@ -15,19 +15,6 @@ pub enum Error {
|
||||
#[error("Could not resolve endpoint for {0}")]
|
||||
ResolveEndpoint(String),
|
||||
|
||||
// === Recovery file ==
|
||||
#[error("Recovery file should start with a spec line, followed by a new line character")]
|
||||
RecoveryFileMissingSpecLine,
|
||||
|
||||
#[error("Recovery file should start with a spec line, followed by a new line character")]
|
||||
RecoveryFileVersionNotSupported,
|
||||
|
||||
#[error("Recovery file should contain an encrypted secret key after the new line character")]
|
||||
RecoverFileMissingEncryptedSecretKey,
|
||||
|
||||
#[error("Recovery file encrypted secret key should be 32 bytes, got {0}")]
|
||||
RecoverFileInvalidSecretKeyLength(usize),
|
||||
|
||||
#[error("Could not convert the passed type into a Url")]
|
||||
InvalidUrl,
|
||||
|
||||
@@ -51,7 +38,7 @@ pub enum Error {
|
||||
Crypto(#[from] pubky_common::crypto::Error),
|
||||
|
||||
#[error(transparent)]
|
||||
Argon(#[from] argon2::Error),
|
||||
RecoveryFile(#[from] pubky_common::recovery_file::Error),
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
|
||||
@@ -6,18 +6,14 @@ use ::pkarr::{
|
||||
};
|
||||
use bytes::Bytes;
|
||||
use pkarr::Keypair;
|
||||
use pubky_common::session::Session;
|
||||
use pubky_common::{
|
||||
recovery_file::{create_recovery_file, decrypt_recovery_file},
|
||||
session::Session,
|
||||
};
|
||||
use reqwest::{RequestBuilder, Response};
|
||||
use url::Url;
|
||||
|
||||
use crate::{
|
||||
error::Result,
|
||||
shared::{
|
||||
list_builder::ListBuilder,
|
||||
recovery_file::{create_recovery_file, decrypt_recovery_file},
|
||||
},
|
||||
PubkyClient,
|
||||
};
|
||||
use crate::{error::Result, shared::list_builder::ListBuilder, PubkyClient};
|
||||
|
||||
static DEFAULT_USER_AGENT: &str = concat!(env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION"),);
|
||||
|
||||
@@ -151,12 +147,12 @@ impl PubkyClient {
|
||||
/// Create a recovery file of the `keypair`, containing the secret key encrypted
|
||||
/// using the `passphrase`.
|
||||
pub fn create_recovery_file(keypair: &Keypair, passphrase: &str) -> Result<Vec<u8>> {
|
||||
create_recovery_file(keypair, passphrase)
|
||||
Ok(create_recovery_file(keypair, passphrase)?)
|
||||
}
|
||||
|
||||
/// Recover a keypair from a recovery file by decrypting the secret key using `passphrase`.
|
||||
pub fn decrypt_recovery_file(recovery_file: &[u8], passphrase: &str) -> Result<Keypair> {
|
||||
decrypt_recovery_file(recovery_file, passphrase)
|
||||
Ok(decrypt_recovery_file(recovery_file, passphrase)?)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,4 +2,3 @@ pub mod auth;
|
||||
pub mod list_builder;
|
||||
pub mod pkarr;
|
||||
pub mod public;
|
||||
pub mod recovery_file;
|
||||
|
||||
@@ -6,13 +6,9 @@ use std::{
|
||||
use js_sys::{Array, Uint8Array};
|
||||
use wasm_bindgen::prelude::{wasm_bindgen, JsValue};
|
||||
|
||||
use reqwest::{IntoUrl, Method, RequestBuilder, Response};
|
||||
use url::Url;
|
||||
use pubky_common::recovery_file::{create_recovery_file, decrypt_recovery_file};
|
||||
|
||||
use crate::{
|
||||
shared::recovery_file::{create_recovery_file, decrypt_recovery_file},
|
||||
PubkyClient,
|
||||
};
|
||||
use crate::{error::Error, PubkyClient};
|
||||
|
||||
mod http;
|
||||
mod keys;
|
||||
@@ -62,7 +58,7 @@ impl PubkyClient {
|
||||
) -> Result<Uint8Array, JsValue> {
|
||||
create_recovery_file(keypair.as_inner(), passphrase)
|
||||
.map(|b| b.as_slice().into())
|
||||
.map_err(|e| e.into())
|
||||
.map_err(|e| Error::from(e).into())
|
||||
}
|
||||
|
||||
/// Create a recovery file of the `keypair`, containing the secret key encrypted
|
||||
@@ -74,7 +70,7 @@ impl PubkyClient {
|
||||
) -> Result<Keypair, JsValue> {
|
||||
decrypt_recovery_file(recovery_file, passphrase)
|
||||
.map(Keypair::from)
|
||||
.map_err(|e| e.into())
|
||||
.map_err(|e| Error::from(e).into())
|
||||
}
|
||||
|
||||
/// Set Pkarr relays used for publishing and resolving Pkarr packets.
|
||||
|
||||
@@ -3,8 +3,6 @@ use crate::PubkyClient;
|
||||
use reqwest::{Method, RequestBuilder, Response};
|
||||
use url::Url;
|
||||
|
||||
use ::pkarr::PublicKey;
|
||||
|
||||
impl PubkyClient {
|
||||
pub(crate) fn request(&self, method: Method, url: Url) -> RequestBuilder {
|
||||
let mut request = self.http.request(method, url).fetch_credentials_include();
|
||||
|
||||
@@ -21,7 +21,7 @@ impl Keypair {
|
||||
}
|
||||
|
||||
let len = secret_key.byte_length();
|
||||
if (len != 32) {
|
||||
if len != 32 {
|
||||
return Err(format!("Expected secret_key to be 32 bytes, got {len}"))?;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user