mirror of
https://github.com/moparisthebest/open-keychain
synced 2025-02-21 05:11:45 -05:00
certs: various improvements
* recognize self-certifications * save signature type * save expiry time * drop encoded data blob from db
This commit is contained in:
parent
2802718efb
commit
1b1304e6e0
@ -55,13 +55,13 @@ public class KeychainContract {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface CertsColumns {
|
interface CertsColumns {
|
||||||
String MASTER_KEY_ID = "master_key_id"; // verified id, foreign key to key_rings._ID
|
String MASTER_KEY_ID = "master_key_id";
|
||||||
String RANK = "rank"; // rank of verified key
|
String RANK = "rank";
|
||||||
String KEY_ID_CERTIFIER = "key_id_certifier"; // verifying id, not a database id
|
String KEY_ID_CERTIFIER = "key_id_certifier";
|
||||||
|
String TYPE = "type";
|
||||||
|
String VERIFIED = "verified";
|
||||||
String CREATION = "creation";
|
String CREATION = "creation";
|
||||||
String EXPIRY = "expiry";
|
String EXPIRY = "expiry";
|
||||||
String VERIFIED = "verified";
|
|
||||||
String KEY_DATA = "key_data"; // certification blob
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ApiAppsColumns {
|
interface ApiAppsColumns {
|
||||||
@ -262,6 +262,9 @@ public class KeychainContract {
|
|||||||
public static final String USER_ID = UserIdsColumns.USER_ID;
|
public static final String USER_ID = UserIdsColumns.USER_ID;
|
||||||
public static final String SIGNER_UID = "signer_user_id";
|
public static final String SIGNER_UID = "signer_user_id";
|
||||||
|
|
||||||
|
public static final int VERIFIED_SECRET = 1;
|
||||||
|
public static final int VERIFIED_SELF = 2;
|
||||||
|
|
||||||
public static final Uri CONTENT_URI = BASE_CONTENT_URI_INTERNAL.buildUpon()
|
public static final Uri CONTENT_URI = BASE_CONTENT_URI_INTERNAL.buildUpon()
|
||||||
.appendPath(BASE_KEY_RINGS).build();
|
.appendPath(BASE_KEY_RINGS).build();
|
||||||
|
|
||||||
|
@ -110,11 +110,11 @@ public class KeychainDatabase extends SQLiteOpenHelper {
|
|||||||
+ CertsColumns.RANK + " INTEGER, " // rank of certified uid
|
+ CertsColumns.RANK + " INTEGER, " // rank of certified uid
|
||||||
|
|
||||||
+ CertsColumns.KEY_ID_CERTIFIER + " INTEGER, " // certifying key
|
+ CertsColumns.KEY_ID_CERTIFIER + " INTEGER, " // certifying key
|
||||||
|
+ CertsColumns.TYPE + " INTEGER, "
|
||||||
|
+ CertsColumns.VERIFIED + " INTEGER, "
|
||||||
+ CertsColumns.CREATION + " INTEGER, "
|
+ CertsColumns.CREATION + " INTEGER, "
|
||||||
+ CertsColumns.EXPIRY + " INTEGER, "
|
+ CertsColumns.EXPIRY + " INTEGER, "
|
||||||
+ CertsColumns.VERIFIED + " INTEGER, "
|
|
||||||
|
|
||||||
+ CertsColumns.KEY_DATA + " BLOB,"
|
|
||||||
+ "PRIMARY KEY(" + CertsColumns.MASTER_KEY_ID + ", " + CertsColumns.RANK + ", "
|
+ "PRIMARY KEY(" + CertsColumns.MASTER_KEY_ID + ", " + CertsColumns.RANK + ", "
|
||||||
+ CertsColumns.KEY_ID_CERTIFIER + "), "
|
+ CertsColumns.KEY_ID_CERTIFIER + "), "
|
||||||
+ "FOREIGN KEY(" + CertsColumns.MASTER_KEY_ID + ") REFERENCES "
|
+ "FOREIGN KEY(" + CertsColumns.MASTER_KEY_ID + ") REFERENCES "
|
||||||
|
@ -439,10 +439,10 @@ public class KeychainProvider extends ContentProvider {
|
|||||||
projectionMap.put(Certs._ID, Tables.CERTS + ".oid AS " + Certs._ID);
|
projectionMap.put(Certs._ID, Tables.CERTS + ".oid AS " + Certs._ID);
|
||||||
projectionMap.put(Certs.MASTER_KEY_ID, Tables.CERTS + "." + Certs.MASTER_KEY_ID);
|
projectionMap.put(Certs.MASTER_KEY_ID, Tables.CERTS + "." + Certs.MASTER_KEY_ID);
|
||||||
projectionMap.put(Certs.RANK, Tables.CERTS + "." + Certs.RANK);
|
projectionMap.put(Certs.RANK, Tables.CERTS + "." + Certs.RANK);
|
||||||
|
projectionMap.put(Certs.VERIFIED, Tables.CERTS + "." + Certs.VERIFIED);
|
||||||
|
projectionMap.put(Certs.TYPE, Tables.CERTS + "." + Certs.TYPE);
|
||||||
projectionMap.put(Certs.CREATION, Tables.CERTS + "." + Certs.CREATION);
|
projectionMap.put(Certs.CREATION, Tables.CERTS + "." + Certs.CREATION);
|
||||||
projectionMap.put(Certs.KEY_ID_CERTIFIER, Tables.CERTS + "." + Certs.KEY_ID_CERTIFIER);
|
projectionMap.put(Certs.KEY_ID_CERTIFIER, Tables.CERTS + "." + Certs.KEY_ID_CERTIFIER);
|
||||||
projectionMap.put(Certs.VERIFIED, Tables.CERTS + "." + Certs.VERIFIED);
|
|
||||||
projectionMap.put(Certs.KEY_DATA, Tables.CERTS + "." + Certs.KEY_DATA);
|
|
||||||
projectionMap.put(Certs.USER_ID, Tables.USER_IDS + "." + UserIds.USER_ID);
|
projectionMap.put(Certs.USER_ID, Tables.USER_IDS + "." + UserIds.USER_ID);
|
||||||
projectionMap.put(Certs.SIGNER_UID, "signer." + UserIds.USER_ID + " AS " + Certs.SIGNER_UID);
|
projectionMap.put(Certs.SIGNER_UID, "signer." + UserIds.USER_ID + " AS " + Certs.SIGNER_UID);
|
||||||
qb.setProjectionMap(projectionMap);
|
qb.setProjectionMap(projectionMap);
|
||||||
|
@ -29,6 +29,8 @@ import android.database.DatabaseUtils;
|
|||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
|
|
||||||
|
import org.spongycastle.bcpg.SignatureSubpacketTags;
|
||||||
|
import org.spongycastle.bcpg.sig.SignatureExpirationTime;
|
||||||
import org.spongycastle.openpgp.PGPException;
|
import org.spongycastle.openpgp.PGPException;
|
||||||
import org.spongycastle.openpgp.PGPSecretKey;
|
import org.spongycastle.openpgp.PGPSecretKey;
|
||||||
import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProvider;
|
import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProvider;
|
||||||
@ -231,22 +233,37 @@ public class ProviderHelper {
|
|||||||
for (String userId : new IterableIterator<String>(masterKey.getUserIDs())) {
|
for (String userId : new IterableIterator<String>(masterKey.getUserIDs())) {
|
||||||
operations.add(buildUserIdOperations(context, masterKeyId, userId, userIdRank));
|
operations.add(buildUserIdOperations(context, masterKeyId, userId, userIdRank));
|
||||||
|
|
||||||
|
// HashMap<Long, PGPSignature> certs = new HashMap<Long,PGPSignature>();
|
||||||
|
|
||||||
// look through signatures for this specific key
|
// look through signatures for this specific key
|
||||||
for (PGPSignature cert : new IterableIterator<PGPSignature>(
|
for (PGPSignature cert : new IterableIterator<PGPSignature>(
|
||||||
masterKey.getSignaturesForID(userId))) {
|
masterKey.getSignaturesForID(userId))) {
|
||||||
long certId = cert.getKeyID();
|
long certId = cert.getKeyID();
|
||||||
boolean verified = false;
|
int verified = 0;
|
||||||
// do verify signatures from our own private keys
|
// verify from the key itself
|
||||||
if(allKeyRings.containsKey(certId)) try {
|
try {
|
||||||
// mark them as verified
|
// verify signatures from known private keys
|
||||||
cert.init(
|
if(allKeyRings.containsKey(certId)) {
|
||||||
new JcaPGPContentVerifierBuilderProvider().setProvider(
|
// mark them as verified
|
||||||
|
cert.init(
|
||||||
|
new JcaPGPContentVerifierBuilderProvider().setProvider(
|
||||||
|
Constants.BOUNCY_CASTLE_PROVIDER_NAME),
|
||||||
|
allKeyRings.get(certId).getPublicKey());
|
||||||
|
verified = cert.verifyCertification(userId, masterKey) ? Certs.VERIFIED_SECRET : 0;
|
||||||
|
Log.d(Constants.TAG, "Verified sig for " + userId + " " + verified + " from "
|
||||||
|
+ PgpKeyHelper.convertKeyIdToHex(certId)
|
||||||
|
);
|
||||||
|
// if that didn't work out, is it at least an own signature?
|
||||||
|
} else if(certId == masterKeyId) {
|
||||||
|
cert.init(
|
||||||
|
new JcaPGPContentVerifierBuilderProvider().setProvider(
|
||||||
Constants.BOUNCY_CASTLE_PROVIDER_NAME),
|
Constants.BOUNCY_CASTLE_PROVIDER_NAME),
|
||||||
allKeyRings.get(certId).getPublicKey());
|
masterKey);
|
||||||
verified = cert.verifyCertification(userId, masterKey);
|
verified = cert.verifyCertification(userId, masterKey) ? Certs.VERIFIED_SELF : 0;
|
||||||
Log.d(Constants.TAG, "Verified sig for " + userId + " " + verified + " from "
|
Log.d(Constants.TAG, "Verified sig for " + userId + " " + verified + " from "
|
||||||
+ PgpKeyHelper.convertKeyIdToHex(cert.getKeyID())
|
+ PgpKeyHelper.convertKeyIdToHex(certId)
|
||||||
);
|
);
|
||||||
|
}
|
||||||
} catch(SignatureException e) {
|
} catch(SignatureException e) {
|
||||||
Log.e(Constants.TAG, "Signature verification failed! "
|
Log.e(Constants.TAG, "Signature verification failed! "
|
||||||
+ PgpKeyHelper.convertKeyIdToHex(masterKey.getKeyID())
|
+ PgpKeyHelper.convertKeyIdToHex(masterKey.getKeyID())
|
||||||
@ -263,7 +280,7 @@ public class ProviderHelper {
|
|||||||
);
|
);
|
||||||
// regardless of verification, save the certification
|
// regardless of verification, save the certification
|
||||||
operations.add(buildCertOperations(
|
operations.add(buildCertOperations(
|
||||||
context, masterKeyId, userIdRank, masterKey.getKeyID(), cert, verified));
|
context, masterKeyId, userIdRank, cert, verified));
|
||||||
}
|
}
|
||||||
|
|
||||||
++userIdRank;
|
++userIdRank;
|
||||||
@ -354,18 +371,21 @@ public class ProviderHelper {
|
|||||||
private static ContentProviderOperation buildCertOperations(Context context,
|
private static ContentProviderOperation buildCertOperations(Context context,
|
||||||
long masterKeyId,
|
long masterKeyId,
|
||||||
int rank,
|
int rank,
|
||||||
long keyId,
|
|
||||||
PGPSignature cert,
|
PGPSignature cert,
|
||||||
boolean verified)
|
int verified)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
ContentValues values = new ContentValues();
|
ContentValues values = new ContentValues();
|
||||||
values.put(Certs.MASTER_KEY_ID, masterKeyId);
|
values.put(Certs.MASTER_KEY_ID, masterKeyId);
|
||||||
values.put(Certs.RANK, rank);
|
values.put(Certs.RANK, rank);
|
||||||
values.put(Certs.KEY_ID_CERTIFIER, cert.getKeyID());
|
values.put(Certs.KEY_ID_CERTIFIER, cert.getKeyID());
|
||||||
|
values.put(Certs.TYPE, cert.getSignatureType());
|
||||||
values.put(Certs.CREATION, cert.getCreationTime().getTime() / 1000);
|
values.put(Certs.CREATION, cert.getCreationTime().getTime() / 1000);
|
||||||
values.put(Certs.EXPIRY, (String) null); // TODO
|
if(cert.getHashedSubPackets().hasSubpacket(SignatureSubpacketTags.EXPIRE_TIME)) {
|
||||||
|
long ext = ((SignatureExpirationTime) cert.getHashedSubPackets().getSubpacket(
|
||||||
|
SignatureSubpacketTags.EXPIRE_TIME)).getTime();
|
||||||
|
values.put(Certs.EXPIRY, cert.getCreationTime().getTime() / 1000 + ext);
|
||||||
|
}
|
||||||
values.put(Certs.VERIFIED, verified);
|
values.put(Certs.VERIFIED, verified);
|
||||||
values.put(Certs.KEY_DATA, cert.getEncoded());
|
|
||||||
|
|
||||||
Uri uri = Certs.buildCertsUri(Long.toString(masterKeyId));
|
Uri uri = Certs.buildCertsUri(Long.toString(masterKeyId));
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ public class ViewCertActivity extends ActionBarActivity
|
|||||||
Certs.CREATION,
|
Certs.CREATION,
|
||||||
Certs.KEY_ID_CERTIFIER,
|
Certs.KEY_ID_CERTIFIER,
|
||||||
Certs.SIGNER_UID,
|
Certs.SIGNER_UID,
|
||||||
Certs.KEY_DATA
|
Certs.TYPE
|
||||||
};
|
};
|
||||||
private static final int INDEX_MASTER_KEY_ID = 1;
|
private static final int INDEX_MASTER_KEY_ID = 1;
|
||||||
private static final int INDEX_USER_ID = 2;
|
private static final int INDEX_USER_ID = 2;
|
||||||
@ -65,6 +65,7 @@ public class ViewCertActivity extends ActionBarActivity
|
|||||||
private static final int INDEX_KEY_ID_CERTIFIER = 4;
|
private static final int INDEX_KEY_ID_CERTIFIER = 4;
|
||||||
private static final int INDEX_UID_CERTIFIER = 5;
|
private static final int INDEX_UID_CERTIFIER = 5;
|
||||||
private static final int INDEX_KEY_DATA = 6;
|
private static final int INDEX_KEY_DATA = 6;
|
||||||
|
private static final int INDEX_KEY_TYPE = 6;
|
||||||
|
|
||||||
private Uri mDataUri;
|
private Uri mDataUri;
|
||||||
|
|
||||||
|
@ -30,6 +30,7 @@ import android.widget.TextView;
|
|||||||
import org.sufficientlysecure.keychain.R;
|
import org.sufficientlysecure.keychain.R;
|
||||||
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
|
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
|
||||||
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
|
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
|
||||||
|
import org.sufficientlysecure.keychain.provider.KeychainContract.Certs;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
@ -108,12 +109,12 @@ public class ViewKeyUserIdsAdapter extends CursorAdapter {
|
|||||||
|
|
||||||
int verified = cursor.getInt(mVerifiedId);
|
int verified = cursor.getInt(mVerifiedId);
|
||||||
// TODO introduce own resources for this :)
|
// TODO introduce own resources for this :)
|
||||||
if(verified == 1)
|
if(verified == Certs.VERIFIED_SECRET)
|
||||||
vVerified.setImageResource(android.R.drawable.presence_online);
|
vVerified.setImageResource(android.R.drawable.presence_online);
|
||||||
else if(verified > 1)
|
else if(verified == Certs.VERIFIED_SELF)
|
||||||
vVerified.setImageResource(android.R.drawable.presence_away);
|
|
||||||
else
|
|
||||||
vVerified.setImageResource(android.R.drawable.presence_invisible);
|
vVerified.setImageResource(android.R.drawable.presence_invisible);
|
||||||
|
else
|
||||||
|
vVerified.setImageResource(android.R.drawable.presence_busy);
|
||||||
|
|
||||||
// don't care further if checkboxes aren't shown
|
// don't care further if checkboxes aren't shown
|
||||||
if (mCheckStates == null) {
|
if (mCheckStates == null) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user