A small and easy-to-use one-time password generator for Java according to RFC 4226 (HOTP) and RFC 6238 (TOTP).
The following features are supported:
- Generation of secrets
- Time-based one-time password (TOTP, RFC 6238) generation based on current time, specific time, OTPAuth URI and more for different HMAC algorithms.
- HMAC-based one-time password (HOTP, RFC 4226) generation based on counter and OTPAuth URI.
- Verification of one-time passwords
- Generation of OTP Auth URI's
<dependency>
<groupId>com.github.bastiaanjansen</groupId>
<artifactId>otp-java</artifactId>
<version>1.2.2</version>
</dependency>
implementation 'com.github.bastiaanjansen:otp-java:1.2.2'
libraryDependencies += "com.github.bastiaanjansen" % "otp-java" % "1.2.2"
<dependency org="com.github.bastiaanjansen" name="otp-java" rev="1.2.2" />
Or you can download the source from the GitHub releases page.
To create a HOTPGenerator
use the HOTPGenerator.Builder
class as follows:
byte[] secret = "VV3KOX7UQJ4KYAKOHMZPPH3US4CJIMH6F3ZKNB5C2OOBQ6V2KIYHM27Q".getBytes();
HOTPGenerator.Builder builder = new HOTPGenerator.Builder(secret);
HOTPGenerator hotp = builder.build();
The above builder creates a HOTPGenerator instance with default values for passwordLength = 6 and algorithm = SHA1. Use the builder to change these defaults:
HOTPGenerator.Builder builder = new HOTPGenerator.Builder(secret);
builder
.withPasswordLength(8)
.withAlgorithm(HMACAlgorithm.SHA256);
HOTPGenerator hotp = builder.build();
When you don't already have a secret, you can let the library generate it:
// To generate a secret with 160 bits
byte[] secret = SecretGenerator.generate();
// To generate a secret with a custom amount of bits
byte[] secret = SecretGenerator.generate(512);
It is also possible to create a HOTPGenerator instance based on an OTPAuth URI. When algorithm or digits are not specified, the default values will be used.
URI uri = new URI("otpauth://hotp/issuer?secret=ABCDEFGHIJKLMNOP&algorithm=SHA1&digits=6&counter=8237");
HOTPGenerator hotp = HOTPGenerator.Builder.fromOTPAuthURI(uri);
Get information about the generator:
byte[] secret = hotp.getSecret();
int passwordLength = hotp.getPasswordLength(); // 6
HMACAlgorithm algorithm = hotp.getAlgorithm(); // HMACAlgorithm.SHA1
After creating an instance of the HOTPGenerator class, a code can be generated by using the generate()
method:
try {
int counter = 5;
String code = hotp.generate(counter);
// To verify a token:
boolean isValid = hotp.verify(code, counter);
// Or verify with a delay window
boolean isValid = hotp.verify(code, counter, 2);
} catch (IllegalStateException e) {
// Handle error
}
TOTPGenerator can accept more paramaters: passwordLength
, period
, algorithm
and secret
. The default values are: passwordLength = 6, period = 30 and algorithm = SHA1.
// Generate a secret (or use your own secret)
byte[] secret = SecretGenerator.generate();
TOTPGenerator.Builder builder = new TOTPGenerator.Builder(secret);
builder
.withPasswordLength(6)
.withAlgorithm(HMACAlgorithm.SHA1) // SHA256 and SHA512 are also supported
.withPeriod(Duration.ofSeconds(30));
TOTPGenerator totp = builder.build();
Or create a TOTPGenerator
instance from an OTPAuth URI:
URI uri = new URI("otpauth://totp/issuer?secret=ABCDEFGHIJKLMNOP&algorithm=SHA1&digits=6&period=30");
TOTPGenerator totp = TOTPGenerator.Builder.fromOTPAuthURI(uri);
Get information about the generator:
byte[] secret = totp.getSecret();
int passwordLength = totp.getPasswordLength(); // 6
HMACAlgorithm algorithm = totp.getAlgorithm(); // HMACAlgorithm.SHA1
Duration period = totp.getPeriod(); // Duration.ofSeconds(30)
After creating an instance of the TOTPGenerator class, a code can be generated by using the generate()
method, similarly with the HOTPGenerator class:
try {
String code = totp.generate();
// To verify a token:
boolean isValid = totp.verify(code);
} catch (IllegalStateException e) {
// Handle error
}
The above code will generate a time-based one-time password based on the current time. The API supports, besides the current time, the creation of codes based on timeSince1970
in seconds, Date
, and Instant
:
try {
// Based on current time
totp.generate();
// Based on specific date
totp.generate(new Date());
// Based on seconds past 1970
totp.generate(9238346823);
// Based on an instant
totp.generate(Instant.now());
} catch (IllegalStateException e) {
// Handle error
}
To easily generate a OTPAuth URI for easy on-boarding, use the getURI()
method for both HOTPGenerator
and TOTPGenerator
. Example for TOTPGenerator
:
TOTPGenerator totp = new TOTPGenerator.Builder(secret).build();
URI uri = totp.getURI("issuer", "account"); // otpauth://totp/issuer:account?period=30&digits=6&secret=SECRET&algorithm=SHA1
OTP-Java is available under the MIT licence. See the LICENCE for more info.