From beccb339049a6f5148805a15298161c81a892534 Mon Sep 17 00:00:00 2001 From: Tom Hacohen Date: Thu, 13 Apr 2017 13:29:05 +0100 Subject: [PATCH] Journal: use journal keys if available. If a journal has a key set to it (usually used for shared journals), use it instead of the symmetric key. The key of the journal is asymmetrically encrypted using our keypair. --- .../syncadapter/journalmanager/Crypto.java | 20 +++++++++++++++---- .../journalmanager/JournalManager.java | 6 ++---- .../syncadapter/SyncAdapterService.java | 12 +++++++++-- .../syncadapter/syncadapter/SyncManager.java | 10 ++++++++-- .../journalmanager/ServiceTest.java | 11 ++++++---- 5 files changed, 43 insertions(+), 16 deletions(-) diff --git a/app/src/main/java/com/etesync/syncadapter/journalmanager/Crypto.java b/app/src/main/java/com/etesync/syncadapter/journalmanager/Crypto.java index b6120c70..92246cca 100644 --- a/app/src/main/java/com/etesync/syncadapter/journalmanager/Crypto.java +++ b/app/src/main/java/com/etesync/syncadapter/journalmanager/Crypto.java @@ -123,8 +123,21 @@ public class Crypto { private SecureRandom _random = null; @Getter private final byte version; - private final byte[] cipherKey; - private final byte[] hmacKey; + private byte[] cipherKey; + private byte[] hmacKey; + + private void setDerivedKey(byte[] derivedKey) { + cipherKey = hmac256("aes".getBytes(Charsets.UTF_8), derivedKey); + hmacKey = hmac256("hmac".getBytes(Charsets.UTF_8), derivedKey); + } + + public CryptoManager(int version, AsymmetricKeyPair keyPair, byte[] encryptedKey) { + Crypto.AsymmetricCryptoManager cryptoManager = new Crypto.AsymmetricCryptoManager(keyPair); + byte[] derivedKey = cryptoManager.decrypt(encryptedKey); + + this.version = (byte) version; + setDerivedKey(derivedKey); + } public CryptoManager(int version, @NonNull String keyBase64, @NonNull String salt) throws Exceptions.IntegrityException, Exceptions.VersionTooNewException { byte[] derivedKey; @@ -139,8 +152,7 @@ public class Crypto { } this.version = (byte) version; - cipherKey = hmac256("aes".getBytes(Charsets.UTF_8), derivedKey); - hmacKey = hmac256("hmac".getBytes(Charsets.UTF_8), derivedKey); + setDerivedKey(derivedKey); } private static final int blockSize = 16; // AES's block size in bytes diff --git a/app/src/main/java/com/etesync/syncadapter/journalmanager/JournalManager.java b/app/src/main/java/com/etesync/syncadapter/journalmanager/JournalManager.java index f190b449..522f311a 100644 --- a/app/src/main/java/com/etesync/syncadapter/journalmanager/JournalManager.java +++ b/app/src/main/java/com/etesync/syncadapter/journalmanager/JournalManager.java @@ -40,7 +40,7 @@ public class JournalManager extends BaseManager { this.client = httpClient; } - public List getJournals(String keyBase64) throws Exceptions.HttpException, Exceptions.IntegrityException, Exceptions.GenericCryptoException { + public List getJournals() throws Exceptions.HttpException { Request request = new Request.Builder() .get() .url(remote) @@ -51,9 +51,7 @@ public class JournalManager extends BaseManager { List ret = GsonHelper.gson.fromJson(body.charStream(), journalType); for (Journal journal : ret) { - Crypto.CryptoManager crypto = new Crypto.CryptoManager(journal.getVersion(), keyBase64, journal.getUid()); journal.processFromJson(); - journal.verify(crypto); } return ret; @@ -157,7 +155,7 @@ public class JournalManager extends BaseManager { setContent(Arrays.copyOfRange(getContent(), HMAC_SIZE, getContent().length)); } - void verify(Crypto.CryptoManager crypto) throws Exceptions.IntegrityException { + public void verify(Crypto.CryptoManager crypto) throws Exceptions.IntegrityException { if (hmac == null) { throw new Exceptions.IntegrityException("HMAC is null!"); } diff --git a/app/src/main/java/com/etesync/syncadapter/syncadapter/SyncAdapterService.java b/app/src/main/java/com/etesync/syncadapter/syncadapter/SyncAdapterService.java index 25bd22bb..abd4f902 100644 --- a/app/src/main/java/com/etesync/syncadapter/syncadapter/SyncAdapterService.java +++ b/app/src/main/java/com/etesync/syncadapter/syncadapter/SyncAdapterService.java @@ -158,8 +158,16 @@ public abstract class SyncAdapterService extends Service { List> journals = new LinkedList<>(); - for (JournalManager.Journal journal : journalsManager.getJournals(settings.password())) { - Crypto.CryptoManager crypto = new Crypto.CryptoManager(journal.getVersion(), settings.password(), journal.getUid()); + for (JournalManager.Journal journal : journalsManager.getJournals()) { + Crypto.CryptoManager crypto; + if (journal.getKey() != null) { + crypto = new Crypto.CryptoManager(journal.getVersion(), settings.getKeyPair(), journal.getKey()); + } else { + crypto = new Crypto.CryptoManager(journal.getVersion(), settings.password(), journal.getUid()); + } + + journal.verify(crypto); + CollectionInfo info = CollectionInfo.fromJson(journal.getContent(crypto)); info.updateFromJournal(journal); diff --git a/app/src/main/java/com/etesync/syncadapter/syncadapter/SyncManager.java b/app/src/main/java/com/etesync/syncadapter/syncadapter/SyncManager.java index 4db3a398..f7481f0c 100644 --- a/app/src/main/java/com/etesync/syncadapter/syncadapter/SyncManager.java +++ b/app/src/main/java/com/etesync/syncadapter/syncadapter/SyncManager.java @@ -33,6 +33,7 @@ import com.etesync.syncadapter.model.SyncEntry; import com.etesync.syncadapter.resource.LocalCollection; import com.etesync.syncadapter.resource.LocalResource; import com.etesync.syncadapter.ui.DebugInfoActivity; +import com.etesync.syncadapter.utils.Base64; import org.apache.commons.collections4.ListUtils; @@ -118,7 +119,12 @@ abstract public class SyncManager { notificationManager.cancel(); App.log.info(String.format(Locale.getDefault(), "Syncing collection %s (version: %d)", journalUid, info.version)); - crypto = new Crypto.CryptoManager(info.version, settings.password(), journalUid); + + if (getJournalEntity().getEncryptedKey() != null) { + crypto = new Crypto.CryptoManager(info.version, settings.getKeyPair(), getJournalEntity().getEncryptedKey()); + } else { + crypto = new Crypto.CryptoManager(info.version, settings.password(), info.uid); + } } protected abstract int notificationId(); @@ -235,7 +241,7 @@ abstract public class SyncManager { private JournalEntity getJournalEntity() { if (_journalEntity == null) - _journalEntity = JournalModel.Journal.fetch(data, info.getServiceEntity(data), journal.getUid()); + _journalEntity = JournalModel.Journal.fetch(data, info.getServiceEntity(data), info.uid); return _journalEntity; } diff --git a/app/src/test/java/com/etesync/syncadapter/journalmanager/ServiceTest.java b/app/src/test/java/com/etesync/syncadapter/journalmanager/ServiceTest.java index b98bdf8b..a905856d 100644 --- a/app/src/test/java/com/etesync/syncadapter/journalmanager/ServiceTest.java +++ b/app/src/test/java/com/etesync/syncadapter/journalmanager/ServiceTest.java @@ -93,7 +93,7 @@ public class ServiceTest { } assertNotNull(caught); - List journals = journalManager.getJournals(Helpers.keyBase64); + List journals = journalManager.getJournals(); assertEquals(journals.size(), 1); CollectionInfo info2 = CollectionInfo.fromJson(journals.get(0).getContent(crypto)); assertEquals(info2.displayName, info.displayName); @@ -103,7 +103,7 @@ public class ServiceTest { journal = new JournalManager.Journal(crypto, info.toJson(), info.uid); journalManager.updateJournal(journal); - journals = journalManager.getJournals(Helpers.keyBase64); + journals = journalManager.getJournals(); assertEquals(journals.size(), 1); info2 = CollectionInfo.fromJson(journals.get(0).getContent(crypto)); assertEquals(info2.displayName, info.displayName); @@ -111,7 +111,7 @@ public class ServiceTest { // Delete journal journalManager.deleteJournal(journal); - journals = journalManager.getJournals(Helpers.keyBase64); + journals = journalManager.getJournals(); assertEquals(journals.size(), 0); // Bad HMAC @@ -124,7 +124,10 @@ public class ServiceTest { try { caught = null; - journalManager.getJournals(Helpers.keyBase64); + for (JournalManager.Journal journal1 : journalManager.getJournals()) { + Crypto.CryptoManager crypto1 = new Crypto.CryptoManager(info.version, Helpers.keyBase64, journal1.getUid()); + journal1.verify(crypto1); + } } catch (Exceptions.IntegrityException e) { caught = e; }