All checks were successful
continuous-integration/drone/push Build is passing
This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [base32](https://github.com/andreasots/base32) | dependencies | minor | `0.4.0` -> `0.5.0` | --- ### Release Notes <details> <summary>andreasots/base32 (base32)</summary> ### [`v0.5.0`](https://github.com/andreasots/base32/compare/v0.4.0...v0.5.0) [Compare Source](https://github.com/andreasots/base32/compare/v0.4.0...v0.5.0) </details> --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4zNjguMCIsInVwZGF0ZWRJblZlciI6IjM3LjM2OC4wIiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIiwibGFiZWxzIjpbXX0=--> Reviewed-on: #24
101 lines
2.7 KiB
Rust
101 lines
2.7 KiB
Rust
use std::time::{SystemTime, UNIX_EPOCH};
|
|
|
|
use base32::Alphabet;
|
|
use clap::{Parser, Subcommand};
|
|
use totp_rfc6238::{HashAlgorithm, TotpGenerator};
|
|
|
|
/// Get the current time since epoch
|
|
pub fn time() -> u64 {
|
|
SystemTime::now()
|
|
.duration_since(UNIX_EPOCH)
|
|
.unwrap()
|
|
.as_secs()
|
|
}
|
|
|
|
/// TOTP - One Time Password generator
|
|
#[derive(Parser, Debug)]
|
|
#[clap(author, version, about, long_about = None)]
|
|
struct Args {
|
|
#[clap(subcommand)]
|
|
command: SubCommands,
|
|
}
|
|
|
|
#[derive(Subcommand, Debug)]
|
|
enum SubCommands {
|
|
/// Setup configuration
|
|
Setup,
|
|
|
|
/// Get a TOTP code
|
|
#[clap(arg_required_else_help = true)]
|
|
Code {
|
|
/// The secret to use
|
|
#[clap(short, long)]
|
|
secret: String,
|
|
|
|
/// Interval between two numbers generation
|
|
#[clap(short, long, default_value_t = 30)]
|
|
topt_step: u64,
|
|
|
|
/// Size of generated secret
|
|
#[clap(short, long, default_value_t = 6)]
|
|
len: usize,
|
|
},
|
|
}
|
|
|
|
fn main() {
|
|
let args: Args = Args::parse();
|
|
|
|
match args.command {
|
|
SubCommands::Setup => {
|
|
println!("To configure TOPT :");
|
|
println!("1. Please open https://mysignins.microsoft.com/security-info");
|
|
println!("2. Click on \"Add method\"");
|
|
println!(
|
|
"3. On the popup that appears, choose \"Authenticator app\" and click \"Add\"."
|
|
);
|
|
println!(
|
|
"4. Click on \"I want to use a different authenticator app\" and click \"Next\""
|
|
);
|
|
println!("5. Click on \"Can't save image ?\" and copy the \"Secret key\"");
|
|
println!(
|
|
"6. Re-run this program running {} code --secret <SECRET>",
|
|
std::env::args().next().unwrap()
|
|
);
|
|
println!("7. Back on the browser, click Next and paste copied code");
|
|
}
|
|
|
|
SubCommands::Code {
|
|
secret,
|
|
topt_step,
|
|
len,
|
|
} => {
|
|
let totp_generator = TotpGenerator::new()
|
|
.set_digit(len)
|
|
.unwrap()
|
|
.set_step(topt_step)
|
|
.unwrap()
|
|
.set_hash_algorithm(HashAlgorithm::SHA1)
|
|
.build();
|
|
|
|
let key = base32::decode(Alphabet::Rfc4648 { padding: true }, &secret).unwrap();
|
|
|
|
let code = totp_generator.get_code(&key);
|
|
let next_update = totp_generator.get_next_update_time().unwrap();
|
|
|
|
println!("Secret = {}", code);
|
|
println!("Next update = {} seconds", next_update - time());
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod test {
|
|
use crate::Args;
|
|
|
|
#[test]
|
|
fn verify_cli() {
|
|
use clap::CommandFactory;
|
|
Args::command().debug_assert()
|
|
}
|
|
}
|