Add tests for generate_current and check_current

Also updated docs to reflect those changes

Signed-off-by: constantoine <cleo.rebert@gmail.com>
This commit is contained in:
constantoine 2022-05-06 12:41:30 +02:00
parent 2c75d046ec
commit 6c19202404
No known key found for this signature in database
GPG Key ID: 0FA097951CF65367
4 changed files with 31 additions and 29 deletions

2
.gitignore vendored
View File

@ -1,2 +1,4 @@
/target /target
Cargo.lock Cargo.lock
.vscode/settings.json
cobertura.xml

View File

@ -1,6 +1,6 @@
[package] [package]
name = "totp-rs" name = "totp-rs"
version = "1.2.1" version = "1.3.0"
authors = ["Cleo Rebert <cleo.rebert@gmail.com>"] authors = ["Cleo Rebert <cleo.rebert@gmail.com>"]
edition = "2021" edition = "2021"
readme = "README.md" readme = "README.md"

View File

@ -17,7 +17,7 @@ With optional feature "serde_support", library-defined types will be Deserialize
Add it to your `Cargo.toml`: Add it to your `Cargo.toml`:
```toml ```toml
[dependencies] [dependencies]
totp-rs = "~1.2" totp-rs = "~1.3"
``` ```
You can then do something like: You can then do something like:
```Rust ```Rust
@ -31,12 +31,9 @@ let totp = TOTP::new(
30, 30,
"supersecret", "supersecret",
); );
let time = SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH).unwrap()
.as_secs();
let url = totp.get_url("user@example.com", "my-org.com"); let url = totp.get_url("user@example.com", "my-org.com");
println!("{}", url); println!("{}", url);
let token = totp.generate(time); let token = totp.generate_current().unwrap();
println!("{}", token); println!("{}", token);
``` ```
@ -45,7 +42,7 @@ println!("{}", token);
Add it to your `Cargo.toml`: Add it to your `Cargo.toml`:
```toml ```toml
[dependencies.totp-rs] [dependencies.totp-rs]
version = "~1.2" version = "~1.3"
features = ["qr"] features = ["qr"]
``` ```
You can then do something like: You can then do something like:
@ -67,6 +64,6 @@ println!("{}", code);
Add it to your `Cargo.toml`: Add it to your `Cargo.toml`:
```toml ```toml
[dependencies.totp-rs] [dependencies.totp-rs]
version = "~1.2" version = "~1.3"
features = ["serde_support"] features = ["serde_support"]
``` ```

View File

@ -19,12 +19,9 @@
//! 30, //! 30,
//! "supersecret", //! "supersecret",
//! ); //! );
//! let time = SystemTime::now()
//! .duration_since(SystemTime::UNIX_EPOCH).unwrap()
//! .as_secs();
//! let url = totp.get_url("user@example.com", "my-org.com"); //! let url = totp.get_url("user@example.com", "my-org.com");
//! println!("{}", url); //! println!("{}", url);
//! let token = totp.generate(time); //! let token = totp.generate_current().unwrap();
//! println!("{}", token); //! println!("{}", token);
//! ``` //! ```
//! //!
@ -165,7 +162,7 @@ impl<T: AsRef<[u8]>> TOTP<T> {
) )
} }
/// Will generate a token according to the provided timestamp in seconds /// Will generate a token given the provided timestamp in seconds
pub fn generate(&self, time: u64) -> String { pub fn generate(&self, time: u64) -> String {
let result: &[u8] = &self.sign(time); let result: &[u8] = &self.sign(time);
let offset = (result.last().unwrap() & 15) as usize; let offset = (result.last().unwrap() & 15) as usize;
@ -183,7 +180,7 @@ impl<T: AsRef<[u8]>> TOTP<T> {
Ok(self.generate(t)) Ok(self.generate(t))
} }
/// Will check if token is valid by current time, accounting [skew](struct.TOTP.html#structfield.skew) /// Will check if token is valid given the provided timestamp in seconds, accounting [skew](struct.TOTP.html#structfield.skew)
pub fn check(&self, token: &str, time: u64) -> bool { pub fn check(&self, token: &str, time: u64) -> bool {
let basestep = time / self.step - (self.skew as u64); let basestep = time / self.step - (self.skew as u64);
for i in 0..self.skew * 2 + 1 { for i in 0..self.skew * 2 + 1 {
@ -223,6 +220,8 @@ impl<T: AsRef<[u8]>> TOTP<T> {
} }
/// Will return a qrcode to automatically add a TOTP as a base64 string. Needs feature `qr` to be enabled! /// Will return a qrcode to automatically add a TOTP as a base64 string. Needs feature `qr` to be enabled!
/// Result will be in the form of a string containing a base64-encoded png, which you can embed in HTML without needing
/// To store the png as a file.
/// ///
/// # Errors /// # Errors
/// ///
@ -248,20 +247,8 @@ impl<T: AsRef<[u8]>> TOTP<T> {
// Draw the border // Draw the border
for x in 0..image_size { for x in 0..image_size {
for y in 0..image_size { for y in 0..image_size {
if y < 8*4 || y >= image_size - 8*4 { if (y < 8*4 || y >= image_size - 8*4) || (x < 8*4 || x >= image_size - 8*4) {
canvas.put_pixel( canvas.put_pixel(x, y, Luma([255]));
x,
y,
Luma([255]),
);
continue;
}
if x < 8*4 || x >= image_size - 8*4 {
canvas.put_pixel(
x,
y,
Luma([255]),
);
} }
} }
} }
@ -378,11 +365,20 @@ mod tests {
} }
#[test] #[test]
fn generates_token() { fn generate_token() {
let totp = TOTP::new(Algorithm::SHA1, 6, 1, 1, "TestSecret"); let totp = TOTP::new(Algorithm::SHA1, 6, 1, 1, "TestSecret");
assert_eq!(totp.generate(1000).as_str(), "718996"); assert_eq!(totp.generate(1000).as_str(), "718996");
} }
#[test]
fn generate_token_current() {
let totp = TOTP::new(Algorithm::SHA1, 6, 1, 1, "TestSecret");
let time = SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH).unwrap()
.as_secs();
assert_eq!(totp.generate(time).as_str(), totp.generate_current().unwrap());
}
#[test] #[test]
fn generates_token_sha256() { fn generates_token_sha256() {
let totp = TOTP::new(Algorithm::SHA256, 6, 1, 1, "TestSecret"); let totp = TOTP::new(Algorithm::SHA256, 6, 1, 1, "TestSecret");
@ -404,6 +400,13 @@ mod tests {
assert!(!totp.check("714250", 2000)); assert!(!totp.check("714250", 2000));
} }
#[test]
fn checks_token_current() {
let totp = TOTP::new(Algorithm::SHA1, 6, 0, 1, "TestSecret");
assert!(totp.check_current(&totp.generate_current().unwrap()).unwrap());
assert!(!totp.check_current("bogus").unwrap());
}
#[test] #[test]
fn checks_token_with_skew() { fn checks_token_with_skew() {
let totp = TOTP::new(Algorithm::SHA1, 6, 1, 1, "TestSecret"); let totp = TOTP::new(Algorithm::SHA1, 6, 1, 1, "TestSecret");