Remember "origin" of gossip keys

This commit is contained in:
Vincent Breitmoser 2018-01-20 22:08:51 +01:00
parent 53953fb058
commit ca8835420d
8 changed files with 46 additions and 21 deletions

View file

@ -187,10 +187,23 @@ public class AutocryptPeerDataAccessObject {
.update(ApiAutocryptPeer.buildByPackageNameAndAutocryptId(packageName, autocryptId), cv, null, null);
}
public void updateKeyGossip(String autocryptId, Date effectiveDate, long masterKeyId) {
public void updateKeyGossipFromAutocrypt(String autocryptId, Date effectiveDate, long masterKeyId) {
updateKeyGossip(autocryptId, effectiveDate, masterKeyId, ApiAutocryptPeer.GOSSIP_ORIGIN_AUTOCRYPT);
}
public void updateKeyGossipFromSignature(String autocryptId, Date effectiveDate, long masterKeyId) {
updateKeyGossip(autocryptId, effectiveDate, masterKeyId, ApiAutocryptPeer.GOSSIP_ORIGIN_SIGNATURE);
}
public void updateKeyGossipFromDedup(String autocryptId, Date effectiveDate, long masterKeyId) {
updateKeyGossip(autocryptId, effectiveDate, masterKeyId, ApiAutocryptPeer.GOSSIP_ORIGIN_DEDUP);
}
private void updateKeyGossip(String autocryptId, Date effectiveDate, long masterKeyId, int origin) {
ContentValues cv = new ContentValues();
cv.put(ApiAutocryptPeer.GOSSIP_MASTER_KEY_ID, masterKeyId);
cv.put(ApiAutocryptPeer.GOSSIP_LAST_SEEN_KEY, effectiveDate.getTime());
cv.put(ApiAutocryptPeer.GOSSIP_ORIGIN, origin);
queryInterface
.update(ApiAutocryptPeer.buildByPackageNameAndAutocryptId(packageName, autocryptId), cv, null, null);
}

View file

@ -110,6 +110,7 @@ public class KeychainContract {
String GOSSIP_MASTER_KEY_ID = "gossip_master_key_id";
String GOSSIP_LAST_SEEN_KEY = "gossip_last_seen_key";
String GOSSIP_ORIGIN = "gossip_origin";
}
public static final String CONTENT_AUTHORITY = Constants.PROVIDER_AUTHORITY;
@ -382,6 +383,10 @@ public class KeychainContract {
public static final String GOSSIP_KEY_IS_EXPIRED = "gossip_key_is_expired";
public static final String GOSSIP_KEY_IS_VERIFIED = "gossip_key_is_verified";
public static final int GOSSIP_ORIGIN_AUTOCRYPT = 0;
public static final int GOSSIP_ORIGIN_SIGNATURE = 10;
public static final int GOSSIP_ORIGIN_DEDUP = 20;
public static Uri buildByKeyUri(Uri uri) {
return CONTENT_URI.buildUpon().appendPath(PATH_BY_KEY_ID).appendPath(uri.getPathSegments().get(1)).build();
}

View file

@ -179,6 +179,7 @@ public class KeychainDatabase extends SQLiteOpenHelper {
+ ApiAutocryptPeerColumns.MASTER_KEY_ID + " INTEGER NULL, "
+ ApiAutocryptPeerColumns.GOSSIP_MASTER_KEY_ID + " INTEGER NULL, "
+ ApiAutocryptPeerColumns.GOSSIP_LAST_SEEN_KEY + " INTEGER NULL, "
+ ApiAutocryptPeerColumns.GOSSIP_ORIGIN + " INTEGER NULL, "
+ "PRIMARY KEY(" + ApiAutocryptPeerColumns.PACKAGE_NAME + ", "
+ ApiAutocryptPeerColumns.IDENTIFIER + "), "
+ "FOREIGN KEY(" + ApiAutocryptPeerColumns.PACKAGE_NAME + ") REFERENCES "
@ -418,26 +419,32 @@ public class KeychainDatabase extends SQLiteOpenHelper {
+ "package_name TEXT NOT NULL, "
+ "identifier TEXT NOT NULL, "
+ "last_seen INTEGER, "
+ "last_seen_key INTEGER NULL, "
+ "is_mutual INTEGER NULL, "
+ "master_key_id INTEGER NULL, "
+ "gossip_master_key_id INTEGER NULL, "
+ "gossip_last_seen_key INTEGER NULL, "
+ "last_seen_key INTEGER, "
+ "is_mutual INTEGER, "
+ "master_key_id INTEGER, "
+ "gossip_master_key_id INTEGER, "
+ "gossip_last_seen_key INTEGER, "
+ "gossip_origin INTEGER, "
+ "PRIMARY KEY(package_name, identifier), "
+ "FOREIGN KEY(package_name) REFERENCES api_apps (package_name) ON DELETE CASCADE"
+ ")");
// Note: Keys from Autocrypt 0.X with state == "reset" (0) are dropped
db.execSQL("INSERT INTO api_autocrypt_peers " +
"(package_name, identifier, last_seen, gossip_last_seen_key, gossip_master_key_id, is_mutual) " +
"(package_name, identifier, last_seen, gossip_last_seen_key, gossip_master_key_id, gossip_origin) " +
"SELECT package_name, identifier, last_updated, last_seen_key, master_key_id, 0 " +
"FROM tmp WHERE state IN (1,2)");
"FROM tmp WHERE state = 1"); // Autocrypt 0.X, "gossip" -> now origin=autocrypt
db.execSQL("INSERT INTO api_autocrypt_peers " +
"(package_name, identifier, last_seen, gossip_last_seen_key, gossip_master_key_id, gossip_origin) " +
"SELECT package_name, identifier, last_updated, last_seen_key, master_key_id, 20 " +
"FROM tmp WHERE state = 2"); // "selected" keys -> now origin=dedup
db.execSQL("INSERT INTO api_autocrypt_peers " +
"(package_name, identifier, last_seen, last_seen_key, master_key_id, is_mutual) " +
"SELECT package_name, identifier, last_updated, last_seen_key, master_key_id, 0 " +
"FROM tmp WHERE state = 3");
"FROM tmp WHERE state = 3"); // Autocrypt 0.X, state = "available"
db.execSQL("INSERT INTO api_autocrypt_peers " +
"(package_name, identifier, last_seen, last_seen_key, master_key_id, is_mutual) " +
"SELECT package_name, identifier, last_updated, last_seen_key, master_key_id, 1 " +
"FROM tmp WHERE state = 4");
"FROM tmp WHERE state = 4"); // from Autocrypt 0.X, state = "mutual"
db.execSQL("DROP TABLE tmp");
db.setTransactionSuccessful();
db.endTransaction();

View file

@ -729,6 +729,7 @@ public class KeychainProvider extends ContentProvider {
projectionMap.put(ApiAutocryptPeer.LAST_SEEN_KEY, ApiAutocryptPeer.LAST_SEEN_KEY);
projectionMap.put(ApiAutocryptPeer.GOSSIP_MASTER_KEY_ID, ApiAutocryptPeer.GOSSIP_MASTER_KEY_ID);
projectionMap.put(ApiAutocryptPeer.GOSSIP_LAST_SEEN_KEY, ApiAutocryptPeer.GOSSIP_LAST_SEEN_KEY);
projectionMap.put(ApiAutocryptPeer.GOSSIP_ORIGIN, ApiAutocryptPeer.GOSSIP_ORIGIN);
projectionMap.put(ApiAutocryptPeer.KEY_IS_REVOKED, "ac_key." + Keys.IS_REVOKED + " AS " + ApiAutocryptPeer.KEY_IS_REVOKED);
projectionMap.put(ApiAutocryptPeer.KEY_IS_EXPIRED, "(CASE" +
" WHEN ac_key." + Keys.EXPIRY + " IS NULL THEN 0" +

View file

@ -94,7 +94,7 @@ class AutocryptInteractor {
// 4. Set peers[gossip-addr].gossip_key to the value of the keydata attribute.
Long newMasterKeyId = saveKeyringResult.savedMasterKeyId;
autocryptPeerDao.updateKeyGossip(autocryptPeerId, effectiveDate, newMasterKeyId);
autocryptPeerDao.updateKeyGossipFromAutocrypt(autocryptPeerId, effectiveDate, newMasterKeyId);
}
@Nullable

View file

@ -577,13 +577,12 @@ public class OpenPgpService extends Service {
long masterKeyId = signatureResult.getKeyId();
if (autocryptPeerMasterKeyId == null) {
// TODO
// Date now = new Date();
// Date effectiveTime = signatureResult.getSignatureTimestamp();
// if (effectiveTime.after(now)) {
// effectiveTime = now;
// }
// autocryptPeerentityDao.updateKeyGossip(autocryptPeerId, effectiveTime, masterKeyId);
Date now = new Date();
Date effectiveTime = signatureResult.getSignatureTimestamp();
if (effectiveTime.after(now)) {
effectiveTime = now;
}
autocryptPeerentityDao.updateKeyGossipFromSignature(autocryptPeerId, effectiveTime, masterKeyId);
return signatureResult.withAutocryptPeerResult(AutocryptPeerResult.NEW);
} else if (masterKeyId == autocryptPeerMasterKeyId) {
return signatureResult.withAutocryptPeerResult(AutocryptPeerResult.OK);

View file

@ -122,7 +122,7 @@ class RemoteDeduplicatePresenter implements LoaderCallbacks<List<KeyInfo>> {
}
long masterKeyId = keyInfoData.get(selectedItem).getMasterKeyId();
autocryptPeerDao.updateKeyGossip(duplicateAddress, new Date(), masterKeyId);
autocryptPeerDao.updateKeyGossipFromDedup(duplicateAddress, new Date(), masterKeyId);
view.finish();
}

View file

@ -305,7 +305,7 @@ public class KeychainExternalProviderTest {
insertSecretKeyringFrom("/test-keys/testring.sec");
insertPublicKeyringFrom("/test-keys/testring.pub");
autocryptPeerDao.updateKeyGossip("tid", new Date(), KEY_ID_PUBLIC);
autocryptPeerDao.updateKeyGossipFromAutocrypt("tid", new Date(), KEY_ID_PUBLIC);
autocryptPeerDao.delete("tid");
Cursor cursor = contentResolver.query(
@ -330,7 +330,7 @@ public class KeychainExternalProviderTest {
insertSecretKeyringFrom("/test-keys/testring.sec");
insertPublicKeyringFrom("/test-keys/testring.pub");
autocryptPeerDao.updateKeyGossip(AUTOCRYPT_PEER, new Date(), KEY_ID_PUBLIC);
autocryptPeerDao.updateKeyGossipFromAutocrypt(AUTOCRYPT_PEER, new Date(), KEY_ID_PUBLIC);
certifyKey(KEY_ID_SECRET, KEY_ID_PUBLIC, USER_ID_1);
Cursor cursor = contentResolver.query(