| Version | Supported |
|---|---|
| 1.0.x | ✅ |
This library implements several security measures to protect TOTP operations:
All code comparisons use MessageDigest.isEqual() which provides constant-time comparison. This prevents timing attacks where an attacker could deduce the correct code by measuring response times.
The ReplayGuard interface and InMemoryReplayGuard implementation prevent the same TOTP code from being used multiple times within its validity window.
Recommendation: For distributed systems, implement ReplayGuard using Redis or a similar distributed cache.
The SecureBytes class ensures that secret keys are:
- Cleared from memory when no longer needed
- Not accidentally logged or serialized
- Properly handled in try-with-resources blocks
Note: Due to JVM limitations, we cannot guarantee that the garbage collector hasn't made copies. For highly sensitive environments, consider using a Hardware Security Module (HSM).
All inputs are strictly validated:
- Secrets must be at least 26 Base32 characters (130 bits of entropy)
- Codes must match the expected digit count
- Configuration parameters are range-checked
Exceptions never contain sensitive data:
- Secret values are never included in error messages
- Error codes enable programmatic handling without parsing messages
- Never log secrets - Use the SecureBytes wrapper
- Encrypt at rest - Store secrets encrypted in your database
- Limit access - Secrets should only be accessible to the authentication service
- Rotate periodically - Implement secret rotation for long-lived accounts
// ✅ Good: Use try-with-resources
try (SecureBytes secret = SecureBytes.wrap(getSecretFromDatabase())) {
return engine.verify(secret.getBytes(), code);
}
// ❌ Bad: Secrets remain in memory
byte[] secret = getSecretFromDatabase();
boolean result = engine.verify(secret, code);
// secret is never cleared!// ✅ Good: Enable replay protection with user context
TOTP totp = TOTP.builder()
.withReplayProtection(Duration.ofMinutes(2))
.build();
totp.verify(secret, code, userId);
// ⚠️ Caution: Without user ID, codes could be shared between users
totp.verify(secret, code);- SHA-1: Use only for compatibility with existing systems
- SHA-256: Recommended for new implementations
- SHA-512: Use when security requirements demand maximum margin
| Threat | Mitigation |
|---|---|
| Timing attacks | Constant-time comparison |
| Replay attacks | ReplayGuard implementation |
| Memory disclosure | SecureBytes auto-clearing |
| Brute force | 6+ digit codes, rate limiting (external) |
| Clock drift | Configurable drift tolerance |
| Threat | Recommendation |
|---|---|
| Secret theft from database | Encrypt secrets at rest |
| Man-in-the-middle | Use TLS for all communications |
| Phishing | User education, hardware tokens |
| Device compromise | Beyond TOTP scope |
If you discover a security vulnerability, please:
- Do not open a public issue
- Email security details to: pratiyush1@gmail.com
- Include:
- Description of the vulnerability
- Steps to reproduce
- Potential impact
- Any suggested fixes
We will respond within 48 hours and work with you to address the issue.
- Initial release with constant-time verification
- Replay attack prevention via ReplayGuard
- SecureBytes for memory protection
- RFC 6238 compliance verified with test vectors