add LocalKeyStorage, don't store public keys larger than 50kb in database

This commit is contained in:
Vincent Breitmoser
2017-02-24 17:25:32 +01:00
parent 2bc05a2cd5
commit c7e01926e1
44 changed files with 314 additions and 150 deletions

View File

@@ -270,7 +270,7 @@ public class BackupOperation extends BaseOperation<BackupKeyringParcel> {
try {
arOutStream = new ArmoredOutputStream(outStream);
byte[] data = mDatabaseInteractor.getPublicKeyRingData(masterKeyId);
byte[] data = mDatabaseInteractor.loadPublicKeyRingData(masterKeyId);
UncachedKeyRing uncachedKeyRing = UncachedKeyRing.decodeFromData(data);
CanonicalizedPublicKeyRing ring = (CanonicalizedPublicKeyRing) uncachedKeyRing.canonicalize(log, 2, true);
ring.encode(arOutStream);
@@ -290,7 +290,7 @@ public class BackupOperation extends BaseOperation<BackupKeyringParcel> {
try {
arOutStream = new ArmoredOutputStream(outStream);
byte[] data = mDatabaseInteractor.getSecretKeyRingData(masterKeyId);
byte[] data = mDatabaseInteractor.loadSecretKeyRingData(masterKeyId);
UncachedKeyRing uncachedKeyRing = UncachedKeyRing.decodeFromData(data);
CanonicalizedSecretKeyRing ring = (CanonicalizedSecretKeyRing) uncachedKeyRing.canonicalize(log, 2, true);
ring.encode(arOutStream);

View File

@@ -25,7 +25,6 @@ import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType;
import org.sufficientlysecure.keychain.pgp.KeyRing;
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingData;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;
import org.sufficientlysecure.keychain.provider.DatabaseInteractor.NotFoundException;
@@ -240,7 +239,7 @@ public class CachedPublicKeyRing extends KeyRing {
public byte[] getEncoded() throws PgpKeyNotFoundException {
try {
return mDatabaseInteractor.getPublicKeyRingData(getMasterKeyId());
return mDatabaseInteractor.loadPublicKeyRingData(getMasterKeyId());
} catch(DatabaseReadWriteInteractor.NotFoundException e) {
throw new PgpKeyNotFoundException(e);
}

View File

@@ -7,9 +7,12 @@ import java.util.ArrayList;
import java.util.HashMap;
import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.util.Log;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType;
import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKeyRing;
@@ -33,15 +36,25 @@ public class DatabaseInteractor {
public static final int FIELD_TYPE_BLOB = 5;
final ContentResolver mContentResolver;
final LocalPublicKeyStorage mLocalPublicKeyStorage;
OperationLog mLog;
int mIndent;
public DatabaseInteractor(ContentResolver contentResolver) {
this(contentResolver, new OperationLog(), 0);
public static DatabaseInteractor createDatabaseInteractor(Context context) {
ContentResolver contentResolver = context.getContentResolver();
LocalPublicKeyStorage localPublicKeyStorage = LocalPublicKeyStorage.getInstance(context);
return new DatabaseInteractor(contentResolver, localPublicKeyStorage);
}
public DatabaseInteractor(ContentResolver contentResolver, OperationLog log, int indent) {
private DatabaseInteractor(ContentResolver contentResolver, LocalPublicKeyStorage localPublicKeyStorage) {
this(contentResolver, localPublicKeyStorage, new OperationLog(), 0);
}
DatabaseInteractor(ContentResolver contentResolver, LocalPublicKeyStorage localPublicKeyStorage,
OperationLog log, int indent) {
mContentResolver = contentResolver;
mLocalPublicKeyStorage = localPublicKeyStorage;
mIndent = indent;
mLog = log;
}
@@ -74,6 +87,10 @@ public class DatabaseInteractor {
return result;
}
Object getGenericDataOrNull(Uri uri, String column, int type) throws NotFoundException {
return getGenericData(uri, new String[]{column}, new int[]{type}, null).get(column);
}
Object getGenericData(Uri uri, String column, int type, String selection)
throws NotFoundException {
return getGenericData(uri, new String[]{column}, new int[]{type}, selection).get(column);
@@ -156,7 +173,7 @@ public class DatabaseInteractor {
long masterKeyId = cursor.getLong(0);
int verified = cursor.getInt(1);
byte[] publicKeyData = getPublicKeyRingData(masterKeyId);
byte[] publicKeyData = loadPublicKeyRingData(masterKeyId);
return new CanonicalizedPublicKeyRing(publicKeyData, verified);
} else {
throw new NotFoundException("Key not found!");
@@ -184,7 +201,7 @@ public class DatabaseInteractor {
throw new NotFoundException("No secret key available or unknown public key!");
}
byte[] secretKeyData = getSecretKeyRingData(masterKeyId);
byte[] secretKeyData = loadSecretKeyRingData(masterKeyId);
return new CanonicalizedSecretKeyRing(secretKeyData, verified);
} else {
throw new NotFoundException("Key not found!");
@@ -228,7 +245,7 @@ public class DatabaseInteractor {
public String getPublicKeyRingAsArmoredString(long masterKeyId)
throws NotFoundException, IOException, PgpGeneralException {
byte[] data = getPublicKeyRingData(masterKeyId);
byte[] data = loadPublicKeyRingData(masterKeyId);
return getKeyRingAsArmoredString(data);
}
@@ -236,14 +253,35 @@ public class DatabaseInteractor {
return mContentResolver;
}
public byte[] getPublicKeyRingData(long masterKeyId) throws NotFoundException {
return (byte[]) getGenericData(KeychainContract.KeyRingData.buildPublicKeyRingUri(masterKeyId),
public final byte[] loadPublicKeyRingData(long masterKeyId) throws NotFoundException {
byte[] data = (byte[]) getGenericDataOrNull(KeyRingData.buildPublicKeyRingUri(masterKeyId),
KeyRingData.KEY_RING_DATA, FIELD_TYPE_BLOB);
if (data == null) {
try {
data = mLocalPublicKeyStorage.readPublicKey(masterKeyId);
} catch (IOException e) {
Log.e(Constants.TAG, "Error reading public key from storage!", e);
throw new NotFoundException();
}
}
if (data == null) {
throw new NotFoundException();
}
return data;
}
public byte[] getSecretKeyRingData(long masterKeyId) throws NotFoundException {
return (byte[]) getGenericData(KeychainContract.KeyRingData.buildSecretKeyRingUri(masterKeyId),
public final byte[] loadSecretKeyRingData(long masterKeyId) throws NotFoundException {
byte[] data = (byte[]) getGenericDataOrNull(KeychainContract.KeyRingData.buildSecretKeyRingUri(masterKeyId),
KeyRingData.KEY_RING_DATA, FIELD_TYPE_BLOB);
if (data == null) {
throw new NotFoundException();
}
return data;
}
public static class NotFoundException extends Exception {

View File

@@ -19,6 +19,15 @@
package org.sufficientlysecure.keychain.provider;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.TimeUnit;
import android.content.ContentProviderOperation;
import android.content.ContentValues;
import android.content.Context;
@@ -68,15 +77,6 @@ import org.sufficientlysecure.keychain.util.ProgressFixedScaler;
import org.sufficientlysecure.keychain.util.ProgressScaler;
import org.sufficientlysecure.keychain.util.Utf8Util;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* This class contains high level methods for database access. Despite its
* name, it is not only a helper but actually the main interface for all
@@ -88,18 +88,26 @@ import java.util.concurrent.TimeUnit;
* method is called to start a new one specifically.
*/
public class DatabaseReadWriteInteractor extends DatabaseInteractor {
private static final int MAX_CACHED_KEY_SIZE = 1024 * 50;
private final Context mContext;
public DatabaseReadWriteInteractor(Context context) {
this(context, new OperationLog(), 0);
public static DatabaseReadWriteInteractor createDatabaseReadWriteInteractor(Context context) {
LocalPublicKeyStorage localPublicKeyStorage = LocalPublicKeyStorage.getInstance(context);
return new DatabaseReadWriteInteractor(context, localPublicKeyStorage);
}
public DatabaseReadWriteInteractor(Context context, OperationLog log) {
this(context, log, 0);
private DatabaseReadWriteInteractor(Context context, LocalPublicKeyStorage localPublicKeyStorage) {
this(context, localPublicKeyStorage, new OperationLog(), 0);
}
public DatabaseReadWriteInteractor(Context context, OperationLog log, int indent) {
super(context.getContentResolver(), log, indent);
private DatabaseReadWriteInteractor(Context context, LocalPublicKeyStorage localPublicKeyStorage, OperationLog log) {
this(context, localPublicKeyStorage, log, 0);
}
private DatabaseReadWriteInteractor(Context context, LocalPublicKeyStorage localPublicKeyStorage, OperationLog log, int indent) {
super(context.getContentResolver(), localPublicKeyStorage, log, indent);
mContext = context;
}
@@ -122,7 +130,7 @@ public class DatabaseReadWriteInteractor extends DatabaseInteractor {
try {
long masterKeyId = cursor.getLong(0);
int verified = cursor.getInt(2);
byte[] blob = getPublicKeyRingData(masterKeyId);
byte[] blob = loadPublicKeyRingData(masterKeyId);
if (blob != null) {
result.put(masterKeyId, new CanonicalizedPublicKeyRing(blob, verified).getPublicKey());
}
@@ -191,18 +199,11 @@ public class DatabaseReadWriteInteractor extends DatabaseInteractor {
operations = new ArrayList<>();
log(LogType.MSG_IP_INSERT_KEYRING);
{ // insert keyring
ContentValues values = new ContentValues();
values.put(KeyRingData.MASTER_KEY_ID, masterKeyId);
try {
values.put(KeyRingData.KEY_RING_DATA, keyRing.getEncoded());
} catch (IOException e) {
log(LogType.MSG_IP_ENCODE_FAIL);
return SaveKeyringResult.RESULT_ERROR;
}
Uri uri = KeyRingData.buildPublicKeyRingUri(masterKeyId);
operations.add(ContentProviderOperation.newInsert(uri).withValues(values).build());
try {
writePublicKeyRing(keyRing, masterKeyId, operations);
} catch (IOException e) {
log(LogType.MSG_IP_ENCODE_FAIL);
return SaveKeyringResult.RESULT_ERROR;
}
log(LogType.MSG_IP_INSERT_SUBKEYS);
@@ -582,6 +583,35 @@ public class DatabaseReadWriteInteractor extends DatabaseInteractor {
}
private void writePublicKeyRing(CanonicalizedPublicKeyRing keyRing, long masterKeyId,
ArrayList<ContentProviderOperation> operations) throws IOException {
byte[] encodedKey = keyRing.getEncoded();
mLocalPublicKeyStorage.writePublicKey(masterKeyId, encodedKey);
ContentValues values = new ContentValues();
values.put(KeyRingData.MASTER_KEY_ID, masterKeyId);
if (encodedKey.length < MAX_CACHED_KEY_SIZE) {
values.put(KeyRingData.KEY_RING_DATA, encodedKey);
} else {
values.put(KeyRingData.KEY_RING_DATA, (byte[]) null);
}
Uri uri = KeyRingData.buildPublicKeyRingUri(masterKeyId);
operations.add(ContentProviderOperation.newInsert(uri).withValues(values).build());
}
private Uri writeSecretKeyRing(CanonicalizedSecretKeyRing keyRing, long masterKeyId) throws IOException {
byte[] encodedKey = keyRing.getEncoded();
ContentValues values = new ContentValues();
values.put(KeyRingData.MASTER_KEY_ID, masterKeyId);
values.put(KeyRingData.KEY_RING_DATA, encodedKey);
// insert new version of this keyRing
Uri uri = KeyRingData.buildSecretKeyRingUri(masterKeyId);
return mContentResolver.insert(uri, values);
}
private static class UserPacketItem implements Comparable<UserPacketItem> {
Integer type;
String userId;
@@ -637,12 +667,8 @@ public class DatabaseReadWriteInteractor extends DatabaseInteractor {
// save secret keyring
try {
ContentValues values = new ContentValues();
values.put(KeyRingData.MASTER_KEY_ID, masterKeyId);
values.put(KeyRingData.KEY_RING_DATA, keyRing.getEncoded());
// insert new version of this keyRing
Uri uri = KeyRingData.buildSecretKeyRingUri(masterKeyId);
if (mContentResolver.insert(uri, values) == null) {
Uri insertedUri = writeSecretKeyRing(keyRing, masterKeyId);
if (insertedUri == null) {
log(LogType.MSG_IS_DB_EXCEPTION);
return SaveKeyringResult.RESULT_ERROR;
}

View File

@@ -0,0 +1,78 @@
package org.sufficientlysecure.keychain.provider;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import android.content.Context;
import okhttp3.internal.Util;
class LocalPublicKeyStorage {
private static final String FORMAT_STR_PUBLIC_KEY = "0x%016x.pub";
private static final String PUBLIC_KEYS_DIR_NAME = "public_keys";
private final File localPublicKeysDir;
public static LocalPublicKeyStorage getInstance(Context context) {
File localPublicKeysDir = new File(context.getFilesDir(), PUBLIC_KEYS_DIR_NAME);
return new LocalPublicKeyStorage(localPublicKeysDir);
}
private LocalPublicKeyStorage(File localPublicKeysDir) {
this.localPublicKeysDir = localPublicKeysDir;
}
private File getPublicKeyFile(long masterKeyId) throws IOException {
if (!localPublicKeysDir.exists()) {
localPublicKeysDir.mkdir();
}
if (!localPublicKeysDir.isDirectory()) {
throw new IOException("Failed creating public key directory!");
}
String keyFilename = String.format(FORMAT_STR_PUBLIC_KEY, masterKeyId);
return new File(localPublicKeysDir, keyFilename);
}
void writePublicKey(long masterKeyId, byte[] encoded) throws IOException {
File publicKeyFile = getPublicKeyFile(masterKeyId);
FileOutputStream fileOutputStream = new FileOutputStream(publicKeyFile);
try {
fileOutputStream.write(encoded);
} finally {
Util.closeQuietly(fileOutputStream);
}
}
byte[] readPublicKey(long masterKeyId) throws IOException {
File publicKeyFile = getPublicKeyFile(masterKeyId);
try {
FileInputStream fileInputStream = new FileInputStream(publicKeyFile);
return readIntoByteArray(fileInputStream);
} catch (FileNotFoundException e) {
return null;
}
}
private static byte[] readIntoByteArray(FileInputStream fileInputStream) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buf = new byte[128];
int bytesRead;
while ((bytesRead = fileInputStream.read(buf)) != -1) {
baos.write(buf, 0, bytesRead);
}
return baos.toByteArray();
}
}

View File

@@ -97,7 +97,7 @@ public class OpenPgpService extends Service {
public void onCreate() {
super.onCreate();
mApiPermissionHelper = new ApiPermissionHelper(this, new ApiDataAccessObject(this));
mDatabaseInteractor = new DatabaseInteractor(getContentResolver());
mDatabaseInteractor = DatabaseInteractor.createDatabaseInteractor(this);
mApiDao = new ApiDataAccessObject(this);
mApiPendingIntentFactory = new ApiPendingIntentFactory(getBaseContext());

View File

@@ -40,7 +40,8 @@ class RequestKeyPermissionPresenter {
PackageManager packageManager = context.getPackageManager();
ApiDataAccessObject apiDataAccessObject = new ApiDataAccessObject(context);
ApiPermissionHelper apiPermissionHelper = new ApiPermissionHelper(context, apiDataAccessObject);
DatabaseInteractor databaseInteractor = new DatabaseInteractor(context.getContentResolver());
DatabaseInteractor databaseInteractor =
DatabaseInteractor.createDatabaseInteractor(context);
return new RequestKeyPermissionPresenter(context, apiDataAccessObject, apiPermissionHelper, packageManager,
databaseInteractor);

View File

@@ -111,7 +111,8 @@ public class KeychainService extends Service implements Progressable {
// just for brevity
KeychainService outerThis = KeychainService.this;
DatabaseReadWriteInteractor databaseInteractor = new DatabaseReadWriteInteractor(outerThis);
DatabaseReadWriteInteractor databaseInteractor =
DatabaseReadWriteInteractor.createDatabaseReadWriteInteractor(outerThis);
if (inputParcel instanceof SignEncryptParcel) {
op = new SignEncryptOperation(outerThis, databaseInteractor, outerThis, mActionCanceled);
} else if (inputParcel instanceof PgpDecryptVerifyInputParcel) {

View File

@@ -321,7 +321,8 @@ public class KeyserverSyncAdapterService extends Service {
private ImportKeyResult directUpdate(Context context, ArrayList<ParcelableKeyRing> keyList,
CryptoInputParcel cryptoInputParcel) {
Log.d(Constants.TAG, "Starting normal update");
ImportOperation importOp = new ImportOperation(context, new DatabaseReadWriteInteractor(context), null);
ImportOperation importOp = new ImportOperation(context,
DatabaseReadWriteInteractor.createDatabaseReadWriteInteractor(context), null);
return importOp.execute(
new ImportKeyringParcel(keyList,
Preferences.getPreferences(context).getPreferredKeyserver()),
@@ -381,7 +382,7 @@ public class KeyserverSyncAdapterService extends Service {
new OperationResult.OperationLog());
}
ImportKeyResult result =
new ImportOperation(context, new DatabaseReadWriteInteractor(context), null, mCancelled)
new ImportOperation(context, DatabaseReadWriteInteractor.createDatabaseReadWriteInteractor(context), null, mCancelled)
.execute(
new ImportKeyringParcel(
keyWrapper,

View File

@@ -245,7 +245,7 @@ public class PassphraseCacheService extends Service {
+ masterKeyId + ", subKeyId " + subKeyId);
// get the type of key (from the database)
CachedPublicKeyRing keyRing = new DatabaseInteractor(getContentResolver()).getCachedPublicKeyRing(masterKeyId);
CachedPublicKeyRing keyRing = DatabaseInteractor.createDatabaseInteractor(this).getCachedPublicKeyRing(masterKeyId);
SecretKeyType keyType = keyRing.getSecretKeyType(subKeyId);
switch (keyType) {

View File

@@ -214,7 +214,7 @@ public class CertifyFingerprintFragment extends LoaderFragment implements
private void certify(Uri dataUri) {
long keyId = 0;
try {
keyId = new DatabaseInteractor(getActivity().getContentResolver())
keyId = DatabaseInteractor.createDatabaseInteractor(getContext())
.getCachedPublicKeyRing(dataUri)
.extractOrGetMasterKeyId();
} catch (PgpKeyNotFoundException e) {

View File

@@ -69,7 +69,8 @@ public class CertifyKeyFragment
.getLongExtra(CertifyKeyActivity.EXTRA_CERTIFY_KEY_ID, Constants.key.none);
if (certifyKeyId != Constants.key.none) {
try {
CachedPublicKeyRing key = (new DatabaseInteractor(getActivity().getContentResolver()))
CachedPublicKeyRing key = (DatabaseInteractor
.createDatabaseInteractor(getContext()))
.getCachedPublicKeyRing(certifyKeyId);
if (key.canCertify()) {
mCertifyKeySpinner.setPreSelectedKeyId(certifyKeyId);

View File

@@ -181,7 +181,7 @@ public class CreateKeyActivity extends BaseSecurityTokenActivity {
if (containsKeys(mScannedFingerprints)) {
try {
long masterKeyId = KeyFormattingUtils.getKeyIdFromFingerprint(mScannedFingerprints);
CachedPublicKeyRing ring = new DatabaseInteractor(getContentResolver()).getCachedPublicKeyRing(masterKeyId);
CachedPublicKeyRing ring = DatabaseInteractor.createDatabaseInteractor(this).getCachedPublicKeyRing(masterKeyId);
ring.getMasterKeyId();
Intent intent = new Intent(this, ViewKeyActivity.class);

View File

@@ -44,7 +44,6 @@ import org.sufficientlysecure.keychain.pgp.KeyRing;
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing;
import org.sufficientlysecure.keychain.provider.DatabaseInteractor;
import org.sufficientlysecure.keychain.provider.DatabaseReadWriteInteractor;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.service.ChangeUnlockParcel;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
@@ -412,7 +411,7 @@ public class CreateKeyFinalFragment extends Fragment {
CreateKeyActivity activity = (CreateKeyActivity) getActivity();
final SaveKeyringParcel changeKeyringParcel;
CachedPublicKeyRing key = (new DatabaseInteractor(activity.getContentResolver()))
CachedPublicKeyRing key = (DatabaseInteractor.createDatabaseInteractor(getContext()))
.getCachedPublicKeyRing(saveKeyResult.mMasterKeyId);
try {
changeKeyringParcel = new SaveKeyringParcel(key.getMasterKeyId(), key.getFingerprint());

View File

@@ -193,7 +193,7 @@ public abstract class DecryptFragment extends Fragment implements LoaderManager.
try {
Intent viewKeyIntent = new Intent(getActivity(), ViewKeyActivity.class);
long masterKeyId = new DatabaseInteractor(getActivity().getContentResolver()).getCachedPublicKeyRing(
long masterKeyId = DatabaseInteractor.createDatabaseInteractor(getContext()).getCachedPublicKeyRing(
KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(keyId)
).getMasterKeyId();
viewKeyIntent.setData(KeyRings.buildGenericKeyRingUri(masterKeyId));

View File

@@ -89,7 +89,7 @@ public class DeleteKeyDialogActivity extends FragmentActivity {
if (mMasterKeyIds.length == 1 && mHasSecret) {
// if mMasterKeyIds.length == 0 we let the DeleteOperation respond
try {
HashMap<String, Object> data = new DatabaseInteractor(getContentResolver()).getUnifiedData(
HashMap<String, Object> data = DatabaseInteractor.createDatabaseInteractor(this).getUnifiedData(
mMasterKeyIds[0], new String[]{
KeychainContract.KeyRings.NAME,
KeychainContract.KeyRings.IS_REVOKED
@@ -269,7 +269,8 @@ public class DeleteKeyDialogActivity extends FragmentActivity {
long masterKeyId = masterKeyIds[0];
try {
HashMap<String, Object> data = new DatabaseInteractor(activity.getContentResolver()).getUnifiedData(
HashMap<String, Object> data = DatabaseInteractor.createDatabaseInteractor(getContext())
.getUnifiedData(
masterKeyId, new String[]{
KeychainContract.KeyRings.NAME,
KeychainContract.KeyRings.HAS_ANY_SECRET

View File

@@ -170,7 +170,7 @@ public class EditIdentitiesFragment extends Fragment
try {
Uri secretUri = KeychainContract.KeyRings.buildUnifiedKeyRingUri(mDataUri);
CachedPublicKeyRing keyRing =
new DatabaseInteractor(getActivity().getContentResolver()).getCachedPublicKeyRing(secretUri);
DatabaseInteractor.createDatabaseInteractor(getContext()).getCachedPublicKeyRing(secretUri);
long masterKeyId = keyRing.getMasterKeyId();
// check if this is a master secret key we can work with

View File

@@ -49,7 +49,6 @@ import org.sufficientlysecure.keychain.pgp.KeyRing;
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing;
import org.sufficientlysecure.keychain.provider.DatabaseInteractor;
import org.sufficientlysecure.keychain.provider.DatabaseReadWriteInteractor;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets;
import org.sufficientlysecure.keychain.provider.DatabaseInteractor.NotFoundException;
@@ -204,7 +203,7 @@ public class EditKeyFragment extends QueueingCryptoOperationFragment<SaveKeyring
try {
Uri secretUri = KeychainContract.KeyRings.buildUnifiedKeyRingUri(mDataUri);
CachedPublicKeyRing keyRing =
new DatabaseInteractor(getActivity().getContentResolver()).getCachedPublicKeyRing(secretUri);
DatabaseInteractor.createDatabaseInteractor(getContext()).getCachedPublicKeyRing(secretUri);
long masterKeyId = keyRing.getMasterKeyId();
// check if this is a master secret key we can work with

View File

@@ -115,7 +115,7 @@ public class EncryptModeAsymmetricFragment extends EncryptModeFragment {
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mDatabaseInteractor = new DatabaseInteractor(getActivity().getContentResolver());
mDatabaseInteractor = DatabaseInteractor.createDatabaseInteractor(getContext());
// preselect keys given, from state or arguments
if (savedInstanceState == null) {

View File

@@ -486,7 +486,8 @@ public class KeyListFragment extends RecyclerFragment<KeySectionedListAdapter>
return;
}
DatabaseInteractor databaseInteractor = new DatabaseInteractor(activity.getContentResolver());
DatabaseInteractor databaseInteractor =
DatabaseInteractor.createDatabaseInteractor(getContext());
Cursor cursor = databaseInteractor.getContentResolver().query(
KeyRings.buildUnifiedKeyRingsUri(), new String[]{
KeyRings.FINGERPRINT

View File

@@ -112,7 +112,7 @@ public class PassphraseDialogActivity extends FragmentActivity {
// handle empty passphrases by directly returning an empty crypto input parcel
try {
CachedPublicKeyRing pubRing =
new DatabaseInteractor(getContentResolver()).getCachedPublicKeyRing(requiredInput.getMasterKeyId());
DatabaseInteractor.createDatabaseInteractor(this).getCachedPublicKeyRing(requiredInput.getMasterKeyId());
// use empty passphrase for empty passphrase
if (pubRing.getSecretKeyType(requiredInput.getSubKeyId()) == SecretKeyType.PASSPHRASE_EMPTY) {
// also return passphrase back to activity
@@ -231,7 +231,8 @@ public class PassphraseDialogActivity extends FragmentActivity {
try {
long subKeyId = mRequiredInput.getSubKeyId();
DatabaseInteractor helper = new DatabaseInteractor(activity.getContentResolver());
DatabaseInteractor helper =
DatabaseInteractor.createDatabaseInteractor(getContext());
CachedPublicKeyRing cachedPublicKeyRing = helper.getCachedPublicKeyRing(
KeychainContract.KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(subKeyId));
// yes the inner try/catch block is necessary, otherwise the final variable
@@ -457,7 +458,7 @@ public class PassphraseDialogActivity extends FragmentActivity {
Long subKeyId = mRequiredInput.getSubKeyId();
CanonicalizedSecretKeyRing secretKeyRing =
new DatabaseInteractor(getActivity().getContentResolver()).getCanonicalizedSecretKeyRing(
DatabaseInteractor.createDatabaseInteractor(getContext()).getCanonicalizedSecretKeyRing(
KeychainContract.KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(subKeyId));
CanonicalizedSecretKey secretKeyToUnlock =
secretKeyRing.getSecretKey(subKeyId);

View File

@@ -29,8 +29,6 @@ import android.widget.ImageView;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
import org.sufficientlysecure.keychain.provider.DatabaseReadWriteInteractor;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.DatabaseInteractor;
import org.sufficientlysecure.keychain.ui.base.BaseActivity;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
@@ -76,7 +74,7 @@ public class QrCodeViewActivity extends BaseActivity {
}
});
DatabaseInteractor databaseInteractor = new DatabaseInteractor(getContentResolver());
DatabaseInteractor databaseInteractor = DatabaseInteractor.createDatabaseInteractor(this);
try {
byte[] blob = databaseInteractor.getCachedPublicKeyRing(dataUri).getFingerprint();
if (blob == null) {

View File

@@ -106,7 +106,7 @@ public class SafeSlingerActivity extends BaseActivity
// retrieve public key blob and start SafeSlinger
Uri uri = KeychainContract.KeyRingData.buildPublicKeyRingUri(masterKeyId);
try {
byte[] keyBlob = new DatabaseInteractor(getContentResolver()).getCachedPublicKeyRing(uri).getEncoded();
byte[] keyBlob = DatabaseInteractor.createDatabaseInteractor(this).getCachedPublicKeyRing(uri).getEncoded();
Intent slingerIntent = new Intent(this, ExchangeActivity.class);

View File

@@ -193,7 +193,8 @@ public class SecurityTokenOperationActivity extends BaseSecurityTokenActivity {
throw new IOException(getString(R.string.error_wrong_security_token));
}
DatabaseInteractor databaseInteractor = new DatabaseInteractor(getContentResolver());
DatabaseInteractor databaseInteractor =
DatabaseInteractor.createDatabaseInteractor(this);
CanonicalizedPublicKeyRing publicKeyRing;
try {
publicKeyRing = databaseInteractor.getCanonicalizedPublicKeyRing(
@@ -232,7 +233,8 @@ public class SecurityTokenOperationActivity extends BaseSecurityTokenActivity {
mSecurityTokenHelper.setPin(new Passphrase("123456"));
mSecurityTokenHelper.setAdminPin(new Passphrase("12345678"));
DatabaseInteractor databaseInteractor = new DatabaseInteractor(getContentResolver());
DatabaseInteractor databaseInteractor =
DatabaseInteractor.createDatabaseInteractor(this);
CanonicalizedSecretKeyRing secretKeyRing;
try {
secretKeyRing = databaseInteractor.getCanonicalizedSecretKeyRing(

View File

@@ -184,7 +184,8 @@ public class ViewCertActivity extends BaseActivity
Intent viewIntent = new Intent(ViewCertActivity.this, ViewKeyActivity.class);
try {
DatabaseInteractor databaseInteractor = new DatabaseInteractor(ViewCertActivity.this.getContentResolver());
DatabaseInteractor databaseInteractor =
DatabaseInteractor.createDatabaseInteractor(ViewCertActivity.this);
long signerMasterKeyId = databaseInteractor.getCachedPublicKeyRing(
KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(mCertifierKeyId)).getMasterKeyId();
viewIntent.setData(KeyRings.buildGenericKeyRingUri(signerMasterKeyId));

View File

@@ -185,7 +185,7 @@ public class ViewKeyActivity extends BaseSecurityTokenActivity implements
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mDatabaseInteractor = new DatabaseInteractor(getContentResolver());
mDatabaseInteractor = DatabaseInteractor.createDatabaseInteractor(this);
mImportOpHelper = new CryptoOperationHelper<>(1, this, this, null);
setTitle(null);
@@ -741,7 +741,7 @@ public class ViewKeyActivity extends BaseSecurityTokenActivity implements
return;
}
try {
long keyId = new DatabaseInteractor(getContentResolver())
long keyId = DatabaseInteractor.createDatabaseInteractor(this)
.getCachedPublicKeyRing(dataUri)
.extractOrGetMasterKeyId();
long[] encryptionKeyIds = new long[]{keyId};
@@ -765,7 +765,7 @@ public class ViewKeyActivity extends BaseSecurityTokenActivity implements
private void startSafeSlinger(Uri dataUri) {
long keyId = 0;
try {
keyId = new DatabaseInteractor(getContentResolver())
keyId = DatabaseInteractor.createDatabaseInteractor(this)
.getCachedPublicKeyRing(dataUri)
.extractOrGetMasterKeyId();
} catch (PgpKeyNotFoundException e) {

View File

@@ -87,7 +87,7 @@ public class ViewKeyAdvActivity extends BaseActivity implements
}
});
mDatabaseInteractor = new DatabaseInteractor(getContentResolver());
mDatabaseInteractor = DatabaseInteractor.createDatabaseInteractor(this);
mViewPager = (ViewPager) findViewById(R.id.pager);
mSlidingTabLayout = (PagerSlidingTabStrip) findViewById(R.id.sliding_tab_layout);

View File

@@ -95,7 +95,7 @@ public class ViewKeyAdvShareFragment extends LoaderFragment implements
View view = inflater.inflate(R.layout.view_key_adv_share_fragment, getContainer());
ContentResolver contentResolver = ViewKeyAdvShareFragment.this.getActivity().getContentResolver();
DatabaseInteractor databaseInteractor = new DatabaseInteractor(contentResolver);
DatabaseInteractor databaseInteractor = DatabaseInteractor.createDatabaseInteractor(getContext());
mNfcHelper = new NfcHelper(getActivity(), databaseInteractor);
mFingerprintView = (TextView) view.findViewById(R.id.view_key_fingerprint);
@@ -202,7 +202,7 @@ public class ViewKeyAdvShareFragment extends LoaderFragment implements
private void startSafeSlinger(Uri dataUri) {
long keyId = 0;
try {
keyId = new DatabaseInteractor(getActivity().getContentResolver())
keyId = DatabaseInteractor.createDatabaseInteractor(getContext())
.getCachedPublicKeyRing(dataUri)
.extractOrGetMasterKeyId();
} catch (PgpKeyNotFoundException e) {
@@ -218,7 +218,8 @@ public class ViewKeyAdvShareFragment extends LoaderFragment implements
if (activity == null || mFingerprint == null) {
return;
}
DatabaseInteractor databaseInteractor = new DatabaseInteractor(activity.getContentResolver());
DatabaseInteractor databaseInteractor =
DatabaseInteractor.createDatabaseInteractor(getContext());
try {
long masterKeyId = databaseInteractor.getCachedPublicKeyRing(mDataUri).extractOrGetMasterKeyId();
@@ -459,7 +460,7 @@ public class ViewKeyAdvShareFragment extends LoaderFragment implements
private void uploadToKeyserver() {
long keyId;
try {
keyId = new DatabaseInteractor(getActivity().getContentResolver())
keyId = DatabaseInteractor.createDatabaseInteractor(getContext())
.getCachedPublicKeyRing(mDataUri)
.extractOrGetMasterKeyId();
} catch (PgpKeyNotFoundException e) {

View File

@@ -75,7 +75,7 @@ public class ImportKeysAdapter extends RecyclerView.Adapter<ImportKeysAdapter.Vi
mListener = listener;
mNonInteractive = nonInteractive;
mDatabaseInteractor = new DatabaseInteractor(activity.getContentResolver());
mDatabaseInteractor = DatabaseInteractor.createDatabaseInteractor(activity);
}
public void setData(List<ImportKeysListEntry> data) {

View File

@@ -105,7 +105,7 @@ public abstract class BaseSecurityTokenActivity extends BaseActivity
final long subKeyId = KeyFormattingUtils.getKeyIdFromFingerprint(mSecurityTokenFingerprints);
try {
CachedPublicKeyRing ring = new DatabaseInteractor(getContentResolver()).getCachedPublicKeyRing(
CachedPublicKeyRing ring = DatabaseInteractor.createDatabaseInteractor(this).getCachedPublicKeyRing(
KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(subKeyId));
long masterKeyId = ring.getMasterKeyId();

View File

@@ -58,7 +58,7 @@ public class LinkedIdWizard extends BaseActivity {
try {
Uri uri = getIntent().getData();
uri = KeychainContract.KeyRings.buildUnifiedKeyRingUri(uri);
CachedPublicKeyRing ring = new DatabaseInteractor(getContentResolver()).getCachedPublicKeyRing(uri);
CachedPublicKeyRing ring = DatabaseInteractor.createDatabaseInteractor(this).getCachedPublicKeyRing(uri);
if (!ring.hasAnySecret()) {
Log.e(Constants.TAG, "Linked Identities can only be added to secret keys!");
finish();

View File

@@ -130,7 +130,7 @@ public class NfcHelper {
try {
long masterKeyId = mDatabaseInteractor.getCachedPublicKeyRing(dataUri)
.extractOrGetMasterKeyId();
mNfcKeyringBytes = mDatabaseInteractor.getPublicKeyRingData(masterKeyId);
mNfcKeyringBytes = mDatabaseInteractor.loadPublicKeyRingData(masterKeyId);
} catch (NotFoundException | PgpKeyNotFoundException e) {
Log.e(Constants.TAG, "key not found!", e);
}

View File

@@ -52,6 +52,10 @@ public class ParcelableFileCache<E extends Parcelable> {
mFilename = filename;
}
public static boolean cacheFileExists(Context context, String filename) {
return new File(context.getCacheDir(), filename).exists();
}
public void writeCache(int numEntries, Iterator<E> it) throws IOException {
DataOutputStream oos = getOutputStream();