A maintained Java library for generating and verifying TOTP (Time-based One-Time Passwords) for Multi-Factor Authentication. Generates QR codes compatible with Google Authenticator, Microsoft Authenticator, and other TOTP apps.
This is an actively maintained fork of java-totp by Sam Stevens. See CHANGELOG.md for all improvements.
- Java 21+
<dependency>
<groupId>io.github.karabela</groupId>
<artifactId>karabela-totp</artifactId>
<version>2.0.0</version>
</dependency>implementation 'io.github.karabela:karabela-totp:2.0.0'For Spring Boot 3.x projects, use the starter for auto-configuration:
<dependency>
<groupId>io.github.karabela</groupId>
<artifactId>karabela-totp-spring-boot-starter</artifactId>
<version>2.0.0</version>
</dependency>See Spring Boot Starter documentation for details.
- Generating secrets
- Generating QR codes
- Verifying one-time passwords
- Using different time providers
- Recovery codes
SecretGenerator secretGenerator = new DefaultSecretGenerator();
String secret = secretGenerator.generate();
// secret = "BP26TDZUZ5SVPZJRIHCAUVREO5EWMHHV"By default, secrets are 32 characters long. This is configurable:
SecretGenerator secretGenerator = new DefaultSecretGenerator(64);Create a QrData instance with the provisioning information:
QrData data = new QrData.Builder()
.label("example@example.com")
.secret(secret)
.issuer("AppName")
.algorithm(HashingAlgorithm.SHA1)
.digits(6)
.period(30)
.build();Generate a PNG QR code image:
QrGenerator generator = new ZxingPngQrGenerator();
byte[] imageData = generator.generate(data);Custom image sizes:
QrGenerator generator = new ZxingPngQrGenerator(500); // 500x500 pixelsimport static org.karabela.totp.util.Utils.getDataUriForImage;
String dataUri = getDataUriForImage(imageData, generator.getImageMimeType());
// dataUri = data:image/png;base64,iVBORw0KGgoAAAANSU...TimeProvider timeProvider = new SystemTimeProvider();
CodeGenerator codeGenerator = new DefaultCodeGenerator();
CodeVerifier verifier = new DefaultCodeVerifier(codeGenerator, timeProvider);
boolean successful = verifier.isValidCode(secret, code);The default is SHA1 (most compatible). SHA256 and SHA512 are also supported:
CodeGenerator codeGenerator = new DefaultCodeGenerator(HashingAlgorithm.SHA512);Note: Most authenticator apps only support SHA1. Using SHA256 or SHA512 may cause compatibility issues with some apps.
Default: 30-second period, ±1 period discrepancy (allows ~30 second clock drift):
DefaultCodeVerifier verifier = new DefaultCodeVerifier(codeGenerator, timeProvider);
verifier.setTimePeriod(60); // 60-second periods
verifier.setAllowedTimePeriodDiscrepancy(2); // allow ±2 periodsCodeGenerator codeGenerator = new DefaultCodeGenerator(HashingAlgorithm.SHA1, 8); // 8-digit codesTimeProvider timeProvider = new SystemTimeProvider();// Fixed clock for deterministic tests
TimeProvider timeProvider = new ClockTimeProvider(Clock.fixed(instant, ZoneOffset.UTC));
// Or use the system UTC clock
TimeProvider timeProvider = new ClockTimeProvider(Clock.systemUTC());Requires commons-net on the classpath:
TimeProvider timeProvider = new NtpTimeProvider("pool.ntp.org");
TimeProvider timeProvider = new NtpTimeProvider("pool.ntp.org", 5000); // 5s timeoutAdd the dependency:
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>3.11.1</version>
</dependency>Generate one-time recovery codes for backup access:
RecoveryCodeGenerator recoveryCodes = new RecoveryCodeGenerator();
String[] codes = recoveryCodes.generateCodes(16);
// codes = ["tf8i-exmo-3lcb-slkm", "boyv-yq75-z99k-r308", ...]Codes are 16 characters (a-z, 0-9), grouped with dashes, providing 82 bits of entropy.
mvn testReplace the dependency:
<!-- Old -->
<groupId>dev.samstevens.totp</groupId>
<artifactId>totp</artifactId>
<!-- New -->
<groupId>io.github.karabela</groupId>
<artifactId>karabela-totp</artifactId>Update imports:
dev.samstevens.totp.* → org.karabela.totp.*
API changes:
ZxingPngQrGenerator.setImageSize()removed — pass size via constructor:new ZxingPngQrGenerator(500)InvalidParameterExceptionreplaced withIllegalArgumentExceptionQrData.Buildernow validates null values (throwsNullPointerException)TotpInforenamed toKarabelaTotp
This project is licensed under the MIT License.
Original work Copyright (c) 2019 Sam Stevens. Fork Copyright (c) 2026 Karabela.