diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java index fcf8f7962..e6e106ba6 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java @@ -96,18 +96,14 @@ public class KeychainContract { public static final String BASE_API_APPS = "api_apps"; public static final String PATH_ACCOUNTS = "accounts"; - public static class KeyRings implements KeyRingsColumns, BaseColumns { + public static class KeyRings implements BaseColumns, KeysColumns, UserIdsColumns { + public static final String MASTER_KEY_ID = "master_key_id"; + public static final String HAS_SECRET = "has_secret"; + public static final Uri CONTENT_URI = BASE_CONTENT_URI_INTERNAL.buildUpon() .appendPath(BASE_KEY_RINGS).build(); - /** - * Use if multiple items get returned - */ public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.sufficientlysecure.openkeychain.key_ring"; - - /** - * Use if a single item is returned - */ public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.sufficientlysecure.openkeychain.key_ring"; public static Uri buildUnifiedKeyRingsUri() { @@ -121,6 +117,24 @@ public class KeychainContract { return CONTENT_URI.buildUpon().appendPath(masterKeyId).build(); } + public static Uri buildUnifiedKeyRingUri(String masterKeyId) { + return CONTENT_URI.buildUpon().appendPath(masterKeyId).appendPath(PATH_UNIFIED).build(); + } + public static Uri buildUnifiedKeyRingUri(Uri uri) { + return CONTENT_URI.buildUpon().appendPath(uri.getPathSegments().get(1)).appendPath(PATH_UNIFIED).build(); + } + } + + public static class KeyRingData implements KeyRingsColumns, BaseColumns { + public static final Uri CONTENT_URI = BASE_CONTENT_URI_INTERNAL.buildUpon() + .appendPath(BASE_KEY_RINGS).build(); + + public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.sufficientlysecure.openkeychain.key_ring_data"; + public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.sufficientlysecure.openkeychain.key_ring_data"; + + public static Uri buildPublicKeyRingUri() { + return CONTENT_URI.buildUpon().appendPath(PATH_PUBLIC).build(); + } public static Uri buildPublicKeyRingUri(String masterKeyId) { return CONTENT_URI.buildUpon().appendPath(masterKeyId).appendPath(PATH_PUBLIC).build(); } @@ -135,12 +149,6 @@ public class KeychainContract { return CONTENT_URI.buildUpon().appendPath(uri.getPathSegments().get(1)).appendPath(PATH_SECRET).build(); } - public static Uri buildUnifiedKeyRingUri(String masterKeyId) { - return CONTENT_URI.buildUpon().appendPath(masterKeyId).appendPath(PATH_UNIFIED).build(); - } - public static Uri buildUnifiedKeyRingUri(Uri uri) { - return CONTENT_URI.buildUpon().appendPath(uri.getPathSegments().get(1)).appendPath(PATH_UNIFIED).build(); - } } public static class Keys implements KeysColumns, BaseColumns { diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java index a4fd1130d..8b1ee4886 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java @@ -26,19 +26,15 @@ import android.database.sqlite.SQLiteConstraintException; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteQueryBuilder; import android.net.Uri; -import android.provider.BaseColumns; import android.text.TextUtils; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.provider.KeychainContract.ApiAccounts; import org.sufficientlysecure.keychain.provider.KeychainContract.ApiApps; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; -import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingsColumns; -import org.sufficientlysecure.keychain.provider.KeychainContract.KeyTypes; +import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingData; import org.sufficientlysecure.keychain.provider.KeychainContract.Keys; -import org.sufficientlysecure.keychain.provider.KeychainContract.KeysColumns; import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds; -import org.sufficientlysecure.keychain.provider.KeychainContract.UserIdsColumns; import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables; import org.sufficientlysecure.keychain.util.Log; @@ -46,13 +42,9 @@ import java.util.Arrays; import java.util.HashMap; public class KeychainProvider extends ContentProvider { - // public static final String ACTION_BROADCAST_DATABASE_CHANGE = Constants.PACKAGE_NAME - // + ".action.DATABASE_CHANGE"; - // - // public static final String EXTRA_BROADCAST_KEY_TYPE = "key_type"; - // public static final String EXTRA_BROADCAST_CONTENT_ITEM_TYPE = "contentItemType"; private static final int KEY_RINGS_UNIFIED = 101; + private static final int KEY_RINGS_PUBLIC = 102; private static final int KEY_RING_UNIFIED = 200; private static final int KEY_RING_KEYS = 201; @@ -79,18 +71,22 @@ public class KeychainProvider extends ContentProvider { String authority = KeychainContract.CONTENT_AUTHORITY; /** - * select from key_ring + * list key_rings * *
          * key_rings/unified
+         * key_rings/public
          * 
*/ matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/" + KeychainContract.PATH_UNIFIED, KEY_RINGS_UNIFIED); + matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + + "/" + KeychainContract.PATH_PUBLIC, + KEY_RINGS_PUBLIC); /** - * select from key_ring + * list key_ring specifics * *
          * key_rings/_/unified
@@ -215,45 +211,44 @@ public class KeychainProvider extends ContentProvider {
             case KEY_RING_UNIFIED:
             case KEY_RINGS_UNIFIED: {
                 HashMap projectionMap = new HashMap();
-                projectionMap.put(BaseColumns._ID, Tables.KEYS + ".oid AS _id");
-                projectionMap.put(KeysColumns.MASTER_KEY_ID, Tables.KEYS + "." + KeysColumns.MASTER_KEY_ID);
-                projectionMap.put(KeysColumns.RANK, Tables.KEYS + "." + KeysColumns.RANK);
-                projectionMap.put(KeysColumns.KEY_ID, KeysColumns.KEY_ID);
-                projectionMap.put(KeysColumns.KEY_SIZE, KeysColumns.KEY_SIZE);
-                projectionMap.put(KeysColumns.IS_REVOKED, KeysColumns.IS_REVOKED);
-                projectionMap.put(KeysColumns.CAN_CERTIFY, KeysColumns.CAN_CERTIFY);
-                projectionMap.put(KeysColumns.CAN_ENCRYPT, KeysColumns.CAN_ENCRYPT);
-                projectionMap.put(KeysColumns.CAN_SIGN, KeysColumns.CAN_SIGN);
-                projectionMap.put(KeysColumns.CREATION, KeysColumns.CREATION);
-                projectionMap.put(KeysColumns.EXPIRY, KeysColumns.EXPIRY);
-                projectionMap.put(KeysColumns.ALGORITHM, KeysColumns.ALGORITHM);
-                projectionMap.put(KeysColumns.FINGERPRINT, KeysColumns.FINGERPRINT);
-                projectionMap.put(UserIdsColumns.USER_ID, UserIdsColumns.USER_ID);
-                projectionMap.put(Tables.KEY_RINGS_SECRET + "." + KeyRings.MASTER_KEY_ID, Tables.KEY_RINGS_SECRET + "." + KeyRingsColumns.MASTER_KEY_ID);
+                projectionMap.put(KeyRings._ID, Tables.KEYS + ".oid AS _id");
+                projectionMap.put(KeyRings.MASTER_KEY_ID, Tables.KEYS + "." + Keys.MASTER_KEY_ID);
+                projectionMap.put(KeyRings.KEY_ID, Keys.KEY_ID);
+                projectionMap.put(KeyRings.KEY_SIZE, Keys.KEY_SIZE);
+                projectionMap.put(KeyRings.IS_REVOKED, Keys.IS_REVOKED);
+                projectionMap.put(KeyRings.CAN_CERTIFY, Keys.CAN_CERTIFY);
+                projectionMap.put(KeyRings.CAN_ENCRYPT, Keys.CAN_ENCRYPT);
+                projectionMap.put(KeyRings.CAN_SIGN, Keys.CAN_SIGN);
+                projectionMap.put(KeyRings.CREATION, Keys.CREATION);
+                projectionMap.put(KeyRings.EXPIRY, Keys.EXPIRY);
+                projectionMap.put(KeyRings.ALGORITHM, Keys.ALGORITHM);
+                projectionMap.put(KeyRings.FINGERPRINT, Keys.FINGERPRINT);
+                projectionMap.put(KeyRings.USER_ID, UserIds.USER_ID);
+                projectionMap.put(KeyRings.HAS_SECRET, "(" + Tables.KEY_RINGS_SECRET + "." + KeyRings.MASTER_KEY_ID + " IS NOT NULL) AS " + KeyRings.HAS_SECRET);
                 qb.setProjectionMap(projectionMap);
 
                 qb.setTables(
                     Tables.KEYS
                         + " INNER JOIN " + Tables.USER_IDS + " ON ("
-                                    + Tables.KEYS + "." + KeysColumns.MASTER_KEY_ID
+                                    + Tables.KEYS + "." + Keys.MASTER_KEY_ID
                                 + " = "
-                                    + Tables.USER_IDS + "." + UserIdsColumns.MASTER_KEY_ID
-                            + " AND " + Tables.USER_IDS + "." + UserIdsColumns.RANK + " = 0"
+                                    + Tables.USER_IDS + "." + UserIds.MASTER_KEY_ID
+                            + " AND " + Tables.USER_IDS + "." + UserIds.RANK + " = 0"
                         + ") LEFT JOIN " + Tables.KEY_RINGS_SECRET + " ON ("
-                            + Tables.KEYS + "." + KeysColumns.MASTER_KEY_ID
+                            + Tables.KEYS + "." + Keys.MASTER_KEY_ID
                                 + " = "
-                            + Tables.KEY_RINGS_SECRET + "." + KeyRingsColumns.MASTER_KEY_ID
+                            + Tables.KEY_RINGS_SECRET + "." + KeyRings.MASTER_KEY_ID
                         + ")"
                     );
-                qb.appendWhere(Tables.KEYS + "." + KeysColumns.RANK + " = 0");
+                qb.appendWhere(Tables.KEYS + "." + Keys.RANK + " = 0");
 
                 if(match == KEY_RING_UNIFIED) {
-                    qb.appendWhere(" AND " + Tables.KEYS + "." + KeysColumns.MASTER_KEY_ID + " = ");
+                    qb.appendWhere(" AND " + Tables.KEYS + "." + Keys.MASTER_KEY_ID + " = ");
                     qb.appendWhereEscapeString(uri.getPathSegments().get(1));
                 } else if (TextUtils.isEmpty(sortOrder)) {
                     sortOrder =
                             Tables.KEY_RINGS_SECRET + "." + KeyRings.MASTER_KEY_ID + " IS NULL DESC"
-                            + Tables.USER_IDS + "." + UserIdsColumns.USER_ID + " ASC";
+                            + Tables.USER_IDS + "." + UserIds.USER_ID + " ASC";
                 }
 
                 // uri to watch is all /key_rings/
@@ -276,38 +271,38 @@ public class KeychainProvider extends ContentProvider {
                     if (i != 0) {
                         emailWhere += " OR ";
                     }
-                    emailWhere += "tmp." + UserIdsColumns.USER_ID + " LIKE ";
+                    emailWhere += "tmp." + UserIds.USER_ID + " LIKE ";
                     // match '*', so it has to be at the *end* of the user id
                     emailWhere += DatabaseUtils.sqlEscapeString("%<" + chunks[i] + ">");
                     gotCondition = true;
                 }
 
                 if (gotCondition) {
-                    qb.appendWhere(" AND EXISTS (SELECT tmp." + BaseColumns._ID + " FROM "
-                            + Tables.USER_IDS + " AS tmp WHERE tmp." + UserIdsColumns.KEY_RING_ROW_ID
-                            + " = " + Tables.KEY_RINGS + "." + BaseColumns._ID + " AND (" + emailWhere
+                    qb.appendWhere(" AND EXISTS (SELECT tmp." + Base._ID + " FROM "
+                            + Tables.USER_IDS + " AS tmp WHERE tmp." + UserIds.KEY_RING_ROW_ID
+                            + " = " + Tables.KEY_RINGS + "." + Base._ID + " AND (" + emailWhere
                             + "))");
                 }*/
 
             case KEY_RING_KEYS: {
                 HashMap projectionMap = new HashMap();
-                projectionMap.put(BaseColumns._ID, Tables.KEYS + ".oid AS _id");
-                projectionMap.put(KeysColumns.MASTER_KEY_ID, Tables.KEYS + "." + KeysColumns.MASTER_KEY_ID);
-                projectionMap.put(KeysColumns.RANK, Tables.KEYS + "." + KeysColumns.RANK);
-                projectionMap.put(KeysColumns.KEY_ID, KeysColumns.KEY_ID);
-                projectionMap.put(KeysColumns.KEY_SIZE, KeysColumns.KEY_SIZE);
-                projectionMap.put(KeysColumns.IS_REVOKED, KeysColumns.IS_REVOKED);
-                projectionMap.put(KeysColumns.CAN_CERTIFY, KeysColumns.CAN_CERTIFY);
-                projectionMap.put(KeysColumns.CAN_ENCRYPT, KeysColumns.CAN_ENCRYPT);
-                projectionMap.put(KeysColumns.CAN_SIGN, KeysColumns.CAN_SIGN);
-                projectionMap.put(KeysColumns.CREATION, KeysColumns.CREATION);
-                projectionMap.put(KeysColumns.EXPIRY, KeysColumns.EXPIRY);
-                projectionMap.put(KeysColumns.ALGORITHM, KeysColumns.ALGORITHM);
-                projectionMap.put(KeysColumns.FINGERPRINT, KeysColumns.FINGERPRINT);
+                projectionMap.put(Keys._ID, Tables.KEYS + ".oid AS _id");
+                projectionMap.put(Keys.MASTER_KEY_ID, Tables.KEYS + "." + Keys.MASTER_KEY_ID);
+                projectionMap.put(Keys.RANK, Tables.KEYS + "." + Keys.RANK);
+                projectionMap.put(Keys.KEY_ID, Keys.KEY_ID);
+                projectionMap.put(Keys.KEY_SIZE, Keys.KEY_SIZE);
+                projectionMap.put(Keys.IS_REVOKED, Keys.IS_REVOKED);
+                projectionMap.put(Keys.CAN_CERTIFY, Keys.CAN_CERTIFY);
+                projectionMap.put(Keys.CAN_ENCRYPT, Keys.CAN_ENCRYPT);
+                projectionMap.put(Keys.CAN_SIGN, Keys.CAN_SIGN);
+                projectionMap.put(Keys.CREATION, Keys.CREATION);
+                projectionMap.put(Keys.EXPIRY, Keys.EXPIRY);
+                projectionMap.put(Keys.ALGORITHM, Keys.ALGORITHM);
+                projectionMap.put(Keys.FINGERPRINT, Keys.FINGERPRINT);
                 qb.setProjectionMap(projectionMap);
 
                 qb.setTables(Tables.KEYS);
-                qb.appendWhere(KeysColumns.MASTER_KEY_ID + " = ");
+                qb.appendWhere(Keys.MASTER_KEY_ID + " = ");
                 qb.appendWhereEscapeString(uri.getPathSegments().get(1));
 
                 break;
@@ -315,7 +310,7 @@ public class KeychainProvider extends ContentProvider {
 
             case KEY_RING_USER_IDS: {
                 HashMap projectionMap = new HashMap();
-                projectionMap.put(BaseColumns._ID, Tables.USER_IDS + ".oid AS _id");
+                projectionMap.put(UserIds._ID, Tables.USER_IDS + ".oid AS _id");
                 projectionMap.put(UserIds.MASTER_KEY_ID, UserIds.MASTER_KEY_ID);
                 projectionMap.put(UserIds.USER_ID, UserIds.USER_ID);
                 projectionMap.put(UserIds.RANK, UserIds.RANK);
@@ -323,36 +318,44 @@ public class KeychainProvider extends ContentProvider {
                 qb.setProjectionMap(projectionMap);
 
                 qb.setTables(Tables.USER_IDS);
-                qb.appendWhere(UserIdsColumns.MASTER_KEY_ID + " = ");
+                qb.appendWhere(UserIds.MASTER_KEY_ID + " = ");
                 qb.appendWhereEscapeString(uri.getPathSegments().get(1));
 
+                if (TextUtils.isEmpty(sortOrder)) {
+                    sortOrder = UserIds.RANK + " ASC";
+                }
+
                 break;
 
             }
 
+            case KEY_RINGS_PUBLIC:
             case KEY_RING_PUBLIC: {
                 HashMap projectionMap = new HashMap();
-                projectionMap.put(BaseColumns._ID, Tables.KEY_RINGS_PUBLIC + ".oid AS _id");
-                projectionMap.put(KeyRings.MASTER_KEY_ID, KeyRings.MASTER_KEY_ID);
-                projectionMap.put(KeyRings.KEY_RING_DATA, KeyRings.KEY_RING_DATA);
+                projectionMap.put(KeyRingData._ID, Tables.KEY_RINGS_PUBLIC + ".oid AS _id");
+                projectionMap.put(KeyRingData.MASTER_KEY_ID, KeyRingData.MASTER_KEY_ID);
+                projectionMap.put(KeyRingData.KEY_RING_DATA, KeyRingData.KEY_RING_DATA);
                 qb.setProjectionMap(projectionMap);
 
                 qb.setTables(Tables.KEY_RINGS_PUBLIC);
-                qb.appendWhere(KeyRingsColumns.MASTER_KEY_ID + " = ");
-                qb.appendWhereEscapeString(uri.getPathSegments().get(1));
+
+                if(match == KEY_RING_PUBLIC) {
+                    qb.appendWhere(KeyRings.MASTER_KEY_ID + " = ");
+                    qb.appendWhereEscapeString(uri.getPathSegments().get(1));
+                }
 
                 break;
             }
 
             case KEY_RING_SECRET: {
                 HashMap projectionMap = new HashMap();
-                projectionMap.put(BaseColumns._ID, Tables.KEY_RINGS_SECRET + ".oid AS _id");
-                projectionMap.put(KeyRings.MASTER_KEY_ID, KeyRings.MASTER_KEY_ID);
-                projectionMap.put(KeyRings.KEY_RING_DATA, KeyRings.KEY_RING_DATA);
+                projectionMap.put(KeyRingData._ID, Tables.KEY_RINGS_SECRET + ".oid AS _id");
+                projectionMap.put(KeyRingData.MASTER_KEY_ID, KeyRingData.MASTER_KEY_ID);
+                projectionMap.put(KeyRingData.KEY_RING_DATA, KeyRingData.KEY_RING_DATA);
                 qb.setProjectionMap(projectionMap);
 
                 qb.setTables(Tables.KEY_RINGS_SECRET);
-                qb.appendWhere(KeyRingsColumns.MASTER_KEY_ID + " = ");
+                qb.appendWhere(KeyRings.MASTER_KEY_ID + " = ");
                 qb.appendWhereEscapeString(uri.getPathSegments().get(1));
 
                 break;
@@ -429,23 +432,23 @@ public class KeychainProvider extends ContentProvider {
             switch (match) {
                 case KEY_RING_PUBLIC:
                     db.insertOrThrow(Tables.KEY_RINGS_PUBLIC, null, values);
-                    keyId = values.getAsLong(KeyRingsColumns.MASTER_KEY_ID);
+                    keyId = values.getAsLong(KeyRings.MASTER_KEY_ID);
                     break;
 
                 case KEY_RING_SECRET:
                     db.insertOrThrow(Tables.KEY_RINGS_SECRET, null, values);
-                    keyId = values.getAsLong(KeyRingsColumns.MASTER_KEY_ID);
+                    keyId = values.getAsLong(KeyRings.MASTER_KEY_ID);
                     break;
 
                 case KEY_RING_KEYS:
                     Log.d(Constants.TAG, "keys");
                     db.insertOrThrow(Tables.KEYS, null, values);
-                    keyId = values.getAsLong(KeysColumns.MASTER_KEY_ID);
+                    keyId = values.getAsLong(Keys.MASTER_KEY_ID);
                     break;
 
                 case KEY_RING_USER_IDS:
                     db.insertOrThrow(Tables.USER_IDS, null, values);
-                    keyId = values.getAsLong(UserIdsColumns.MASTER_KEY_ID);
+                    keyId = values.getAsLong(UserIds.MASTER_KEY_ID);
                     break;
 
                 case API_APPS:
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java
index 18eaa375a..339e6a069 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java
@@ -43,6 +43,7 @@ import org.sufficientlysecure.keychain.pgp.PgpHelper;
 import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
 import org.sufficientlysecure.keychain.provider.KeychainContract.ApiApps;
 import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
+import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingData;
 import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;
 import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
 import org.sufficientlysecure.keychain.remote.AccountSettings;
@@ -65,11 +66,11 @@ public class ProviderHelper {
      */
     public static PGPKeyRing getPGPKeyRing(Context context, Uri queryUri) {
         Cursor cursor = context.getContentResolver().query(queryUri,
-                new String[]{KeyRings._ID, KeyRings.KEY_RING_DATA}, null, null, null);
+                new String[]{KeyRings._ID, KeyRingData.KEY_RING_DATA}, null, null, null);
 
         PGPKeyRing keyRing = null;
         if (cursor != null && cursor.moveToFirst()) {
-            int keyRingDataCol = cursor.getColumnIndex(KeyRings.KEY_RING_DATA);
+            int keyRingDataCol = cursor.getColumnIndex(KeyRingData.KEY_RING_DATA);
 
             byte[] data = cursor.getBlob(keyRingDataCol);
             if (data != null) {
@@ -156,7 +157,7 @@ public class ProviderHelper {
      */
     public static PGPPublicKeyRing getPGPPublicKeyRing(Context context,
                                                                     long masterKeyId) {
-        Uri queryUri = KeyRings.buildPublicKeyRingUri(Long.toString(masterKeyId));
+        Uri queryUri = KeyRingData.buildPublicKeyRingUri(Long.toString(masterKeyId));
         return (PGPPublicKeyRing) getPGPKeyRing(context, queryUri);
     }
 
@@ -165,7 +166,7 @@ public class ProviderHelper {
      */
     public static PGPSecretKeyRing getPGPSecretKeyRing(Context context,
                                                                     long masterKeyId) {
-        Uri queryUri = KeyRings.buildSecretKeyRingUri(Long.toString(masterKeyId));
+        Uri queryUri = KeyRingData.buildSecretKeyRingUri(Long.toString(masterKeyId));
         return (PGPSecretKeyRing) getPGPKeyRing(context, queryUri);
     }
 
@@ -178,12 +179,11 @@ public class ProviderHelper {
         long masterKeyId = masterKey.getKeyID();
 
         // IF there is a secret key, preserve it!
-        // TODO This even necessary?
-        // PGPSecretKeyRing secretRing = ProviderHelper.getPGPSecretKeyRing(context, masterKeyId);
+        PGPSecretKeyRing secretRing = ProviderHelper.getPGPSecretKeyRing(context, masterKeyId);
 
         // delete old version of this keyRing, which also deletes all keys and userIds on cascade
         try {
-            context.getContentResolver().delete(KeyRings.buildPublicKeyRingUri(Long.toString(masterKeyId)), null, null);
+            context.getContentResolver().delete(KeyRingData.buildPublicKeyRingUri(Long.toString(masterKeyId)), null, null);
         } catch (UnsupportedOperationException e) {
             Log.e(Constants.TAG, "Key could not be deleted! Maybe we are creating a new one!", e);
         }
@@ -193,11 +193,11 @@ public class ProviderHelper {
         // NOTE: If we would not use the same _ID again,
         // getting back to the ViewKeyActivity would result in Nullpointer,
         // because the currently loaded key would be gone from the database
-        values.put(KeyRings.MASTER_KEY_ID, masterKeyId);
-        values.put(KeyRings.KEY_RING_DATA, keyRing.getEncoded());
+        values.put(KeyRingData.MASTER_KEY_ID, masterKeyId);
+        values.put(KeyRingData.KEY_RING_DATA, keyRing.getEncoded());
 
         // insert new version of this keyRing
-        Uri uri = KeyRings.buildPublicKeyRingUri(Long.toString(masterKeyId));
+        Uri uri = KeyRingData.buildPublicKeyRingUri(Long.toString(masterKeyId));
         Uri insertedUri = context.getContentResolver().insert(uri, values);
 
         // save all keys and userIds included in keyRing object in database
@@ -233,31 +233,43 @@ public class ProviderHelper {
         }
 
         // Save the saved keyring (if any)
-        // TODO this even necessary? see above...
-        // if(secretRing != null)
-            // saveKeyRing(context, secretRing);
+        if(secretRing != null) {
+            saveKeyRing(context, secretRing);
+        }
 
     }
 
     /**
-     * Saves PGPSecretKeyRing with its keys and userIds in DB
+     * Saves a PGPSecretKeyRing in the DB. This will only work if a corresponding public keyring
+     * is already in the database!
      */
     @SuppressWarnings("unchecked")
     public static void saveKeyRing(Context context, PGPSecretKeyRing keyRing) throws IOException {
-        PGPSecretKey masterKey = keyRing.getSecretKey();
-        long masterKeyId = masterKey.getKeyID();
+        long masterKeyId = keyRing.getPublicKey().getKeyID();
 
-        // TODO Make sure there is a public key for this secret key in the db (create one maybe)
+        // save secret keyring
+        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(Long.toString(masterKeyId));
+        context.getContentResolver().insert(uri, values);
 
-        {
-            ContentValues values = new ContentValues();
-            values.put(KeyRings.MASTER_KEY_ID, masterKeyId);
-            values.put(KeyRings.KEY_RING_DATA, keyRing.getEncoded());
-            // insert new version of this keyRing
-            Uri uri = KeyRings.buildSecretKeyRingUri(Long.toString(masterKeyId));
-            context.getContentResolver().insert(uri, values);
-        }
+    }
 
+    /**
+     * Saves (or updates) a pair of public and secret KeyRings in the database
+     */
+    @SuppressWarnings("unchecked")
+    public static void saveKeyRing(Context context, PGPPublicKeyRing pubRing, PGPSecretKeyRing privRing) throws IOException {
+        long masterKeyId = pubRing.getPublicKey().getKeyID();
+
+        // delete secret keyring (so it isn't unnecessarily saved by public-saveKeyRing below)
+        context.getContentResolver().delete(KeyRingData.buildSecretKeyRingUri(Long.toString(masterKeyId)), null, null);
+
+        // save public keyring
+        saveKeyRing(context, pubRing);
+        saveKeyRing(context, privRing);
     }
 
     /**
@@ -314,24 +326,14 @@ public class ProviderHelper {
         return ContentProviderOperation.newInsert(uri).withValues(values).build();
     }
 
-    public static void deletePublicKeyRing(Context context, long masterKeyId) {
-        ContentResolver cr = context.getContentResolver();
-        cr.delete(KeyRings.buildPublicKeyRingUri(Long.toString(masterKeyId)), null, null);
-    }
-
-    public static void deleteSecretKeyRing(Context context, long masterKeyId) {
-        ContentResolver cr = context.getContentResolver();
-        cr.delete(KeyRings.buildSecretKeyRingUri(Long.toString(masterKeyId)), null, null);
-    }
-
     public static boolean hasSecretKeyByMasterKeyId(Context context, long masterKeyId) {
-        Uri queryUri = KeyRings.buildSecretKeyRingUri(Long.toString(masterKeyId));
+        Uri queryUri = KeyRingData.buildSecretKeyRingUri(Long.toString(masterKeyId));
         // see if we can get our master key id back from the uri
         return getMasterKeyId(context, queryUri) == masterKeyId;
     }
 
-    /**
-     * Get master key id of key
+    /** Find the master key id related to a given query. The id will either be extracted from the
+     * query, which should work for all specific /key_rings/ queries, or will be queried if it can't.
      */
     public static long getMasterKeyId(Context context, Uri queryUri) {
         // try extracting from the uri first
@@ -339,39 +341,25 @@ public class ProviderHelper {
             return Long.parseLong(queryUri.getPathSegments().get(1));
         } catch(NumberFormatException e) {
             // didn't work? oh well.
+            Log.d(Constants.TAG, "Couldn't get masterKeyId from URI, querying...");
         }
-
-        Cursor cursor = context.getContentResolver().query(queryUri, new String[] {
-                KeyRings.MASTER_KEY_ID
-        }, null, null, null);
-
-        long masterKeyId = 0;
-        try {
-            if (cursor != null && cursor.moveToFirst()) {
-                int masterKeyIdCol = cursor.getColumnIndexOrThrow(KeyRings.MASTER_KEY_ID);
-
-                masterKeyId = cursor.getLong(masterKeyIdCol);
-            }
-        } finally {
-            if (cursor != null) {
-                cursor.close();
-            }
-        }
-
-        return masterKeyId;
+        Object data = getUnifiedData(context, queryUri, KeyRings.MASTER_KEY_ID);
+        if(data instanceof Long)
+            return (Long) data;
+        // TODO better error handling?
+        return 0L;
     }
 
-    public static ArrayList getKeyRingsAsArmoredString(Context context, Uri uri,
-                                                               long[] masterKeyIds) {
+    public static ArrayList getKeyRingsAsArmoredString(Context context, long[] masterKeyIds) {
         ArrayList output = new ArrayList();
 
         if (masterKeyIds != null && masterKeyIds.length > 0) {
 
-            Cursor cursor = getCursorWithSelectedKeyringMasterKeyIds(context, uri, masterKeyIds);
+            Cursor cursor = getCursorWithSelectedKeyringMasterKeyIds(context, masterKeyIds);
 
             if (cursor != null) {
-                int masterIdCol = cursor.getColumnIndex(KeyRings.MASTER_KEY_ID);
-                int dataCol = cursor.getColumnIndex(KeyRings.KEY_RING_DATA);
+                int masterIdCol = cursor.getColumnIndex(KeyRingData.MASTER_KEY_ID);
+                int dataCol = cursor.getColumnIndex(KeyRingData.KEY_RING_DATA);
                 if (cursor.moveToFirst()) {
                     do {
                         Log.d(Constants.TAG, "masterKeyId: " + cursor.getLong(masterIdCol));
@@ -421,48 +409,11 @@ public class ProviderHelper {
             return null;
         }
     }
-
-    public static byte[] getKeyRingsAsByteArray(Context context, Uri uri, long[] masterKeyIds) {
-        ByteArrayOutputStream bos = new ByteArrayOutputStream();
-
-        if (masterKeyIds != null && masterKeyIds.length > 0) {
-
-            Cursor cursor = getCursorWithSelectedKeyringMasterKeyIds(context, uri, masterKeyIds);
-
-            if (cursor != null) {
-                int masterIdCol = cursor.getColumnIndex(KeyRings.MASTER_KEY_ID);
-                int dataCol = cursor.getColumnIndex(KeyRings.KEY_RING_DATA);
-                if (cursor.moveToFirst()) {
-                    do {
-                        Log.d(Constants.TAG, "masterKeyId: " + cursor.getLong(masterIdCol));
-
-                        // get actual keyring data blob and write it to ByteArrayOutputStream
-                        try {
-                            bos.write(cursor.getBlob(dataCol));
-                        } catch (IOException e) {
-                            Log.e(Constants.TAG, "IOException", e);
-                        }
-                    } while (cursor.moveToNext());
-                }
-            }
-
-            if (cursor != null) {
-                cursor.close();
-            }
-
-        } else {
-            Log.e(Constants.TAG, "No master keys given!");
-        }
-
-        return bos.toByteArray();
-    }
-
-    private static Cursor getCursorWithSelectedKeyringMasterKeyIds(Context context, Uri baseUri,
-                                                                   long[] masterKeyIds) {
+    private static Cursor getCursorWithSelectedKeyringMasterKeyIds(Context context, long[] masterKeyIds) {
         Cursor cursor = null;
         if (masterKeyIds != null && masterKeyIds.length > 0) {
 
-            String inMasterKeyList = KeyRings.MASTER_KEY_ID + " IN (";
+            String inMasterKeyList = KeyRingData.MASTER_KEY_ID + " IN (";
             for (int i = 0; i < masterKeyIds.length; ++i) {
                 if (i != 0) {
                     inMasterKeyList += ", ";
@@ -471,9 +422,9 @@ public class ProviderHelper {
             }
             inMasterKeyList += ")";
 
-            cursor = context.getContentResolver().query(baseUri,
-                    new String[]{KeyRings._ID, KeyRings.MASTER_KEY_ID, KeyRings.KEY_RING_DATA},
-                    inMasterKeyList, null, null);
+            cursor = context.getContentResolver().query(KeyRingData.buildPublicKeyRingUri(), new String[] {
+                    KeyRingData._ID, KeyRingData.MASTER_KEY_ID, KeyRingData.KEY_RING_DATA
+                }, inMasterKeyList, null, null);
         }
 
         return cursor;
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java
index f9e143d87..6ee209c5c 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java
@@ -518,8 +518,8 @@ public class KeychainIntentService extends IntentService
                     PgpKeyOperation.Pair pair =
                         keyOperations.buildSecretKey(privkey, pubkey, saveParams);
                     setProgress(R.string.progress_saving_key_ring, 90, 100);
-                    ProviderHelper.saveKeyRing(this, pair.first);
-                    ProviderHelper.saveKeyRing(this, pair.second);
+                    // save the pair
+                    ProviderHelper.saveKeyRing(this, pair.second, pair.first);
                     setProgress(R.string.progress_done, 100, 100);
                 }
                 PassphraseCacheService.addCachedPassphrase(this, masterKeyId, newPassphrase);
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java
index 0caf60aa1..e6fd59d55 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java
@@ -57,6 +57,7 @@ import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
 import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
 import org.sufficientlysecure.keychain.provider.KeychainContract;
 import org.sufficientlysecure.keychain.provider.ProviderHelper;
+import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingData;
 import org.sufficientlysecure.keychain.service.KeychainIntentService;
 import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
 import org.sufficientlysecure.keychain.service.PassphraseCacheService;
@@ -345,7 +346,7 @@ public class EditKeyActivity extends ActionBarActivity implements EditorListener
                 }
                 return true;
             case R.id.menu_key_edit_delete:
-                Uri convertUri = KeychainContract.KeyRings.buildSecretKeyRingUri(mDataUri);
+                Uri convertUri = KeyRingData.buildSecretKeyRingUri(mDataUri);
                     // Message is received after key is deleted
                     Handler returnHandler = new Handler() {
                         @Override
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java
index cc0abe48a..ecd742896 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java
@@ -58,12 +58,9 @@ import org.sufficientlysecure.keychain.Id;
 import org.sufficientlysecure.keychain.R;
 import org.sufficientlysecure.keychain.helper.ExportHelper;
 import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
-import org.sufficientlysecure.keychain.provider.KeychainContract;
 import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
-import org.sufficientlysecure.keychain.provider.KeychainContract.KeyTypes;
+import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingData;
 import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
-import org.sufficientlysecure.keychain.provider.KeychainDatabase;
-import org.sufficientlysecure.keychain.provider.ProviderHelper;
 import org.sufficientlysecure.keychain.ui.adapter.HighlightQueryCursorAdapter;
 import org.sufficientlysecure.keychain.ui.dialog.DeleteKeyDialogFragment;
 import org.sufficientlysecure.keychain.util.Log;
@@ -257,11 +254,11 @@ public class KeyListFragment extends Fragment
 
     // These are the rows that we will retrieve.
     static final String[] PROJECTION = new String[]{
-            KeychainContract.KeyRings._ID,
-            KeychainContract.Keys.MASTER_KEY_ID,
-            KeychainContract.UserIds.USER_ID,
-            KeychainContract.Keys.IS_REVOKED,
-            KeychainDatabase.Tables.KEY_RINGS_SECRET + "." + KeychainContract.KeyRings.MASTER_KEY_ID
+            KeyRings._ID,
+            KeyRings.MASTER_KEY_ID,
+            KeyRings.USER_ID,
+            KeyRings.IS_REVOKED,
+            KeyRings.HAS_SECRET
     };
 
     static final int INDEX_MASTER_KEY_ID = 1;
@@ -269,11 +266,8 @@ public class KeyListFragment extends Fragment
     static final int INDEX_IS_REVOKED = 3;
     static final int INDEX_HAS_SECRET = 4;
 
-    static final String SORT_ORDER =
-            // show secret before public key
-            KeychainDatabase.Tables.KEY_RINGS_SECRET + "." + KeychainContract.KeyRings.MASTER_KEY_ID + " IS NULL ASC, " +
-                    // sort by user id otherwise
-                    UserIds.USER_ID + " ASC";
+    // show secret before public key, sort by user id otherwise
+    static final String SORT_ORDER = KeyRings.HAS_SECRET + " DESC, " + UserIds.USER_ID + " ASC";
 
     @Override
     public Loader onCreateLoader(int id, Bundle args) {
@@ -283,7 +277,7 @@ public class KeyListFragment extends Fragment
         String where = null;
         String whereArgs[] = null;
         if (mCurQuery != null) {
-            where = KeychainContract.UserIds.USER_ID + " LIKE ?";
+            where = KeyRings.USER_ID + " LIKE ?";
             whereArgs = new String[]{"%" + mCurQuery + "%"};
         }
         // Now create and return a CursorLoader that will take care of
@@ -329,17 +323,15 @@ public class KeyListFragment extends Fragment
             viewIntent = new Intent(getActivity(), ViewKeyActivityJB.class);
         }
         viewIntent.setData(
-                KeychainContract
-                        .KeyRings.buildGenericKeyRingUri(
-                                            Long.toString(mAdapter.getMasterKeyId(position))));
+                KeyRings.buildGenericKeyRingUri(Long.toString(mAdapter.getMasterKeyId(position))));
         startActivity(viewIntent);
     }
 
     @TargetApi(11)
-    protected void encrypt(ActionMode mode, long[] keyRingMasterKeyIds) {
+    protected void encrypt(ActionMode mode, long[] masterKeyIds) {
         Intent intent = new Intent(getActivity(), EncryptActivity.class);
         intent.setAction(EncryptActivity.ACTION_ENCRYPT);
-        intent.putExtra(EncryptActivity.EXTRA_ENCRYPTION_KEY_IDS, keyRingMasterKeyIds);
+        intent.putExtra(EncryptActivity.EXTRA_ENCRYPTION_KEY_IDS, masterKeyIds);
         // used instead of startActivity set actionbar based on callingPackage
         startActivityForResult(intent, 0);
 
@@ -507,7 +499,7 @@ public class KeyListFragment extends Fragment
                 Button button = (Button) view.findViewById(R.id.edit);
                 TextView revoked = (TextView) view.findViewById(R.id.revoked);
 
-                if (!cursor.isNull(KeyListFragment.INDEX_HAS_SECRET)) {
+                if (cursor.getInt(KeyListFragment.INDEX_HAS_SECRET) != 0) {
                     // this is a secret key - show the edit button
                     statusDivider.setVisibility(View.VISIBLE);
                     statusLayout.setVisibility(View.VISIBLE);
@@ -518,9 +510,7 @@ public class KeyListFragment extends Fragment
                     button.setOnClickListener(new OnClickListener() {
                         public void onClick(View view) {
                             Intent editIntent = new Intent(getActivity(), EditKeyActivity.class);
-                            editIntent.setData(
-                                    KeychainContract.KeyRings
-                                            .buildSecretKeyRingUri(Long.toString(id)));
+                            editIntent.setData(KeyRingData.buildSecretKeyRingUri(Long.toString(id)));
                             editIntent.setAction(EditKeyActivity.ACTION_EDIT_KEY);
                             startActivityForResult(editIntent, 0);
                         }
@@ -581,7 +571,7 @@ public class KeyListFragment extends Fragment
                 throw new IllegalStateException("couldn't move cursor to position " + position);
             }
 
-            if (!mCursor.isNull(KeyListFragment.INDEX_HAS_SECRET)) {
+            if (mCursor.getInt(KeyListFragment.INDEX_HAS_SECRET) != 0) {
                 { // set contact count
                     int num = mCursor.getCount();
                     String contactsTotal = getResources().getQuantityString(R.plurals.n_contacts, num, num);
@@ -621,7 +611,7 @@ public class KeyListFragment extends Fragment
             }
 
             // early breakout: all secret keys are assigned id 0
-            if (!mCursor.isNull(KeyListFragment.INDEX_HAS_SECRET)) {
+            if (mCursor.getInt(KeyListFragment.INDEX_HAS_SECRET) != 0) {
                 return 1L;
             }
             // otherwise, return the first character of the name as ID
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
index 2437270e5..b60e75fa9 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
@@ -185,8 +185,8 @@ public class ViewKeyActivity extends ActionBarActivity {
         } else {
             // get public keyring as ascii armored string
             long masterKeyId = ProviderHelper.getMasterKeyId(this, dataUri);
-            ArrayList keyringArmored = ProviderHelper.getKeyRingsAsArmoredString(this,
-                    dataUri, new long[]{masterKeyId});
+            ArrayList keyringArmored = ProviderHelper.getKeyRingsAsArmoredString(
+                    this, new long[]{ masterKeyId });
 
             content = keyringArmored.get(0);
 
@@ -216,8 +216,8 @@ public class ViewKeyActivity extends ActionBarActivity {
     private void copyToClipboard(Uri dataUri) {
         // get public keyring as ascii armored string
         long masterKeyId = ProviderHelper.getMasterKeyId(this, dataUri);
-        ArrayList keyringArmored = ProviderHelper.getKeyRingsAsArmoredString(this, dataUri,
-                new long[]{masterKeyId});
+        ArrayList keyringArmored = ProviderHelper.getKeyRingsAsArmoredString(
+                this, new long[]{ masterKeyId });
 
         ClipboardReflection.copyToClipboard(this, keyringArmored.get(0));
         Toast.makeText(getApplicationContext(), R.string.key_copied_to_clipboard, Toast.LENGTH_LONG)
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java
index 75853ac2a..616200800 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java
@@ -38,7 +38,10 @@ import com.beardedhen.androidbootstrap.BootstrapButton;
 import org.sufficientlysecure.keychain.Constants;
 import org.sufficientlysecure.keychain.R;
 import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
-import org.sufficientlysecure.keychain.provider.KeychainContract;
+import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
+import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;
+import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
+import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingData;
 import org.sufficientlysecure.keychain.provider.ProviderHelper;
 import org.sufficientlysecure.keychain.ui.adapter.ViewKeyKeysAdapter;
 import org.sufficientlysecure.keychain.ui.adapter.ViewKeyUserIdsAdapter;
@@ -124,6 +127,7 @@ public class ViewKeyMainFragment extends Fragment implements
 
         { // label whether secret key is available, and edit button if it is
             final long masterKeyId = ProviderHelper.getMasterKeyId(getActivity(), mDataUri);
+            // TODO do this some other way...
             if (ProviderHelper.hasSecretKeyByMasterKeyId(getActivity(), masterKeyId)) {
                 // set this attribute. this is a LITTLE unclean, but we have the info available
                 // right here, so why not.
@@ -141,8 +145,7 @@ public class ViewKeyMainFragment extends Fragment implements
                     public void onClick(View view) {
                         Intent editIntent = new Intent(getActivity(), EditKeyActivity.class);
                         editIntent.setData(
-                                KeychainContract
-                                        .KeyRings.buildSecretKeyRingUri(
+                                KeyRingData.buildSecretKeyRingUri(
                                         Long.toString(masterKeyId)));
                         editIntent.setAction(EditKeyActivity.ACTION_EDIT_KEY);
                         startActivityForResult(editIntent, 0);
@@ -161,7 +164,7 @@ public class ViewKeyMainFragment extends Fragment implements
             // TODO see todo note above, doing this here for now
             mActionCertify.setOnClickListener(new View.OnClickListener() {
                 public void onClick(View view) {
-                    certifyKey(KeychainContract.KeyRings.buildGenericKeyRingUri(
+                    certifyKey(KeyRings.buildGenericKeyRingUri(
                             Long.toString(masterKeyId)
                     ));
                 }
@@ -190,31 +193,26 @@ public class ViewKeyMainFragment extends Fragment implements
     }
 
     static final String[] USER_IDS_PROJECTION =
-            new String[]{
-                    KeychainContract.UserIds._ID,
-                    KeychainContract.UserIds.USER_ID,
-                    KeychainContract.UserIds.RANK,
+            new String[] {
+                    UserIds._ID,
+                    UserIds.USER_ID,
+                    UserIds.RANK,
             };
     static final int INDEX_UID_UID = 1;
-    static final String USER_IDS_SORT_ORDER =
-            KeychainContract.UserIds.RANK + " COLLATE LOCALIZED ASC";
 
-    static final String[] KEYS_PROJECTION =
-            new String[]{KeychainContract.Keys._ID, KeychainContract.Keys.KEY_ID,
-                    KeychainContract.Keys.ALGORITHM, KeychainContract.Keys.RANK,
-                    KeychainContract.Keys.KEY_SIZE, KeychainContract.Keys.CAN_CERTIFY,
-                    KeychainContract.Keys.CAN_SIGN, KeychainContract.Keys.CAN_ENCRYPT,
-                    KeychainContract.Keys.IS_REVOKED, KeychainContract.Keys.CREATION,
-                    KeychainContract.Keys.EXPIRY, KeychainContract.Keys.FINGERPRINT};
-    static final String KEYS_SORT_ORDER = KeychainContract.Keys.RANK + " ASC";
+    static final String[] KEYS_PROJECTION = new String[] {
+            Keys._ID,
+            Keys.KEY_ID, Keys.RANK,
+            Keys.ALGORITHM, Keys.KEY_SIZE,
+            Keys.CAN_CERTIFY, Keys.CAN_ENCRYPT,
+            Keys.CAN_SIGN, Keys.IS_REVOKED,
+            Keys.CREATION, Keys.EXPIRY,
+            Keys.FINGERPRINT
+    };
     static final int KEYS_INDEX_KEY_ID = 1;
-    static final int KEYS_INDEX_ALGORITHM = 2;
-    static final int KEYS_INDEX_RANK = 3;
+    static final int KEYS_INDEX_ALGORITHM = 3;
     static final int KEYS_INDEX_KEY_SIZE = 4;
-    static final int KEYS_INDEX_CAN_CERTIFY = 5;
-    static final int KEYS_INDEX_CAN_SIGN = 6;
-    static final int KEYS_INDEX_CAN_ENCRYPT = 7;
-    static final int KEYS_INDEX_IS_REVOKED = 8;
+    static final int KEYS_INDEX_CAN_ENCRYPT = 6;
     static final int KEYS_INDEX_CREATION = 9;
     static final int KEYS_INDEX_EXPIRY = 10;
     static final int KEYS_INDEX_FINGERPRINT = 11;
@@ -222,19 +220,18 @@ public class ViewKeyMainFragment extends Fragment implements
     public Loader onCreateLoader(int id, Bundle args) {
         switch (id) {
             case LOADER_ID_USER_IDS: {
-                Uri baseUri = KeychainContract.UserIds.buildUserIdsUri(mDataUri);
+                Uri baseUri = UserIds.buildUserIdsUri(mDataUri);
 
                 // Now create and return a CursorLoader that will take care of
                 // creating a Cursor for the data being displayed.
-                return new CursorLoader(getActivity(), baseUri, USER_IDS_PROJECTION, null, null,
-                        USER_IDS_SORT_ORDER);
+                return new CursorLoader(getActivity(), baseUri, USER_IDS_PROJECTION, null, null, null);
             }
             case LOADER_ID_KEYS: {
-                Uri baseUri = KeychainContract.Keys.buildKeysUri(mDataUri);
+                Uri baseUri = Keys.buildKeysUri(mDataUri);
 
                 // Now create and return a CursorLoader that will take care of
                 // creating a Cursor for the data being displayed.
-                return new CursorLoader(getActivity(), baseUri, KEYS_PROJECTION, null, null, KEYS_SORT_ORDER);
+                return new CursorLoader(getActivity(), baseUri, KEYS_PROJECTION, null, null, null);
             }
 
             default:
@@ -343,7 +340,7 @@ public class ViewKeyMainFragment extends Fragment implements
 
     private void encryptToContact(Uri dataUri) {
         // TODO preselect from uri? should be feasible without trivial query
-        long keyId = Long.parseLong(dataUri.getPathSegments().get(1));
+        long keyId = ProviderHelper.getMasterKeyId(getActivity(), dataUri);
 
         long[] encryptionKeyIds = new long[]{ keyId };
         Intent intent = new Intent(getActivity(), EncryptActivity.class);
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteKeyDialogFragment.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteKeyDialogFragment.java
index 57dbb7794..feaa0b4cd 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteKeyDialogFragment.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteKeyDialogFragment.java
@@ -20,8 +20,6 @@ package org.sufficientlysecure.keychain.ui.dialog;
 import android.app.AlertDialog;
 import android.app.Dialog;
 import android.content.DialogInterface;
-import android.database.Cursor;
-import android.net.Uri;
 import android.os.Bundle;
 import android.os.Message;
 import android.os.Messenger;
@@ -35,14 +33,13 @@ import android.widget.LinearLayout;
 import android.widget.TextView;
 
 import org.sufficientlysecure.keychain.Constants;
-import org.sufficientlysecure.keychain.Id;
 import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.provider.KeychainContract;
+import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingData;
+import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
 import org.sufficientlysecure.keychain.provider.KeychainDatabase;
 import org.sufficientlysecure.keychain.provider.ProviderHelper;
 import org.sufficientlysecure.keychain.util.Log;
 
-import java.util.ArrayList;
 import java.util.HashMap;
 
 public class DeleteKeyDialogFragment extends DialogFragment {
@@ -107,13 +104,11 @@ public class DeleteKeyDialogFragment extends DialogFragment {
             long masterKeyId = masterKeyIds[0];
 
             HashMap data = ProviderHelper.getUnifiedData(activity, masterKeyId, new String[]{
-                    KeychainContract.UserIds.USER_ID,
-                    KeychainDatabase.Tables.KEY_RINGS_SECRET + "." + KeychainContract.KeyRings.MASTER_KEY_ID
+                    KeyRings.USER_ID,
+                    KeyRings.HAS_SECRET
             });
-            String userId = (String) data.get(KeychainContract.UserIds.USER_ID);
-            boolean hasSecret = data.get(
-                    KeychainDatabase.Tables.KEY_RINGS_SECRET + "." + KeychainContract.KeyRings.MASTER_KEY_ID
-            ) instanceof Long;
+            String userId = (String) data.get(KeyRings.USER_ID);
+            boolean hasSecret = ((Long) data.get(KeyRings.HAS_SECRET)) == 1;
 
             // Hide the Checkbox and TextView since this is a single selection,user will be notified through message
             mDeleteSecretKeyView.setVisibility(View.GONE);
@@ -136,7 +131,7 @@ public class DeleteKeyDialogFragment extends DialogFragment {
                 boolean success = false;
                 for(long masterKeyId : masterKeyIds) {
                     int count = activity.getContentResolver().delete(
-                            KeychainContract.KeyRings.buildPublicKeyRingUri(Long.toString(masterKeyId)), null, null
+                            KeyRingData.buildPublicKeyRingUri(Long.toString(masterKeyId)), null, null
                         );
                     if(count > 0)
                     success = true;
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ShareQrCodeDialogFragment.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ShareQrCodeDialogFragment.java
index 1b81c8b3b..dc9fa6235 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ShareQrCodeDialogFragment.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ShareQrCodeDialogFragment.java
@@ -107,7 +107,7 @@ public class ShareQrCodeDialogFragment extends DialogFragment {
             long masterKeyId = ProviderHelper.getMasterKeyId(getActivity(), dataUri);
             // get public keyring as ascii armored string
             ArrayList keyringArmored = ProviderHelper.getKeyRingsAsArmoredString(
-                    getActivity(), dataUri, new long[] { masterKeyId });
+                    getActivity(), new long[] { masterKeyId });
 
             // TODO: binary?