Try the encryption change in the SettingsActivity and restore backup if it fails
This commit is contained in:
parent
64fbdd93d3
commit
a20dc326bc
7 changed files with 193 additions and 80 deletions
|
@ -53,16 +53,13 @@ import static org.shadowice.flocke.andotp.Utilities.Constants.AuthMethod;
|
|||
public class AuthenticateActivity extends ThemedActivity
|
||||
implements EditText.OnEditorActionListener {
|
||||
public static final String AUTH_EXTRA_NAME_PASSWORD_KEY = "password_key";
|
||||
public static final String AUTH_EXTRA_NAME_FATAL = "fatal";
|
||||
public static final String AUTH_EXTRA_NAME_SAVE_DATABASE = "save_database";
|
||||
public static final String AUTH_EXTRA_NAME_NEW_ENCRYPTION = "new_encryption";
|
||||
public static final String AUTH_EXTRA_NAME_MESSAGE = "message";
|
||||
|
||||
boolean saveDatabase = false;
|
||||
boolean fatal = true;
|
||||
|
||||
private String password;
|
||||
|
||||
AuthMethod authMethod;
|
||||
String newEncryption = "";
|
||||
boolean oldPassword = false;
|
||||
|
||||
TextInputEditText passwordInput;
|
||||
|
@ -84,8 +81,7 @@ public class AuthenticateActivity extends ThemedActivity
|
|||
|
||||
Intent callingIntent = getIntent();
|
||||
int labelMsg = callingIntent.getIntExtra(AUTH_EXTRA_NAME_MESSAGE, R.string.auth_msg_authenticate);
|
||||
saveDatabase = callingIntent.getBooleanExtra(AUTH_EXTRA_NAME_SAVE_DATABASE, false);
|
||||
fatal = callingIntent.getBooleanExtra(AUTH_EXTRA_NAME_FATAL, true);
|
||||
newEncryption = callingIntent.getStringExtra(AUTH_EXTRA_NAME_NEW_ENCRYPTION);
|
||||
|
||||
TextView passwordLabel = v.findViewById(R.id.passwordLabel);
|
||||
TextInputLayout passwordLayout = v.findViewById(R.id.passwordLayout);
|
||||
|
@ -173,26 +169,18 @@ public class AuthenticateActivity extends ThemedActivity
|
|||
|
||||
// End with a result
|
||||
public void finishWithResult(boolean success, byte[] key) {
|
||||
if (success || fatal) {
|
||||
Intent data = new Intent();
|
||||
Intent data = new Intent();
|
||||
|
||||
data.putExtra(AUTH_EXTRA_NAME_SAVE_DATABASE, saveDatabase);
|
||||
if (newEncryption != null && ! newEncryption.isEmpty())
|
||||
data.putExtra(AUTH_EXTRA_NAME_NEW_ENCRYPTION, newEncryption);
|
||||
|
||||
if (key != null)
|
||||
data.putExtra(AUTH_EXTRA_NAME_PASSWORD_KEY, key);
|
||||
if (key != null)
|
||||
data.putExtra(AUTH_EXTRA_NAME_PASSWORD_KEY, key);
|
||||
|
||||
if (success)
|
||||
setResult(RESULT_OK, data);
|
||||
if (success)
|
||||
setResult(RESULT_OK, data);
|
||||
|
||||
finish();
|
||||
} else {
|
||||
passwordInput.setText("");
|
||||
|
||||
if (authMethod == AuthMethod.PASSWORD)
|
||||
Toast.makeText(this, R.string.auth_toast_password_again, Toast.LENGTH_LONG).show();
|
||||
else if (authMethod == AuthMethod.PIN)
|
||||
Toast.makeText(this, R.string.auth_toast_pin_again, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
finish();
|
||||
}
|
||||
|
||||
// Go back to the main activity
|
||||
|
|
|
@ -62,7 +62,6 @@ import java.nio.charset.StandardCharsets;
|
|||
import java.util.ArrayList;
|
||||
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
public class BackupActivity extends BaseActivity {
|
||||
private final static int INTENT_OPEN_DOCUMENT_PLAIN = 200;
|
||||
|
@ -88,7 +87,7 @@ public class BackupActivity extends BaseActivity {
|
|||
private static final String DEFAULT_BACKUP_MIMETYPE_CRYPT = "binary/aes";
|
||||
private static final String DEFAULT_BACKUP_MIMETYPE_PGP = "application/pgp-encrypted";
|
||||
|
||||
public static final String EXTRA_NAME_ENCRYPTION_KEY = "encryption_key";
|
||||
public static final String BACKUP_EXTRA_NAME_ENCRYPTION_KEY = "encryption_key";
|
||||
|
||||
private SecretKey encryptionKey = null;
|
||||
|
||||
|
@ -117,8 +116,8 @@ public class BackupActivity extends BaseActivity {
|
|||
View v = stub.inflate();
|
||||
|
||||
Intent callingIntent = getIntent();
|
||||
byte[] keyMaterial = callingIntent.getByteArrayExtra(EXTRA_NAME_ENCRYPTION_KEY);
|
||||
encryptionKey = new SecretKeySpec(keyMaterial, 0, keyMaterial.length, "AES");
|
||||
byte[] keyMaterial = callingIntent.getByteArrayExtra(BACKUP_EXTRA_NAME_ENCRYPTION_KEY);
|
||||
encryptionKey = EncryptionHelper.generateSymmetricKey(keyMaterial);
|
||||
|
||||
// Plain-text
|
||||
|
||||
|
|
|
@ -72,11 +72,9 @@ import java.util.HashMap;
|
|||
|
||||
import javax.crypto.SecretKey;
|
||||
|
||||
import static org.shadowice.flocke.andotp.Activities.AuthenticateActivity.AUTH_EXTRA_NAME_FATAL;
|
||||
import static org.shadowice.flocke.andotp.Activities.AuthenticateActivity.AUTH_EXTRA_NAME_MESSAGE;
|
||||
import static org.shadowice.flocke.andotp.Activities.AuthenticateActivity.AUTH_EXTRA_NAME_PASSWORD_KEY;
|
||||
import static org.shadowice.flocke.andotp.Activities.AuthenticateActivity.AUTH_EXTRA_NAME_SAVE_DATABASE;
|
||||
import static org.shadowice.flocke.andotp.Activities.BackupActivity.EXTRA_NAME_ENCRYPTION_KEY;
|
||||
import static org.shadowice.flocke.andotp.Activities.BackupActivity.BACKUP_EXTRA_NAME_ENCRYPTION_KEY;
|
||||
import static org.shadowice.flocke.andotp.Activities.SettingsActivity.SETTINGS_EXTRA_NAME_ENCRYPTION_CHANGED;
|
||||
import static org.shadowice.flocke.andotp.Activities.SettingsActivity.SETTINGS_EXTRA_NAME_ENCRYPTION_KEY;
|
||||
import static org.shadowice.flocke.andotp.Utilities.Constants.AuthMethod;
|
||||
|
@ -130,7 +128,7 @@ public class MainActivity extends BaseActivity
|
|||
.show();
|
||||
}
|
||||
|
||||
public void authenticate(int messageId, boolean saveDatabase, boolean fatal) {
|
||||
public void authenticate(int messageId) {
|
||||
AuthMethod authMethod = settings.getAuthMethod();
|
||||
|
||||
if (authMethod == AuthMethod.DEVICE) {
|
||||
|
@ -141,8 +139,6 @@ public class MainActivity extends BaseActivity
|
|||
}
|
||||
} else if (authMethod == AuthMethod.PASSWORD || authMethod == AuthMethod.PIN) {
|
||||
Intent authIntent = new Intent(this, AuthenticateActivity.class);
|
||||
authIntent.putExtra(AUTH_EXTRA_NAME_SAVE_DATABASE, saveDatabase);
|
||||
authIntent.putExtra(AUTH_EXTRA_NAME_FATAL, fatal);
|
||||
authIntent.putExtra(AUTH_EXTRA_NAME_MESSAGE, messageId);
|
||||
startActivityForResult(authIntent, INTENT_INTERNAL_AUTHENTICATE);
|
||||
}
|
||||
|
@ -324,7 +320,7 @@ public class MainActivity extends BaseActivity
|
|||
if (requireAuthentication) {
|
||||
if (settings.getAuthMethod() != AuthMethod.NONE) {
|
||||
requireAuthentication = false;
|
||||
authenticate(R.string.auth_msg_authenticate,false, true);
|
||||
authenticate(R.string.auth_msg_authenticate);
|
||||
}
|
||||
} else {
|
||||
if (encryptionType == EncryptionType.KEYSTORE) {
|
||||
|
@ -335,7 +331,7 @@ public class MainActivity extends BaseActivity
|
|||
populateAdapter();
|
||||
} else if (encryptionType == EncryptionType.PASSWORD) {
|
||||
if (adapter.getEncryptionKey() == null) {
|
||||
authenticate(R.string.auth_msg_authenticate,false, true);
|
||||
authenticate(R.string.auth_msg_authenticate);
|
||||
} else {
|
||||
populateAdapter();
|
||||
}
|
||||
|
@ -396,11 +392,10 @@ public class MainActivity extends BaseActivity
|
|||
}
|
||||
} else if (requestCode == INTENT_INTERNAL_SETTINGS && resultCode == RESULT_OK) {
|
||||
boolean encryptionChanged = intent.getBooleanExtra(SETTINGS_EXTRA_NAME_ENCRYPTION_CHANGED, false);
|
||||
byte[] newKey = intent.getByteArrayExtra(SETTINGS_EXTRA_NAME_ENCRYPTION_KEY);
|
||||
|
||||
if (encryptionChanged) {
|
||||
byte[] newKey = intent.getByteArrayExtra(SETTINGS_EXTRA_NAME_ENCRYPTION_KEY);
|
||||
updateEncryption(newKey, true);
|
||||
}
|
||||
if (encryptionChanged)
|
||||
updateEncryption(newKey);
|
||||
} else if (requestCode == INTENT_INTERNAL_AUTHENTICATE) {
|
||||
if (resultCode != RESULT_OK) {
|
||||
Toast.makeText(getBaseContext(), R.string.toast_auth_failed_fatal, Toast.LENGTH_LONG).show();
|
||||
|
@ -413,15 +408,13 @@ public class MainActivity extends BaseActivity
|
|||
} else {
|
||||
requireAuthentication = false;
|
||||
|
||||
boolean saveDatabase = intent.getBooleanExtra(AUTH_EXTRA_NAME_SAVE_DATABASE, false);
|
||||
byte[] authKey = intent.getByteArrayExtra(AUTH_EXTRA_NAME_PASSWORD_KEY);
|
||||
|
||||
updateEncryption(authKey, saveDatabase);
|
||||
updateEncryption(authKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateEncryption(byte[] newKey, boolean saveDatabase) {
|
||||
private void updateEncryption(byte[] newKey) {
|
||||
SecretKey encryptionKey = null;
|
||||
|
||||
encryptionType = settings.getEncryption();
|
||||
|
@ -432,17 +425,13 @@ public class MainActivity extends BaseActivity
|
|||
if (newKey != null && newKey.length > 0) {
|
||||
encryptionKey = EncryptionHelper.generateSymmetricKey(newKey);
|
||||
} else {
|
||||
authenticate(R.string.auth_msg_confirm_encryption, true, false);
|
||||
authenticate(R.string.auth_msg_confirm_encryption);
|
||||
}
|
||||
}
|
||||
|
||||
if (encryptionKey != null) {
|
||||
if (encryptionKey != null)
|
||||
adapter.setEncryptionKey(encryptionKey);
|
||||
|
||||
if (saveDatabase)
|
||||
adapter.saveEntries();
|
||||
}
|
||||
|
||||
populateAdapter();
|
||||
}
|
||||
|
||||
|
@ -520,10 +509,11 @@ public class MainActivity extends BaseActivity
|
|||
|
||||
if (id == R.id.action_backup) {
|
||||
Intent backupIntent = new Intent(this, BackupActivity.class);
|
||||
backupIntent.putExtra(EXTRA_NAME_ENCRYPTION_KEY, adapter.getEncryptionKey().getEncoded());
|
||||
backupIntent.putExtra(BACKUP_EXTRA_NAME_ENCRYPTION_KEY, adapter.getEncryptionKey().getEncoded());
|
||||
startActivityForResult(backupIntent, INTENT_INTERNAL_BACKUP);
|
||||
} else if (id == R.id.action_settings) {
|
||||
Intent settingsIntent = new Intent(this, SettingsActivity.class);
|
||||
settingsIntent.putExtra(SETTINGS_EXTRA_NAME_ENCRYPTION_KEY, adapter.getEncryptionKey().getEncoded());
|
||||
startActivityForResult(settingsIntent, INTENT_INTERNAL_SETTINGS);
|
||||
} else if (id == R.id.action_about){
|
||||
Intent aboutIntent = new Intent(this, AboutActivity.class);
|
||||
|
|
|
@ -36,21 +36,36 @@ import android.widget.Toast;
|
|||
|
||||
import org.openintents.openpgp.util.OpenPgpAppPreference;
|
||||
import org.openintents.openpgp.util.OpenPgpKeyPreference;
|
||||
import org.shadowice.flocke.andotp.Database.Entry;
|
||||
import org.shadowice.flocke.andotp.Preferences.CredentialsPreference;
|
||||
import org.shadowice.flocke.andotp.R;
|
||||
import org.shadowice.flocke.andotp.Utilities.DatabaseHelper;
|
||||
import org.shadowice.flocke.andotp.Utilities.EncryptionHelper;
|
||||
import org.shadowice.flocke.andotp.Utilities.KeyStoreHelper;
|
||||
import org.shadowice.flocke.andotp.Utilities.Settings;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import javax.crypto.SecretKey;
|
||||
|
||||
import static org.shadowice.flocke.andotp.Activities.AuthenticateActivity.AUTH_EXTRA_NAME_MESSAGE;
|
||||
import static org.shadowice.flocke.andotp.Activities.AuthenticateActivity.AUTH_EXTRA_NAME_NEW_ENCRYPTION;
|
||||
import static org.shadowice.flocke.andotp.Activities.AuthenticateActivity.AUTH_EXTRA_NAME_PASSWORD_KEY;
|
||||
import static org.shadowice.flocke.andotp.Utilities.Constants.AuthMethod;
|
||||
import static org.shadowice.flocke.andotp.Utilities.Constants.EncryptionType;
|
||||
|
||||
public class SettingsActivity extends BaseActivity
|
||||
implements SharedPreferences.OnSharedPreferenceChangeListener{
|
||||
private static final int INTENT_INTERNAL_AUTHENTICATE = 300;
|
||||
|
||||
public static final String SETTINGS_EXTRA_NAME_ENCRYPTION_CHANGED = "encryption_changed";
|
||||
public static final String SETTINGS_EXTRA_NAME_ENCRYPTION_KEY = "encryption_key";
|
||||
|
||||
SettingsFragment fragment;
|
||||
|
||||
SecretKey encryptionKey = null;
|
||||
boolean encryptionChanged = false;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
@ -64,6 +79,10 @@ public class SettingsActivity extends BaseActivity
|
|||
ViewStub stub = findViewById(R.id.container_stub);
|
||||
stub.inflate();
|
||||
|
||||
Intent callingIntent = getIntent();
|
||||
byte[] keyMaterial = callingIntent.getByteArrayExtra(SETTINGS_EXTRA_NAME_ENCRYPTION_KEY);
|
||||
encryptionKey = EncryptionHelper.generateSymmetricKey(keyMaterial);
|
||||
|
||||
fragment = new SettingsFragment();
|
||||
|
||||
getFragmentManager().beginTransaction()
|
||||
|
@ -74,13 +93,11 @@ public class SettingsActivity extends BaseActivity
|
|||
sharedPref.registerOnSharedPreferenceChangeListener(this);
|
||||
}
|
||||
|
||||
public void finishWithResult(boolean encryptionChanged, byte[] newKey) {
|
||||
public void finishWithResult() {
|
||||
Intent data = new Intent();
|
||||
|
||||
data.putExtra(SETTINGS_EXTRA_NAME_ENCRYPTION_CHANGED, encryptionChanged);
|
||||
|
||||
if (newKey != null)
|
||||
data.putExtra(SETTINGS_EXTRA_NAME_ENCRYPTION_KEY, newKey);
|
||||
data.putExtra(SETTINGS_EXTRA_NAME_ENCRYPTION_KEY, encryptionKey.getEncoded());
|
||||
|
||||
setResult(RESULT_OK, data);
|
||||
finish();
|
||||
|
@ -88,13 +105,13 @@ public class SettingsActivity extends BaseActivity
|
|||
|
||||
@Override
|
||||
public boolean onSupportNavigateUp() {
|
||||
finishWithResult(false,null);
|
||||
finishWithResult();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
finishWithResult(false, null);
|
||||
finishWithResult();
|
||||
super.onBackPressed();
|
||||
}
|
||||
|
||||
|
@ -106,10 +123,75 @@ public class SettingsActivity extends BaseActivity
|
|||
}
|
||||
}
|
||||
|
||||
private void tryEncryptionChangeWithAuth(EncryptionType newEnc) {
|
||||
Intent authIntent = new Intent(this, AuthenticateActivity.class);
|
||||
authIntent.putExtra(AUTH_EXTRA_NAME_NEW_ENCRYPTION, newEnc.name());
|
||||
authIntent.putExtra(AUTH_EXTRA_NAME_MESSAGE, R.string.auth_msg_confirm_encryption);
|
||||
startActivityForResult(authIntent, INTENT_INTERNAL_AUTHENTICATE);
|
||||
}
|
||||
|
||||
private boolean tryEncryptionChange(EncryptionType newEnc, byte[] newKey) {
|
||||
Toast upgrading = Toast.makeText(this, R.string.settings_toast_encryption_changing, Toast.LENGTH_LONG);
|
||||
upgrading.show();
|
||||
|
||||
if (DatabaseHelper.backupDatabase(this)) {
|
||||
ArrayList<Entry> entries = DatabaseHelper.loadDatabase(this, encryptionKey);
|
||||
|
||||
SecretKey newEncryptionKey;
|
||||
|
||||
if (newEnc == EncryptionType.KEYSTORE) {
|
||||
newEncryptionKey = KeyStoreHelper.loadEncryptionKeyFromKeyStore(this);
|
||||
} else if (newKey != null && newKey.length > 0) {
|
||||
newEncryptionKey = EncryptionHelper.generateSymmetricKey(newKey);
|
||||
} else {
|
||||
upgrading.cancel();
|
||||
DatabaseHelper.restoreDatabaseBackup(this);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (DatabaseHelper.saveDatabase(this, entries, newEncryptionKey)) {
|
||||
encryptionKey = newEncryptionKey;
|
||||
encryptionChanged = true;
|
||||
|
||||
fragment.encryption.setValue(newEnc.name().toLowerCase());
|
||||
|
||||
upgrading.cancel();
|
||||
Toast.makeText(this, R.string.settings_toast_encryption_change_success, Toast.LENGTH_LONG).show();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
DatabaseHelper.restoreDatabaseBackup(this);
|
||||
|
||||
upgrading.cancel();
|
||||
Toast.makeText(this, R.string.settings_toast_encryption_change_failed, Toast.LENGTH_LONG).show();
|
||||
} else {
|
||||
upgrading.cancel();
|
||||
Toast.makeText(this, R.string.settings_toast_encryption_backup_failed, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
if (fragment.pgpKey.handleOnActivityResult(requestCode, resultCode, data)) {
|
||||
|
||||
if (requestCode == INTENT_INTERNAL_AUTHENTICATE) {
|
||||
if (resultCode == RESULT_OK) {
|
||||
byte[] authKey = data.getByteArrayExtra(AUTH_EXTRA_NAME_PASSWORD_KEY);
|
||||
String newEnc = data.getStringExtra(AUTH_EXTRA_NAME_NEW_ENCRYPTION);
|
||||
|
||||
if (authKey != null && authKey.length > 0 && newEnc != null && !newEnc.isEmpty()) {
|
||||
EncryptionType newEncType = EncryptionType.valueOf(newEnc);
|
||||
tryEncryptionChange(newEncType, authKey);
|
||||
} else {
|
||||
Toast.makeText(this, R.string.settings_toast_encryption_no_key, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
} else {
|
||||
Toast.makeText(this, R.string.settings_toast_encryption_auth_failed, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
} else if (fragment.pgpKey.handleOnActivityResult(requestCode, resultCode, data)) {
|
||||
// handled by OpenPgpKeyPreference
|
||||
return;
|
||||
}
|
||||
|
@ -134,10 +216,10 @@ public class SettingsActivity extends BaseActivity
|
|||
addPreferencesFromResource(R.xml.preferences);
|
||||
|
||||
CredentialsPreference credentialsPreference = (CredentialsPreference) findPreference(getString(R.string.settings_key_auth));
|
||||
credentialsPreference.setEncryptionChangeHandler(new CredentialsPreference.EncryptionChangeHandler() {
|
||||
credentialsPreference.setEncryptionChangeCallback(new CredentialsPreference.EncryptionChangeCallback() {
|
||||
@Override
|
||||
public void onEncryptionChanged(byte[] newKey) {
|
||||
((SettingsActivity) getActivity()).finishWithResult(true, newKey);
|
||||
public boolean testEncryptionChange(byte[] newKey) {
|
||||
return ((SettingsActivity) getActivity()).tryEncryptionChange(settings.getEncryption(), newKey);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -160,16 +242,15 @@ public class SettingsActivity extends BaseActivity
|
|||
if (settings.getAuthCredentials(authMethod).isEmpty()) {
|
||||
Toast.makeText(getActivity(), R.string.settings_toast_encryption_invalid_without_credentials, Toast.LENGTH_LONG).show();
|
||||
return false;
|
||||
} else {
|
||||
KeyStoreHelper.wipeKeys(preference.getContext());
|
||||
}
|
||||
}
|
||||
|
||||
((SettingsActivity) getActivity()).tryEncryptionChangeWithAuth(encryptionType);
|
||||
} else if (encryptionType == EncryptionType.KEYSTORE) {
|
||||
((SettingsActivity) getActivity()).tryEncryptionChange(encryptionType, null);
|
||||
}
|
||||
|
||||
encryption.setValue(newEncryption);
|
||||
((SettingsActivity) getActivity()).finishWithResult(true, null);
|
||||
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -25,7 +25,6 @@ package org.shadowice.flocke.andotp.Preferences;
|
|||
import android.app.AlertDialog;
|
||||
import android.app.KeyguardManager;
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.preference.DialogPreference;
|
||||
import android.support.design.widget.TextInputEditText;
|
||||
import android.support.design.widget.TextInputLayout;
|
||||
|
@ -34,7 +33,6 @@ import android.text.InputType;
|
|||
import android.text.TextWatcher;
|
||||
import android.text.method.PasswordTransformationMethod;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Base64;
|
||||
import android.view.View;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ArrayAdapter;
|
||||
|
@ -45,15 +43,11 @@ import android.widget.ListView;
|
|||
import android.widget.Toast;
|
||||
|
||||
import org.shadowice.flocke.andotp.R;
|
||||
import org.shadowice.flocke.andotp.Utilities.EncryptionHelper;
|
||||
import org.shadowice.flocke.andotp.Utilities.Settings;
|
||||
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static android.content.Context.AUDIO_SERVICE;
|
||||
import static android.content.Context.KEYGUARD_SERVICE;
|
||||
import static org.shadowice.flocke.andotp.Utilities.Constants.AuthMethod;
|
||||
import static org.shadowice.flocke.andotp.Utilities.Constants.EncryptionType;
|
||||
|
@ -62,8 +56,8 @@ public class CredentialsPreference extends DialogPreference
|
|||
implements AdapterView.OnItemClickListener, View.OnClickListener, TextWatcher {
|
||||
public static final AuthMethod DEFAULT_VALUE = AuthMethod.NONE;
|
||||
|
||||
public interface EncryptionChangeHandler {
|
||||
void onEncryptionChanged(byte[] newKey);
|
||||
public interface EncryptionChangeCallback {
|
||||
boolean testEncryptionChange(byte[] newKey);
|
||||
}
|
||||
|
||||
private List<String> entries;
|
||||
|
@ -76,7 +70,7 @@ public class CredentialsPreference extends DialogPreference
|
|||
|
||||
private Settings settings;
|
||||
private AuthMethod value = AuthMethod.NONE;
|
||||
private EncryptionChangeHandler handler = null;
|
||||
private EncryptionChangeCallback encryptionChangeCallback = null;
|
||||
|
||||
private LinearLayout credentialsLayout;
|
||||
private TextInputLayout passwordLayout;
|
||||
|
@ -94,8 +88,8 @@ public class CredentialsPreference extends DialogPreference
|
|||
setDialogLayoutResource(R.layout.component_authentication);
|
||||
}
|
||||
|
||||
public void setEncryptionChangeHandler(EncryptionChangeHandler handler) {
|
||||
this.handler = handler;
|
||||
public void setEncryptionChangeCallback(EncryptionChangeCallback cb) {
|
||||
this.encryptionChangeCallback = cb;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -184,11 +178,16 @@ public class CredentialsPreference extends DialogPreference
|
|||
}
|
||||
}
|
||||
|
||||
if (settings.getEncryption() == EncryptionType.PASSWORD) {
|
||||
if (newKey == null || encryptionChangeCallback == null)
|
||||
return;
|
||||
|
||||
if (! encryptionChangeCallback.testEncryptionChange(newKey))
|
||||
return;
|
||||
}
|
||||
|
||||
persistString(value.toString().toLowerCase());
|
||||
setSummary(entries.get(entryValues.indexOf(value)));
|
||||
|
||||
if (settings.getEncryption() == EncryptionType.PASSWORD && newKey != null && handler != null)
|
||||
handler.onEncryptionChanged(newKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -31,18 +31,63 @@ import org.shadowice.flocke.andotp.Database.Entry;
|
|||
import org.shadowice.flocke.andotp.R;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import javax.crypto.SecretKey;
|
||||
|
||||
public class DatabaseHelper {
|
||||
public static final String SETTINGS_FILE = "secrets.dat";
|
||||
public static final String SETTINGS_FILE_BACKUP = "secrets.dat.bck";
|
||||
|
||||
public static void wipeDatabase(Context context) {
|
||||
File db = new File(context.getFilesDir() + "/" + SETTINGS_FILE);
|
||||
db.delete();
|
||||
}
|
||||
|
||||
private static void copyFile(File src, File dst)
|
||||
throws IOException {
|
||||
try (InputStream in = new FileInputStream(src)) {
|
||||
try (OutputStream out = new FileOutputStream(dst)) {
|
||||
byte[] buffer = new byte[1024];
|
||||
int len;
|
||||
while ((len = in.read(buffer)) > 0) {
|
||||
out.write(buffer, 0, len);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean backupDatabase(Context context) {
|
||||
File original = new File(context.getFilesDir() + "/" + SETTINGS_FILE);
|
||||
File backup = new File(context.getFilesDir() + "/" + SETTINGS_FILE_BACKUP);
|
||||
|
||||
try {
|
||||
copyFile(original, backup);
|
||||
} catch (IOException e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean restoreDatabaseBackup(Context context) {
|
||||
File original = new File(context.getFilesDir() + "/" + SETTINGS_FILE);
|
||||
File backup = new File(context.getFilesDir() + "/" + SETTINGS_FILE_BACKUP);
|
||||
|
||||
try {
|
||||
copyFile(backup, original);
|
||||
} catch (IOException e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Database functions */
|
||||
public static boolean saveDatabase(Context context, ArrayList<Entry> entries, SecretKey encryptionKey) {
|
||||
if (encryptionKey == null) {
|
||||
|
|
|
@ -75,6 +75,17 @@
|
|||
<string name="settings_toast_encryption_invalid_without_credentials">You first need to set a
|
||||
Password or PIN before changing the encryption!</string>
|
||||
|
||||
<string name="settings_toast_encryption_changing">Trying to change the database encryption,
|
||||
please wait!</string>
|
||||
<string name="settings_toast_encryption_change_success">Successfully changed the database
|
||||
encryption!</string>
|
||||
<string name="settings_toast_encryption_change_failed">Failed to change database encryption,
|
||||
restored database from internal backup!</string>
|
||||
<string name="settings_toast_encryption_backup_failed">Failed to create an internal
|
||||
backup, aborting!</string>
|
||||
<string name="settings_toast_encryption_no_key">Failed to get the encryption key, aborting!</string>
|
||||
<string name="settings_toast_encryption_auth_failed">Authentication failed, aborting!</string>
|
||||
|
||||
<string name="settings_toast_auth_upgrade_failed">Failed to silently upgrade your password / PIN
|
||||
to the new encryption, please manually reset it in the settings!</string>
|
||||
|
||||
|
|
Loading…
Reference in a new issue