mirror of
https://github.com/etesync/android
synced 2024-12-23 23:18:46 +00:00
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.
This commit is contained in:
parent
43803b6d3e
commit
beccb33904
@ -123,8 +123,21 @@ public class Crypto {
|
|||||||
private SecureRandom _random = null;
|
private SecureRandom _random = null;
|
||||||
@Getter
|
@Getter
|
||||||
private final byte version;
|
private final byte version;
|
||||||
private final byte[] cipherKey;
|
private byte[] cipherKey;
|
||||||
private final byte[] hmacKey;
|
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 {
|
public CryptoManager(int version, @NonNull String keyBase64, @NonNull String salt) throws Exceptions.IntegrityException, Exceptions.VersionTooNewException {
|
||||||
byte[] derivedKey;
|
byte[] derivedKey;
|
||||||
@ -139,8 +152,7 @@ public class Crypto {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.version = (byte) version;
|
this.version = (byte) version;
|
||||||
cipherKey = hmac256("aes".getBytes(Charsets.UTF_8), derivedKey);
|
setDerivedKey(derivedKey);
|
||||||
hmacKey = hmac256("hmac".getBytes(Charsets.UTF_8), derivedKey);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final int blockSize = 16; // AES's block size in bytes
|
private static final int blockSize = 16; // AES's block size in bytes
|
||||||
|
@ -40,7 +40,7 @@ public class JournalManager extends BaseManager {
|
|||||||
this.client = httpClient;
|
this.client = httpClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Journal> getJournals(String keyBase64) throws Exceptions.HttpException, Exceptions.IntegrityException, Exceptions.GenericCryptoException {
|
public List<Journal> getJournals() throws Exceptions.HttpException {
|
||||||
Request request = new Request.Builder()
|
Request request = new Request.Builder()
|
||||||
.get()
|
.get()
|
||||||
.url(remote)
|
.url(remote)
|
||||||
@ -51,9 +51,7 @@ public class JournalManager extends BaseManager {
|
|||||||
List<Journal> ret = GsonHelper.gson.fromJson(body.charStream(), journalType);
|
List<Journal> ret = GsonHelper.gson.fromJson(body.charStream(), journalType);
|
||||||
|
|
||||||
for (Journal journal : ret) {
|
for (Journal journal : ret) {
|
||||||
Crypto.CryptoManager crypto = new Crypto.CryptoManager(journal.getVersion(), keyBase64, journal.getUid());
|
|
||||||
journal.processFromJson();
|
journal.processFromJson();
|
||||||
journal.verify(crypto);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -157,7 +155,7 @@ public class JournalManager extends BaseManager {
|
|||||||
setContent(Arrays.copyOfRange(getContent(), HMAC_SIZE, getContent().length));
|
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) {
|
if (hmac == null) {
|
||||||
throw new Exceptions.IntegrityException("HMAC is null!");
|
throw new Exceptions.IntegrityException("HMAC is null!");
|
||||||
}
|
}
|
||||||
|
@ -158,8 +158,16 @@ public abstract class SyncAdapterService extends Service {
|
|||||||
|
|
||||||
List<Pair<JournalManager.Journal, CollectionInfo>> journals = new LinkedList<>();
|
List<Pair<JournalManager.Journal, CollectionInfo>> journals = new LinkedList<>();
|
||||||
|
|
||||||
for (JournalManager.Journal journal : journalsManager.getJournals(settings.password())) {
|
for (JournalManager.Journal journal : journalsManager.getJournals()) {
|
||||||
Crypto.CryptoManager crypto = new Crypto.CryptoManager(journal.getVersion(), settings.password(), journal.getUid());
|
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));
|
CollectionInfo info = CollectionInfo.fromJson(journal.getContent(crypto));
|
||||||
info.updateFromJournal(journal);
|
info.updateFromJournal(journal);
|
||||||
|
|
||||||
|
@ -33,6 +33,7 @@ import com.etesync.syncadapter.model.SyncEntry;
|
|||||||
import com.etesync.syncadapter.resource.LocalCollection;
|
import com.etesync.syncadapter.resource.LocalCollection;
|
||||||
import com.etesync.syncadapter.resource.LocalResource;
|
import com.etesync.syncadapter.resource.LocalResource;
|
||||||
import com.etesync.syncadapter.ui.DebugInfoActivity;
|
import com.etesync.syncadapter.ui.DebugInfoActivity;
|
||||||
|
import com.etesync.syncadapter.utils.Base64;
|
||||||
|
|
||||||
import org.apache.commons.collections4.ListUtils;
|
import org.apache.commons.collections4.ListUtils;
|
||||||
|
|
||||||
@ -118,7 +119,12 @@ abstract public class SyncManager {
|
|||||||
notificationManager.cancel();
|
notificationManager.cancel();
|
||||||
|
|
||||||
App.log.info(String.format(Locale.getDefault(), "Syncing collection %s (version: %d)", journalUid, info.version));
|
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();
|
protected abstract int notificationId();
|
||||||
@ -235,7 +241,7 @@ abstract public class SyncManager {
|
|||||||
|
|
||||||
private JournalEntity getJournalEntity() {
|
private JournalEntity getJournalEntity() {
|
||||||
if (_journalEntity == null)
|
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;
|
return _journalEntity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,7 +93,7 @@ public class ServiceTest {
|
|||||||
}
|
}
|
||||||
assertNotNull(caught);
|
assertNotNull(caught);
|
||||||
|
|
||||||
List<JournalManager.Journal> journals = journalManager.getJournals(Helpers.keyBase64);
|
List<JournalManager.Journal> journals = journalManager.getJournals();
|
||||||
assertEquals(journals.size(), 1);
|
assertEquals(journals.size(), 1);
|
||||||
CollectionInfo info2 = CollectionInfo.fromJson(journals.get(0).getContent(crypto));
|
CollectionInfo info2 = CollectionInfo.fromJson(journals.get(0).getContent(crypto));
|
||||||
assertEquals(info2.displayName, info.displayName);
|
assertEquals(info2.displayName, info.displayName);
|
||||||
@ -103,7 +103,7 @@ public class ServiceTest {
|
|||||||
journal = new JournalManager.Journal(crypto, info.toJson(), info.uid);
|
journal = new JournalManager.Journal(crypto, info.toJson(), info.uid);
|
||||||
journalManager.updateJournal(journal);
|
journalManager.updateJournal(journal);
|
||||||
|
|
||||||
journals = journalManager.getJournals(Helpers.keyBase64);
|
journals = journalManager.getJournals();
|
||||||
assertEquals(journals.size(), 1);
|
assertEquals(journals.size(), 1);
|
||||||
info2 = CollectionInfo.fromJson(journals.get(0).getContent(crypto));
|
info2 = CollectionInfo.fromJson(journals.get(0).getContent(crypto));
|
||||||
assertEquals(info2.displayName, info.displayName);
|
assertEquals(info2.displayName, info.displayName);
|
||||||
@ -111,7 +111,7 @@ public class ServiceTest {
|
|||||||
// Delete journal
|
// Delete journal
|
||||||
journalManager.deleteJournal(journal);
|
journalManager.deleteJournal(journal);
|
||||||
|
|
||||||
journals = journalManager.getJournals(Helpers.keyBase64);
|
journals = journalManager.getJournals();
|
||||||
assertEquals(journals.size(), 0);
|
assertEquals(journals.size(), 0);
|
||||||
|
|
||||||
// Bad HMAC
|
// Bad HMAC
|
||||||
@ -124,7 +124,10 @@ public class ServiceTest {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
caught = null;
|
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) {
|
} catch (Exceptions.IntegrityException e) {
|
||||||
caught = e;
|
caught = e;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user