TotpGenerator

Struct TotpGenerator 

Source
pub struct TotpGenerator;
Expand description

TOTP Generator for Two-Factor Authentication

Provides cryptographic functions for TOTP secret generation, QR code creation, code verification, backup code management, and AES-256-GCM encryption.

§Security Features

  • TOTP Secret: 32-byte random Base32-encoded secret (RFC 4648)
  • QR Code: otpauth:// URI format for authenticator apps
  • Backup Codes: 10 secure random 8-character alphanumeric codes
  • Encryption: AES-256-GCM authenticated encryption for secrets
  • Hashing: bcrypt (cost factor 12) for backup codes
  • Time Window: ±30 seconds tolerance for clock skew (±1 step)

Implementations§

Source§

impl TotpGenerator

Source

pub fn generate_secret() -> String

Generate a random TOTP secret (Base32-encoded, 32 bytes)

Returns a 52-character Base32 string suitable for TOTP generation.

§Example
let secret = TotpGenerator::generate_secret();
assert_eq!(secret.len(), 52); // Base32 encoding of 32 bytes
Source

pub fn generate_qr_code( secret: &str, issuer: &str, account_name: &str, ) -> Result<String, String>

Generate QR code data URL for authenticator apps

Creates an otpauth://totp/ URI and encodes it as a PNG QR code data URL.

§Arguments
  • secret - Base32-encoded TOTP secret
  • issuer - Service name (e.g., “KoproGo”)
  • account_name - User identifier (e.g., email address)
§Returns

Base64-encoded PNG image data URL: data:image/png;base64,...

§Errors

Returns error if QR code generation or image encoding fails.

Source

pub fn verify_code(secret: &str, code: &str) -> Result<bool, String>

Verify TOTP code with ±1 time window tolerance

Validates a 6-digit TOTP code against the secret with 30-second time steps. Accepts codes from current step, previous step (t-30s), and next step (t+30s).

§Arguments
  • secret - Base32-encoded TOTP secret (unencrypted)
  • code - 6-digit TOTP code to verify
§Returns

Ok(true) if code is valid, Ok(false) if invalid format/value

§Example
let secret = TotpGenerator::generate_secret();
let code = TotpGenerator::generate_current_code(&secret)?;
assert!(TotpGenerator::verify_code(&secret, &code)?);
Source

pub fn generate_backup_codes() -> Vec<String>

Generate 10 secure random backup codes (8 characters each)

Each code is in format XXXX-XXXX with uppercase alphanumeric characters (excluding ambiguous chars: 0, O, 1, I, L).

§Returns

Vector of 10 unique backup codes

§Example
let codes = TotpGenerator::generate_backup_codes();
assert_eq!(codes.len(), 10);
assert!(codes[0].len() == 9); // "XXXX-XXXX"
Source

pub fn hash_backup_code(code: &str) -> Result<String, String>

Hash backup code using bcrypt (cost factor 12)

§Arguments
  • code - Plain text backup code (e.g., “ABCD-EFGH”)
§Returns

Bcrypt hash string (60 characters)

§Errors

Returns error if bcrypt hashing fails

Source

pub fn verify_backup_code(code: &str, hash: &str) -> Result<bool, String>

Verify backup code against bcrypt hash

§Arguments
  • code - Plain text backup code
  • hash - Bcrypt hash to verify against
§Returns

Ok(true) if code matches hash, Ok(false) otherwise

Source

pub fn encrypt_secret(secret: &str, key: &[u8; 32]) -> Result<String, String>

Encrypt TOTP secret using AES-256-GCM

§Arguments
  • secret - Plain text Base32 secret
  • key - 32-byte AES-256 key (from environment variable)
§Returns

Base64-encoded ciphertext with prepended nonce (12 bytes + ciphertext)

§Security
  • Uses AES-256-GCM for authenticated encryption
  • Random 96-bit nonce per encryption
  • Authenticated with GMAC tag
§Errors

Returns error if encryption fails or key is invalid

Source

pub fn decrypt_secret(encrypted: &str, key: &[u8; 32]) -> Result<String, String>

Decrypt TOTP secret using AES-256-GCM

§Arguments
  • encrypted - Base64-encoded ciphertext with prepended nonce
  • key - 32-byte AES-256 key (same as used for encryption)
§Returns

Plain text Base32 secret

§Errors

Returns error if decryption fails, key is invalid, or ciphertext is corrupted

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<T> Chain<T> for T

§

fn len(&self) -> usize

The number of items that this chain link consists of.
§

fn append_to(self, v: &mut Vec<T>)

Append the elements in this link to the chain.
§

impl<T> Fake for T

§

fn fake<U>(&self) -> U
where Self: FakeBase<U>,

§

fn fake_with_rng<U, R>(&self, rng: &mut R) -> U
where R: Rng + ?Sized, Self: FakeBase<U>,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
§

impl<Unshared, Shared> IntoShared<Shared> for Unshared
where Shared: FromUnshared<Unshared>,

§

fn into_shared(self) -> Shared

Creates a shared type from an unshared type.
§

impl<T> Pointable for T

§

const ALIGN: usize

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
§

impl<T> PolicyExt for T
where T: ?Sized,

§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] only if self and other return Action::Follow. Read more
§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

impl<T> ErasedDestructor for T
where T: 'static,