certs: provider cleanup and bugfixing

This commit is contained in:
Vincent Breitmoser 2014-03-15 19:57:22 +01:00
parent 6bacb5ff51
commit 5c28da44d6
6 changed files with 75 additions and 84 deletions

View File

@ -451,6 +451,9 @@ public class KeychainProvider extends ContentProvider {
projectionMap.put(KeyRingsColumns.MASTER_KEY_ID, Tables.KEY_RINGS + "."
+ KeyRingsColumns.MASTER_KEY_ID);
// this is the count of known secret keys who certified this uid
projectionMap.put("verified", "COUNT(" + Tables.KEYS + "." + Keys._ID + ") AS verified");
return projectionMap;
}
@ -659,38 +662,37 @@ public class KeychainProvider extends ContentProvider {
break;
case PUBLIC_KEY_RING_BY_MASTER_KEY_ID_USER_ID:
qb.setTables(Tables.USER_IDS + " INNER JOIN " + Tables.KEY_RINGS + " ON " + "("
+ Tables.KEY_RINGS + "." + BaseColumns._ID + " = " + Tables.USER_IDS + "."
+ KeysColumns.KEY_RING_ROW_ID + " )");
qb.appendWhere(Tables.KEY_RINGS + "." + KeyRingsColumns.MASTER_KEY_ID + " = ");
qb.appendWhereEscapeString(uri.getPathSegments().get(3));
qb.setProjectionMap(getProjectionMapForUserIds());
break;
case PUBLIC_KEY_RING_USER_ID:
case SECRET_KEY_RING_USER_ID:
qb.setTables(Tables.USER_IDS
+ " LEFT JOIN " + Tables.CERTS
+ " ON ("
+ " INNER JOIN " + Tables.KEY_RINGS + " ON ("
+ Tables.KEY_RINGS + "." + BaseColumns._ID + " = "
+ Tables.USER_IDS + "." + KeysColumns.KEY_RING_ROW_ID
+ ") LEFT JOIN " + Tables.CERTS + " ON ("
+ Tables.USER_IDS + "." + UserIds.KEY_RING_ROW_ID + " = "
+ Tables.CERTS + "." + Certs.KEY_RING_ROW_ID
+ " AND " + Tables.USER_IDS + "." + UserIds.RANK + " = "
+ Tables.CERTS + "." + Certs.RANK
+ ") LEFT JOIN " + Tables.KEYS + " ON ("
+ Tables.KEYS + "." + Keys.KEY_ID + " = "
+ Tables.CERTS + "." + Certs.KEY_ID_CERTIFIER
// might introduce a "trusted" flag later? for now, we simply assume
// every private key's signature is good.
+ " AND " + Tables.KEYS + "." + Keys.TYPE
+ " == " + KeyTypes.SECRET
+ ")");
groupBy = Tables.USER_IDS + "." + UserIds.RANK;
HashMap<String, String> pmap = new HashMap<String, String>();
pmap.put(UserIds._ID, Tables.USER_IDS + "." + UserIds._ID);
pmap.put(UserIds.USER_ID, Tables.USER_IDS + "." + UserIds.USER_ID);
pmap.put(UserIds.RANK, Tables.USER_IDS + "." + UserIds.RANK);
pmap.put("verified", "COUNT(" + Tables.CERTS + "." + Certs._ID + ") AS verified");
qb.setProjectionMap(pmap);
qb.setProjectionMap(getProjectionMapForUserIds());
qb.appendWhere(Tables.USER_IDS + "." + UserIdsColumns.KEY_RING_ROW_ID + " = ");
qb.appendWhereEscapeString(uri.getPathSegments().get(2));
if(match == PUBLIC_KEY_RING_BY_MASTER_KEY_ID_USER_ID) {
qb.appendWhere(Tables.KEY_RINGS + "." + KeyRingsColumns.MASTER_KEY_ID + " = ");
qb.appendWhereEscapeString(uri.getPathSegments().get(3));
} else {
qb.appendWhere(Tables.USER_IDS + "." + UserIdsColumns.KEY_RING_ROW_ID + " = ");
qb.appendWhereEscapeString(uri.getPathSegments().get(2));
}
break;
@ -728,7 +730,8 @@ public class KeychainProvider extends ContentProvider {
+ "signer." + Keys.RANK + " = 0"
+ ")");
// groupBy = Tables.USER_IDS + "." + UserIds.RANK;
groupBy = Tables.CERTS + "." + Certs.RANK + ", "
+ Tables.CERTS + "." + Certs.KEY_ID_CERTIFIER;
HashMap<String, String> pmap2 = new HashMap<String, String>();
pmap2.put(Certs._ID, Tables.CERTS + "." + Certs._ID);

View File

@ -207,7 +207,7 @@ public class ProviderHelper {
}
// get a list of owned secret keys, for verification filtering
Map<Long, PGPKeyRing> allKeyRings = getPGPKeyRings(context, KeyRings.buildPublicKeyRingsUri());
Map<Long, PGPKeyRing> allKeyRings = getPGPKeyRings(context, KeyRings.buildSecretKeyRingsUri());
int userIdRank = 0;
for (String userId : new IterableIterator<String>(masterKey.getUserIDs())) {
@ -218,35 +218,34 @@ public class ProviderHelper {
masterKey.getSignaturesForID(userId))) {
long certId = cert.getKeyID();
boolean verified = false;
// only care for signatures from our own private keys
// do verify signatures from our own private keys
if(allKeyRings.containsKey(certId)) try {
// mark them as verified
cert.init(new JcaPGPContentVerifierBuilderProvider().setProvider("SC"), allKeyRings.get(certId).getPublicKey());
cert.init(
new JcaPGPContentVerifierBuilderProvider().setProvider(
Constants.BOUNCY_CASTLE_PROVIDER_NAME),
allKeyRings.get(certId).getPublicKey());
verified = cert.verifyCertification(userId, masterKey);
// TODO: at this point, we only save signatures from available secret keys.
// should we save all? those are quite a lot of rows for info we don't really
// use. I left it out for now - it is available from key servers, so we can
// always get it later.
Log.d(Constants.TAG, "sig for " + userId + " " + verified + " from "
Log.d(Constants.TAG, "Verified sig for " + userId + " " + verified + " from "
+ PgpKeyHelper.convertKeyIdToHex(cert.getKeyID())
);
operations.add(buildPublicCertOperations(
context, keyRingRowId, userIdRank, masterKey.getKeyID(), cert, verified));
} catch(SignatureException e) {
Log.e(Constants.TAG, "Signature verification failed.", e);
} catch(PGPException e) {
Log.e(Constants.TAG, "Signature verification failed.", e);
} else {
Log.d(Constants.TAG, "ignored sig for "
Log.e(Constants.TAG, "Signature verification failed! "
+ PgpKeyHelper.convertKeyIdToHex(masterKey.getKeyID())
+ " from "
+ PgpKeyHelper.convertKeyIdToHex(cert.getKeyID())
);
operations.add(buildPublicCertOperations(
context, keyRingRowId, userIdRank, masterKey.getKeyID(), cert, false));
+ PgpKeyHelper.convertKeyIdToHex(cert.getKeyID()), e);
} catch(PGPException e) {
Log.e(Constants.TAG, "Signature verification failed! "
+ PgpKeyHelper.convertKeyIdToHex(masterKey.getKeyID())
+ " from "
+ PgpKeyHelper.convertKeyIdToHex(cert.getKeyID()), e);
}
// if we wanted to save all, not just our own verifications
// buildPublicCertOperations(context, keyRingRowId, rank, cert, verified);
Log.d(Constants.TAG, "sig for " + userId + " from "
+ PgpKeyHelper.convertKeyIdToHex(cert.getKeyID())
);
// regardless of verification, save the certification
operations.add(buildPublicCertOperations(
context, keyRingRowId, userIdRank, masterKey.getKeyID(), cert, verified));
}
++userIdRank;

View File

@ -43,6 +43,7 @@ import org.sufficientlysecure.keychain.helper.Preferences;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.KeychainDatabase;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
@ -164,7 +165,7 @@ public class CertifyKeyActivity extends ActionBarActivity implements
KeychainContract.KeyRings._ID,
KeychainContract.KeyRings.MASTER_KEY_ID,
KeychainContract.Keys.FINGERPRINT,
KeychainContract.UserIds.USER_ID
KeychainContract.UserIds.USER_ID,
};
static final int INDEX_MASTER_KEY_ID = 1;
static final int INDEX_FINGERPRINT = 2;
@ -174,10 +175,11 @@ public class CertifyKeyActivity extends ActionBarActivity implements
new String[]{
KeychainContract.UserIds._ID,
KeychainContract.UserIds.USER_ID,
KeychainContract.UserIds.RANK
KeychainContract.UserIds.RANK,
"verified"
};
static final String USER_IDS_SORT_ORDER =
KeychainContract.UserIds.RANK + " ASC";
KeychainDatabase.Tables.USER_IDS + "." + KeychainContract.UserIds.RANK + " ASC";
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {

View File

@ -53,12 +53,17 @@ public class ViewCertActivity extends ActionBarActivity
KeychainContract.Certs._ID,
KeychainContract.Certs.KEY_ID,
KeychainContract.UserIds.USER_ID,
KeychainContract.Certs.RANK,
KeychainContract.Certs.CREATION,
KeychainContract.Certs.KEY_ID_CERTIFIER,
"signer_uid",
KeychainContract.Certs.KEY_DATA
};
private static final int INDEX_KEY_ID = 1;
private static final int INDEX_USER_ID = 2;
private static final int INDEX_CREATION = 3;
private static final int INDEX_KEY_ID_CERTIFIER = 4;
private static final int INDEX_UID_CERTIFIER = 5;
private static final int INDEX_KEY_DATA = 6;
private Uri mDataUri;
@ -78,7 +83,6 @@ public class ViewCertActivity extends ActionBarActivity
mSigneeKey = (TextView) findViewById(R.id.signee_key);
mSigneeUid = (TextView) findViewById(R.id.signee_uid);
mRank = (TextView) findViewById(R.id.subkey_rank);
mAlgorithm = (TextView) findViewById(R.id.algorithm);
mType = (TextView) findViewById(R.id.signature_type);
mCreation = (TextView) findViewById(R.id.creation);
@ -108,29 +112,26 @@ public class ViewCertActivity extends ActionBarActivity
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
if(data.moveToFirst()) {
String signeeKey = "0x" + PgpKeyHelper.convertKeyIdToHex(data.getLong(1));
String signeeKey = "0x" + PgpKeyHelper.convertKeyIdToHex(data.getLong(INDEX_KEY_ID));
mSigneeKey.setText(signeeKey);
String signeeUid = data.getString(2);
String signeeUid = data.getString(INDEX_USER_ID);
mSigneeUid.setText(signeeUid);
String subkey_rank = Integer.toString(data.getInt(3));
mRank.setText(subkey_rank);
Date creationDate = new Date(data.getLong(4) * 1000);
Date creationDate = new Date(data.getLong(INDEX_CREATION) * 1000);
mCreation.setText(DateFormat.getDateFormat(getApplicationContext()).format(creationDate));
mSignerKeyId = data.getLong(5);
mSignerKeyId = data.getLong(INDEX_KEY_ID_CERTIFIER);
String signerKey = "0x" + PgpKeyHelper.convertKeyIdToHex(mSignerKeyId);
mSignerKey.setText(signerKey);
String signerUid = data.getString(6);
String signerUid = data.getString(INDEX_UID_CERTIFIER);
if(signerUid != null)
mSignerUid.setText(signerUid);
else
mSignerUid.setText(R.string.unknown_uid);
byte[] sigData = data.getBlob(7);
byte[] sigData = data.getBlob(INDEX_KEY_DATA);
PGPSignature sig = PgpConversionHelper.BytesToPGPSignature(sigData);
if(sig != null) {
String algorithmStr = PgpKeyHelper.getAlgorithmInfo(sig.getKeyAlgorithm(), 0);

View File

@ -198,22 +198,26 @@ public class ViewKeyMainFragment extends Fragment implements
static final int KEYRING_INDEX_MASTER_KEY_ID = 1;
static final int KEYRING_INDEX_USER_ID = 2;
static final String[] USER_IDS_PROJECTION =
new String[]{
KeychainContract.UserIds._ID,
KeychainContract.UserIds.USER_ID,
KeychainContract.UserIds.RANK,
};
static final String[] USER_IDS_PROJECTION = new String[]{
KeychainContract.UserIds._ID,
KeychainContract.UserIds.USER_ID,
KeychainContract.UserIds.RANK,
"verified",
};
// not the main user id
static final String USER_IDS_SELECTION =
KeychainDatabase.Tables.USER_IDS + "." + KeychainContract.UserIds.RANK + " > 0 ";
static final String USER_IDS_SORT_ORDER =
KeychainContract.UserIds.RANK + " COLLATE LOCALIZED ASC";
KeychainDatabase.Tables.USER_IDS + "." + KeychainContract.UserIds.RANK + " COLLATE LOCALIZED ASC";
static final String[] KEYS_PROJECTION =
new String[]{KeychainContract.Keys._ID, KeychainContract.Keys.KEY_ID,
static final String[] KEYS_PROJECTION = new String[]{
KeychainContract.Keys._ID, KeychainContract.Keys.KEY_ID,
KeychainContract.Keys.IS_MASTER_KEY, KeychainContract.Keys.ALGORITHM,
KeychainContract.Keys.KEY_SIZE, KeychainContract.Keys.CAN_CERTIFY,
KeychainContract.Keys.CAN_SIGN, KeychainContract.Keys.CAN_ENCRYPT,
KeychainContract.Keys.CREATION, KeychainContract.Keys.EXPIRY,
KeychainContract.Keys.FINGERPRINT};
KeychainContract.Keys.FINGERPRINT
};
static final String KEYS_SORT_ORDER = KeychainContract.Keys.RANK + " ASC";
static final int KEYS_INDEX_ID = 0;
static final int KEYS_INDEX_KEY_ID = 1;

View File

@ -60,24 +60,6 @@
android:paddingRight="5dip" />
</TableRow>
<TableRow
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:paddingRight="10dip"
android:text="@string/label_subkey_rank" />
<TextView
android:id="@+id/subkey_rank"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:paddingRight="5dip" />
</TableRow>
<TableRow
android:layout_width="fill_parent"
android:layout_height="fill_parent">