From 3f39b3a1bab7711505909635da7007e3fd12e7fa Mon Sep 17 00:00:00 2001 From: constantoine Date: Wed, 5 Oct 2022 17:32:31 +0200 Subject: [PATCH 1/6] Add coverage for rfc.rs Signed-off-by: constantoine --- src/rfc.rs | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/rfc.rs b/src/rfc.rs index 94dda8b..38a0ede 100644 --- a/src/rfc.rs +++ b/src/rfc.rs @@ -313,6 +313,21 @@ mod tests { assert!(totp.is_ok()); } + #[test] + #[cfg(feature = "otpauth")] + fn rfc_with_default_set_values() { + let mut rfc = Rfc6238::with_defaults(GOOD_SECRET.to_string()).unwrap(); + let ok = rfc.digits(8); + assert!(ok.is_ok()); + assert_eq!(rfc.account_name, ""); + assert_eq!(rfc.issuer, Some("".to_string())); + rfc.issuer("Github".to_string()); + rfc.account_name("constantoine".to_string()); + assert_eq!(rfc.account_name, "constantoine"); + assert_eq!(rfc.issuer, Some("Github".to_string())); + assert_eq!(rfc.digits, 8) + } + #[test] #[cfg(not(feature = "otpauth"))] fn rfc_with_default_set_values() { @@ -325,4 +340,24 @@ mod tests { assert!(ok.is_ok()); assert_eq!(rfc.digits, 8) } + + #[test] + #[cfg(not(feature = "otpauth"))] + fn digits_error() { + let error = crate::Rfc6238Error::InvalidDigits(9); + assert_eq!( + error.to_string(), + "Implementations MUST extract a 6-digit code at a minimum and possibly 7 and 8-digit code. 9 digits is not allowed".to_string() + ) + } + + #[test] + #[cfg(not(feature = "otpauth"))] + fn secret_length_error() { + let error = Rfc6238Error::SecretTooSmall(120); + assert_eq!( + error.to_string(), + "The length of the shared secret MUST be at least 128 bits. 120 bits is not enough".to_string() + ) + } } From b308f7455db38a6c39d2ac1c18c494bae0772879 Mon Sep 17 00:00:00 2001 From: constantoine Date: Mon, 10 Oct 2022 10:22:52 +0200 Subject: [PATCH 2/6] Add tests for secret.rs Signed-off-by: constantoine --- src/secret.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/secret.rs b/src/secret.rs index 115566e..9ca6c2f 100644 --- a/src/secret.rs +++ b/src/secret.rs @@ -242,4 +242,28 @@ mod tests { Secret::Encoded(_) => panic!("should be raw"), } } + + #[test] + #[cfg(feature = "gen_secret")] + fn secret_gen_default() { + match Secret::default() { + Secret::Raw(secret) => assert_eq!(secret.len(), 20), + Secret::Encoded(_) => panic!("should be raw"), + } + } + + #[test] + #[cfg(feature = "gen_secret")] + fn secret_empty() { + let non_ascii = vec![240, 159, 146, 150]; + let sec = Secret::Encoded(std::str::from_utf8(&non_ascii).unwrap().to_owned()); + + let to_r = sec.to_raw(); + + assert!(to_r.is_err()); + + let to_b = sec.to_bytes(); + + assert!(to_b.is_err()); + } } From 9a202c20ec12f24ea7779ab611e3789dd5aa0e37 Mon Sep 17 00:00:00 2001 From: constantoine Date: Mon, 10 Oct 2022 10:34:52 +0200 Subject: [PATCH 3/6] Fix coverage for secret.rs Signed-off-by: constantoine --- src/secret.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/secret.rs b/src/secret.rs index 9ca6c2f..6edde97 100644 --- a/src/secret.rs +++ b/src/secret.rs @@ -237,19 +237,19 @@ mod tests { #[test] #[cfg(feature = "gen_secret")] fn secret_gen_secret() { - match Secret::generate_secret() { - Secret::Raw(secret) => assert_eq!(secret.len(), 20), - Secret::Encoded(_) => panic!("should be raw"), - } + let sec = Secret::generate_secret(); + + assert!(matches!(sec, Secret::Raw(_))); + assert_eq!(sec.to_bytes().unwrap().len(), 20); } #[test] #[cfg(feature = "gen_secret")] fn secret_gen_default() { - match Secret::default() { - Secret::Raw(secret) => assert_eq!(secret.len(), 20), - Secret::Encoded(_) => panic!("should be raw"), - } + let sec = Secret::default(); + + assert!(matches!(sec, Secret::Raw(_))); + assert_eq!(sec.to_bytes().unwrap().len(), 20); } #[test] From 60514fde9ae3fc18c1aec9036ec92b2c87abc25c Mon Sep 17 00:00:00 2001 From: constantoine Date: Mon, 10 Oct 2022 11:08:40 +0200 Subject: [PATCH 4/6] Add tests Signed-off-by: constantoine --- src/lib.rs | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 74b5c40..9e4316b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -750,6 +750,31 @@ mod tests { assert_eq!(url.as_str(), "otpauth://totp/Github:constantoine%40github.com?issuer=Github&secret=KRSXG5CTMVRXEZLUKN2XAZLSKNSWG4TFOQ&digits=6&algorithm=SHA512"); } + #[test] + #[cfg(all(feature = "otpauth", feature = "gen_secret"))] + fn ttl() { + let secret = Secret::default(); + let totp_rfc = Rfc6238::with_defaults(secret.to_bytes().unwrap()).unwrap(); + let totp = TOTP::from_rfc6238(totp_rfc); + assert!(totp.is_ok()); + } + + #[test] + #[cfg(feature = "otpauth")] + fn ttl_ok() { + let totp = TOTP::new( + Algorithm::SHA512, + 6, + 1, + 1, + "TestSecretSuperSecret", + Some("Github".to_string()), + "constantoine@github.com".to_string(), + ) + .unwrap(); + assert!(totp.ttl().is_ok()); + } + #[test] #[cfg(not(feature = "otpauth"))] fn returns_base32() { @@ -889,6 +914,24 @@ mod tests { assert_eq!(totp.step, 60); } + #[test] + #[cfg(feature = "otpauth")] + fn from_url_query_sha512() { + let totp = TOTP::>::from_url("otpauth://totp/GitHub:test?secret=KRSXG5CTMVRXEZLUKN2XAZLSKNSWG4TFOQ&digits=8&period=60&algorithm=SHA512").unwrap(); + assert_eq!( + totp.secret, + base32::decode( + base32::Alphabet::RFC4648 { padding: false }, + "KRSXG5CTMVRXEZLUKN2XAZLSKNSWG4TFOQ" + ) + .unwrap() + ); + assert_eq!(totp.algorithm, Algorithm::SHA512); + assert_eq!(totp.digits, 8); + assert_eq!(totp.skew, 1); + assert_eq!(totp.step, 60); + } + #[test] #[cfg(feature = "otpauth")] fn from_url_to_url() { @@ -906,6 +949,24 @@ mod tests { assert_eq!(totp.get_url(), totp_bis.get_url()); } + #[test] + #[cfg(feature = "otpauth")] + fn from_url_unknown_param() { + let totp = TOTP::>::from_url("otpauth://totp/GitHub:test?secret=KRSXG5CTMVRXEZLUKN2XAZLSKNSWG4TFOQ&digits=8&period=60&algorithm=SHA256&foo=bar").unwrap(); + assert_eq!( + totp.secret, + base32::decode( + base32::Alphabet::RFC4648 { padding: false }, + "KRSXG5CTMVRXEZLUKN2XAZLSKNSWG4TFOQ" + ) + .unwrap() + ); + assert_eq!(totp.algorithm, Algorithm::SHA256); + assert_eq!(totp.digits, 8); + assert_eq!(totp.skew, 1); + assert_eq!(totp.step, 60); + } + #[test] #[cfg(feature = "otpauth")] fn from_url_issuer_special() { @@ -943,6 +1004,24 @@ mod tests { assert_eq!(totp.issuer.unwrap(), "GitHub"); } + #[test] + #[cfg(feature = "otpauth")] + fn from_url_wrong_scheme() { + let totp = TOTP::>::from_url("http://totp/GitHub:test?issuer=GitHub&secret=KRSXG5CTMVRXEZLUKN2XAZLSKNSWG4TFOQ&digits=8&period=60&algorithm=SHA256"); + assert!(totp.is_err()); + let err = totp.unwrap_err(); + assert!(matches!(err, TotpUrlError::Scheme(_))); + } + + #[test] + #[cfg(feature = "otpauth")] + fn from_url_wrong_algo() { + let totp = TOTP::>::from_url("otpauth://totp/GitHub:test?issuer=GitHub&secret=KRSXG5CTMVRXEZLUKN2XAZLSKNSWG4TFOQ&digits=8&period=60&algorithm=MD5"); + assert!(totp.is_err()); + let err = totp.unwrap_err(); + assert!(matches!(err, TotpUrlError::Algorithm(_))); + } + #[test] #[cfg(feature = "otpauth")] fn from_url_query_different_issuers() { @@ -981,4 +1060,23 @@ mod tests { "025809c9db9c2c918930e018549c90929a083ee757156737812bad40ded64312c1526c73d8f2f59d5c203b97141ddfc331b1192e234f4f43257f50a6d05e382f" ); } + + #[test] + #[cfg(feature = "qr")] + fn generates_qr_ok() { + use sha2::{Digest, Sha512}; + + let totp = TOTP::new( + Algorithm::SHA1, + 6, + 1, + 1, + "TestSecretSuperSecret", + Some("Github".to_string()), + "constantoine@github.com".to_string(), + ) + .unwrap(); + let qr = totp.get_qr(); + assert!(qr.is_ok()); + } } From 0131d7e07778773eeca0ff37f3bee74c6fb55ed9 Mon Sep 17 00:00:00 2001 From: constantoine Date: Mon, 10 Oct 2022 11:12:44 +0200 Subject: [PATCH 5/6] Cargo fmt Signed-off-by: constantoine --- Cargo.toml | 2 +- src/rfc.rs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ec56a91..6a25c01 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,7 +15,7 @@ categories = ["authentication", "web-programming"] features = [ "qr", "serde_support", "otpauth" ] [features] -default = [] +default = ["qr", "gen_secret"] otpauth = ["url", "urlencoding"] qr = ["qrcodegen", "image", "base64", "otpauth"] serde_support = ["serde"] diff --git a/src/rfc.rs b/src/rfc.rs index 38a0ede..34204a7 100644 --- a/src/rfc.rs +++ b/src/rfc.rs @@ -357,7 +357,8 @@ mod tests { let error = Rfc6238Error::SecretTooSmall(120); assert_eq!( error.to_string(), - "The length of the shared secret MUST be at least 128 bits. 120 bits is not enough".to_string() + "The length of the shared secret MUST be at least 128 bits. 120 bits is not enough" + .to_string() ) } } From 0f917c4aac56f4d58a32db0b1c861a8c2c5a8079 Mon Sep 17 00:00:00 2001 From: constantoine Date: Mon, 10 Oct 2022 11:15:57 +0200 Subject: [PATCH 6/6] Fix warning Signed-off-by: constantoine --- src/lib.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 9e4316b..329002d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1064,8 +1064,6 @@ mod tests { #[test] #[cfg(feature = "qr")] fn generates_qr_ok() { - use sha2::{Digest, Sha512}; - let totp = TOTP::new( Algorithm::SHA1, 6,