Skip to content

Commit

Permalink
Merge pull request #13 from jaysonsantos/add-dump-seed
Browse files Browse the repository at this point in the history
feat: Implement dump-seeds command
  • Loading branch information
jaysonsantos authored Dec 27, 2023
2 parents b437d20 + 59dd0df commit 225ecb7
Show file tree
Hide file tree
Showing 9 changed files with 61 additions and 15 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ enum Config {
#[structopt(short, long, help = "output type", default_value)]
output: Output,
},
DumpSeeds,
}

pub fn setup_error_handlers() -> Result<()> {
Expand Down Expand Up @@ -135,6 +136,22 @@ async fn work() -> Result<()> {
}
output.print(output_data)?;
}
Config::DumpSeeds => {
let client = get_saved_client()?;
let mut services: Vec<AuthenticatorToken> = match mambembe_keyring::get() {
Ok(services) => services,
Err(MambembeKeyringError::NoPasswordFound) => {
let services = client.list_authenticator_tokens().await?;
mambembe_keyring::set(&services).unwrap();
services
}
Err(err) => return Err(err.into()),
};
for service in services.iter_mut() {
client.initialize_authenticator_token(service)?;
println!("Servie: {} Seed: {}", service.name, &service.dump_seed()?);
}
}
}

// client.check_current_device().await?;
Expand Down
1 change: 1 addition & 0 deletions keyring/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ mambembe-lib = { path = "../lib" }
serde = "1.0.193"
serde_json = "1.0.108"
thiserror = "1.0.51"
tracing = "0.1.26"

[features]
with-keyring = ["keyring"]
Expand Down
5 changes: 5 additions & 0 deletions keyring/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use mambembe_lib::{models::AuthenticatorToken, AuthyClient};
use serde::{de::DeserializeOwned, Serialize};
use serde_json::{from_str, to_string_pretty};
use thiserror::Error;
use tracing::instrument;

#[cfg(feature = "without-keyring")]
use crate::local::{Keyring, KeyringError};
Expand Down Expand Up @@ -37,17 +38,20 @@ pub trait Data<T> {
}

impl<T> Data<T> for AuthyClient {
#[instrument]
fn get_keyring() -> &'static Keyring {
&DEVICES
}
}

impl<T> Data<T> for Vec<AuthenticatorToken> {
#[instrument]
fn get_keyring() -> &'static Keyring {
&TOKENS
}
}

#[instrument]
pub fn get<T>() -> Result<T>
where
T: DeserializeOwned + Data<T>,
Expand All @@ -60,6 +64,7 @@ where
Ok(from_str(&data)?)
}

#[instrument(skip(data))]
pub fn set<T>(data: &T) -> Result<()>
where
T: Serialize + Data<T>,
Expand Down
1 change: 1 addition & 0 deletions lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ aes = "0.8.3"
async-trait = "0.1.75"
cbc = { version = "0.1.2", features = ["block-padding", "alloc"] }
data-encoding = "2.5.0"
hex = "0.4.3"
hmac = "0.12.1"
itertools = "0.12.0"
json = "0.12.4"
Expand Down
16 changes: 8 additions & 8 deletions lib/src/client.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::fs;
use std::{fmt::Write, fs};

use async_trait::async_trait;
use rand::{thread_rng, Rng};
Expand Down Expand Up @@ -49,11 +49,11 @@ impl TimeSync {
TimeSync::Future {
last_time_checked: _,
time_offset,
} => (time + time_offset),
} => time + time_offset,
TimeSync::Past {
last_time_checked: _,
time_offset,
} => (time - time_offset),
} => time - time_offset,
}
}
}
Expand Down Expand Up @@ -108,10 +108,10 @@ impl AuthyClient {
pub fn with_url(url: &str, device_name: &str, backup_password: &str) -> Result<Self> {
let mut signature = [0u8; 32];
thread_rng().fill(&mut signature);
let signature = signature
.iter()
.map(|n| format!("{:x}", n))
.collect::<String>();
let signature = signature.iter().fold(String::new(), |mut output, n| {
let _ = write!(output, "{:x}", n);
output
});

Ok(Self {
url: url.parse()?,
Expand Down Expand Up @@ -236,7 +236,7 @@ impl AuthyClientApi for AuthyClient {
#[instrument]
async fn complete_registration(&mut self, pin: &str) -> Result<()> {
// I'm assuming this is used for idempotency so this should suffice
let uuid = format!("{:x}", md5::compute(&pin.as_bytes()));
let uuid = format!("{:x}", md5::compute(pin.as_bytes()));
let payload = AuthyCompleteRegistrationRequest {
api_key: API_KEY.to_string(),
locale: DEFAULT_LOCALE.to_string(),
Expand Down
18 changes: 14 additions & 4 deletions lib/src/models.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
use data_encoding::HEXLOWER;
use data_encoding::{BASE32, HEXLOWER};
use serde::{Deserialize, Serialize};
use sha2::Digest;

use crate::{
client::TimeSync, crypto::decrypt_data, error::Result, password::derive_key,
tokens::calculate_future_tokens, MambembeError,
client::TimeSync,
crypto::decrypt_data,
error::Result,
password::derive_key,
tokens::{calculate_future_tokens, decode_seed},
MambembeError,
};

pub type Pin = String;
Expand Down Expand Up @@ -36,7 +40,7 @@ pub enum CheckRegistrationStatus {

impl Device {
pub(crate) fn hash_secret(&self) -> String {
format!("{:x}", sha2::Sha256::digest(&self.secret_seed.as_bytes()))
format!("{:x}", sha2::Sha256::digest(self.secret_seed.as_bytes()))
}
}

Expand Down Expand Up @@ -89,6 +93,12 @@ impl AuthenticatorToken {

Ok(data.to_ascii_uppercase())
}

pub fn dump_seed(&self) -> Result<String> {
self.decrypt_seed()
.map(decode_seed)
.map(|seed| BASE32.encode(&seed)) // Re-encode again because most of the clients expect this
}
}

#[cfg(test)]
Expand Down
12 changes: 11 additions & 1 deletion lib/src/tokens.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,22 @@ pub(crate) fn calculate_token(
digits: usize,
time_sync: Option<&TimeSync>,
) -> InternalResult<String> {
let seed = BASE32_NOPAD.decode(seed)?;
let seed = decode_seed(seed);
// let seed = HEXLOWER.encode(&seed);
let time = get_time(time_sync);
let s = build_slauth_context(&seed, digits, time / OTHERS_DEFAULT_PERIOD);
Ok(s.gen())
}

pub(crate) fn decode_seed<T>(seed: T) -> Vec<u8>
where
T: AsRef<[u8]>,
{
BASE32_NOPAD
.decode(seed.as_ref())
.unwrap_or_else(|_| seed.as_ref().to_vec())
}

#[tracing::instrument]
pub(crate) fn build_slauth_context(seed: &[u8], digits: usize, padded_time: u64) -> HOTPContext {
HOTPBuilder::new()
Expand Down
4 changes: 2 additions & 2 deletions stub_server/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,15 @@ impl WiremockRunner {

check_process(
&compose()
.args(&["up", "-d"])
.args(["up", "-d"])
.output()
.await
.wrap_err("error to bring wiremock up")?,
)?;

let host = check_process(
&compose()
.args(&["port", "wiremock", "8080"])
.args(["port", "wiremock", "8080"])
.output()
.await
.wrap_err("failed to get wiremock port")?,
Expand Down

0 comments on commit 225ecb7

Please sign in to comment.