commit d1e04d7c6e63e621d02dd69a55143fe7912c8236 Author: Cleo Rebert Date: Sat Apr 11 21:24:50 2020 +0200 First commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..96ef6c0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/target +Cargo.lock diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..a43c562 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "totp" +version = "0.1.0" +authors = ["Cleo Rebert "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +otpauth = "0.4.1" +qrcode = "0.12.0" +image = "0.23.3" +base64 = "0.12.0" diff --git a/README.md b/README.md new file mode 100644 index 0000000..a488b7a --- /dev/null +++ b/README.md @@ -0,0 +1,11 @@ +# totp-rs + +This library is a cheap wrapper around otpauth, qrcode and image to seamlessly manage Time-based One-Time Password authentification + +## How to use + +Add this to your Cargo.toml +```toml +[dependencies.totp] +git = "https://github.com/constantoine/totp-ts" +``` diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..932ccf3 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,31 @@ +//! This library is a cheap wrapper around otpauth, qrcode and image to seamlessly manage +//! Time-based One-Time Password authentification + +use std::time::{SystemTime, UNIX_EPOCH}; +use otpauth::TOTP; + +use qrcode::QrCode; +use image::Luma; +use base64; + +/// Will check if provided code is valid with provided secret, with a tolerance of 15 seconds offest +pub fn verify(code: u32, secret: String) -> bool { + let auth = TOTP::new(secret); + let now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs(); + for i in 0..2 { + if auth.verify(code, 30, now - 15 + i * 15) { + return true; + } + } + false +} + +/// Will return a qrcode to automatically add a TOTP as a base64 string +pub fn get_qr(secret: String, mail: String) -> String { + let auth = TOTP::new(secret); + let code = QrCode::new(auth.to_uri(format!("account:{}@42l.fr", mail), "42l.fr".to_string())).unwrap(); + let mut vec = Vec::new(); + let encoder = image::png::PNGEncoder::new(&mut vec); + encoder.encode(&code.render::>().build().to_vec(), 360, 360, image::ColorType::L8).unwrap(); + base64::encode(vec) +}