Skip to content

Commit

Permalink
update import, export logic and add capability to change the algorith…
Browse files Browse the repository at this point in the history
…m used to generate passwords
  • Loading branch information
kryptonbutterfly committed Jan 10, 2025
1 parent 422c34f commit 2a5d289
Show file tree
Hide file tree
Showing 14 changed files with 387 additions and 69 deletions.
4 changes: 2 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>kryptonbutterfly</groupId>
<artifactId>tiny_totp</artifactId>
<version>4.1.0</version>
<version>4.2.0</version>
<name>TinyTOTP</name>
<description>A TOTP client</description>

Expand Down Expand Up @@ -89,7 +89,7 @@
<dependency>
<groupId>kryptonbutterfly</groupId>
<artifactId>linear_algebra</artifactId>
<version>3.0.0</version>
<version>4.0.0</version>
</dependency>
</dependencies>

Expand Down
2 changes: 2 additions & 0 deletions src/kryptonbutterfly/totp/TinyTotp.java
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ private static void setLookAndFeel()
| SecurityException e)
{
e.printStackTrace();
System.err.println("Failed setting program dock name. — Ignoring");
}

try
Expand All @@ -138,6 +139,7 @@ private static void setLookAndFeel()
| UnsupportedLookAndFeelException e)
{
e.printStackTrace();
System.err.println("Failed to apply System look and feel. – Ignoring");
}
}

Expand Down
1 change: 1 addition & 0 deletions src/kryptonbutterfly/totp/TotpConstants.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ public interface TotpConstants

public static final String LABEL_ACCOUNT_NAME = "Account Name";
public static final String LABEL_SECRET_KEY = "Secret Key";
public static final String LABEL_HASH_ALGO = "Hash Algorithm";
public static final String LABEL_ISSUER = "Issuer";
public static final String LABEL_CATEGORY = "Category";
public static final String LABEL_PASSWORD_INTERVAL = "Password interval in s";
Expand Down
2 changes: 1 addition & 1 deletion src/kryptonbutterfly/totp/misc/TotpGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public static String generateTotp(TotpEntry entry, char[] password, long current
entry.decryptSecret(password),
steps,
entry.totpLength,
"HmacSHA1");
"Hmac" + entry.algorithm);
}

@SneakyThrows
Expand Down
42 changes: 0 additions & 42 deletions src/kryptonbutterfly/totp/misc/UrlQueryParams.java

This file was deleted.

26 changes: 26 additions & 0 deletions src/kryptonbutterfly/totp/misc/otp/Digits.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package kryptonbutterfly.totp.misc.otp;

enum Digits
{
_6(6),
_7(7),
_8(8);

public final int digits;

Digits(int digits)
{
this.digits = digits;
}

public static Digits of(String value)
{
return switch (value)
{
case "6" -> _6;
case "7" -> _7;
case "8" -> _8;
default -> null;
};
}
}
97 changes: 97 additions & 0 deletions src/kryptonbutterfly/totp/misc/otp/OtpUri.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package kryptonbutterfly.totp.misc.otp;

import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.util.HashMap;

import kryptonbutterfly.totp.prefs.OtpAlgo;

public sealed interface OtpUri permits TotpUri
{
static final String PROTOCOL_TERMINATOR = "://";
static final String PROTOCOL = "otpauth://";
static final String TYPE_TERMINATOR = "/";
static final String PATH_TERMINATOR = "?";
static final String PARAM_DELIM = "=";
static final String QUERY_DELIM = "&";
static final String ISSUER_TERMINATOR = ":";

static final String SECRET = "secret";
static final String ALGORITHM = "algorithm";
static final String DIGITS = "digits";
static final String COUNTER = "counter";
static final String PERIOD = "period";
static final String ISSUER = "issuer";

public static final int DEFAULT_PERIOD = 30;
public static final Digits DEFAULT_DIGITS = Digits._6;
public static final OtpAlgo DEFAULT_ALGO = OtpAlgo.SHA1;

public String toStringUrl();

public String account();

public String secret();

public OtpAlgo algorithm();

public int digits();

public int counter();

public int period();

public String type();

public String issuer();

public static OtpUri parseOtpUrl(String url) throws MalformedURLException, URISyntaxException
{
if (!url.startsWith(PROTOCOL))
{
final int term = url.indexOf(PROTOCOL_TERMINATOR);
if (term < 0)
throw new MalformedURLException("No protocol specified.");
final var protocol = url.substring(term);
throw new MalformedURLException(
"Invalid protocol '%s' for OTP URL. Expected %s.".formatted(protocol, PROTOCOL));
}
final var urlPart = url.substring(PROTOCOL.length());

final int typeTerm = urlPart.indexOf(TYPE_TERMINATOR);
if (typeTerm < 0)
throw new MalformedURLException("OTP URL is missing type declaration!");
final var type = urlPart.substring(0, typeTerm);
return switch (type)
{
case "totp" -> TotpUri.parse(url);
case "htop" -> throw new IllegalStateException(
"HTOP's currently are not supported.");
default -> throw new MalformedURLException(
"'%s' is not a valid OTP type!".formatted(type));
};
}

public static String buildOtpUriString(OtpUri uri, HashMap<String, String> query)
{
final var sb = new StringBuilder(PROTOCOL)
.append(uri.type())
.append(TYPE_TERMINATOR)
.append(uri.account())
.append(PATH_TERMINATOR);

boolean isFirst = true;
for (final var p : query.entrySet())
{
if (isFirst)
isFirst = false;
else
sb.append(QUERY_DELIM);
sb.append(p.getKey())
.append(PARAM_DELIM)
.append(p.getValue());
}

return sb.toString();
}
}
Loading

0 comments on commit 2a5d289

Please sign in to comment.