All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.mangoo.utils.totp.TotpValidator Maven / Gradle / Ivy

The newest version!
package io.mangoo.utils.totp;

import com.google.common.base.Preconditions;
import io.mangoo.constants.Hmac;

/**
 * A Time-based One-time Password (TOTP) validator.
 * 
 * 

* As per RFC 6238 (section 5.2): *

*

* "An OTP generated within the same time step will be the same. When an OTP is * received at a validation system, it doesn't know a client's exact timestamp * when an OTP was generated. The validation system may typically use the * timestamp when an OTP is received for OTP comparison. Due to network latency, * the gap (as measured by T, that is, the number of time steps since T0) * between the time that the OTP was generated and the time that the OTP arrives * at the receiving system may be large. The receiving time at the validation * system and the actual OTP generation may not fall within the same time-step * window that produced the same OTP. When an OTP is generated at the end of a * time-step window, the receiving time most likely falls into the next * time-step window. A validation system SHOULD typically set a policy for an * acceptable OTP transmission delay window for validation. The validation * system should compare OTPs not only with the receiving timestamp but also the * past timestamps that are within the transmission delay. A larger acceptable * delay window would expose a larger window for attacks. We RECOMMEND that at * most one time step is allowed as the network delay." *

* *

* Example: *

* *
 * // We will let the TOTP generation time == TOTP validation time so validation will succeed.
 * final long time = System.currentTimeMillis(); 
 * byte[] key = "...";
 * TOTP totp = TOTP.key(key).build(time);
 * boolean valid = TOTPValidator.window(0).isValid(key, totp.timeStep(), totp.digits(), totp.hmacShaAlgorithm(), totp.value(), time);
 * // Should print "TOTP = ..., valid = true"
 * System.out.printf("TOTP = %s, valid = %s%n", totp.value(), valid);
 * 
* * @author Johnny Mongiat * * @see RFC 6238 (section 5.2) */ public final class TotpValidator { /** The default window verification size. */ public static final int DEFAULT_WINDOW = 1; private final int window; /** * Creates a new instance of {@code TOTPValidator} initialized with the * specified {@code window} verification size. * * @param window * the window verification size * * @throws IllegalArgumentException * if {@code window} is < 0. */ private TotpValidator(int window) { Preconditions.checkArgument(window >= 0); this.window = window; } /** * Returns a new {@link TotpValidator} instance initialized with the * {@link #DEFAULT_WINDOW} verification size. * * @return a new {@link TotpValidator} instance. */ public static TotpValidator defaultWindow() { return window(DEFAULT_WINDOW); } /** * Returns a new {@link TotpValidator} instance initialized with the * specified {@code window} verification size. * * @param window * the window verification size * * @return a new {@link TotpValidator} instance. * * @throws IllegalArgumentException * if {@code window} is {@literal <} 0. */ public static TotpValidator window(int window) { return new TotpValidator(window); } /** * Returns {@code true} if the specified TOTP {@code value} matches the * value of the TOTP generated at validation, otherwise {@code false}. The * current system time (current time in milliseconds since the UNIX epoch) * is used as the validation reference time. * * @param key * the encoded shared secret key * @param timeStep * the time step size in milliseconds * @param digits * the number of digits a TOTP should contain * @param hmacShaAlgorithm * {@link Hmac} * @param value * the TOTP value to validate * * @return {@code true} if the specified TOTP {@code code} value matches the * code value of the TOTP generated at validation, otherwise * {@code false}. */ public boolean isValid(byte[] key, long timeStep, int digits, String hmacShaAlgorithm, String value) { return isValid(key, timeStep, digits, hmacShaAlgorithm, value, System.currentTimeMillis()); } /** * Returns {@code true} if the specified TOTP {@code value} matches the * value of the TOTP generated at validation, otherwise {@code false}. * * @param key * the encoded shared secret key * @param timeStep * the time step size in milliseconds * @param digits * the number of digits a TOTP should contain * @param hmacShaAlgorithm * {@link Hmac} * @param value * the TOTP value to validate * @param validationTime * the validation reference time in milliseconds * * @return {@code true} if the specified TOTP {@code code} value matches the * code value of the TOTP generated at validation, otherwise * {@code false}. */ public boolean isValid(byte[] key, long timeStep, int digits, String hmacShaAlgorithm, String value, long validationTime) { var result = false; TotpBuilder builder = Totp.key(key).timeStep(timeStep).digits(digits).hmacSha(hmacShaAlgorithm); for (int i = -window; i <= window; i++) { final long time = validationTime + (i * timeStep); final var vtotp = builder.build(time); if (vtotp.value().equals(value)) { result = true; break; } } return result; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy