diff --git a/pom.xml b/pom.xml
index 9b97070..68e64e2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -14,6 +14,13 @@
4.12
test
+
+
+ pl.pragmatists
+ JUnitParams
+ 1.1.1
+ test
+
diff --git a/src/test/java/com/eatthepath/otp/HmacOneTimePasswordGeneratorTest.java b/src/test/java/com/eatthepath/otp/HmacOneTimePasswordGeneratorTest.java
index 8eb80ba..2f7962e 100644
--- a/src/test/java/com/eatthepath/otp/HmacOneTimePasswordGeneratorTest.java
+++ b/src/test/java/com/eatthepath/otp/HmacOneTimePasswordGeneratorTest.java
@@ -29,8 +29,12 @@
import javax.crypto.spec.SecretKeySpec;
+import junitparams.JUnitParamsRunner;
+import junitparams.Parameters;
import org.junit.Test;
+import org.junit.runner.RunWith;
+@RunWith(JUnitParamsRunner.class)
public class HmacOneTimePasswordGeneratorTest {
@Test(expected = IllegalArgumentException.class)
@@ -65,27 +69,22 @@ public void testGetAlgorithm() throws NoSuchAlgorithmException {
* RFC 4226, Appendix D.
*/
@Test
- public void testGetOneTimePassword() throws InvalidKeyException, NoSuchAlgorithmException {
+ @Parameters({
+ "0, 755224",
+ "1, 287082",
+ "2, 359152",
+ "3, 969429",
+ "4, 338314",
+ "5, 254676",
+ "6, 287922",
+ "7, 162583",
+ "8, 399871",
+ "9, 520489" })
+ public void testGenerateOneTimePassword(final int counter, final int expectedOneTimePassword) throws Exception {
final HmacOneTimePasswordGenerator hmacOneTimePasswordGenerator = this.getDefaultGenerator();
final Key key = new SecretKeySpec("12345678901234567890".getBytes(StandardCharsets.US_ASCII), "RAW");
-
- final int[] expectedValues = new int[] {
- 755224,
- 287082,
- 359152,
- 969429,
- 338314,
- 254676,
- 287922,
- 162583,
- 399871,
- 520489
- };
-
- for (int i = 0; i < expectedValues.length; i++) {
- assertEquals(expectedValues[i], hmacOneTimePasswordGenerator.generateOneTimePassword(key, i));
- }
+ assertEquals(expectedOneTimePassword, hmacOneTimePasswordGenerator.generateOneTimePassword(key, counter));
}
protected HmacOneTimePasswordGenerator getDefaultGenerator() throws NoSuchAlgorithmException {
diff --git a/src/test/java/com/eatthepath/otp/TimeBasedOneTimePasswordGeneratorTest.java b/src/test/java/com/eatthepath/otp/TimeBasedOneTimePasswordGeneratorTest.java
index b8d4f09..f011064 100644
--- a/src/test/java/com/eatthepath/otp/TimeBasedOneTimePasswordGeneratorTest.java
+++ b/src/test/java/com/eatthepath/otp/TimeBasedOneTimePasswordGeneratorTest.java
@@ -33,8 +33,12 @@
import javax.crypto.spec.SecretKeySpec;
+import junitparams.JUnitParamsRunner;
+import junitparams.Parameters;
import org.junit.Test;
+import org.junit.runner.RunWith;
+@RunWith(JUnitParamsRunner.class)
public class TimeBasedOneTimePasswordGeneratorTest extends HmacOneTimePasswordGeneratorTest {
@Override
@@ -54,93 +58,40 @@ public void testGetTimeStep() throws NoSuchAlgorithmException {
}
/**
- * Tests time-based one-time password generation using HMAC-SHA1 and the test vectors from
- * RFC 6238, Appendix B.
+ * Tests time-based one-time password generation using the test vectors from
+ * RFC 6238, Appendix B. Note that the RFC
+ * incorrectly states that the same key is used for all test vectors. The
+ * >errata correctly points out that
+ * different keys are used for each of the various HMAC algorithms.
*/
@Test
- public void testGenerateOneTimePasswordSha1() throws NoSuchAlgorithmException, InvalidKeyException {
- final TimeBasedOneTimePasswordGenerator totp =
- new TimeBasedOneTimePasswordGenerator(30, TimeUnit.SECONDS, 8, TimeBasedOneTimePasswordGenerator.TOTP_ALGORITHM_HMAC_SHA1);
-
- final Key key;
- {
- final String keyString = "12345678901234567890";
- key = new SecretKeySpec(keyString.getBytes(StandardCharsets.US_ASCII), "RAW");
- }
-
- final Map expectedPasswords = new HashMap<>();
- expectedPasswords.put(new Date(TimeUnit.SECONDS.toMillis(59)), 94287082);
- expectedPasswords.put(new Date(TimeUnit.SECONDS.toMillis(1111111109)), 7081804);
- expectedPasswords.put(new Date(TimeUnit.SECONDS.toMillis(1111111111)), 14050471);
- expectedPasswords.put(new Date(TimeUnit.SECONDS.toMillis(1234567890)), 89005924);
- expectedPasswords.put(new Date(TimeUnit.SECONDS.toMillis(2000000000)), 69279037);
- expectedPasswords.put(new Date(TimeUnit.SECONDS.toMillis(20000000000L)), 65353130);
+ @Parameters({
+ "59, 94287082, 12345678901234567890, HmacSHA1",
+ "1111111109, 7081804, 12345678901234567890, HmacSHA1",
+ "1111111111, 14050471, 12345678901234567890, HmacSHA1",
+ "1234567890, 89005924, 12345678901234567890, HmacSHA1",
+ "2000000000, 69279037, 12345678901234567890, HmacSHA1",
+ "20000000000, 65353130, 12345678901234567890, HmacSHA1",
+ "59, 46119246, 12345678901234567890123456789012, HmacSHA256",
+ "1111111109, 68084774, 12345678901234567890123456789012, HmacSHA256",
+ "1111111111, 67062674, 12345678901234567890123456789012, HmacSHA256",
+ "1234567890, 91819424, 12345678901234567890123456789012, HmacSHA256",
+ "2000000000, 90698825, 12345678901234567890123456789012, HmacSHA256",
+ "20000000000, 77737706, 12345678901234567890123456789012, HmacSHA256",
+ "59, 90693936, 1234567890123456789012345678901234567890123456789012345678901234, HmacSHA512",
+ "1111111109, 25091201, 1234567890123456789012345678901234567890123456789012345678901234, HmacSHA512",
+ "1111111111, 99943326, 1234567890123456789012345678901234567890123456789012345678901234, HmacSHA512",
+ "1234567890, 93441116, 1234567890123456789012345678901234567890123456789012345678901234, HmacSHA512",
+ "2000000000, 38618901, 1234567890123456789012345678901234567890123456789012345678901234, HmacSHA512",
+ "20000000000, 47863826, 1234567890123456789012345678901234567890123456789012345678901234, HmacSHA512" })
+ public void testGenerateOneTimePassword(final long epochSeconds, final int expectedOneTimePassword, final String keyString, final String algorithm) throws Exception {
- this.validateOneTimePasswords(totp, key, expectedPasswords);
- }
-
- /**
- * Tests time-based one-time password generation using HMAC-SHA256 and the test vectors from
- * RFC 6238, Appendix B.
- */
- @Test
- public void testGenerateOneTimePasswordSha256() throws NoSuchAlgorithmException, InvalidKeyException {
final TimeBasedOneTimePasswordGenerator totp =
- new TimeBasedOneTimePasswordGenerator(30, TimeUnit.SECONDS, 8, TimeBasedOneTimePasswordGenerator.TOTP_ALGORITHM_HMAC_SHA256);
-
- final Key key;
- {
- // The RFC incorrectly states that the same key is used for all test vectors, but that's not actually true;
- // see the errata (https://www.rfc-editor.org/errata_search.php?rfc=6238&eid=2866) for details
- final String keyString = "12345678901234567890123456789012";
- key = new SecretKeySpec(keyString.getBytes(StandardCharsets.US_ASCII), "RAW");
- }
-
- final Map expectedPasswords = new HashMap<>();
- expectedPasswords.put(new Date(TimeUnit.SECONDS.toMillis(59)), 46119246);
- expectedPasswords.put(new Date(TimeUnit.SECONDS.toMillis(1111111109)), 68084774);
- expectedPasswords.put(new Date(TimeUnit.SECONDS.toMillis(1111111111)), 67062674);
- expectedPasswords.put(new Date(TimeUnit.SECONDS.toMillis(1234567890)), 91819424);
- expectedPasswords.put(new Date(TimeUnit.SECONDS.toMillis(2000000000)), 90698825);
- expectedPasswords.put(new Date(TimeUnit.SECONDS.toMillis(20000000000L)), 77737706);
-
- this.validateOneTimePasswords(totp, key, expectedPasswords);
- }
-
- /**
- * Tests time-based one-time password generation using HMAC-SHA512 and the test vectors from
- * RFC 6238, Appendix B.
- */
- @Test
- public void testGenerateOneTimePasswordSha512() throws NoSuchAlgorithmException, InvalidKeyException {
- final TimeBasedOneTimePasswordGenerator totp =
- new TimeBasedOneTimePasswordGenerator(30, TimeUnit.SECONDS, 8, TimeBasedOneTimePasswordGenerator.TOTP_ALGORITHM_HMAC_SHA512);
-
- final Key key;
- {
- // The RFC incorrectly states that the same key is used for all test vectors, but that's not actually true;
- // see the errata (https://www.rfc-editor.org/errata_search.php?rfc=6238&eid=2866) for details
- final String keyString = "1234567890123456789012345678901234567890123456789012345678901234";
- key = new SecretKeySpec(keyString.getBytes(StandardCharsets.US_ASCII), "RAW");
- }
-
- final Map expectedPasswords = new HashMap<>();
- expectedPasswords.put(new Date(TimeUnit.SECONDS.toMillis(59)), 90693936);
- expectedPasswords.put(new Date(TimeUnit.SECONDS.toMillis(1111111109)), 25091201);
- expectedPasswords.put(new Date(TimeUnit.SECONDS.toMillis(1111111111)), 99943326);
- expectedPasswords.put(new Date(TimeUnit.SECONDS.toMillis(1234567890)), 93441116);
- expectedPasswords.put(new Date(TimeUnit.SECONDS.toMillis(2000000000)), 38618901);
- expectedPasswords.put(new Date(TimeUnit.SECONDS.toMillis(20000000000L)), 47863826);
-
- this.validateOneTimePasswords(totp, key, expectedPasswords);
- }
+ new TimeBasedOneTimePasswordGenerator(30, TimeUnit.SECONDS, 8, algorithm);
- private void validateOneTimePasswords(final TimeBasedOneTimePasswordGenerator totp, final Key key, final Map expectedPasswords) throws InvalidKeyException {
- for (final Map.Entry entry : expectedPasswords.entrySet()) {
- final Date date = entry.getKey();
- final int expectedPassword = entry.getValue();
+ final Key key = new SecretKeySpec(keyString.getBytes(StandardCharsets.US_ASCII), "RAW");
+ final Date date = new Date(TimeUnit.SECONDS.toMillis(epochSeconds));
- assertEquals(expectedPassword, totp.generateOneTimePassword(key, date));
- }
+ assertEquals(expectedOneTimePassword, totp.generateOneTimePassword(key, date));
}
}