Table of Contents

Totp Class

Definition

Namespace
Bodu.Security.Cryptography
Assembly
Bodu.Security.Cryptography.dll
Package
Bodu.Security.Cryptography 1.2.0
Source
Totp.GenerateCode.cs

Provides the Time-based One-Time Password (TOTP) algorithm defined in RFC 6238, generating and verifying the time-derived codes used for two-factor authentication. This class cannot be instantiated.

public static class Totp
Inheritance
Totp
Inherited Members

Examples

byte[] secret = Base32.Decode("JBSWY3DPEHPK3PXP");  // from an otpauth:// URI

string code = Totp.GenerateCode(secret, DateTimeOffset.UtcNow);
bool ok = Totp.VerifyCode(secret, userInput, DateTimeOffset.UtcNow);   // ±1 step by default

Remarks

TOTP is Hotp with a counter derived from the current time: the counter is the number of whole time steps of periodSeconds that have elapsed since an epoch (the Unix epoch by default), and the code is then computed exactly as for HOTP. Because a code changes each step, verification accepts a small window of adjacent steps to tolerate clock drift and transmission delay.

As with Hotp, the shared secret is supplied as raw key bytes; decode a Base32 otpauth:// secret to bytes before calling these methods. The default 30-second period and 6-digit, SHA-1 configuration match the de facto authenticator-application defaults.

Like the rest of the library, this implementation offers best-effort side-channel resistance and has not been independently audited.

Methods

GenerateCode(ReadOnlySpan<byte>, DateTimeOffset, DateTimeOffset, int, int, OtpHashAlgorithm)

Generates the RFC 6238 TOTP code for the specified secret and timestamp, counting time steps from an explicit epoch.

public static string GenerateCode(ReadOnlySpan<byte> secret, DateTimeOffset timestamp, DateTimeOffset epoch, int digits, int periodSeconds, OtpHashAlgorithm algorithm)

Parameters

secret ReadOnlySpan<byte>

The shared secret key, as raw bytes.

timestamp DateTimeOffset

The instant for which to generate the code.

epoch DateTimeOffset

The epoch from which time steps are counted (RFC 6238 T0).

digits int

The number of decimal digits in the returned code.

periodSeconds int

The time-step length, in seconds.

algorithm OtpHashAlgorithm

The HMAC hash algorithm to use.

Returns

string

The zero-padded decimal code, exactly digits characters long.

Exceptions

ArgumentOutOfRangeException

digits is less than 6 or greater than 8, periodSeconds is less than 1, algorithm is not a defined OtpHashAlgorithm value, or timestamp is earlier than epoch.

GenerateCode(ReadOnlySpan<byte>, DateTimeOffset, int, int, OtpHashAlgorithm)

Generates the RFC 6238 TOTP code for the specified secret and timestamp, counting time steps from the Unix epoch.

public static string GenerateCode(ReadOnlySpan<byte> secret, DateTimeOffset timestamp, int digits = 6, int periodSeconds = 30, OtpHashAlgorithm algorithm = OtpHashAlgorithm.Sha1)

Parameters

secret ReadOnlySpan<byte>

The shared secret key, as raw bytes.

timestamp DateTimeOffset

The instant for which to generate the code.

digits int

The number of decimal digits in the returned code.

periodSeconds int

The time-step length, in seconds.

algorithm OtpHashAlgorithm

The HMAC hash algorithm to use.

Returns

string

The zero-padded decimal code, exactly digits characters long.

Exceptions

ArgumentOutOfRangeException

digits is less than 6 or greater than 8, periodSeconds is less than 1, algorithm is not a defined OtpHashAlgorithm value, or timestamp is earlier than the Unix epoch.

VerifyCode(ReadOnlySpan<byte>, ReadOnlySpan<char>, DateTimeOffset, int, int, int, OtpHashAlgorithm)

Verifies a candidate code against the RFC 6238 TOTP codes within a window of time steps around the specified timestamp, counting time steps from the Unix epoch.

public static bool VerifyCode(ReadOnlySpan<byte> secret, ReadOnlySpan<char> code, DateTimeOffset timestamp, int window = 1, int digits = 6, int periodSeconds = 30, OtpHashAlgorithm algorithm = OtpHashAlgorithm.Sha1)

Parameters

secret ReadOnlySpan<byte>

The shared secret key, as raw bytes.

code ReadOnlySpan<char>

The candidate code supplied by the user.

timestamp DateTimeOffset

The instant at which the code is being verified.

window int

The number of time steps on each side of the current step to also accept, tolerating clock drift.

digits int

The expected number of decimal digits.

periodSeconds int

The time-step length, in seconds.

algorithm OtpHashAlgorithm

The HMAC hash algorithm to use.

Returns

bool

true if code matches any accepted time step; otherwise, false.

Exceptions

ArgumentOutOfRangeException

digits is less than 6 or greater than 8, window is negative, periodSeconds is less than 1, algorithm is not a defined OtpHashAlgorithm value, or timestamp is earlier than the Unix epoch.

VerifyCode(ReadOnlySpan<byte>, ReadOnlySpan<char>, DateTimeOffset, int, out int, int, int, OtpHashAlgorithm)

Verifies a candidate code against the RFC 6238 TOTP codes within a window of time steps and reports which step matched, counting time steps from the Unix epoch.

public static bool VerifyCode(ReadOnlySpan<byte> secret, ReadOnlySpan<char> code, DateTimeOffset timestamp, int window, out int matchedStepOffset, int digits = 6, int periodSeconds = 30, OtpHashAlgorithm algorithm = OtpHashAlgorithm.Sha1)

Parameters

secret ReadOnlySpan<byte>

The shared secret key, as raw bytes.

code ReadOnlySpan<char>

The candidate code supplied by the user.

timestamp DateTimeOffset

The instant at which the code is being verified.

window int

The number of time steps on each side of the current step to also accept.

matchedStepOffset int

When this method returns true, the signed step offset that matched (0 is the current step, negative is earlier, positive is later); otherwise, 0. Useful for detecting persistent client clock drift.

digits int

The expected number of decimal digits.

periodSeconds int

The time-step length, in seconds.

algorithm OtpHashAlgorithm

The HMAC hash algorithm to use.

Returns

bool

true if code matches any accepted time step; otherwise, false.

Remarks

Every step in the window is scanned; matching does not short-circuit. A wider window tolerates more drift but admits more valid codes at once, so keep it small (the default accepts the current step and one on each side).

Exceptions

ArgumentOutOfRangeException

digits is less than 6 or greater than 8, window is negative, periodSeconds is less than 1, algorithm is not a defined OtpHashAlgorithm value, or timestamp is earlier than the Unix epoch.

Applies to

ProductVersions
.NET8, 10