Move a lot of the static constants to the Constants class
This commit is contained in:
parent
a3a285bebc
commit
bcc82f9d5b
15 changed files with 218 additions and 211 deletions
|
@ -32,8 +32,10 @@ import org.apache.commons.codec.binary.Hex;
|
|||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.shadowice.flocke.andotp.Database.Entry;
|
||||
import org.shadowice.flocke.andotp.Utilities.Constants;
|
||||
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.TokenCalculator;
|
||||
|
||||
import java.io.File;
|
||||
|
@ -52,11 +54,10 @@ import java.util.Arrays;
|
|||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
import static org.shadowice.flocke.andotp.Utilities.TokenCalculator.TOTP_DEFAULT_PERIOD;
|
||||
|
||||
public class ApplicationTest extends ApplicationTestCase<Application> {
|
||||
|
||||
public ApplicationTest() {
|
||||
|
@ -69,29 +70,29 @@ public class ApplicationTest extends ApplicationTestCase<Application> {
|
|||
byte[] keySHA256 = "12345678901234567890123456789012".getBytes(StandardCharsets.US_ASCII);
|
||||
byte[] keySHA512 = "1234567890123456789012345678901234567890123456789012345678901234".getBytes(StandardCharsets.US_ASCII);
|
||||
|
||||
assertEquals(94287082, TokenCalculator.TOTP_RFC6238(keySHA1, TOTP_DEFAULT_PERIOD, 59L, 8, TokenCalculator.HashAlgorithm.SHA1));
|
||||
assertEquals(46119246, TokenCalculator.TOTP_RFC6238(keySHA256, TOTP_DEFAULT_PERIOD, 59L, 8, TokenCalculator.HashAlgorithm.SHA256));
|
||||
assertEquals(90693936, TokenCalculator.TOTP_RFC6238(keySHA512, TOTP_DEFAULT_PERIOD, 59L, 8, TokenCalculator.HashAlgorithm.SHA512));
|
||||
assertEquals(94287082, TokenCalculator.TOTP_RFC6238(keySHA1, TokenCalculator.TOTP_DEFAULT_PERIOD, 59L, 8, TokenCalculator.HashAlgorithm.SHA1));
|
||||
assertEquals(46119246, TokenCalculator.TOTP_RFC6238(keySHA256, TokenCalculator.TOTP_DEFAULT_PERIOD, 59L, 8, TokenCalculator.HashAlgorithm.SHA256));
|
||||
assertEquals(90693936, TokenCalculator.TOTP_RFC6238(keySHA512, TokenCalculator.TOTP_DEFAULT_PERIOD, 59L, 8, TokenCalculator.HashAlgorithm.SHA512));
|
||||
|
||||
assertEquals(7081804, TokenCalculator.TOTP_RFC6238(keySHA1, TOTP_DEFAULT_PERIOD, 1111111109L, 8, TokenCalculator.HashAlgorithm.SHA1));
|
||||
assertEquals(68084774, TokenCalculator.TOTP_RFC6238(keySHA256, TOTP_DEFAULT_PERIOD, 1111111109L, 8, TokenCalculator.HashAlgorithm.SHA256));
|
||||
assertEquals(25091201, TokenCalculator.TOTP_RFC6238(keySHA512, TOTP_DEFAULT_PERIOD, 1111111109L, 8, TokenCalculator.HashAlgorithm.SHA512));
|
||||
assertEquals(7081804, TokenCalculator.TOTP_RFC6238(keySHA1, TokenCalculator.TOTP_DEFAULT_PERIOD, 1111111109L, 8, TokenCalculator.HashAlgorithm.SHA1));
|
||||
assertEquals(68084774, TokenCalculator.TOTP_RFC6238(keySHA256, TokenCalculator.TOTP_DEFAULT_PERIOD, 1111111109L, 8, TokenCalculator.HashAlgorithm.SHA256));
|
||||
assertEquals(25091201, TokenCalculator.TOTP_RFC6238(keySHA512, TokenCalculator.TOTP_DEFAULT_PERIOD, 1111111109L, 8, TokenCalculator.HashAlgorithm.SHA512));
|
||||
|
||||
assertEquals(14050471, TokenCalculator.TOTP_RFC6238(keySHA1, TOTP_DEFAULT_PERIOD, 1111111111L, 8, TokenCalculator.HashAlgorithm.SHA1));
|
||||
assertEquals(67062674, TokenCalculator.TOTP_RFC6238(keySHA256, TOTP_DEFAULT_PERIOD, 1111111111L, 8, TokenCalculator.HashAlgorithm.SHA256));
|
||||
assertEquals(99943326, TokenCalculator.TOTP_RFC6238(keySHA512, TOTP_DEFAULT_PERIOD, 1111111111L, 8, TokenCalculator.HashAlgorithm.SHA512));
|
||||
assertEquals(14050471, TokenCalculator.TOTP_RFC6238(keySHA1, TokenCalculator.TOTP_DEFAULT_PERIOD, 1111111111L, 8, TokenCalculator.HashAlgorithm.SHA1));
|
||||
assertEquals(67062674, TokenCalculator.TOTP_RFC6238(keySHA256, TokenCalculator.TOTP_DEFAULT_PERIOD, 1111111111L, 8, TokenCalculator.HashAlgorithm.SHA256));
|
||||
assertEquals(99943326, TokenCalculator.TOTP_RFC6238(keySHA512, TokenCalculator.TOTP_DEFAULT_PERIOD, 1111111111L, 8, TokenCalculator.HashAlgorithm.SHA512));
|
||||
|
||||
assertEquals(89005924, TokenCalculator.TOTP_RFC6238(keySHA1, TOTP_DEFAULT_PERIOD, 1234567890L, 8, TokenCalculator.HashAlgorithm.SHA1));
|
||||
assertEquals(91819424, TokenCalculator.TOTP_RFC6238(keySHA256, TOTP_DEFAULT_PERIOD, 1234567890L, 8, TokenCalculator.HashAlgorithm.SHA256));
|
||||
assertEquals(93441116, TokenCalculator.TOTP_RFC6238(keySHA512, TOTP_DEFAULT_PERIOD, 1234567890L, 8, TokenCalculator.HashAlgorithm.SHA512));
|
||||
assertEquals(89005924, TokenCalculator.TOTP_RFC6238(keySHA1, TokenCalculator.TOTP_DEFAULT_PERIOD, 1234567890L, 8, TokenCalculator.HashAlgorithm.SHA1));
|
||||
assertEquals(91819424, TokenCalculator.TOTP_RFC6238(keySHA256, TokenCalculator.TOTP_DEFAULT_PERIOD, 1234567890L, 8, TokenCalculator.HashAlgorithm.SHA256));
|
||||
assertEquals(93441116, TokenCalculator.TOTP_RFC6238(keySHA512, TokenCalculator.TOTP_DEFAULT_PERIOD, 1234567890L, 8, TokenCalculator.HashAlgorithm.SHA512));
|
||||
|
||||
assertEquals(69279037, TokenCalculator.TOTP_RFC6238(keySHA1, TOTP_DEFAULT_PERIOD, 2000000000L, 8, TokenCalculator.HashAlgorithm.SHA1));
|
||||
assertEquals(90698825, TokenCalculator.TOTP_RFC6238(keySHA256, TOTP_DEFAULT_PERIOD, 2000000000L, 8, TokenCalculator.HashAlgorithm.SHA256));
|
||||
assertEquals(38618901, TokenCalculator.TOTP_RFC6238(keySHA512, TOTP_DEFAULT_PERIOD, 2000000000L, 8, TokenCalculator.HashAlgorithm.SHA512));
|
||||
assertEquals(69279037, TokenCalculator.TOTP_RFC6238(keySHA1, TokenCalculator.TOTP_DEFAULT_PERIOD, 2000000000L, 8, TokenCalculator.HashAlgorithm.SHA1));
|
||||
assertEquals(90698825, TokenCalculator.TOTP_RFC6238(keySHA256, TokenCalculator.TOTP_DEFAULT_PERIOD, 2000000000L, 8, TokenCalculator.HashAlgorithm.SHA256));
|
||||
assertEquals(38618901, TokenCalculator.TOTP_RFC6238(keySHA512, TokenCalculator.TOTP_DEFAULT_PERIOD, 2000000000L, 8, TokenCalculator.HashAlgorithm.SHA512));
|
||||
|
||||
assertEquals(65353130, TokenCalculator.TOTP_RFC6238(keySHA1, TOTP_DEFAULT_PERIOD, 20000000000L, 8, TokenCalculator.HashAlgorithm.SHA1));
|
||||
assertEquals(77737706, TokenCalculator.TOTP_RFC6238(keySHA256, TOTP_DEFAULT_PERIOD, 20000000000L, 8, TokenCalculator.HashAlgorithm.SHA256));
|
||||
assertEquals(47863826, TokenCalculator.TOTP_RFC6238(keySHA512, TOTP_DEFAULT_PERIOD, 20000000000L, 8, TokenCalculator.HashAlgorithm.SHA512));
|
||||
assertEquals(65353130, TokenCalculator.TOTP_RFC6238(keySHA1, TokenCalculator.TOTP_DEFAULT_PERIOD, 20000000000L, 8, TokenCalculator.HashAlgorithm.SHA1));
|
||||
assertEquals(77737706, TokenCalculator.TOTP_RFC6238(keySHA256, TokenCalculator.TOTP_DEFAULT_PERIOD, 20000000000L, 8, TokenCalculator.HashAlgorithm.SHA256));
|
||||
assertEquals(47863826, TokenCalculator.TOTP_RFC6238(keySHA512, TokenCalculator.TOTP_DEFAULT_PERIOD, 20000000000L, 8, TokenCalculator.HashAlgorithm.SHA512));
|
||||
}
|
||||
|
||||
|
||||
|
@ -106,6 +107,8 @@ public class ApplicationTest extends ApplicationTestCase<Application> {
|
|||
"\"digits\":6," +
|
||||
"\"type\":\"TOTP\"," +
|
||||
"\"algorithm\":\"SHA1\"," +
|
||||
"\"thumbnail\":\"Default\"," +
|
||||
"\"last_used\":0," +
|
||||
"\"tags\":[\"test1\",\"test2\"]}";
|
||||
|
||||
Entry e = new Entry(new JSONObject(s));
|
||||
|
@ -170,10 +173,11 @@ public class ApplicationTest extends ApplicationTestCase<Application> {
|
|||
keyStore.load(null);
|
||||
keyStore.deleteEntry("settings");
|
||||
|
||||
new File(context.getFilesDir() + "/" + DatabaseHelper.SETTINGS_FILE).delete();
|
||||
new File(context.getFilesDir() + "/" + DatabaseHelper.KEY_FILE).delete();
|
||||
new File(context.getFilesDir() + "/" + Constants.FILENAME_DATABASE).delete();
|
||||
new File(context.getFilesDir() + "/" + Constants.FILENAME_ENCRYPTED_KEY).delete();
|
||||
|
||||
ArrayList<Entry> b = DatabaseHelper.loadDatabase(context);
|
||||
SecretKey encryptionKey = KeyStoreHelper.loadEncryptionKeyFromKeyStore(context);
|
||||
ArrayList<Entry> b = DatabaseHelper.loadDatabase(context, encryptionKey);
|
||||
assertEquals(0, b.size());
|
||||
|
||||
ArrayList<Entry> a = new ArrayList<>();
|
||||
|
@ -187,13 +191,13 @@ public class ApplicationTest extends ApplicationTestCase<Application> {
|
|||
e.setSecret("secret2".getBytes());
|
||||
a.add(e);
|
||||
|
||||
DatabaseHelper.saveDatabase(context, a);
|
||||
b = DatabaseHelper.loadDatabase(context);
|
||||
DatabaseHelper.saveDatabase(context, a, encryptionKey);
|
||||
b = DatabaseHelper.loadDatabase(context, encryptionKey);
|
||||
|
||||
assertEquals(a, b);
|
||||
|
||||
new File(context.getFilesDir() + "/" + DatabaseHelper.SETTINGS_FILE).delete();
|
||||
new File(context.getFilesDir() + "/" + DatabaseHelper.KEY_FILE).delete();
|
||||
new File(context.getFilesDir() + "/" + Constants.FILENAME_DATABASE).delete();
|
||||
new File(context.getFilesDir() + "/" + Constants.FILENAME_ENCRYPTED_KEY).delete();
|
||||
}
|
||||
|
||||
public void testEncryptionHelper() throws NoSuchPaddingException, BadPaddingException, InvalidKeyException, NoSuchAlgorithmException, IllegalBlockSizeException, UnsupportedEncodingException, InvalidAlgorithmParameterException, DecoderException {
|
||||
|
|
|
@ -42,6 +42,7 @@ import android.widget.Toast;
|
|||
import org.apache.commons.codec.binary.Hex;
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
import org.shadowice.flocke.andotp.R;
|
||||
import org.shadowice.flocke.andotp.Utilities.Constants;
|
||||
import org.shadowice.flocke.andotp.Utilities.EncryptionHelper;
|
||||
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
@ -52,10 +53,6 @@ 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_NEW_ENCRYPTION = "new_encryption";
|
||||
public static final String AUTH_EXTRA_NAME_MESSAGE = "message";
|
||||
|
||||
private String password;
|
||||
|
||||
AuthMethod authMethod;
|
||||
|
@ -80,8 +77,8 @@ public class AuthenticateActivity extends ThemedActivity
|
|||
View v = stub.inflate();
|
||||
|
||||
Intent callingIntent = getIntent();
|
||||
int labelMsg = callingIntent.getIntExtra(AUTH_EXTRA_NAME_MESSAGE, R.string.auth_msg_authenticate);
|
||||
newEncryption = callingIntent.getStringExtra(AUTH_EXTRA_NAME_NEW_ENCRYPTION);
|
||||
int labelMsg = callingIntent.getIntExtra(Constants.EXTRA_AUTH_MESSAGE, R.string.auth_msg_authenticate);
|
||||
newEncryption = callingIntent.getStringExtra(Constants.EXTRA_AUTH_NEW_ENCRYPTION);
|
||||
|
||||
TextView passwordLabel = v.findViewById(R.id.passwordLabel);
|
||||
TextInputLayout passwordLayout = v.findViewById(R.id.passwordLayout);
|
||||
|
@ -172,10 +169,10 @@ public class AuthenticateActivity extends ThemedActivity
|
|||
Intent data = new Intent();
|
||||
|
||||
if (newEncryption != null && ! newEncryption.isEmpty())
|
||||
data.putExtra(AUTH_EXTRA_NAME_NEW_ENCRYPTION, newEncryption);
|
||||
data.putExtra(Constants.EXTRA_AUTH_NEW_ENCRYPTION, newEncryption);
|
||||
|
||||
if (key != null)
|
||||
data.putExtra(AUTH_EXTRA_NAME_PASSWORD_KEY, key);
|
||||
data.putExtra(Constants.EXTRA_AUTH_PASSWORD_KEY, key);
|
||||
|
||||
if (success)
|
||||
setResult(RESULT_OK, data);
|
||||
|
|
|
@ -50,6 +50,7 @@ import org.openintents.openpgp.util.OpenPgpApi;
|
|||
import org.openintents.openpgp.util.OpenPgpServiceConnection;
|
||||
import org.shadowice.flocke.andotp.Database.Entry;
|
||||
import org.shadowice.flocke.andotp.R;
|
||||
import org.shadowice.flocke.andotp.Utilities.Constants;
|
||||
import org.shadowice.flocke.andotp.Utilities.DatabaseHelper;
|
||||
import org.shadowice.flocke.andotp.Utilities.EncryptionHelper;
|
||||
import org.shadowice.flocke.andotp.Utilities.FileHelper;
|
||||
|
@ -64,31 +65,6 @@ import java.util.ArrayList;
|
|||
import javax.crypto.SecretKey;
|
||||
|
||||
public class BackupActivity extends BaseActivity {
|
||||
private final static int INTENT_OPEN_DOCUMENT_PLAIN = 200;
|
||||
private final static int INTENT_SAVE_DOCUMENT_PLAIN = 201;
|
||||
private final static int INTENT_OPEN_DOCUMENT_CRYPT = 202;
|
||||
private final static int INTENT_SAVE_DOCUMENT_CRYPT = 203;
|
||||
private final static int INTENT_OPEN_DOCUMENT_PGP = 204;
|
||||
private final static int INTENT_SAVE_DOCUMENT_PGP = 205;
|
||||
private final static int INTENT_ENCRYPT_PGP = 206;
|
||||
private final static int INTENT_DECRYPT_PGP = 207;
|
||||
|
||||
private final static int PERMISSIONS_REQUEST_READ_IMPORT_PLAIN = 210;
|
||||
private final static int PERMISSIONS_REQUEST_WRITE_EXPORT_PLAIN = 211;
|
||||
private final static int PERMISSIONS_REQUEST_READ_IMPORT_CRYPT = 212;
|
||||
private final static int PERMISSIONS_REQUEST_WRITE_EXPORT_CRYPT = 213;
|
||||
private final static int PERMISSIONS_REQUEST_READ_IMPORT_PGP = 214;
|
||||
private final static int PERMISSIONS_REQUEST_WRITE_EXPORT_PGP = 215;
|
||||
|
||||
private static final String DEFAULT_BACKUP_FILENAME_PLAIN = "otp_accounts.json";
|
||||
private static final String DEFAULT_BACKUP_FILENAME_CRYPT = "otp_accounts.json.aes";
|
||||
private static final String DEFAULT_BACKUP_FILENAME_PGP = "otp_accounts.json.gpg";
|
||||
private static final String DEFAULT_BACKUP_MIMETYPE_PLAIN = "application/json";
|
||||
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 BACKUP_EXTRA_NAME_ENCRYPTION_KEY = "encryption_key";
|
||||
|
||||
private SecretKey encryptionKey = null;
|
||||
|
||||
private OpenPgpServiceConnection pgpServiceConnection;
|
||||
|
@ -116,7 +92,7 @@ public class BackupActivity extends BaseActivity {
|
|||
View v = stub.inflate();
|
||||
|
||||
Intent callingIntent = getIntent();
|
||||
byte[] keyMaterial = callingIntent.getByteArrayExtra(BACKUP_EXTRA_NAME_ENCRYPTION_KEY);
|
||||
byte[] keyMaterial = callingIntent.getByteArrayExtra(Constants.EXTRA_BACKUP_ENCRYPTION_KEY);
|
||||
encryptionKey = EncryptionHelper.generateSymmetricKey(keyMaterial);
|
||||
|
||||
// Plain-text
|
||||
|
@ -134,7 +110,7 @@ public class BackupActivity extends BaseActivity {
|
|||
restorePlain.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
openFileWithPermissions(INTENT_OPEN_DOCUMENT_PLAIN, PERMISSIONS_REQUEST_READ_IMPORT_PLAIN);
|
||||
openFileWithPermissions(Constants.INTENT_BACKUP_OPEN_DOCUMENT_PLAIN, Constants.PERMISSIONS_BACKUP_READ_IMPORT_PLAIN);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -157,14 +133,14 @@ public class BackupActivity extends BaseActivity {
|
|||
backupCrypt.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
saveFileWithPermissions(DEFAULT_BACKUP_MIMETYPE_CRYPT, DEFAULT_BACKUP_FILENAME_CRYPT, INTENT_SAVE_DOCUMENT_CRYPT, PERMISSIONS_REQUEST_WRITE_EXPORT_CRYPT);
|
||||
saveFileWithPermissions(Constants.BACKUP_MIMETYPE_CRYPT, Constants.BACKUP_FILENAME_CRYPT, Constants.INTENT_BACKUP_SAVE_DOCUMENT_CRYPT, Constants.PERMISSIONS_BACKUP_WRITE_EXPORT_CRYPT);
|
||||
}
|
||||
});
|
||||
|
||||
restoreCrypt.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
openFileWithPermissions(INTENT_OPEN_DOCUMENT_CRYPT, PERMISSIONS_REQUEST_READ_IMPORT_CRYPT);
|
||||
openFileWithPermissions(Constants.INTENT_BACKUP_OPEN_DOCUMENT_CRYPT, Constants.PERMISSIONS_BACKUP_READ_IMPORT_CRYPT);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -192,14 +168,14 @@ public class BackupActivity extends BaseActivity {
|
|||
backupPGP.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
saveFileWithPermissions(DEFAULT_BACKUP_MIMETYPE_PGP, DEFAULT_BACKUP_FILENAME_PGP, INTENT_SAVE_DOCUMENT_PGP, PERMISSIONS_REQUEST_WRITE_EXPORT_PGP);
|
||||
saveFileWithPermissions(Constants.BACKUP_MIMETYPE_PGP, Constants.BACKUP_FILENAME_PGP, Constants.INTENT_BACKUP_SAVE_DOCUMENT_PGP, Constants.PERMISSIONS_BACKUP_WRITE_EXPORT_PGP);
|
||||
}
|
||||
});
|
||||
|
||||
restorePGP.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
openFileWithPermissions(INTENT_OPEN_DOCUMENT_PGP, PERMISSIONS_REQUEST_READ_IMPORT_PGP);
|
||||
openFileWithPermissions(Constants.INTENT_BACKUP_OPEN_DOCUMENT_PGP, Constants.PERMISSIONS_BACKUP_READ_IMPORT_PGP);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -240,39 +216,39 @@ public class BackupActivity extends BaseActivity {
|
|||
// Get the result from permission requests
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) {
|
||||
if (requestCode == PERMISSIONS_REQUEST_READ_IMPORT_PLAIN) {
|
||||
if (requestCode == Constants.PERMISSIONS_BACKUP_READ_IMPORT_PLAIN) {
|
||||
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
showOpenFileSelector(INTENT_OPEN_DOCUMENT_PLAIN);
|
||||
showOpenFileSelector(Constants.INTENT_BACKUP_OPEN_DOCUMENT_PLAIN);
|
||||
} else {
|
||||
Toast.makeText(this, R.string.backup_toast_storage_permissions, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
} else if (requestCode == PERMISSIONS_REQUEST_WRITE_EXPORT_PLAIN) {
|
||||
} else if (requestCode == Constants.PERMISSIONS_BACKUP_WRITE_EXPORT_PLAIN) {
|
||||
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
showSaveFileSelector(DEFAULT_BACKUP_MIMETYPE_PLAIN, DEFAULT_BACKUP_FILENAME_PLAIN, INTENT_SAVE_DOCUMENT_PLAIN);
|
||||
showSaveFileSelector(Constants.BACKUP_MIMETYPE_PLAIN, Constants.BACKUP_FILENAME_PLAIN, Constants.INTENT_BACKUP_SAVE_DOCUMENT_PLAIN);
|
||||
} else {
|
||||
Toast.makeText(this, R.string.backup_toast_storage_permissions, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
} else if (requestCode == PERMISSIONS_REQUEST_READ_IMPORT_CRYPT) {
|
||||
} else if (requestCode == Constants.PERMISSIONS_BACKUP_READ_IMPORT_CRYPT) {
|
||||
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
showOpenFileSelector(INTENT_OPEN_DOCUMENT_CRYPT);
|
||||
showOpenFileSelector(Constants.INTENT_BACKUP_OPEN_DOCUMENT_CRYPT);
|
||||
} else {
|
||||
Toast.makeText(this, R.string.backup_toast_storage_permissions, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
} else if (requestCode == PERMISSIONS_REQUEST_WRITE_EXPORT_CRYPT) {
|
||||
} else if (requestCode == Constants.PERMISSIONS_BACKUP_WRITE_EXPORT_CRYPT) {
|
||||
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
showSaveFileSelector(DEFAULT_BACKUP_MIMETYPE_CRYPT, DEFAULT_BACKUP_FILENAME_CRYPT, INTENT_SAVE_DOCUMENT_CRYPT);
|
||||
showSaveFileSelector(Constants.BACKUP_MIMETYPE_CRYPT, Constants.BACKUP_FILENAME_CRYPT, Constants.INTENT_BACKUP_SAVE_DOCUMENT_CRYPT);
|
||||
} else {
|
||||
Toast.makeText(this, R.string.backup_toast_storage_permissions, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
} else if (requestCode == PERMISSIONS_REQUEST_READ_IMPORT_PGP) {
|
||||
} else if (requestCode == Constants.PERMISSIONS_BACKUP_READ_IMPORT_PGP) {
|
||||
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
showOpenFileSelector(INTENT_OPEN_DOCUMENT_PGP);
|
||||
showOpenFileSelector(Constants.INTENT_BACKUP_OPEN_DOCUMENT_PGP);
|
||||
} else {
|
||||
Toast.makeText(this, R.string.backup_toast_storage_permissions, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
} else if (requestCode == PERMISSIONS_REQUEST_WRITE_EXPORT_PGP) {
|
||||
} else if (requestCode == Constants.PERMISSIONS_BACKUP_WRITE_EXPORT_PGP) {
|
||||
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
showSaveFileSelector(DEFAULT_BACKUP_MIMETYPE_PGP, DEFAULT_BACKUP_FILENAME_PGP, INTENT_SAVE_DOCUMENT_PGP);
|
||||
showSaveFileSelector(Constants.BACKUP_MIMETYPE_PGP, Constants.BACKUP_FILENAME_PGP, Constants.INTENT_BACKUP_SAVE_DOCUMENT_PGP);
|
||||
} else {
|
||||
Toast.makeText(this, R.string.backup_toast_storage_permissions, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
@ -286,31 +262,31 @@ public class BackupActivity extends BaseActivity {
|
|||
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
|
||||
super.onActivityResult(requestCode, resultCode, intent);
|
||||
|
||||
if (requestCode == INTENT_OPEN_DOCUMENT_PLAIN && resultCode == RESULT_OK) {
|
||||
if (requestCode == Constants.INTENT_BACKUP_OPEN_DOCUMENT_PLAIN && resultCode == RESULT_OK) {
|
||||
if (intent != null) {
|
||||
doRestorePlain(intent.getData());
|
||||
}
|
||||
} else if (requestCode == INTENT_SAVE_DOCUMENT_PLAIN && resultCode == RESULT_OK) {
|
||||
} else if (requestCode == Constants.INTENT_BACKUP_SAVE_DOCUMENT_PLAIN && resultCode == RESULT_OK) {
|
||||
if (intent != null) {
|
||||
doBackupPlain(intent.getData());
|
||||
}
|
||||
} else if (requestCode == INTENT_OPEN_DOCUMENT_CRYPT && resultCode == RESULT_OK) {
|
||||
} else if (requestCode == Constants.INTENT_BACKUP_OPEN_DOCUMENT_CRYPT && resultCode == RESULT_OK) {
|
||||
if (intent != null) {
|
||||
doRestoreCrypt(intent.getData());
|
||||
}
|
||||
} else if (requestCode == INTENT_SAVE_DOCUMENT_CRYPT && resultCode == RESULT_OK) {
|
||||
} else if (requestCode == Constants.INTENT_BACKUP_SAVE_DOCUMENT_CRYPT && resultCode == RESULT_OK) {
|
||||
if (intent != null) {
|
||||
doBackupCrypt(intent.getData());
|
||||
}
|
||||
} else if (requestCode == INTENT_OPEN_DOCUMENT_PGP && resultCode == RESULT_OK) {
|
||||
} else if (requestCode == Constants.INTENT_BACKUP_OPEN_DOCUMENT_PGP && resultCode == RESULT_OK) {
|
||||
if (intent != null)
|
||||
restoreEncryptedWithPGP(intent.getData(), null);
|
||||
} else if (requestCode == INTENT_SAVE_DOCUMENT_PGP && resultCode == RESULT_OK) {
|
||||
} else if (requestCode == Constants.INTENT_BACKUP_SAVE_DOCUMENT_PGP && resultCode == RESULT_OK) {
|
||||
if (intent != null)
|
||||
backupEncryptedWithPGP(intent.getData(), null);
|
||||
} else if (requestCode == INTENT_ENCRYPT_PGP && resultCode == RESULT_OK) {
|
||||
} else if (requestCode == Constants.INTENT_BACKUP_ENCRYPT_PGP && resultCode == RESULT_OK) {
|
||||
backupEncryptedWithPGP(encryptTargetFile, intent);
|
||||
} else if (requestCode == INTENT_DECRYPT_PGP && resultCode == RESULT_OK) {
|
||||
} else if (requestCode == Constants.INTENT_BACKUP_DECRYPT_PGP && resultCode == RESULT_OK) {
|
||||
restoreEncryptedWithPGP(decryptSourceFile, intent);
|
||||
}
|
||||
}
|
||||
|
@ -324,12 +300,12 @@ public class BackupActivity extends BaseActivity {
|
|||
intent.setType("*/*");
|
||||
startActivityForResult(intent, intentId);
|
||||
} else {
|
||||
if (intentId == INTENT_OPEN_DOCUMENT_PLAIN)
|
||||
doRestorePlain(Tools.buildUri(settings.getBackupDir(), DEFAULT_BACKUP_FILENAME_PLAIN));
|
||||
else if (intentId == INTENT_OPEN_DOCUMENT_CRYPT)
|
||||
doRestoreCrypt(Tools.buildUri(settings.getBackupDir(), DEFAULT_BACKUP_FILENAME_CRYPT));
|
||||
else if (intentId == INTENT_OPEN_DOCUMENT_PGP)
|
||||
restoreEncryptedWithPGP(Tools.buildUri(settings.getBackupDir(), DEFAULT_BACKUP_FILENAME_PGP), null);
|
||||
if (intentId == Constants.INTENT_BACKUP_OPEN_DOCUMENT_PLAIN)
|
||||
doRestorePlain(Tools.buildUri(settings.getBackupDir(), Constants.BACKUP_FILENAME_PLAIN));
|
||||
else if (intentId == Constants.INTENT_BACKUP_OPEN_DOCUMENT_CRYPT)
|
||||
doRestoreCrypt(Tools.buildUri(settings.getBackupDir(), Constants.BACKUP_FILENAME_CRYPT));
|
||||
else if (intentId == Constants.INTENT_BACKUP_OPEN_DOCUMENT_PGP)
|
||||
restoreEncryptedWithPGP(Tools.buildUri(settings.getBackupDir(), Constants.BACKUP_FILENAME_PGP), null);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -342,12 +318,12 @@ public class BackupActivity extends BaseActivity {
|
|||
startActivityForResult(intent, intentId);
|
||||
} else {
|
||||
if (Tools.mkdir(settings.getBackupDir())) {
|
||||
if (intentId == INTENT_SAVE_DOCUMENT_PLAIN)
|
||||
doBackupPlain(Tools.buildUri(settings.getBackupDir(), DEFAULT_BACKUP_FILENAME_PLAIN));
|
||||
else if (intentId == INTENT_SAVE_DOCUMENT_CRYPT)
|
||||
doBackupCrypt(Tools.buildUri(settings.getBackupDir(), DEFAULT_BACKUP_FILENAME_CRYPT));
|
||||
else if (intentId == INTENT_SAVE_DOCUMENT_PGP)
|
||||
backupEncryptedWithPGP(Tools.buildUri(settings.getBackupDir(), DEFAULT_BACKUP_FILENAME_PGP), null);
|
||||
if (intentId == Constants.INTENT_BACKUP_SAVE_DOCUMENT_PLAIN)
|
||||
doBackupPlain(Tools.buildUri(settings.getBackupDir(), Constants.BACKUP_FILENAME_PLAIN));
|
||||
else if (intentId == Constants.INTENT_BACKUP_SAVE_DOCUMENT_CRYPT)
|
||||
doBackupCrypt(Tools.buildUri(settings.getBackupDir(), Constants.BACKUP_FILENAME_CRYPT));
|
||||
else if (intentId == Constants.INTENT_BACKUP_SAVE_DOCUMENT_PGP)
|
||||
backupEncryptedWithPGP(Tools.buildUri(settings.getBackupDir(), Constants.BACKUP_FILENAME_PGP), null);
|
||||
} else {
|
||||
Toast.makeText(this, R.string.backup_toast_mkdir_failed, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
@ -428,7 +404,7 @@ public class BackupActivity extends BaseActivity {
|
|||
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialogInterface, int i) {
|
||||
saveFileWithPermissions(DEFAULT_BACKUP_MIMETYPE_PLAIN, DEFAULT_BACKUP_FILENAME_PLAIN, INTENT_SAVE_DOCUMENT_PLAIN, PERMISSIONS_REQUEST_WRITE_EXPORT_PLAIN);
|
||||
saveFileWithPermissions(Constants.BACKUP_MIMETYPE_PLAIN, Constants.BACKUP_FILENAME_PLAIN, Constants.INTENT_BACKUP_SAVE_DOCUMENT_PLAIN, Constants.PERMISSIONS_BACKUP_WRITE_EXPORT_PLAIN);
|
||||
}
|
||||
})
|
||||
.setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
|
||||
|
@ -523,7 +499,7 @@ public class BackupActivity extends BaseActivity {
|
|||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
OpenPgpApi api = new OpenPgpApi(this, pgpServiceConnection.getService());
|
||||
Intent result = api.executeApi(decryptIntent, is, os);
|
||||
handleOpenPGPResult(result, os, uri, INTENT_DECRYPT_PGP);
|
||||
handleOpenPGPResult(result, os, uri, Constants.INTENT_BACKUP_DECRYPT_PGP);
|
||||
}
|
||||
|
||||
private void doBackupEncrypted(Uri uri, String data) {
|
||||
|
@ -563,7 +539,7 @@ public class BackupActivity extends BaseActivity {
|
|||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
OpenPgpApi api = new OpenPgpApi(this, pgpServiceConnection.getService());
|
||||
Intent result = api.executeApi(encryptIntent, is, os);
|
||||
handleOpenPGPResult(result, os, uri, INTENT_ENCRYPT_PGP);
|
||||
handleOpenPGPResult(result, os, uri, Constants.INTENT_BACKUP_ENCRYPT_PGP);
|
||||
}
|
||||
|
||||
public String outputStreamToString(ByteArrayOutputStream os) {
|
||||
|
@ -572,10 +548,10 @@ public class BackupActivity extends BaseActivity {
|
|||
|
||||
public void handleOpenPGPResult(Intent result, ByteArrayOutputStream os, Uri file, int requestCode) {
|
||||
if (result.getIntExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR) == OpenPgpApi.RESULT_CODE_SUCCESS) {
|
||||
if (requestCode == INTENT_ENCRYPT_PGP) {
|
||||
if (requestCode == Constants.INTENT_BACKUP_ENCRYPT_PGP) {
|
||||
if (os != null)
|
||||
doBackupEncrypted(file, outputStreamToString(os));
|
||||
} else if (requestCode == INTENT_DECRYPT_PGP) {
|
||||
} else if (requestCode == Constants.INTENT_BACKUP_DECRYPT_PGP) {
|
||||
if (os != null) {
|
||||
if (settings.getOpenPGPVerify()) {
|
||||
OpenPgpSignatureResult sigResult = result.getParcelableExtra(OpenPgpApi.RESULT_SIGNATURE);
|
||||
|
@ -594,9 +570,9 @@ public class BackupActivity extends BaseActivity {
|
|||
PendingIntent pi = result.getParcelableExtra(OpenPgpApi.RESULT_INTENT);
|
||||
|
||||
// Small hack to keep the target file even after user interaction
|
||||
if (requestCode == INTENT_ENCRYPT_PGP) {
|
||||
if (requestCode == Constants.INTENT_BACKUP_ENCRYPT_PGP) {
|
||||
encryptTargetFile = file;
|
||||
} else if (requestCode == INTENT_DECRYPT_PGP) {
|
||||
} else if (requestCode == Constants.INTENT_BACKUP_DECRYPT_PGP) {
|
||||
decryptSourceFile = file;
|
||||
}
|
||||
|
||||
|
|
|
@ -58,6 +58,7 @@ import com.google.zxing.integration.android.IntentResult;
|
|||
|
||||
import org.shadowice.flocke.andotp.Database.Entry;
|
||||
import org.shadowice.flocke.andotp.R;
|
||||
import org.shadowice.flocke.andotp.Utilities.Constants;
|
||||
import org.shadowice.flocke.andotp.Utilities.EncryptionHelper;
|
||||
import org.shadowice.flocke.andotp.Utilities.KeyStoreHelper;
|
||||
import org.shadowice.flocke.andotp.Utilities.TokenCalculator;
|
||||
|
@ -72,20 +73,12 @@ import java.util.HashMap;
|
|||
|
||||
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_PASSWORD_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;
|
||||
import static org.shadowice.flocke.andotp.Utilities.Constants.EncryptionType;
|
||||
import static org.shadowice.flocke.andotp.Utilities.Settings.SortMode;
|
||||
import static org.shadowice.flocke.andotp.Utilities.Constants.SortMode;
|
||||
|
||||
public class MainActivity extends BaseActivity
|
||||
implements SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
private static final int INTENT_INTERNAL_AUTHENTICATE = 100;
|
||||
private static final int INTENT_INTERNAL_SETTINGS = 101;
|
||||
private static final int INTENT_INTERNAL_BACKUP = 102;
|
||||
|
||||
private EntriesCardAdapter adapter;
|
||||
private FloatingActionMenu floatingActionMenu;
|
||||
|
@ -135,12 +128,12 @@ public class MainActivity extends BaseActivity
|
|||
KeyguardManager km = (KeyguardManager) getSystemService(KEYGUARD_SERVICE);
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP && km.isKeyguardSecure()) {
|
||||
Intent authIntent = km.createConfirmDeviceCredentialIntent(getString(R.string.dialog_title_auth), getString(R.string.dialog_msg_auth));
|
||||
startActivityForResult(authIntent, INTENT_INTERNAL_AUTHENTICATE);
|
||||
startActivityForResult(authIntent, Constants.INTENT_MAIN_AUTHENTICATE);
|
||||
}
|
||||
} else if (authMethod == AuthMethod.PASSWORD || authMethod == AuthMethod.PIN) {
|
||||
Intent authIntent = new Intent(this, AuthenticateActivity.class);
|
||||
authIntent.putExtra(AUTH_EXTRA_NAME_MESSAGE, messageId);
|
||||
startActivityForResult(authIntent, INTENT_INTERNAL_AUTHENTICATE);
|
||||
authIntent.putExtra(Constants.EXTRA_AUTH_MESSAGE, messageId);
|
||||
startActivityForResult(authIntent, Constants.INTENT_MAIN_AUTHENTICATE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -385,18 +378,18 @@ public class MainActivity extends BaseActivity
|
|||
Toast.makeText(this, R.string.toast_invalid_qr_code, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
} else if (requestCode == INTENT_INTERNAL_BACKUP && resultCode == RESULT_OK) {
|
||||
} else if (requestCode == Constants.INTENT_MAIN_BACKUP && resultCode == RESULT_OK) {
|
||||
if (intent.getBooleanExtra("reload", false)) {
|
||||
adapter.loadEntries();
|
||||
refreshTags();
|
||||
}
|
||||
} 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);
|
||||
} else if (requestCode == Constants.INTENT_MAIN_SETTINGS && resultCode == RESULT_OK) {
|
||||
boolean encryptionChanged = intent.getBooleanExtra(Constants.EXTRA_SETTINGS_ENCRYPTION_CHANGED, false);
|
||||
byte[] newKey = intent.getByteArrayExtra(Constants.EXTRA_SETTINGS_ENCRYPTION_KEY);
|
||||
|
||||
if (encryptionChanged)
|
||||
updateEncryption(newKey);
|
||||
} else if (requestCode == INTENT_INTERNAL_AUTHENTICATE) {
|
||||
} else if (requestCode == Constants.INTENT_MAIN_AUTHENTICATE) {
|
||||
if (resultCode != RESULT_OK) {
|
||||
Toast.makeText(getBaseContext(), R.string.toast_auth_failed_fatal, Toast.LENGTH_LONG).show();
|
||||
|
||||
|
@ -408,7 +401,7 @@ public class MainActivity extends BaseActivity
|
|||
} else {
|
||||
requireAuthentication = false;
|
||||
|
||||
byte[] authKey = intent.getByteArrayExtra(AUTH_EXTRA_NAME_PASSWORD_KEY);
|
||||
byte[] authKey = intent.getByteArrayExtra(Constants.EXTRA_AUTH_PASSWORD_KEY);
|
||||
updateEncryption(authKey);
|
||||
}
|
||||
}
|
||||
|
@ -509,12 +502,12 @@ public class MainActivity extends BaseActivity
|
|||
|
||||
if (id == R.id.action_backup) {
|
||||
Intent backupIntent = new Intent(this, BackupActivity.class);
|
||||
backupIntent.putExtra(BACKUP_EXTRA_NAME_ENCRYPTION_KEY, adapter.getEncryptionKey().getEncoded());
|
||||
startActivityForResult(backupIntent, INTENT_INTERNAL_BACKUP);
|
||||
backupIntent.putExtra(Constants.EXTRA_BACKUP_ENCRYPTION_KEY, adapter.getEncryptionKey().getEncoded());
|
||||
startActivityForResult(backupIntent, Constants.INTENT_MAIN_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);
|
||||
settingsIntent.putExtra(Constants.EXTRA_SETTINGS_ENCRYPTION_KEY, adapter.getEncryptionKey().getEncoded());
|
||||
startActivityForResult(settingsIntent, Constants.INTENT_MAIN_SETTINGS);
|
||||
} else if (id == R.id.action_about){
|
||||
Intent aboutIntent = new Intent(this, AboutActivity.class);
|
||||
startActivity(aboutIntent);
|
||||
|
|
|
@ -39,6 +39,7 @@ 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.Constants;
|
||||
import org.shadowice.flocke.andotp.Utilities.DatabaseHelper;
|
||||
import org.shadowice.flocke.andotp.Utilities.EncryptionHelper;
|
||||
import org.shadowice.flocke.andotp.Utilities.KeyStoreHelper;
|
||||
|
@ -48,19 +49,11 @@ 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;
|
||||
|
@ -80,7 +73,7 @@ public class SettingsActivity extends BaseActivity
|
|||
stub.inflate();
|
||||
|
||||
Intent callingIntent = getIntent();
|
||||
byte[] keyMaterial = callingIntent.getByteArrayExtra(SETTINGS_EXTRA_NAME_ENCRYPTION_KEY);
|
||||
byte[] keyMaterial = callingIntent.getByteArrayExtra(Constants.EXTRA_SETTINGS_ENCRYPTION_KEY);
|
||||
encryptionKey = EncryptionHelper.generateSymmetricKey(keyMaterial);
|
||||
|
||||
fragment = new SettingsFragment();
|
||||
|
@ -96,8 +89,8 @@ public class SettingsActivity extends BaseActivity
|
|||
public void finishWithResult() {
|
||||
Intent data = new Intent();
|
||||
|
||||
data.putExtra(SETTINGS_EXTRA_NAME_ENCRYPTION_CHANGED, encryptionChanged);
|
||||
data.putExtra(SETTINGS_EXTRA_NAME_ENCRYPTION_KEY, encryptionKey.getEncoded());
|
||||
data.putExtra(Constants.EXTRA_SETTINGS_ENCRYPTION_CHANGED, encryptionChanged);
|
||||
data.putExtra(Constants.EXTRA_SETTINGS_ENCRYPTION_KEY, encryptionKey.getEncoded());
|
||||
|
||||
setResult(RESULT_OK, data);
|
||||
finish();
|
||||
|
@ -125,9 +118,9 @@ 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);
|
||||
authIntent.putExtra(Constants.EXTRA_AUTH_NEW_ENCRYPTION, newEnc.name());
|
||||
authIntent.putExtra(Constants.EXTRA_AUTH_MESSAGE, R.string.auth_msg_confirm_encryption);
|
||||
startActivityForResult(authIntent, Constants.INTENT_SETTINGS_AUTHENTICATE);
|
||||
}
|
||||
|
||||
private boolean tryEncryptionChange(EncryptionType newEnc, byte[] newKey) {
|
||||
|
@ -177,10 +170,10 @@ public class SettingsActivity extends BaseActivity
|
|||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
|
||||
if (requestCode == INTENT_INTERNAL_AUTHENTICATE) {
|
||||
if (requestCode == Constants.INTENT_SETTINGS_AUTHENTICATE) {
|
||||
if (resultCode == RESULT_OK) {
|
||||
byte[] authKey = data.getByteArrayExtra(AUTH_EXTRA_NAME_PASSWORD_KEY);
|
||||
String newEnc = data.getStringExtra(AUTH_EXTRA_NAME_NEW_ENCRYPTION);
|
||||
byte[] authKey = data.getByteArrayExtra(Constants.EXTRA_AUTH_PASSWORD_KEY);
|
||||
String newEnc = data.getStringExtra(Constants.EXTRA_AUTH_NEW_ENCRYPTION);
|
||||
|
||||
if (authKey != null && authKey.length > 0 && newEnc != null && !newEnc.isEmpty()) {
|
||||
EncryptionType newEncType = EncryptionType.valueOf(newEnc);
|
||||
|
|
|
@ -41,7 +41,9 @@ import java.util.Objects;
|
|||
import java.util.Set;
|
||||
|
||||
public class Entry {
|
||||
public enum OTPType { TOTP, STEAM}
|
||||
public enum OTPType {
|
||||
TOTP, STEAM
|
||||
}
|
||||
public static Set<OTPType> PublicTypes = EnumSet.of(OTPType.TOTP);
|
||||
|
||||
private static final OTPType DEFAULT_TYPE = OTPType.TOTP;
|
||||
|
|
|
@ -39,6 +39,7 @@ import android.widget.Button;
|
|||
import android.widget.EditText;
|
||||
|
||||
import org.shadowice.flocke.andotp.R;
|
||||
import org.shadowice.flocke.andotp.Utilities.Constants;
|
||||
import org.shadowice.flocke.andotp.Utilities.EncryptionHelper;
|
||||
import org.shadowice.flocke.andotp.Utilities.KeyStoreHelper;
|
||||
|
||||
|
@ -52,7 +53,6 @@ public class PasswordEncryptedPreference extends DialogPreference
|
|||
PASSWORD, PIN
|
||||
}
|
||||
|
||||
public static final String KEY_ALIAS = "password";
|
||||
private KeyPair key;
|
||||
|
||||
private static final String DEFAULT_VALUE = "";
|
||||
|
@ -70,7 +70,7 @@ public class PasswordEncryptedPreference extends DialogPreference
|
|||
super(context, attrs);
|
||||
|
||||
try {
|
||||
key = KeyStoreHelper.loadOrGenerateAsymmetricKeyPair(context, KEY_ALIAS);
|
||||
key = KeyStoreHelper.loadOrGenerateAsymmetricKeyPair(context, Constants.KEYSTORE_ALIAS_PASSWORD);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
|
|
@ -22,7 +22,12 @@
|
|||
|
||||
package org.shadowice.flocke.andotp.Utilities;
|
||||
|
||||
import android.os.Environment;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class Constants {
|
||||
// Enums
|
||||
public enum AuthMethod {
|
||||
NONE, PASSWORD, PIN, DEVICE
|
||||
}
|
||||
|
@ -31,8 +36,74 @@ public class Constants {
|
|||
KEYSTORE, PASSWORD
|
||||
}
|
||||
|
||||
final static String ALGORITHM_SYMMETRIC = "AES/GCM/NoPadding";
|
||||
final static String ALGORITHM_ASYMMETRIC = "RSA/ECB/PKCS1Padding";
|
||||
public enum SortMode {
|
||||
UNSORTED, LABEL, LAST_USED
|
||||
}
|
||||
|
||||
final static int AUTH_SALT_LENGTH = 16;
|
||||
// Intents (Format: A0x with A = parent Activity, x = number of the intent)
|
||||
public final static int INTENT_MAIN_AUTHENTICATE = 100;
|
||||
public final static int INTENT_MAIN_SETTINGS = 101;
|
||||
public final static int INTENT_MAIN_BACKUP = 102;
|
||||
|
||||
public final static int INTENT_BACKUP_OPEN_DOCUMENT_PLAIN = 200;
|
||||
public final static int INTENT_BACKUP_SAVE_DOCUMENT_PLAIN = 201;
|
||||
public final static int INTENT_BACKUP_OPEN_DOCUMENT_CRYPT = 202;
|
||||
public final static int INTENT_BACKUP_SAVE_DOCUMENT_CRYPT = 203;
|
||||
public final static int INTENT_BACKUP_OPEN_DOCUMENT_PGP = 204;
|
||||
public final static int INTENT_BACKUP_SAVE_DOCUMENT_PGP = 205;
|
||||
public final static int INTENT_BACKUP_ENCRYPT_PGP = 206;
|
||||
public final static int INTENT_BACKUP_DECRYPT_PGP = 207;
|
||||
|
||||
public static final int INTENT_SETTINGS_AUTHENTICATE = 300;
|
||||
|
||||
// Permission requests (Format: A1x with A = parent Activity, x = number of the request)
|
||||
public final static int PERMISSIONS_BACKUP_READ_IMPORT_PLAIN = 210;
|
||||
public final static int PERMISSIONS_BACKUP_WRITE_EXPORT_PLAIN = 211;
|
||||
public final static int PERMISSIONS_BACKUP_READ_IMPORT_CRYPT = 212;
|
||||
public final static int PERMISSIONS_BACKUP_WRITE_EXPORT_CRYPT = 213;
|
||||
public final static int PERMISSIONS_BACKUP_READ_IMPORT_PGP = 214;
|
||||
public final static int PERMISSIONS_BACKUP_WRITE_EXPORT_PGP = 215;
|
||||
|
||||
// Intent extras
|
||||
public final static String EXTRA_AUTH_PASSWORD_KEY = "password_key";
|
||||
public final static String EXTRA_AUTH_NEW_ENCRYPTION = "new_encryption";
|
||||
public final static String EXTRA_AUTH_MESSAGE = "message";
|
||||
|
||||
public final static String EXTRA_BACKUP_ENCRYPTION_KEY = "encryption_key";
|
||||
|
||||
public final static String EXTRA_SETTINGS_ENCRYPTION_CHANGED = "encryption_changed";
|
||||
public final static String EXTRA_SETTINGS_ENCRYPTION_KEY = "encryption_key";
|
||||
|
||||
// Encryption algorithms and definitions
|
||||
final static String ALGORITHM_SYMMETRIC = "AES/GCM/NoPadding";
|
||||
final static String ALGORITHM_ASYMMETRIC = "RSA/ECB/PKCS1Padding";
|
||||
|
||||
final static int ENCRYPTION_KEY_LENGTH = 16;
|
||||
final static int ENCRYPTION_IV_LENGTH = 12;
|
||||
|
||||
final static int PBKDF2_MIN_ITERATIONS = 1000;
|
||||
final static int PBKDF2_MAX_ITERATIONS = 5000;
|
||||
final static int PBKDF2_DEFAULT_ITERATIONS = 1000;
|
||||
final static int PBKDF2_LENGTH = 512;
|
||||
final static int PBKDF2_SALT_LENGTH = 16;
|
||||
|
||||
// KeyStore
|
||||
public final static String KEYSTORE_ALIAS_PASSWORD = "password";
|
||||
public final static String KEYSTORE_ALIAS_WRAPPING = "settings";
|
||||
|
||||
// Database files
|
||||
public final static String FILENAME_ENCRYPTED_KEY = "otp.key";
|
||||
public final static String FILENAME_DATABASE = "secrets.dat";
|
||||
public final static String FILENAME_DATABASE_BACKUP = "secrets.dat.bck";
|
||||
|
||||
// Backup files
|
||||
public final static String BACKUP_FOLDER = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "andOTP";
|
||||
|
||||
public final static String BACKUP_FILENAME_PLAIN = "otp_accounts.json";
|
||||
public final static String BACKUP_FILENAME_CRYPT = "otp_accounts.json.aes";
|
||||
public final static String BACKUP_FILENAME_PGP = "otp_accounts.json.gpg";
|
||||
|
||||
public final static String BACKUP_MIMETYPE_PLAIN = "application/json";
|
||||
public final static String BACKUP_MIMETYPE_CRYPT = "binary/aes";
|
||||
public final static String BACKUP_MIMETYPE_PGP = "application/pgp-encrypted";
|
||||
}
|
||||
|
|
|
@ -41,11 +41,9 @@ 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);
|
||||
File db = new File(context.getFilesDir() + "/" + Constants.FILENAME_DATABASE);
|
||||
db.delete();
|
||||
}
|
||||
|
||||
|
@ -63,8 +61,8 @@ public class DatabaseHelper {
|
|||
}
|
||||
|
||||
public static boolean backupDatabase(Context context) {
|
||||
File original = new File(context.getFilesDir() + "/" + SETTINGS_FILE);
|
||||
File backup = new File(context.getFilesDir() + "/" + SETTINGS_FILE_BACKUP);
|
||||
File original = new File(context.getFilesDir() + "/" + Constants.FILENAME_DATABASE);
|
||||
File backup = new File(context.getFilesDir() + "/" + Constants.FILENAME_DATABASE_BACKUP);
|
||||
|
||||
try {
|
||||
copyFile(original, backup);
|
||||
|
@ -76,8 +74,8 @@ public class DatabaseHelper {
|
|||
}
|
||||
|
||||
public static boolean restoreDatabaseBackup(Context context) {
|
||||
File original = new File(context.getFilesDir() + "/" + SETTINGS_FILE);
|
||||
File backup = new File(context.getFilesDir() + "/" + SETTINGS_FILE_BACKUP);
|
||||
File original = new File(context.getFilesDir() + "/" + Constants.FILENAME_DATABASE);
|
||||
File backup = new File(context.getFilesDir() + "/" + Constants.FILENAME_DATABASE_BACKUP);
|
||||
|
||||
try {
|
||||
copyFile(backup, original);
|
||||
|
@ -100,7 +98,7 @@ public class DatabaseHelper {
|
|||
try {
|
||||
byte[] data = EncryptionHelper.encrypt(encryptionKey, jsonString.getBytes());
|
||||
|
||||
FileHelper.writeBytesToFile(new File(context.getFilesDir() + "/" + SETTINGS_FILE), data);
|
||||
FileHelper.writeBytesToFile(new File(context.getFilesDir() + "/" + Constants.FILENAME_DATABASE), data);
|
||||
|
||||
} catch (Exception error) {
|
||||
error.printStackTrace();
|
||||
|
@ -115,7 +113,7 @@ public class DatabaseHelper {
|
|||
|
||||
if (encryptionKey != null) {
|
||||
try {
|
||||
byte[] data = FileHelper.readFileToBytes(new File(context.getFilesDir() + "/" + SETTINGS_FILE));
|
||||
byte[] data = FileHelper.readFileToBytes(new File(context.getFilesDir() + "/" + Constants.FILENAME_DATABASE));
|
||||
data = EncryptionHelper.decrypt(encryptionKey, data);
|
||||
|
||||
entries = stringToEntries(new String(data));
|
||||
|
|
|
@ -51,18 +51,7 @@ import javax.crypto.spec.IvParameterSpec;
|
|||
import javax.crypto.spec.PBEKeySpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
import static org.shadowice.flocke.andotp.Utilities.Constants.ALGORITHM_ASYMMETRIC;
|
||||
import static org.shadowice.flocke.andotp.Utilities.Constants.ALGORITHM_SYMMETRIC;
|
||||
|
||||
public class EncryptionHelper {
|
||||
private final static int KEY_LENGTH = 16;
|
||||
private final static int IV_LENGTH = 12;
|
||||
|
||||
public final static int PBKDF2_MIN_ITERATIONS = 1000;
|
||||
public final static int PBKDF2_MAX_ITERATIONS = 5000;
|
||||
public final static int PBKDF2_OLD_DEFAULT_ITERATIONS = 1000;
|
||||
private final static int PBKDF2_LENGTH = 512;
|
||||
|
||||
public static class PBKDF2Credentials {
|
||||
public byte[] password;
|
||||
public byte[] key;
|
||||
|
@ -70,7 +59,7 @@ public class EncryptionHelper {
|
|||
|
||||
public static int generateRandomIterations() {
|
||||
Random rand = new Random();
|
||||
return rand.nextInt((PBKDF2_MAX_ITERATIONS - PBKDF2_MIN_ITERATIONS) + 1) + PBKDF2_MIN_ITERATIONS;
|
||||
return rand.nextInt((Constants.PBKDF2_MAX_ITERATIONS - Constants.PBKDF2_MIN_ITERATIONS) + 1) + Constants.PBKDF2_MIN_ITERATIONS;
|
||||
}
|
||||
|
||||
public static byte[] generateRandom(int length) {
|
||||
|
@ -83,7 +72,7 @@ public class EncryptionHelper {
|
|||
public static PBKDF2Credentials generatePBKDF2Credentials(String password, byte[] salt, int iter)
|
||||
throws NoSuchAlgorithmException, InvalidKeySpecException {
|
||||
SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
|
||||
KeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt, iter, PBKDF2_LENGTH);
|
||||
KeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt, iter, Constants.PBKDF2_LENGTH);
|
||||
|
||||
byte[] array = secretKeyFactory.generateSecret(keySpec).getEncoded();
|
||||
|
||||
|
@ -109,7 +98,7 @@ public class EncryptionHelper {
|
|||
|
||||
public static byte[] encrypt(SecretKey secretKey, IvParameterSpec iv, byte[] plainText)
|
||||
throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, UnsupportedEncodingException, BadPaddingException, IllegalBlockSizeException {
|
||||
Cipher cipher = Cipher.getInstance(ALGORITHM_SYMMETRIC);
|
||||
Cipher cipher = Cipher.getInstance(Constants.ALGORITHM_SYMMETRIC);
|
||||
cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);
|
||||
|
||||
return cipher.doFinal(plainText);
|
||||
|
@ -117,7 +106,7 @@ public class EncryptionHelper {
|
|||
|
||||
public static byte[] encrypt(SecretKey secretKey, byte[] plaintext)
|
||||
throws NoSuchPaddingException, BadPaddingException, InvalidKeyException, NoSuchAlgorithmException, IllegalBlockSizeException, UnsupportedEncodingException, InvalidAlgorithmParameterException {
|
||||
final byte[] iv = new byte[IV_LENGTH];
|
||||
final byte[] iv = new byte[Constants.ENCRYPTION_IV_LENGTH];
|
||||
new SecureRandom().nextBytes(iv);
|
||||
|
||||
byte[] cipherText = encrypt(secretKey, new IvParameterSpec(iv), plaintext);
|
||||
|
@ -131,7 +120,7 @@ public class EncryptionHelper {
|
|||
|
||||
public static byte[] encrypt(PublicKey publicKey, byte[] plaintext)
|
||||
throws NoSuchPaddingException, BadPaddingException, InvalidKeyException, NoSuchAlgorithmException, IllegalBlockSizeException, UnsupportedEncodingException, InvalidAlgorithmParameterException {
|
||||
Cipher cipher = Cipher.getInstance(ALGORITHM_ASYMMETRIC);
|
||||
Cipher cipher = Cipher.getInstance(Constants.ALGORITHM_ASYMMETRIC);
|
||||
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
|
||||
|
||||
return cipher.doFinal(plaintext);
|
||||
|
@ -139,7 +128,7 @@ public class EncryptionHelper {
|
|||
|
||||
public static byte[] decrypt(SecretKey secretKey, IvParameterSpec iv, byte[] cipherText)
|
||||
throws NoSuchPaddingException, InvalidKeyException, NoSuchAlgorithmException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException {
|
||||
Cipher cipher = Cipher.getInstance(ALGORITHM_SYMMETRIC);
|
||||
Cipher cipher = Cipher.getInstance(Constants.ALGORITHM_SYMMETRIC);
|
||||
cipher.init(Cipher.DECRYPT_MODE, secretKey, iv);
|
||||
|
||||
return cipher.doFinal(cipherText);
|
||||
|
@ -147,15 +136,15 @@ public class EncryptionHelper {
|
|||
|
||||
public static byte[] decrypt(SecretKey secretKey, byte[] cipherText)
|
||||
throws NoSuchPaddingException, InvalidKeyException, NoSuchAlgorithmException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException {
|
||||
byte[] iv = Arrays.copyOfRange(cipherText, 0, IV_LENGTH);
|
||||
byte[] encrypted = Arrays.copyOfRange(cipherText, IV_LENGTH, cipherText.length);
|
||||
byte[] iv = Arrays.copyOfRange(cipherText, 0, Constants.ENCRYPTION_IV_LENGTH);
|
||||
byte[] encrypted = Arrays.copyOfRange(cipherText, Constants.ENCRYPTION_IV_LENGTH, cipherText.length);
|
||||
|
||||
return decrypt(secretKey, new IvParameterSpec(iv), encrypted);
|
||||
}
|
||||
|
||||
public static byte[] decrypt(PrivateKey privateKey, byte[] cipherText)
|
||||
throws NoSuchPaddingException, InvalidKeyException, NoSuchAlgorithmException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException {
|
||||
Cipher cipher = Cipher.getInstance(ALGORITHM_ASYMMETRIC);
|
||||
Cipher cipher = Cipher.getInstance(Constants.ALGORITHM_ASYMMETRIC);
|
||||
cipher.init(Cipher.DECRYPT_MODE, privateKey);
|
||||
|
||||
return cipher.doFinal(cipherText);
|
||||
|
@ -172,7 +161,7 @@ public class EncryptionHelper {
|
|||
|
||||
// Generate secret key if none exists
|
||||
if (!keyFile.exists()) {
|
||||
final byte[] raw = EncryptionHelper.generateRandom(KEY_LENGTH);
|
||||
final byte[] raw = EncryptionHelper.generateRandom(Constants.ENCRYPTION_KEY_LENGTH);
|
||||
|
||||
final SecretKey key = new SecretKeySpec(raw, "AES");
|
||||
final byte[] wrapped = wrapper.wrap(key);
|
||||
|
|
|
@ -45,19 +45,16 @@ import javax.crypto.SecretKey;
|
|||
import javax.security.auth.x500.X500Principal;
|
||||
|
||||
public class KeyStoreHelper {
|
||||
public static final String KEY_FILE = "otp.key";
|
||||
|
||||
public static final String KEYSTORE_ALIAS_WRAPPING = "settings";
|
||||
|
||||
public static void wipeKeys(Context context) {
|
||||
File keyFile = new File(context.getFilesDir() + "/" + KEY_FILE);
|
||||
File keyFile = new File(context.getFilesDir() + "/" + Constants.FILENAME_ENCRYPTED_KEY);
|
||||
keyFile.delete();
|
||||
|
||||
try {
|
||||
final KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
|
||||
keyStore.load(null);
|
||||
if (keyStore.containsAlias(KEYSTORE_ALIAS_WRAPPING))
|
||||
keyStore.deleteEntry(KEYSTORE_ALIAS_WRAPPING);
|
||||
if (keyStore.containsAlias(Constants.KEYSTORE_ALIAS_WRAPPING))
|
||||
keyStore.deleteEntry(Constants.KEYSTORE_ALIAS_WRAPPING);
|
||||
} catch (GeneralSecurityException | IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
@ -106,7 +103,7 @@ public class KeyStoreHelper {
|
|||
KeyPair pair = null;
|
||||
|
||||
try {
|
||||
pair = KeyStoreHelper.loadOrGenerateAsymmetricKeyPair(context, KEYSTORE_ALIAS_WRAPPING);
|
||||
pair = KeyStoreHelper.loadOrGenerateAsymmetricKeyPair(context, Constants.KEYSTORE_ALIAS_WRAPPING);
|
||||
} catch (GeneralSecurityException | IOException e) {
|
||||
e.printStackTrace();
|
||||
UIHelper.showGenericDialog(context, R.string.dialog_title_encryption_error, R.string.dialog_msg_keystore_error);
|
||||
|
@ -114,7 +111,7 @@ public class KeyStoreHelper {
|
|||
|
||||
if (pair != null) {
|
||||
try {
|
||||
return EncryptionHelper.loadOrGenerateWrappedKey(new File(context.getFilesDir() + "/" + KEY_FILE), pair);
|
||||
return EncryptionHelper.loadOrGenerateWrappedKey(new File(context.getFilesDir() + "/" + Constants.FILENAME_ENCRYPTED_KEY), pair);
|
||||
} catch (GeneralSecurityException | IOException e) {
|
||||
e.printStackTrace();
|
||||
UIHelper.showGenericDialog(context, R.string.dialog_title_encryption_error, R.string.dialog_msg_unwrap_error);
|
||||
|
|
|
@ -26,8 +26,6 @@ import java.security.KeyStore;
|
|||
import javax.crypto.Cipher;
|
||||
import javax.crypto.SecretKey;
|
||||
|
||||
import static org.shadowice.flocke.andotp.Utilities.Constants.ALGORITHM_ASYMMETRIC;
|
||||
|
||||
/**
|
||||
* Wraps {@link SecretKey} instances using a public/private key pair stored in
|
||||
* the platform {@link KeyStore}. This allows us to protect symmetric keys with
|
||||
|
@ -49,7 +47,7 @@ public class SecretKeyWrapper {
|
|||
@SuppressLint("GetInstance")
|
||||
public SecretKeyWrapper(KeyPair keyPair)
|
||||
throws GeneralSecurityException, IOException {
|
||||
mCipher = Cipher.getInstance(ALGORITHM_ASYMMETRIC);
|
||||
mCipher = Cipher.getInstance(Constants.ALGORITHM_ASYMMETRIC);
|
||||
mPair = keyPair;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,15 +24,12 @@ package org.shadowice.flocke.andotp.Utilities;
|
|||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Environment;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.util.Base64;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.shadowice.flocke.andotp.Preferences.CredentialsPreference;
|
||||
import org.shadowice.flocke.andotp.R;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.KeyPair;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
@ -42,21 +39,14 @@ import java.util.HashSet;
|
|||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.shadowice.flocke.andotp.Preferences.PasswordEncryptedPreference.KEY_ALIAS;
|
||||
import static org.shadowice.flocke.andotp.Utilities.EncryptionHelper.PBKDF2_OLD_DEFAULT_ITERATIONS;
|
||||
import static org.shadowice.flocke.andotp.Utilities.Constants.AuthMethod;
|
||||
import static org.shadowice.flocke.andotp.Utilities.Constants.EncryptionType;
|
||||
import static org.shadowice.flocke.andotp.Utilities.Constants.SortMode;
|
||||
|
||||
public class Settings {
|
||||
private static final String DEFAULT_BACKUP_FOLDER = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "andOTP";
|
||||
|
||||
private Context context;
|
||||
private SharedPreferences settings;
|
||||
|
||||
public enum SortMode {
|
||||
UNSORTED, LABEL, LAST_USED
|
||||
}
|
||||
|
||||
public Settings(Context context) {
|
||||
this.context = context;
|
||||
this.settings = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
|
@ -68,7 +58,7 @@ public class Settings {
|
|||
private void setupDeviceDependedDefaults() {
|
||||
if (! settings.contains(getResString(R.string.settings_key_backup_directory))
|
||||
|| settings.getString(getResString(R.string.settings_key_backup_directory), "").isEmpty()) {
|
||||
setString(R.string.settings_key_backup_directory, DEFAULT_BACKUP_FOLDER);
|
||||
setString(R.string.settings_key_backup_directory, Constants.BACKUP_FOLDER);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -87,7 +77,7 @@ public class Settings {
|
|||
String plainPassword = getBackupPassword();
|
||||
|
||||
try {
|
||||
KeyPair key = KeyStoreHelper.loadOrGenerateAsymmetricKeyPair(context, KEY_ALIAS);
|
||||
KeyPair key = KeyStoreHelper.loadOrGenerateAsymmetricKeyPair(context, Constants.KEYSTORE_ALIAS_PASSWORD);
|
||||
byte[] encPassword = EncryptionHelper.encrypt(key.getPublic(), plainPassword.getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
setString(R.string.settings_key_backup_password_enc, Base64.encodeToString(encPassword, Base64.URL_SAFE));
|
||||
|
@ -270,7 +260,7 @@ public class Settings {
|
|||
String storedSalt = getString(R.string.settings_key_auth_salt, "");
|
||||
|
||||
if (storedSalt.isEmpty()) {
|
||||
byte[] newSalt = EncryptionHelper.generateRandom(Constants.AUTH_SALT_LENGTH);
|
||||
byte[] newSalt = EncryptionHelper.generateRandom(Constants.PBKDF2_SALT_LENGTH);
|
||||
setSalt(newSalt);
|
||||
|
||||
return newSalt;
|
||||
|
@ -281,9 +271,9 @@ public class Settings {
|
|||
|
||||
public int getIterations(AuthMethod method) {
|
||||
if (method == AuthMethod.PASSWORD)
|
||||
return getIntValue(R.string.settings_key_auth_password_iter, PBKDF2_OLD_DEFAULT_ITERATIONS);
|
||||
return getIntValue(R.string.settings_key_auth_password_iter, Constants.PBKDF2_DEFAULT_ITERATIONS);
|
||||
else if (method == AuthMethod.PIN)
|
||||
return getIntValue(R.string.settings_key_auth_pin_iter, PBKDF2_OLD_DEFAULT_ITERATIONS);
|
||||
return getIntValue(R.string.settings_key_auth_pin_iter, Constants.PBKDF2_DEFAULT_ITERATIONS);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
@ -359,7 +349,7 @@ public class Settings {
|
|||
}
|
||||
|
||||
public String getBackupDir() {
|
||||
return getString(R.string.settings_key_backup_directory, DEFAULT_BACKUP_FOLDER);
|
||||
return getString(R.string.settings_key_backup_directory, Constants.BACKUP_FOLDER);
|
||||
}
|
||||
|
||||
public String getBackupPassword() {
|
||||
|
@ -373,7 +363,7 @@ public class Settings {
|
|||
String password = "";
|
||||
|
||||
try {
|
||||
KeyPair key = KeyStoreHelper.loadOrGenerateAsymmetricKeyPair(context, KEY_ALIAS);
|
||||
KeyPair key = KeyStoreHelper.loadOrGenerateAsymmetricKeyPair(context, Constants.KEYSTORE_ALIAS_PASSWORD);
|
||||
password = new String(EncryptionHelper.decrypt(key.getPrivate(), encPassword), StandardCharsets.UTF_8);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
|
|
|
@ -64,7 +64,7 @@ import java.util.concurrent.Callable;
|
|||
|
||||
import javax.crypto.SecretKey;
|
||||
|
||||
import static org.shadowice.flocke.andotp.Utilities.Settings.SortMode;
|
||||
import static org.shadowice.flocke.andotp.Utilities.Constants.SortMode;
|
||||
|
||||
public class EntriesCardAdapter extends RecyclerView.Adapter<EntryViewHolder>
|
||||
implements ItemTouchHelperAdapter, Filterable {
|
||||
|
|
|
@ -43,7 +43,6 @@ import java.util.List;
|
|||
|
||||
public class EntryViewHolder extends RecyclerView.ViewHolder
|
||||
implements ItemTouchHelperViewHolder {
|
||||
|
||||
private Context context;
|
||||
private Callback callback;
|
||||
private boolean tapToReveal;
|
||||
|
|
Loading…
Reference in a new issue