parent
f616350aae
commit
c17bc0dbfb
5 changed files with 58 additions and 6 deletions
|
@ -93,11 +93,13 @@ public class MainActivity extends BaseActivity
|
|||
final EditText labelInput = (EditText) inputView.findViewById(R.id.manual_label);
|
||||
final EditText secretInput = (EditText) inputView.findViewById(R.id.manual_secret);
|
||||
final EditText periodInput = (EditText) inputView.findViewById(R.id.manual_period);
|
||||
final EditText digitsInput = (EditText) inputView.findViewById(R.id.manual_digits);
|
||||
final Spinner algorithmInput = (Spinner) inputView.findViewById(R.id.manual_algorithm);
|
||||
|
||||
typeInput.setAdapter(new ArrayAdapter<>(this, android.R.layout.simple_expandable_list_item_1, Entry.OTPType.values()));
|
||||
algorithmInput.setAdapter(new ArrayAdapter<>(this, android.R.layout.simple_expandable_list_item_1, TokenCalculator.HashAlgorithm.values()));
|
||||
periodInput.setText(Integer.toString(TokenCalculator.TOTP_DEFAULT_PERIOD));
|
||||
digitsInput.setText(Integer.toString(TokenCalculator.TOTP_DEFAULT_DIGITS));
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
builder.setTitle(R.string.dialog_title_manual_entry)
|
||||
|
@ -112,8 +114,9 @@ public class MainActivity extends BaseActivity
|
|||
String label = labelInput.getText().toString();
|
||||
String secret = secretInput.getText().toString();
|
||||
int period = Integer.parseInt(periodInput.getText().toString());
|
||||
int digits = Integer.parseInt(digitsInput.getText().toString());
|
||||
|
||||
Entry e = new Entry(type, secret, period, label, algorithm);
|
||||
Entry e = new Entry(type, secret, period, digits, label, algorithm);
|
||||
e.updateOTP();
|
||||
adapter.addEntry(e);
|
||||
adapter.saveEntries();
|
||||
|
|
|
@ -42,11 +42,13 @@ public class Entry {
|
|||
private static final String JSON_SECRET = "secret";
|
||||
private static final String JSON_LABEL = "label";
|
||||
private static final String JSON_PERIOD = "period";
|
||||
private static final String JSON_DIGITS = "digits";
|
||||
private static final String JSON_TYPE = "type";
|
||||
private static final String JSON_ALGORITHM = "algorithm";
|
||||
|
||||
private OTPType type = OTPType.TOTP;
|
||||
private int period = TokenCalculator.TOTP_DEFAULT_PERIOD;
|
||||
private int digits = TokenCalculator.TOTP_DEFAULT_DIGITS;
|
||||
private TokenCalculator.HashAlgorithm algorithm = TokenCalculator.DEFAULT_ALGORITHM;
|
||||
private byte[] secret;
|
||||
private String label;
|
||||
|
@ -55,10 +57,11 @@ public class Entry {
|
|||
|
||||
public Entry(){}
|
||||
|
||||
public Entry(OTPType type, String secret, int period, String label, TokenCalculator.HashAlgorithm algorithm) {
|
||||
public Entry(OTPType type, String secret, int period, int digits, String label, TokenCalculator.HashAlgorithm algorithm) {
|
||||
this.type = type;
|
||||
this.secret = new Base32().decode(secret.toUpperCase());
|
||||
this.period = period;
|
||||
this.digits = digits;
|
||||
this.label = label;
|
||||
this.algorithm = algorithm;
|
||||
}
|
||||
|
@ -83,6 +86,7 @@ public class Entry {
|
|||
|
||||
String issuer = uri.getQueryParameter("issuer");
|
||||
String period = uri.getQueryParameter("period");
|
||||
String digits = uri.getQueryParameter("digits");
|
||||
String algorithm = uri.getQueryParameter("algorithm");
|
||||
|
||||
if(issuer != null){
|
||||
|
@ -98,6 +102,12 @@ public class Entry {
|
|||
this.period = TokenCalculator.TOTP_DEFAULT_PERIOD;
|
||||
}
|
||||
|
||||
if (digits != null) {
|
||||
this.digits = Integer.parseInt(digits);
|
||||
} else {
|
||||
this.digits = TokenCalculator.TOTP_DEFAULT_DIGITS;
|
||||
}
|
||||
|
||||
if (algorithm != null) {
|
||||
this.algorithm = TokenCalculator.HashAlgorithm.valueOf(algorithm.toUpperCase());
|
||||
} else {
|
||||
|
@ -110,6 +120,12 @@ public class Entry {
|
|||
this.label = jsonObj.getString(JSON_LABEL);
|
||||
this.period = jsonObj.getInt(JSON_PERIOD);
|
||||
|
||||
try {
|
||||
this.digits = jsonObj.getInt(JSON_DIGITS);
|
||||
} catch(JSONException e) {
|
||||
this.digits = TokenCalculator.TOTP_DEFAULT_DIGITS;
|
||||
}
|
||||
|
||||
try {
|
||||
this.type = OTPType.valueOf(jsonObj.getString(JSON_TYPE));
|
||||
} catch(JSONException e) {
|
||||
|
@ -128,6 +144,7 @@ public class Entry {
|
|||
jsonObj.put(JSON_SECRET, new String(new Base32().encode(getSecret())));
|
||||
jsonObj.put(JSON_LABEL, getLabel());
|
||||
jsonObj.put(JSON_PERIOD, getPeriod());
|
||||
jsonObj.put(JSON_DIGITS, getDigits());
|
||||
jsonObj.put(JSON_TYPE, getType().toString());
|
||||
jsonObj.put(JSON_ALGORITHM, algorithm.toString());
|
||||
|
||||
|
@ -166,6 +183,14 @@ public class Entry {
|
|||
this.period = period;
|
||||
}
|
||||
|
||||
public int getDigits() {
|
||||
return digits;
|
||||
}
|
||||
|
||||
public void setDigits(int digits) {
|
||||
this.digits = digits;
|
||||
}
|
||||
|
||||
public TokenCalculator.HashAlgorithm getAlgorithm() {
|
||||
return this.algorithm;
|
||||
}
|
||||
|
@ -187,7 +212,7 @@ public class Entry {
|
|||
long counter = time / this.getPeriod();
|
||||
|
||||
if (counter > last_update) {
|
||||
currentOTP = TokenCalculator.TOTP(secret, period, algorithm);
|
||||
currentOTP = TokenCalculator.TOTP(secret, period, digits, algorithm);
|
||||
last_update = counter;
|
||||
|
||||
return true;
|
||||
|
@ -202,6 +227,7 @@ public class Entry {
|
|||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Entry entry = (Entry) o;
|
||||
return period == entry.period &&
|
||||
digits == entry.digits &&
|
||||
type == entry.type &&
|
||||
algorithm == entry.algorithm &&
|
||||
Arrays.equals(secret, entry.secret) &&
|
||||
|
@ -210,6 +236,6 @@ public class Entry {
|
|||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(type, period, algorithm, secret, label);
|
||||
return Objects.hash(type, period, digits, algorithm, secret, label);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ import javax.crypto.spec.SecretKeySpec;
|
|||
|
||||
public class TokenCalculator {
|
||||
public static final int TOTP_DEFAULT_PERIOD = 30;
|
||||
public static final int TOTP_DEFAULT_DIGITS = 6;
|
||||
|
||||
public enum HashAlgorithm {
|
||||
SHA1, SHA256, SHA512
|
||||
|
@ -50,8 +51,8 @@ public class TokenCalculator {
|
|||
return mac.doFinal(data);
|
||||
}
|
||||
|
||||
public static String TOTP(byte[] secret, int period, HashAlgorithm algorithm) {
|
||||
return String.format("%06d", TOTP(secret, period, System.currentTimeMillis() / 1000, 6, algorithm));
|
||||
public static String TOTP(byte[] secret, int period, int digits, HashAlgorithm algorithm) {
|
||||
return String.format("%0" + digits + "d", TOTP(secret, period, System.currentTimeMillis() / 1000, digits, algorithm));
|
||||
}
|
||||
|
||||
public static int TOTP(byte[] key, int period, long time, int digits, HashAlgorithm algorithm)
|
||||
|
|
|
@ -86,6 +86,27 @@
|
|||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal" >
|
||||
|
||||
<TextView
|
||||
android:layout_weight="2"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/label_digits"/>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/manual_digits"
|
||||
android:layout_weight="7"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="number"
|
||||
android:hint="@string/label_digits"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
<string name="label_type">Type</string>
|
||||
<string name="label_secret">Secret</string>
|
||||
<string name="label_period">Period</string>
|
||||
<string name="label_digits">Digits</string>
|
||||
<string name="label_label">Label</string>
|
||||
<string name="label_algorithm">Algorithm</string>
|
||||
|
||||
|
|
Loading…
Reference in a new issue