totp-lib

Security-hardened TOTP for Java

Maven Central Java 21+ RFC 6238 MIT License

Installation

Maven
Gradle (Kotlin)
Gradle (Groovy)
<dependency>
    <groupId>io.github.pratiyush</groupId>
    <artifactId>totp-lib</artifactId>
    <version>1.0.3</version>
</dependency>
implementation("io.github.pratiyush:totp-lib:1.0.3")
implementation 'io.github.pratiyush:totp-lib:1.0.3'

Quick Start

import io.github.pratiyush.totp.*;

// 1. Generate a secret for a new user
String secret = SecretGenerator.generate(Algorithm.SHA256);

// 2. Create TOTP instance
TOTP totp = TOTP.defaultInstance();

// 3. Generate a code
String code = totp.generate(secret);

// 4. Verify user input
boolean valid = totp.verify(secret, userCode);

Replay Attack Prevention

Prevent the same TOTP code from being used twice within its validity window.

import io.github.pratiyush.totp.TOTP;
import java.time.Duration;

// Create TOTP with replay protection (2-minute window)
TOTP totp = TOTP.builder()
    .withReplayProtection(Duration.ofMinutes(2))
    .build();

// Verify with user ID for per-user tracking
boolean valid = totp.verify(secret, code, userId);
// Same code + same userId = rejected on second attempt

QR Code for Authenticator Apps

Generate QR codes compatible with Google Authenticator, Microsoft Authenticator, Authy, and others.

import io.github.pratiyush.totp.QRCodeGenerator;
import java.nio.file.Path;

// Save QR code as PNG file
QRCodeGenerator.saveToFile(
    secret, "user@example.com", "MyApp",
    Path.of("qr.png"), 250
);

// Or get as Base64 for embedding in HTML
String base64 = QRCodeGenerator.generateBase64(
    secret, "user@example.com", "MyApp", 250);

// Or get a data URI ready for <img src="...">
String dataUri = QRCodeGenerator.generateDataUri(
    secret, "user@example.com", "MyApp", 250);

// Build otpauth:// URI manually
String uri = QRCodeGenerator.buildOtpauthUri(
    secret, "user@example.com", "MyApp",
    Algorithm.SHA256, 6, 30);

Custom Configuration

// Full custom config
TOTPConfig config = TOTPConfig.builder()
    .algorithm(Algorithm.SHA256)  // SHA1, SHA256, SHA512
    .digits(8)                    // 6-8 digits
    .periodSeconds(30)            // 15-120 seconds
    .allowedDrift(1)              // time window tolerance
    .build();

TOTP totp = TOTP.builder()
    .config(config)
    .build();

Preset Configurations

// Google Authenticator compatible (SHA-1, 6 digits, 30s)
TOTPConfig.defaultConfig();

// Recommended for new apps (SHA-256, 6 digits, 30s)
TOTPConfig.sha256Config();

// Maximum security (SHA-512, 8 digits, 30s)
TOTPConfig.highSecurityConfig();

Secure Memory Handling

Secrets are automatically cleared from memory when no longer needed.

// SecureBytes implements AutoCloseable
try (SecureBytes secret = SecureBytes.wrap(rawSecretBytes)) {
    boolean valid = engine.verify(secret.getBytes(), code);
} // secret bytes are zeroed out here automatically

// Never log or serialize secrets
// SecureBytes.toString() returns "[REDACTED]"

Spring Boot Integration Example

@Service
public class TwoFactorAuthService {

    private final TOTP totp = TOTP.builder()
        .algorithm(Algorithm.SHA256)
        .withReplayProtection(Duration.ofMinutes(2))
        .build();

    public String enrollUser(String userId) {
        String secret = SecretGenerator.generate(Algorithm.SHA256);
        // Store secret encrypted in database
        userRepository.saveTotpSecret(userId, encrypt(secret));
        return secret;
    }

    public boolean verifyCode(String userId, String code) {
        String secret = decrypt(userRepository.getTotpSecret(userId));
        return totp.verify(secret, code, userId);
    }

    public String getQrCodeDataUri(String userId, String email) {
        String secret = decrypt(userRepository.getTotpSecret(userId));
        return QRCodeGenerator.generateDataUri(
            secret, email, "MyApp", 250);
    }
}
🔒

Constant-Time Verification

All comparisons use constant-time algorithms to prevent timing attacks.

🛡

Replay Attack Prevention

Built-in ReplayGuard prevents the same code from being used twice.

📦

Zero Dependencies

Core TOTP requires no external libraries. QR and logging are optional.

RFC 6238 Compliant

Full compliance with TOTP (RFC 6238) and HOTP (RFC 4226) standards.

📱

QR Code Generation

Works with Google Authenticator, Microsoft Authenticator, Authy, and more.

💪

Secure Memory

SecureBytes wrapper automatically clears secrets from memory after use.

API Reference

TOTP

MethodDescription
generate(secret)Generate code for current time
generateAt(secret, instant)Generate code for specific time
verify(secret, code)Verify a code
verify(secret, code, userId)Verify with replay protection
getSecondsRemaining()Seconds until current code expires

SecretGenerator

MethodDescription
generate()Generate 160-bit secret
generate(algorithm)Generate algorithm-appropriate secret
isValid(secret)Validate a Base32 secret

QRCodeGenerator

MethodDescription
generateBase64(...)Generate Base64 PNG
generateDataUri(...)Generate data URI for HTML
saveToFile(...)Save to file
buildOtpauthUri(...)Build otpauth:// URI

Algorithm Support

AlgorithmKey SizeUse Case
SHA-120 bytesLegacy compatibility
SHA-25632 bytesRecommended
SHA-51264 bytesMaximum security