TOTP QR Scan: Set account name from otpauth label

This commit is contained in:
Eldad Zack
2022-02-01 18:46:53 +01:00
parent f922dc5ec4
commit e0c4c452be
3 changed files with 43 additions and 45 deletions
@@ -125,8 +125,9 @@ class AddTOTPActivity : AppCompatActivity() {
if (result != null) {
if (result.contents != null) {
try {
val secretKey = TOTPHelper.getSecretKey(result.contents)
mViewModel.setSecretKey(secretKey)
val totp = TOTPHelper(result.contents)
mViewModel.setSecretKey(totp.secret)
mViewModel.setAccountName(totp.label)
} catch (e: Exception) {
e.printStackTrace()
}
@@ -70,6 +70,10 @@ class AddTOTPViewModel @Inject constructor(private val appDatabase: com.yogeshpa
this.secretKey.value = secretKey
}
fun setAccountName(accountName: String) {
this.accountName.value = accountName
}
fun deleteAccount(accountId: String, onDeleted: () -> Unit) {
viewModelScope.launch {
appDatabase.getDao().deleteAccount(accountId)
@@ -5,61 +5,54 @@ import android.net.Uri;
import org.apache.commons.codec.binary.Base32;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Locale;
import java.net.URLDecoder;
public class TOTPHelper {
public static final String SHA1 = "HmacSHA1";
public String secret;
public String label;
public String issuer;
public static String generate(String secret) {
return String.format(Locale.getDefault(), "%06d", generate(new Base32().decode(secret.toUpperCase()), System.currentTimeMillis() / 1000, 6));
}
public static long getProgress() {
return 30 - ((System.currentTimeMillis() / 1000) % 30);
}
public static String getSecretKey(String contents) throws Exception {
contents = contents.replaceFirst("otpauth", "http");
Uri uri = Uri.parse(contents);
URL url = new URL(contents);
if (!url.getProtocol().equals("http")) {
throw new Exception("Invalid Protocol");
}
if (!url.getHost().equals("totp")) {
throw new Exception("unknown otp type");
}
String secret = uri.getQueryParameter("secret");
if (secret == null)
throw new Exception("Empty secret");
return secret;
}
public static int generate(byte[] key, long t, int digits) {
return TokenCalculator.TOTP_RFC6238(key, 30, t, digits, TokenCalculator.DEFAULT_ALGORITHM, 0);
}
/**
* Returns the label with issuer prefix removed (if present)
*
* @param issuer - Name of the issuer to remove from the label
* @param label - Full label from which the issuer should be removed
* @return - label with the issuer removed
*/
private static String getStrippedLabel(String issuer, String label) {
if (issuer == null || issuer.isEmpty() || !label.startsWith(issuer + ":")) {
return label.trim();
} else {
return label.substring(issuer.length() + 1).trim();
}
public static long getProgress() {
return 30 - ((System.currentTimeMillis() / 1000) % 30);
}
public TOTPHelper(String uriString) throws Exception {
uriString = uriString.replaceFirst("otpauth", "http");
Uri uri = Uri.parse(uriString);
URL url = new URL(uriString);
label = url.getPath().substring(1); // Remove leading slash `/`
label = URLDecoder.decode(label, StandardCharsets.UTF_8.toString());
if (!url.getProtocol().equals("http")) {
throw new Exception("Invalid Protocol");
}
if (!url.getHost().equals("totp")) {
throw new Exception("unknown otp type");
}
secret = uri.getQueryParameter("secret");
if (secret == null)
throw new Exception("Empty secret");
issuer = uri.getQueryParameter("issuer");
if (issuer == null) {
issuer = "";
}
}
}