Compare commits

..

4 Commits

5 changed files with 87 additions and 71 deletions

View File

@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.cringe_studios</groupId> <groupId>com.cringe_studios</groupId>
<artifactId>CringeAuthenticatorLibrary</artifactId> <artifactId>CringeAuthenticatorLibrary</artifactId>
<version>1.3</version> <version>1.4</version>
<name>CringeAuthenticatorLibrary</name> <name>CringeAuthenticatorLibrary</name>
<description>The Library of the Cringe Authenticator</description> <description>The Library of the Cringe Authenticator</description>
<build> <build>

View File

@ -45,10 +45,10 @@ public abstract class OTP {
* @param counter REQUIRED if HOTP, otherwise meaningless. The initial counter for HOTP (eg 21, if user reloaded counter 21 times) * @param counter REQUIRED if HOTP, otherwise meaningless. The initial counter for HOTP (eg 21, if user reloaded counter 21 times)
* @param periodInSeconds OPTIONAL (default 30) for TOTP, the refresh rate of the TOTP * @param periodInSeconds OPTIONAL (default 30) for TOTP, the refresh rate of the TOTP
* @param checksum OPTIONAL: appends a checksum digit to the end of the string * @param checksum OPTIONAL: appends a checksum digit to the end of the string
* @return returns your wallet to the lost-and-found office * @return returns a valid OTP object, which can be used to create a new OTP pin
*/ */
public static OTP createNewOTP(OTPType type, String secret, OTPAlgorithm algorithm, int digits, long counter, long periodInSeconds, boolean checksum) throws OTPException{ public static OTP createNewOTP(OTPType type, String secret, OTPAlgorithm algorithm, int digits, long counter, long periodInSeconds, boolean checksum) throws OTPException{
if(type == null) return null; if(type == null) throw new OTPException("No OTP Type given!");
return type.instance(secret, algorithm, digits, counter, periodInSeconds, checksum); return type.instance(secret, algorithm, digits, counter, periodInSeconds, checksum);
} }

View File

@ -1,6 +1,6 @@
package com.cringe_studios.cringe_authenticator_library; package com.cringe_studios.cringe_authenticator_library;
public class OTPException extends RuntimeException { public class OTPException extends Exception {
private static final long serialVersionUID = 4635395862998258574L; private static final long serialVersionUID = 4635395862998258574L;

View File

@ -16,15 +16,15 @@ public enum OTPType {
return friendlyName; return friendlyName;
} }
public OTP instance(String secret, OTPAlgorithm algorithm, int digits, long counter, long periodInSeconds, boolean checksum) { public OTP instance(String secret, OTPAlgorithm algorithm, int digits, long counter, long periodInSeconds, boolean checksum) throws OTPException {
if(/*type == null ||*/ secret == null /*|| counter < 0*/) { if(/*type == null ||*/ secret == null || secret.length() == 0/*|| counter < 0*/) {
return null; throw new OTPException("Invalid Secret!");
} }
try { try {
Base32.decode(secret); Base32.decode(secret);
}catch (IllegalArgumentException e) { }catch (IllegalArgumentException e) {
throw new OTPException("Your secret is invalid! Please rescan the code!", e); throw new OTPException("Invalid Secret!", e);
} }
switch(this) { switch(this) {
@ -32,7 +32,7 @@ public enum OTPType {
return new com.cringe_studios.cringe_authenticator_library.impl.HOTP(secret, algorithm, digits, counter, periodInSeconds, checksum); return new com.cringe_studios.cringe_authenticator_library.impl.HOTP(secret, algorithm, digits, counter, periodInSeconds, checksum);
case TOTP: case TOTP:
return new com.cringe_studios.cringe_authenticator_library.impl.TOTP(secret, algorithm, digits, counter, periodInSeconds, checksum); return new com.cringe_studios.cringe_authenticator_library.impl.TOTP(secret, algorithm, digits, counter, periodInSeconds, checksum);
default: return null; default: throw new OTPException("No OTP Type given!"); //Respect, if you run this code
} }
} }
} }

View File

@ -2,6 +2,7 @@ package test;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertThrows;
import java.math.BigInteger; import java.math.BigInteger;
@ -14,6 +15,7 @@ import org.junit.jupiter.api.Test;
import com.cringe_studios.cringe_authenticator_library.OTP; import com.cringe_studios.cringe_authenticator_library.OTP;
import com.cringe_studios.cringe_authenticator_library.OTPAlgorithm; import com.cringe_studios.cringe_authenticator_library.OTPAlgorithm;
import com.cringe_studios.cringe_authenticator_library.OTPException;
import com.cringe_studios.cringe_authenticator_library.OTPType; import com.cringe_studios.cringe_authenticator_library.OTPType;
import com.cringe_studios.cringe_authenticator_library.impl.Base32; import com.cringe_studios.cringe_authenticator_library.impl.Base32;
import com.cringe_studios.cringe_authenticator_library.impl.TOTP; import com.cringe_studios.cringe_authenticator_library.impl.TOTP;
@ -36,34 +38,44 @@ public class OTPTest {
} }
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
OTP testOTP1 = OTPType.HOTP.instance(base32secret, OTPAlgorithm.SHA1, 6, i, 30, false); int tempi = i;
String calculatedPin = testOTP1.getPin(); assertDoesNotThrow(() ->{
OTP testOTP1 = OTPType.HOTP.instance(base32secret, OTPAlgorithm.SHA1, 6, tempi, 30, false);
if(VERBOSE) { String calculatedPin = testOTP1.getPin();
System.out.println(calculatedPin + " == " + expectedValues[i]);
} if(VERBOSE) {
System.out.println(calculatedPin + " == " + expectedValues[tempi]);
assertEquals(calculatedPin, expectedValues[i]); }
assertEquals(calculatedPin, expectedValues[tempi]);
});
} }
} }
@Test @Test
public void lengthTest() { public void lengthTest() {
String secret = "1"; assertDoesNotThrow(() -> {
String base32secret = Base32.encode(hexStr2Bytes(secret)); String secret = "1";
OTP testOTP1 = OTP.createNewOTP(OTPType.HOTP, base32secret, OTPAlgorithm.SHA1, 1, 0, 0, false); String base32secret = Base32.encode(hexStr2Bytes(secret));
assertDoesNotThrow(() -> testOTP1.getPin()); OTP testOTP1 = OTP.createNewOTP(OTPType.HOTP, base32secret, OTPAlgorithm.SHA1, 1, 0, 0, false);
assertDoesNotThrow(() -> testOTP1.getPin());
secret = "100";
base32secret = Base32.encode(hexStr2Bytes(secret)); secret = "100";
OTP testOTP2 = OTP.createNewOTP(OTPType.HOTP, base32secret, OTPAlgorithm.SHA256, 0, 0, 0, false); base32secret = Base32.encode(hexStr2Bytes(secret));
assertDoesNotThrow(() -> testOTP2.getPin()); OTP testOTP2 = OTP.createNewOTP(OTPType.HOTP, base32secret, OTPAlgorithm.SHA256, 0, 0, 0, false);
assertDoesNotThrow(() -> testOTP2.getPin());
OTP testOTP3 = OTP.createNewOTP(OTPType.HOTP, base32secret, OTPAlgorithm.SHA512, 50, 0, 0, false);
assertDoesNotThrow(() -> testOTP3.getPin()); OTP testOTP3 = OTP.createNewOTP(OTPType.HOTP, base32secret, OTPAlgorithm.SHA512, 50, 0, 0, false);
assertDoesNotThrow(() -> testOTP3.getPin());
OTP testOTP4 = OTP.createNewOTP(OTPType.HOTP, base32secret, OTPAlgorithm.SHA512, 10, 0, 0, false);
assertDoesNotThrow(() -> testOTP4.getPin()); OTP testOTP4 = OTP.createNewOTP(OTPType.HOTP, base32secret, OTPAlgorithm.SHA512, 10, 0, 0, false);
assertDoesNotThrow(() -> testOTP4.getPin());
assertThrows(OTPException.class, () -> {
OTP testOTP5 = OTP.createNewOTP(OTPType.HOTP, "", OTPAlgorithm.SHA1, 8, 0, 0, false);
assertNotNull(testOTP5);
});
});
} }
private static byte[] hexStr2Bytes(String hex) { private static byte[] hexStr2Bytes(String hex) {
@ -113,49 +125,53 @@ public class OTPTest {
String seed64 = Base32.encode(hexStr2Bytes(base16seed64)); String seed64 = Base32.encode(hexStr2Bytes(base16seed64));
long testTime[] = { 59L, 1111111109L, 1111111111L, 1234567890L, 2000000000L, 20000000000L }; long testTime[] = { 59L, 1111111109L, 1111111111L, 1234567890L, 2000000000L, 20000000000L };
TOTP testOTP1 = (TOTP) OTPType.TOTP.instance(seed, OTPAlgorithm.SHA1, 8, 0, 30, false);
TOTP testOTP256 = (TOTP) OTPType.TOTP.instance(seed32, OTPAlgorithm.SHA256, 8, 0, 30, false); assertDoesNotThrow(() -> {
TOTP testOTP512 = (TOTP) OTPType.TOTP.instance(seed64, OTPAlgorithm.SHA512, 8, 0, 30, false);
TOTP testOTP1 = (TOTP) OTPType.TOTP.instance(seed, OTPAlgorithm.SHA1, 8, 0, 30, false);
long X = 30; TOTP testOTP256 = (TOTP) OTPType.TOTP.instance(seed32, OTPAlgorithm.SHA256, 8, 0, 30, false);
TOTP testOTP512 = (TOTP) OTPType.TOTP.instance(seed64, OTPAlgorithm.SHA512, 8, 0, 30, false);
String steps = "0";
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); long X = 30;
df.setTimeZone(TimeZone.getTimeZone("UTC"));
String steps = "0";
try { DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
if(VERBOSE) { df.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println("+---------------+-----------------------+--------+--------+");
System.out.println("| Time(sec) | Time (UTC format) | TOTP | Mode |"); try {
System.out.println("+---------------+-----------------------+--------+--------+");
}
for (int i = 0; i < testTime.length; i++) {
String fmtTime = String.format("%1$-11s", testTime[i]);
String utcTime = df.format(new Date(testTime[i] * 1000));
String sha1Pin = testOTP1.getPinAt(testTime[i]);
String sha256Pin = testOTP256.getPinAt(testTime[i]);
String sha512Pin = testOTP512.getPinAt(testTime[i]);
if(VERBOSE) { if(VERBOSE) {
System.out.println("| " + fmtTime + " | " + utcTime + " |" + sha1Pin + "| SHA1 |"); System.out.println("+---------------+-----------------------+--------+--------+");
System.out.println("| " + fmtTime + " | " + utcTime + " |" + sha256Pin + "| SHA256 |"); System.out.println("| Time(sec) | Time (UTC format) | TOTP | Mode |");
System.out.println("| " + fmtTime + " | " + utcTime + " |" + sha512Pin + "| SHA512 |");
System.out.println("+---------------+-----------------------+--------+--------+"); System.out.println("+---------------+-----------------------+--------+--------+");
} }
assertEquals(expectedValues[i * 3 + 0], sha1Pin); for (int i = 0; i < testTime.length; i++) {
assertEquals(expectedValues[i * 3 + 1], sha256Pin); String fmtTime = String.format("%1$-11s", testTime[i]);
assertEquals(expectedValues[i * 3 + 2], sha512Pin); String utcTime = df.format(new Date(testTime[i] * 1000));
String sha1Pin = testOTP1.getPinAt(testTime[i]);
String sha256Pin = testOTP256.getPinAt(testTime[i]);
String sha512Pin = testOTP512.getPinAt(testTime[i]);
if(VERBOSE) {
System.out.println("| " + fmtTime + " | " + utcTime + " |" + sha1Pin + "| SHA1 |");
System.out.println("| " + fmtTime + " | " + utcTime + " |" + sha256Pin + "| SHA256 |");
System.out.println("| " + fmtTime + " | " + utcTime + " |" + sha512Pin + "| SHA512 |");
System.out.println("+---------------+-----------------------+--------+--------+");
}
assertEquals(expectedValues[i * 3 + 0], sha1Pin);
assertEquals(expectedValues[i * 3 + 1], sha256Pin);
assertEquals(expectedValues[i * 3 + 2], sha512Pin);
}
} catch (final Exception e) {
e.printStackTrace();
} }
} catch (final Exception e) { });
e.printStackTrace();
}
} }
// @org.junit.jupiter.api.Test // @org.junit.jupiter.api.Test