Compare commits
5 Commits
1a56ee42de
...
0.0.1
Author | SHA1 | Date | |
---|---|---|---|
3794c4d175 | |||
ac9f033656 | |||
5350b380e2 | |||
84d1a3cc9b | |||
96656afdae |
8
Cargo.lock
generated
8
Cargo.lock
generated
@ -20,10 +20,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.13.0"
|
||||
name = "base32"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
|
||||
checksum = "23ce669cd6c8588f79e15cf450314f9638f967fc5770ff1c7c1deb0925ea7cfa"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
@ -260,7 +260,7 @@ checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb"
|
||||
name = "totp_generator"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"base32",
|
||||
"clap",
|
||||
"totp_rfc6238",
|
||||
]
|
||||
|
@ -7,5 +7,5 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
totp_rfc6238 = "0.5.0"
|
||||
base64 = "0.13.0"
|
||||
clap = { version = "3.1.6", features = ["derive"] }
|
||||
base32 = "0.4.0"
|
||||
clap = { version = "3.1.6", features = ["derive"] }
|
||||
|
79
src/main.rs
79
src/main.rs
@ -1,34 +1,77 @@
|
||||
use clap::Parser;
|
||||
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 {
|
||||
/// The secret to use
|
||||
#[clap(short, long)]
|
||||
secret: String,
|
||||
#[clap(subcommand)]
|
||||
command: SubCommands
|
||||
}
|
||||
|
||||
/// Interval between two numbers generation
|
||||
#[clap(short, long, default_value_t = 30)]
|
||||
topt_step: u64,
|
||||
#[derive(Subcommand, Debug)]
|
||||
enum SubCommands {
|
||||
/// Setup configuration
|
||||
Setup,
|
||||
|
||||
/// Size of generated secret
|
||||
#[clap(short, long, default_value_t = 6)]
|
||||
len: usize,
|
||||
/// 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();
|
||||
|
||||
let totp_generator = TotpGenerator::new()
|
||||
.set_digit(args.len).unwrap()
|
||||
.set_step(args.topt_step).unwrap()
|
||||
.set_hash_algorithm(HashAlgorithm::SHA1)
|
||||
.build();
|
||||
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");
|
||||
}
|
||||
|
||||
let key = base64::decode(args.secret).unwrap();
|
||||
let code = totp_generator.get_code(&key);
|
||||
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();
|
||||
|
||||
println!("Secret len = {}", code);
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user