Implement manual entry of HOTP accounts
This commit is contained in:
parent
c8d47ca3bf
commit
e76b3c3b96
4 changed files with 75 additions and 6 deletions
|
@ -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 static final int HOTP_INITIAL_COUNTER = 1;
|
||||
public static final int STEAM_DEFAULT_DIGITS = 5;
|
||||
|
||||
private static final char[] STEAMCHARS = new char[] {
|
||||
|
|
|
@ -33,6 +33,7 @@ import android.widget.AdapterView;
|
|||
import android.widget.ArrayAdapter;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.Spinner;
|
||||
|
||||
import com.github.aakira.expandablelayout.ExpandableLayoutListenerAdapter;
|
||||
|
@ -57,8 +58,11 @@ public class ManualEntryDialog {
|
|||
final Spinner typeInput = inputView.findViewById(R.id.manual_type);
|
||||
final EditText labelInput = inputView.findViewById(R.id.manual_label);
|
||||
final EditText secretInput = inputView.findViewById(R.id.manual_secret);
|
||||
final EditText counterInput = inputView.findViewById(R.id.manual_counter);
|
||||
final EditText periodInput = inputView.findViewById(R.id.manual_period);
|
||||
final EditText digitsInput = inputView.findViewById(R.id.manual_digits);
|
||||
final LinearLayout counterLayout = inputView.findViewById(R.id.manual_layout_counter);
|
||||
final LinearLayout periodLayout = inputView.findViewById(R.id.manual_layout_period);
|
||||
final Spinner algorithmInput = inputView.findViewById(R.id.manual_algorithm);
|
||||
final Button tagsInput = inputView.findViewById(R.id.manual_tags);
|
||||
|
||||
|
@ -75,6 +79,7 @@ public class ManualEntryDialog {
|
|||
|
||||
periodInput.setText(String.format(Locale.US, "%d", TokenCalculator.TOTP_DEFAULT_PERIOD));
|
||||
digitsInput.setText(String.format(Locale.US, "%d", TokenCalculator.TOTP_DEFAULT_DIGITS));
|
||||
counterInput.setText(String.format(Locale.US, "%d", TokenCalculator.HOTP_INITIAL_COUNTER));
|
||||
|
||||
typeInput.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
||||
@Override
|
||||
|
@ -82,6 +87,9 @@ public class ManualEntryDialog {
|
|||
Entry.OTPType type = (Entry.OTPType) adapterView.getSelectedItem();
|
||||
|
||||
if (type == Entry.OTPType.STEAM) {
|
||||
counterLayout.setVisibility(View.GONE);
|
||||
periodLayout.setVisibility(View.VISIBLE);
|
||||
|
||||
digitsInput.setText(String.format(Locale.US, "%d", TokenCalculator.STEAM_DEFAULT_DIGITS));
|
||||
periodInput.setText(String.format(Locale.US, "%d", TokenCalculator.TOTP_DEFAULT_PERIOD));
|
||||
algorithmInput.setSelection(algorithmAdapter.getPosition(TokenCalculator.HashAlgorithm.SHA1));
|
||||
|
@ -89,7 +97,18 @@ public class ManualEntryDialog {
|
|||
digitsInput.setEnabled(false);
|
||||
periodInput.setEnabled(false);
|
||||
algorithmInput.setEnabled(false);
|
||||
} else {
|
||||
} else if (type == Entry.OTPType.TOTP) {
|
||||
counterLayout.setVisibility(View.GONE);
|
||||
periodLayout.setVisibility(View.VISIBLE);
|
||||
|
||||
digitsInput.setText(String.format(Locale.US, "%d", TokenCalculator.TOTP_DEFAULT_DIGITS));
|
||||
digitsInput.setEnabled(true);
|
||||
periodInput.setEnabled(true);
|
||||
algorithmInput.setEnabled(true);
|
||||
} else if (type == Entry.OTPType.HOTP) {
|
||||
counterLayout.setVisibility(View.VISIBLE);
|
||||
periodLayout.setVisibility(View.GONE);
|
||||
|
||||
digitsInput.setText(String.format(Locale.US, "%d", TokenCalculator.TOTP_DEFAULT_DIGITS));
|
||||
digitsInput.setEnabled(true);
|
||||
periodInput.setEnabled(true);
|
||||
|
@ -166,18 +185,26 @@ public class ManualEntryDialog {
|
|||
Entry.OTPType type = (Entry.OTPType) typeInput.getSelectedItem();
|
||||
TokenCalculator.HashAlgorithm algorithm = (TokenCalculator.HashAlgorithm) algorithmInput.getSelectedItem();
|
||||
|
||||
if (type == Entry.OTPType.TOTP || type == Entry.OTPType.STEAM) {
|
||||
String label = labelInput.getText().toString();
|
||||
String secret = secretInput.getText().toString();
|
||||
int period = Integer.parseInt(periodInput.getText().toString());
|
||||
int digits = Integer.parseInt(digitsInput.getText().toString());
|
||||
|
||||
if (type == Entry.OTPType.TOTP || type == Entry.OTPType.STEAM) {
|
||||
int period = Integer.parseInt(periodInput.getText().toString());
|
||||
|
||||
Entry e = new Entry(type, secret, period, digits, label, algorithm, tagsAdapter.getActiveTags());
|
||||
e.updateOTP();
|
||||
adapter.addEntry(e);
|
||||
adapter.saveEntries();
|
||||
|
||||
callingActivity.refreshTags();
|
||||
} else if (type == Entry.OTPType.HOTP) {
|
||||
long counter = Long.parseLong(counterInput.getText().toString());
|
||||
|
||||
Entry e = new Entry(type, secret, counter, digits, label, algorithm, tagsAdapter.getActiveTags());
|
||||
e.updateOTP();
|
||||
adapter.addEntry(e);
|
||||
adapter.saveEntries();
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -204,12 +231,26 @@ public class ManualEntryDialog {
|
|||
@Override
|
||||
public void afterTextChanged(Editable editable) {
|
||||
if (TextUtils.isEmpty(labelInput.getText()) || TextUtils.isEmpty(secretInput.getText())
|
||||
|| TextUtils.isEmpty(periodInput.getText()) || Integer.parseInt(periodInput.getText().toString()) == 0
|
||||
|| TextUtils.isEmpty(digitsInput.getText()) || Integer.parseInt(digitsInput.getText().toString()) == 0) {
|
||||
positiveButton.setEnabled(false);
|
||||
} else {
|
||||
Entry.OTPType type = (Entry.OTPType) typeInput.getSelectedItem();
|
||||
if (type == Entry.OTPType.HOTP) {
|
||||
if (TextUtils.isEmpty(counterInput.getText())) {
|
||||
positiveButton.setEnabled(false);
|
||||
} else {
|
||||
positiveButton.setEnabled(true);
|
||||
}
|
||||
} else if (type == Entry.OTPType.TOTP || type == Entry.OTPType.STEAM) {
|
||||
if (TextUtils.isEmpty(periodInput.getText()) || Integer.parseInt(periodInput.getText().toString()) == 0) {
|
||||
positiveButton.setEnabled(false);
|
||||
} else {
|
||||
positiveButton.setEnabled(true);
|
||||
}
|
||||
} else {
|
||||
positiveButton.setEnabled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -217,5 +258,6 @@ public class ManualEntryDialog {
|
|||
secretInput.addTextChangedListener(watcher);
|
||||
periodInput.addTextChangedListener(watcher);
|
||||
digitsInput.addTextChangedListener(watcher);
|
||||
counterInput.addTextChangedListener(watcher);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,6 +70,30 @@
|
|||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/manual_layout_counter"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:visibility="gone" >
|
||||
|
||||
<TextView
|
||||
android:layout_weight="3"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/label_counter"/>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/manual_counter"
|
||||
android:layout_weight="7"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="number"
|
||||
android:hint="@string/label_counter"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
@ -111,6 +135,7 @@
|
|||
app:ael_expanded="false">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/manual_layout_period"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
<string name="label_secret">Secret</string>
|
||||
<string name="label_period">Period</string>
|
||||
<string name="label_digits">Digits</string>
|
||||
<string name="label_counter">Counter</string>
|
||||
<string name="label_label">Label</string>
|
||||
<string name="label_algorithm">Algorithm</string>
|
||||
<string name="label_tags">Tags</string>
|
||||
|
|
Loading…
Reference in a new issue