2424import java .security .InvalidKeyException ;
2525import java .security .Key ;
2626import java .security .NoSuchAlgorithmException ;
27- import java .util . Date ;
28- import java .util . concurrent . TimeUnit ;
27+ import java .time . Duration ;
28+ import java .time . Instant ;
2929
3030/**
3131 * <p>Generates time-based one-time passwords (TOTP) as specified in
3737 * @author <a href="https://github.com/jchambers">Jon Chambers</a>
3838 */
3939public class TimeBasedOneTimePasswordGenerator extends HmacOneTimePasswordGenerator {
40- private final long timeStepMillis ;
40+ private final Duration timeStep ;
41+
42+ /**
43+ * The default time-step for a time-based one-time password generator (30 seconds).
44+ */
45+ public static final Duration DEFAULT_TIME_STEP = Duration .ofSeconds (30 );
4146
4247 /**
4348 * A string identifier for the HMAC-SHA1 algorithm (required by HOTP and allowed by TOTP). HMAC-SHA1 is the default
@@ -65,48 +70,45 @@ public class TimeBasedOneTimePasswordGenerator extends HmacOneTimePasswordGenera
6570 * happen except in cases of serious misconfiguration
6671 */
6772 public TimeBasedOneTimePasswordGenerator () throws NoSuchAlgorithmException {
68- this (30 , TimeUnit . SECONDS );
73+ this (DEFAULT_TIME_STEP );
6974 }
7075
7176 /**
7277 * Constructs a new time-based one-time password generator with the given time-step and a default password length
7378 * ({@value com.eatthepath.otp.HmacOneTimePasswordGenerator#DEFAULT_PASSWORD_LENGTH} decimal digits) and HMAC
7479 * algorithm ({@value com.eatthepath.otp.HmacOneTimePasswordGenerator#HOTP_HMAC_ALGORITHM}).
7580 *
76- * @param timeStep the magnitude of the time-step for this generator
77- * @param timeStepUnit the units for the the given time step
81+ * @param timeStep the time-step for this generator
7882 *
7983 * @throws NoSuchAlgorithmException if the underlying JRE doesn't support the
8084 * {@value com.eatthepath.otp.HmacOneTimePasswordGenerator#HOTP_HMAC_ALGORITHM} algorithm, which should never
8185 * happen except in cases of serious misconfiguration
8286 */
83- public TimeBasedOneTimePasswordGenerator (final long timeStep , final TimeUnit timeStepUnit ) throws NoSuchAlgorithmException {
84- this (timeStep , timeStepUnit , HmacOneTimePasswordGenerator .DEFAULT_PASSWORD_LENGTH );
87+ public TimeBasedOneTimePasswordGenerator (final Duration timeStep ) throws NoSuchAlgorithmException {
88+ this (timeStep , HmacOneTimePasswordGenerator .DEFAULT_PASSWORD_LENGTH );
8589 }
8690
8791 /**
8892 * Constructs a new time-based one-time password generator with the given time-step and password length and a
8993 * default HMAC algorithm ({@value com.eatthepath.otp.HmacOneTimePasswordGenerator#HOTP_HMAC_ALGORITHM}).
9094 *
91- * @param timeStep the magnitude of the time-step for this generator
92- * @param timeStepUnit the units for the the given time step
95+ * @param timeStep the time-step for this generator
9396 * @param passwordLength the length, in decimal digits, of the one-time passwords to be generated; must be between
9497 * 6 and 8, inclusive
9598 *
9699 * @throws NoSuchAlgorithmException if the underlying JRE doesn't support the
97100 * {@value com.eatthepath.otp.HmacOneTimePasswordGenerator#HOTP_HMAC_ALGORITHM} algorithm, which should never
98101 * happen except in cases of serious misconfiguration
99102 */
100- public TimeBasedOneTimePasswordGenerator (final long timeStep , final TimeUnit timeStepUnit , final int passwordLength ) throws NoSuchAlgorithmException {
101- this (timeStep , timeStepUnit , passwordLength , TOTP_ALGORITHM_HMAC_SHA1 );
103+ public TimeBasedOneTimePasswordGenerator (final Duration timeStep , final int passwordLength ) throws NoSuchAlgorithmException {
104+ this (timeStep , passwordLength , TOTP_ALGORITHM_HMAC_SHA1 );
102105 }
103106
104107 /**
105108 * Constructs a new time-based one-time password generator with the given time-step, password length, and HMAC
106109 * algorithm.
107110 *
108- * @param timeStep the magnitude of the time-step for this generator
109- * @param timeStepUnit the units for the the given time step
111+ * @param timeStep the time-step for this generator
110112 * @param passwordLength the length, in decimal digits, of the one-time passwords to be generated; must be between
111113 * 6 and 8, inclusive
112114 * @param algorithm the name of the {@link javax.crypto.Mac} algorithm to use when generating passwords; TOTP allows
@@ -120,10 +122,10 @@ public TimeBasedOneTimePasswordGenerator(final long timeStep, final TimeUnit tim
120122 * @see com.eatthepath.otp.TimeBasedOneTimePasswordGenerator#TOTP_ALGORITHM_HMAC_SHA256
121123 * @see com.eatthepath.otp.TimeBasedOneTimePasswordGenerator#TOTP_ALGORITHM_HMAC_SHA512
122124 */
123- public TimeBasedOneTimePasswordGenerator (final long timeStep , final TimeUnit timeStepUnit , final int passwordLength , final String algorithm ) throws NoSuchAlgorithmException {
125+ public TimeBasedOneTimePasswordGenerator (final Duration timeStep , final int passwordLength , final String algorithm ) throws NoSuchAlgorithmException {
124126 super (passwordLength , algorithm );
125127
126- this .timeStepMillis = timeStepUnit . toMillis ( timeStep ) ;
128+ this .timeStep = timeStep ;
127129 }
128130
129131 /**
@@ -137,18 +139,16 @@ public TimeBasedOneTimePasswordGenerator(final long timeStep, final TimeUnit tim
137139 *
138140 * @throws InvalidKeyException if the given key is inappropriate for initializing the {@link Mac} for this generator
139141 */
140- public int generateOneTimePassword (final Key key , final Date timestamp ) throws InvalidKeyException {
141- return this .generateOneTimePassword (key , timestamp .getTime () / this .timeStepMillis );
142+ public int generateOneTimePassword (final Key key , final Instant timestamp ) throws InvalidKeyException {
143+ return this .generateOneTimePassword (key , timestamp .toEpochMilli () / this .timeStep . toMillis () );
142144 }
143145
144146 /**
145147 * Returns the time step used by this generator.
146148 *
147- * @param timeUnit the units of time in which to return the time step
148- *
149- * @return the time step used by this generator in the given units of time
149+ * @return the time step used by this generator
150150 */
151- public long getTimeStep (final TimeUnit timeUnit ) {
152- return timeUnit . convert ( this .timeStepMillis , TimeUnit . MILLISECONDS ) ;
151+ public Duration getTimeStep () {
152+ return this .timeStep ;
153153 }
154154}
0 commit comments