mirror of
https://github.com/beemdevelopment/Aegis.git
synced 2025-05-14 05:52:52 +00:00
Merge branch 'master' of https://github.com/alexbakker/Aegis
This commit is contained in:
commit
855f5e519f
12 changed files with 103 additions and 328 deletions
|
@ -1,88 +0,0 @@
|
|||
package me.impy.aegis;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.support.design.widget.FloatingActionButton;
|
||||
import android.os.Bundle;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
|
||||
import me.impy.aegis.crypto.KeyInfo;
|
||||
|
||||
public class AddProfileActivity extends AegisActivity {
|
||||
private KeyProfile _keyProfile;
|
||||
|
||||
private EditText _profileName;
|
||||
private TextView _textAlgorithm;
|
||||
private TextView _textIssuer;
|
||||
private TextView _textPeriod;
|
||||
private TextView _textOtp;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
setContentView(R.layout.activity_add_profile);
|
||||
|
||||
_profileName = findViewById(R.id.addProfileName);
|
||||
_textAlgorithm = findViewById(R.id.tvAlgorithm);
|
||||
_textIssuer = findViewById(R.id.tvIssuer);
|
||||
_textPeriod = findViewById(R.id.tvPeriod);
|
||||
_textOtp = findViewById(R.id.tvOtp);
|
||||
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
getSupportActionBar().setDisplayShowTitleEnabled(false);
|
||||
|
||||
_keyProfile = (KeyProfile) getIntent().getSerializableExtra("KeyProfile");
|
||||
|
||||
initializeForm();
|
||||
|
||||
FloatingActionButton fab = findViewById(R.id.fab);
|
||||
fab.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
Intent resultIntent = new Intent();
|
||||
|
||||
_keyProfile.getEntry().setName(_profileName.getText().toString());
|
||||
resultIntent.putExtra("KeyProfile", _keyProfile);
|
||||
|
||||
setResult(Activity.RESULT_OK, resultIntent);
|
||||
finish();
|
||||
}
|
||||
});
|
||||
//_profileName.setText(_keyProfile.Info.getAccountName());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setPreferredTheme(boolean nightMode) {
|
||||
if (nightMode) {
|
||||
setTheme(R.style.AppTheme_Dark_TransparentActionBar);
|
||||
} else {
|
||||
setTheme(R.style.AppTheme_Default_TransparentActionBar);
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeForm() {
|
||||
KeyInfo info = _keyProfile.getEntry().getInfo();
|
||||
_profileName.setText(info.getAccountName());
|
||||
_textAlgorithm.setText(info.getAlgorithm(false));
|
||||
_textIssuer.setText(info.getIssuer());
|
||||
_textPeriod.setText(info.getPeriod() + " seconds");
|
||||
|
||||
String otp = _keyProfile.refreshCode();
|
||||
_textOtp.setText(otp.substring(0, 3) + " " + otp.substring(3));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case android.R.id.home:
|
||||
onBackPressed();
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,8 +1,6 @@
|
|||
package me.impy.aegis;
|
||||
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Context;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Process;
|
||||
|
||||
import javax.crypto.SecretKey;
|
||||
|
@ -10,14 +8,12 @@ import javax.crypto.SecretKey;
|
|||
import me.impy.aegis.crypto.CryptoUtils;
|
||||
import me.impy.aegis.crypto.slots.PasswordSlot;
|
||||
|
||||
public class DerivationTask extends AsyncTask<DerivationTask.Params, Void, SecretKey> {
|
||||
public class DerivationTask extends ProgressDialogTask<DerivationTask.Params, SecretKey> {
|
||||
private Callback _cb;
|
||||
private ProgressDialog _dialog;
|
||||
|
||||
public DerivationTask(Context context, Callback cb) {
|
||||
super(context, "Deriving key from password");
|
||||
_cb = cb;
|
||||
_dialog = new ProgressDialog(context);
|
||||
_dialog.setCancelable(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -35,17 +31,9 @@ public class DerivationTask extends AsyncTask<DerivationTask.Params, Void, Secre
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
_dialog.setMessage("Deriving key from password");
|
||||
_dialog.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(SecretKey key) {
|
||||
if (_dialog.isShowing()) {
|
||||
_dialog.dismiss();
|
||||
}
|
||||
super.onPostExecute(key);
|
||||
_cb.onTaskFinished(key);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,8 @@ import android.widget.EditText;
|
|||
import android.widget.ImageView;
|
||||
import android.widget.Spinner;
|
||||
|
||||
import com.amulyakhare.textdrawable.TextDrawable;
|
||||
|
||||
import me.impy.aegis.crypto.CryptoUtils;
|
||||
import me.impy.aegis.crypto.KeyInfo;
|
||||
import me.impy.aegis.crypto.KeyInfoException;
|
||||
|
@ -23,12 +25,15 @@ import me.impy.aegis.db.DatabaseEntry;
|
|||
import me.impy.aegis.encoding.Base32;
|
||||
import me.impy.aegis.helpers.AuthHelper;
|
||||
import me.impy.aegis.helpers.SpinnerHelper;
|
||||
import me.impy.aegis.helpers.TextDrawableHelper;
|
||||
|
||||
public class EditProfileActivity extends AegisActivity {
|
||||
private boolean _isNew = false;
|
||||
private boolean _edited = false;
|
||||
private KeyProfile _profile;
|
||||
|
||||
private ImageView _iconView;
|
||||
|
||||
private EditText _textName;
|
||||
private EditText _textIssuer;
|
||||
private EditText _textPeriod;
|
||||
|
@ -49,13 +54,17 @@ public class EditProfileActivity extends AegisActivity {
|
|||
bar.setDisplayHomeAsUpEnabled(true);
|
||||
|
||||
// if the intent doesn't contain a KeyProfile, create a new one
|
||||
_profile = (KeyProfile) getIntent().getSerializableExtra("KeyProfile");
|
||||
Intent intent = getIntent();
|
||||
_profile = (KeyProfile) intent.getSerializableExtra("KeyProfile");
|
||||
_isNew = intent.getBooleanExtra("isNew", false);
|
||||
if (_profile == null) {
|
||||
_isNew = true;
|
||||
_profile = new KeyProfile();
|
||||
}
|
||||
if (_isNew) {
|
||||
setTitle("Add profile");
|
||||
}
|
||||
|
||||
_iconView = findViewById(R.id.profile_drawable);
|
||||
_textName = findViewById(R.id.text_name);
|
||||
_textIssuer = findViewById(R.id.text_issuer);
|
||||
_textPeriod = findViewById(R.id.text_period);
|
||||
|
@ -79,12 +88,24 @@ public class EditProfileActivity extends AegisActivity {
|
|||
_spinnerAlgo.setOnItemSelectedListener(_selectedListener);
|
||||
_spinnerDigits.setOnTouchListener(_selectedListener);
|
||||
_spinnerDigits.setOnItemSelectedListener(_selectedListener);
|
||||
|
||||
// update the icon if the text changed
|
||||
_textName.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) { }
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
TextDrawable drawable = TextDrawableHelper.generate(s.toString());
|
||||
_iconView.setImageDrawable(drawable);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void updateFields() {
|
||||
DatabaseEntry entry = _profile.getEntry();
|
||||
ImageView imageView = findViewById(R.id.profile_drawable);
|
||||
imageView.setImageDrawable(_profile.getDrawable());
|
||||
_iconView.setImageDrawable(_profile.getDrawable());
|
||||
|
||||
_textName.setText(entry.getName());
|
||||
_textIssuer.setText(entry.getInfo().getIssuer());
|
||||
|
|
|
@ -8,6 +8,7 @@ import java.lang.reflect.UndeclaredThrowableException;
|
|||
|
||||
import me.impy.aegis.crypto.otp.OTP;
|
||||
import me.impy.aegis.db.DatabaseEntry;
|
||||
import me.impy.aegis.helpers.TextDrawableHelper;
|
||||
|
||||
public class KeyProfile implements Serializable {
|
||||
private String _code;
|
||||
|
@ -38,14 +39,6 @@ public class KeyProfile implements Serializable {
|
|||
}
|
||||
|
||||
public TextDrawable getDrawable() {
|
||||
String name = _entry.getName();
|
||||
if (name == null || name.length() <= 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ColorGenerator generator = ColorGenerator.MATERIAL;
|
||||
int color = generator.getColor(name);
|
||||
|
||||
return TextDrawable.builder().buildRound(name.substring(0, 1).toUpperCase(), color);
|
||||
return TextDrawableHelper.generate(getEntry().getName());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -326,9 +326,17 @@ public class MainActivity extends AegisActivity implements KeyProfileView.Listen
|
|||
saveDatabase();
|
||||
}
|
||||
|
||||
private void onEnterKeyInfo() {
|
||||
private void startEditProfileActivity(int requestCode, KeyProfile profile, boolean isNew) {
|
||||
Intent intent = new Intent(this, EditProfileActivity.class);
|
||||
startActivityForResult(intent, CODE_ENTER_KEYINFO);
|
||||
if (profile != null) {
|
||||
intent.putExtra("KeyProfile", profile);
|
||||
}
|
||||
intent.putExtra("isNew", isNew);
|
||||
startActivityForResult(intent, requestCode);
|
||||
}
|
||||
|
||||
private void onEnterKeyInfo() {
|
||||
startEditProfileActivity(CODE_ENTER_KEYINFO, null, true);
|
||||
}
|
||||
|
||||
private void onScanKeyInfo() {
|
||||
|
@ -341,10 +349,8 @@ public class MainActivity extends AegisActivity implements KeyProfileView.Listen
|
|||
|
||||
private void onScanKeyInfoResult(int resultCode, Intent data) {
|
||||
if (resultCode == RESULT_OK) {
|
||||
KeyProfile keyProfile = (KeyProfile)data.getSerializableExtra("KeyProfile");
|
||||
Intent intent = new Intent(this, AddProfileActivity.class);
|
||||
intent.putExtra("KeyProfile", keyProfile);
|
||||
startActivityForResult(intent, CODE_ADD_KEYINFO);
|
||||
KeyProfile profile = (KeyProfile)data.getSerializableExtra("KeyProfile");
|
||||
startEditProfileActivity(CODE_ADD_KEYINFO, profile, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -509,9 +515,7 @@ public class MainActivity extends AegisActivity implements KeyProfileView.Listen
|
|||
|
||||
editLayout.setOnClickListener(view -> {
|
||||
bottomDialog.dismiss();
|
||||
Intent intent = new Intent(this, EditProfileActivity.class);
|
||||
intent.putExtra("KeyProfile", profile);
|
||||
startActivityForResult(intent, CODE_EDIT_KEYINFO);
|
||||
startEditProfileActivity(CODE_EDIT_KEYINFO, profile, false);
|
||||
});
|
||||
|
||||
return bottomDialog;
|
||||
|
|
34
app/src/main/java/me/impy/aegis/ProgressDialogTask.java
Normal file
34
app/src/main/java/me/impy/aegis/ProgressDialogTask.java
Normal file
|
@ -0,0 +1,34 @@
|
|||
package me.impy.aegis;
|
||||
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Context;
|
||||
import android.os.AsyncTask;
|
||||
import android.support.annotation.CallSuper;
|
||||
|
||||
public abstract class ProgressDialogTask<Params, Result> extends AsyncTask<Params, Void, Result> {
|
||||
private ProgressDialog _dialog;
|
||||
|
||||
public ProgressDialogTask(Context context, String message) {
|
||||
_dialog = new ProgressDialog(context);
|
||||
_dialog.setCancelable(false);
|
||||
_dialog.setMessage(message);
|
||||
}
|
||||
|
||||
@CallSuper
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
_dialog.show();
|
||||
}
|
||||
|
||||
@CallSuper
|
||||
@Override
|
||||
protected void onPostExecute(Result result) {
|
||||
if (_dialog.isShowing()) {
|
||||
_dialog.dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
protected final ProgressDialog getDialog() {
|
||||
return _dialog;
|
||||
}
|
||||
}
|
|
@ -58,6 +58,7 @@ public class ScannerActivity extends AegisActivity implements ZXingScannerView.R
|
|||
try {
|
||||
KeyInfo info = KeyInfo.fromURL(rawResult.getText());
|
||||
KeyProfile profile = new KeyProfile(new DatabaseEntry(info));
|
||||
profile.getEntry().setName(info.getAccountName());
|
||||
|
||||
Intent resultIntent = new Intent();
|
||||
resultIntent.putExtra("KeyProfile", profile);
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
package me.impy.aegis;
|
||||
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Context;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Process;
|
||||
|
||||
import java.lang.reflect.UndeclaredThrowableException;
|
||||
|
@ -18,16 +16,14 @@ import me.impy.aegis.crypto.slots.Slot;
|
|||
import me.impy.aegis.crypto.slots.SlotCollection;
|
||||
import me.impy.aegis.crypto.slots.SlotIntegrityException;
|
||||
|
||||
public class SlotCollectionTask<T extends Slot> extends AsyncTask<SlotCollectionTask.Params, Void, MasterKey> {
|
||||
public class SlotCollectionTask<T extends Slot> extends ProgressDialogTask<SlotCollectionTask.Params, MasterKey> {
|
||||
private Callback _cb;
|
||||
private Class<T> _type;
|
||||
private ProgressDialog _dialog;
|
||||
|
||||
public SlotCollectionTask(Class<T> type, Context context, Callback cb) {
|
||||
super(context, "Decrypting database");
|
||||
_cb = cb;
|
||||
_type = type;
|
||||
_dialog = new ProgressDialog(context);
|
||||
_dialog.setCancelable(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -70,17 +66,9 @@ public class SlotCollectionTask<T extends Slot> extends AsyncTask<SlotCollection
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
_dialog.setMessage("Decrypting database");
|
||||
_dialog.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(MasterKey masterKey) {
|
||||
if (_dialog.isShowing()) {
|
||||
_dialog.dismiss();
|
||||
}
|
||||
super.onPostExecute(masterKey);
|
||||
_cb.onTaskFinished(masterKey);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
package me.impy.aegis.helpers;
|
||||
|
||||
import com.amulyakhare.textdrawable.TextDrawable;
|
||||
import com.amulyakhare.textdrawable.util.ColorGenerator;
|
||||
|
||||
public class TextDrawableHelper {
|
||||
private TextDrawableHelper() {
|
||||
|
||||
}
|
||||
|
||||
public static TextDrawable generate(String s) {
|
||||
if (s == null || s.length() <= 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ColorGenerator generator = ColorGenerator.MATERIAL;
|
||||
int color = generator.getColor(s);
|
||||
return TextDrawable.builder().buildRound(s.substring(0, 1).toUpperCase(), color);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue