From ad3c9e101cdeb38b5756d81d41cf538e7f92606b Mon Sep 17 00:00:00 2001 From: ameba23 Date: Mon, 19 Apr 2021 09:00:05 +0200 Subject: [PATCH] Implement BackupPayloadDecoder --- .../socialbackup/BackupPayloadDecoder.java | 12 ++ .../BackupPayloadDecoderImpl.java | 114 ++++++++++++++++++ .../briar/socialbackup/SocialBackup.java | 25 ++++ .../recovery/ReturnShardIntegrationTest.java | 17 ++- 4 files changed, 165 insertions(+), 3 deletions(-) create mode 100644 briar-core/src/main/java/org/briarproject/briar/socialbackup/BackupPayloadDecoderImpl.java diff --git a/briar-core/src/main/java/org/briarproject/briar/socialbackup/BackupPayloadDecoder.java b/briar-core/src/main/java/org/briarproject/briar/socialbackup/BackupPayloadDecoder.java index d48b8246d..e5bde9592 100644 --- a/briar-core/src/main/java/org/briarproject/briar/socialbackup/BackupPayloadDecoder.java +++ b/briar-core/src/main/java/org/briarproject/briar/socialbackup/BackupPayloadDecoder.java @@ -1,4 +1,16 @@ package org.briarproject.briar.socialbackup; +import org.briarproject.bramble.api.FormatException; +import org.briarproject.bramble.api.crypto.SecretKey; +import org.briarproject.bramble.api.nullsafety.NotNullByDefault; +import org.briarproject.briar.api.socialbackup.BackupPayload; + +import java.security.GeneralSecurityException; + +@NotNullByDefault public interface BackupPayloadDecoder { + SocialBackup decodeBackupPayload( + SecretKey secret, + BackupPayload backupPayload, byte[] nonce) throws FormatException, + GeneralSecurityException; } diff --git a/briar-core/src/main/java/org/briarproject/briar/socialbackup/BackupPayloadDecoderImpl.java b/briar-core/src/main/java/org/briarproject/briar/socialbackup/BackupPayloadDecoderImpl.java new file mode 100644 index 000000000..59ce9cc03 --- /dev/null +++ b/briar-core/src/main/java/org/briarproject/briar/socialbackup/BackupPayloadDecoderImpl.java @@ -0,0 +1,114 @@ +package org.briarproject.briar.socialbackup; + +import org.briarproject.bramble.api.FormatException; +import org.briarproject.bramble.api.client.ClientHelper; +import org.briarproject.bramble.api.contact.Contact; +import org.briarproject.bramble.api.contact.ContactId; +import org.briarproject.bramble.api.crypto.AgreementPrivateKey; +import org.briarproject.bramble.api.crypto.AgreementPublicKey; +import org.briarproject.bramble.api.crypto.AuthenticatedCipher; +import org.briarproject.bramble.api.crypto.PrivateKey; +import org.briarproject.bramble.api.crypto.PublicKey; +import org.briarproject.bramble.api.crypto.SecretKey; +import org.briarproject.bramble.api.data.BdfList; +import org.briarproject.bramble.api.identity.Author; +import org.briarproject.bramble.api.identity.Identity; +import org.briarproject.bramble.api.identity.LocalAuthor; +import org.briarproject.bramble.api.plugin.TransportId; +import org.briarproject.bramble.api.properties.TransportProperties; +import org.briarproject.briar.api.socialbackup.BackupPayload; +import org.briarproject.briar.api.socialbackup.MessageParser; +import org.briarproject.briar.api.socialbackup.Shard; + +import java.security.GeneralSecurityException; +import java.security.SecureRandom; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import javax.inject.Inject; +import javax.inject.Provider; + +import static org.briarproject.briar.socialbackup.SocialBackupConstants.AUTH_TAG_BYTES; + +public class BackupPayloadDecoderImpl { + private final ClientHelper clientHelper; + private final Provider cipherProvider; + private final SecureRandom secureRandom; + private final MessageParser messageParser; + + @Inject + BackupPayloadDecoderImpl(ClientHelper clientHelper, + Provider cipherProvider, + SecureRandom secureRandom, + MessageParser messageParser) { + this.clientHelper = clientHelper; + this.cipherProvider = cipherProvider; + this.secureRandom = secureRandom; + this.messageParser = messageParser; + } + + public SocialBackup decodeBackupPayload( + SecretKey secret, + BackupPayload backupPayload, byte[] nonce) + throws FormatException, GeneralSecurityException { + + AuthenticatedCipher cipher = cipherProvider.get(); + cipher.init(false, secret, nonce); + byte[] plaintext = + new byte[backupPayload.getBytes().length - AUTH_TAG_BYTES]; + int decrypted = cipher.process(backupPayload.getBytes(), 0, + backupPayload.getBytes().length, plaintext, 0); + if (decrypted != plaintext.length) throw new AssertionError(); + + BdfList backup = clientHelper.toList(plaintext); + int version = backup.getLong(0).intValue(); + BdfList bdfIdentity = backup.getList(1); + BdfList bdfContactData = backup.getList(2); + + LocalAuthor localAuthor = + (LocalAuthor) clientHelper + .parseAndValidateAuthor(bdfIdentity.getList(0)); + //TODO + byte[] authorPrivateKeyBytes = bdfIdentity.getRaw(1); + + PublicKey handshakePublicKey = + new AgreementPublicKey(bdfIdentity.getRaw(2)); + PrivateKey handShakePrivateKey = + new AgreementPrivateKey(bdfIdentity.getRaw(3)); + + Long created = System.currentTimeMillis(); + + Identity identity = new Identity(localAuthor, handshakePublicKey, + handShakePrivateKey, created); + + List contactDataList = new ArrayList(); + + for (int i = 0; i < bdfContactData.size(); i++) { + BdfList bdfData = bdfContactData.getList(i); + + Author author = + clientHelper.parseAndValidateAuthor(bdfData.getList(0)); + String alias = bdfData.getString(1); + // 2 - public key or null + byte[] publicKeyBytes = bdfData.getRaw(2); + + // 3 - properties dictionary + Map properties = clientHelper + .parseAndValidateTransportPropertiesMap( + bdfData.getDictionary(3)); + // 4 shard or null + BdfList shardList = bdfData.getList(4); + Shard shard = shardList == null ? null : + messageParser.parseShardMessage(shardList); + ContactId contactId = new ContactId(i); + Contact contact = + new Contact(contactId, author, author.getId(), alias, + handshakePublicKey, false); + ContactData contactData = + new ContactData(contact, properties, shard); + contactDataList.add(contactData); + } + return new SocialBackup(identity, contactDataList, version); + } +} diff --git a/briar-core/src/main/java/org/briarproject/briar/socialbackup/SocialBackup.java b/briar-core/src/main/java/org/briarproject/briar/socialbackup/SocialBackup.java index 01c2cddab..341d04816 100644 --- a/briar-core/src/main/java/org/briarproject/briar/socialbackup/SocialBackup.java +++ b/briar-core/src/main/java/org/briarproject/briar/socialbackup/SocialBackup.java @@ -1,4 +1,29 @@ package org.briarproject.briar.socialbackup; +import org.briarproject.bramble.api.identity.Identity; + +import java.util.List; + public class SocialBackup { + private Identity identity; + private List contacts; + private int version; + + SocialBackup (Identity identity, List contacts, int version) { + this.identity = identity; + this.contacts = contacts; + this.version = version; + } + + public Identity getIdentity() { + return identity; + } + + public List getContacts() { + return contacts; + } + + public int getVersion() { + return version; + } } diff --git a/briar-core/src/test/java/org/briarproject/briar/socialbackup/recovery/ReturnShardIntegrationTest.java b/briar-core/src/test/java/org/briarproject/briar/socialbackup/recovery/ReturnShardIntegrationTest.java index 4c9556dc5..6ac49754a 100644 --- a/briar-core/src/test/java/org/briarproject/briar/socialbackup/recovery/ReturnShardIntegrationTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/socialbackup/recovery/ReturnShardIntegrationTest.java @@ -4,6 +4,9 @@ import org.briarproject.bramble.BrambleCoreIntegrationTestEagerSingletons; import org.briarproject.bramble.api.lifecycle.LifecycleManager; import org.briarproject.bramble.test.BrambleTestCase; import org.briarproject.bramble.test.TestDatabaseConfigModule; +import org.briarproject.briar.api.socialbackup.BackupPayload; +import org.briarproject.briar.api.socialbackup.ReturnShardPayload; +import org.briarproject.briar.api.socialbackup.Shard; import org.briarproject.briar.api.socialbackup.recovery.CustodianTask; import org.briarproject.briar.api.socialbackup.recovery.SecretOwnerTask; import org.junit.After; @@ -13,6 +16,7 @@ import org.junit.Test; import java.io.File; import java.net.InetAddress; import java.util.Arrays; +import java.util.concurrent.Executor; import static junit.framework.TestCase.fail; import static org.briarproject.bramble.test.TestUtils.deleteTestDirectory; @@ -51,6 +55,12 @@ public class ReturnShardIntegrationTest extends BrambleTestCase { CustodianTask custodianTask = custodian.getCustodianTask(); byte[] payload = "its nice to be important but its more important to be nice".getBytes(); + Shard shard = new Shard("secretid".getBytes(), "shard".getBytes()); + BackupPayload backupPayload = new BackupPayload("backup payload".getBytes()); + ReturnShardPayload returnShardPayload = new ReturnShardPayload(shard, backupPayload); + +// payloadBytes = clientHelper + SecretOwnerTask.Observer ownerObserver = state -> { if (state instanceof SecretOwnerTask.State.Listening) { @@ -60,8 +70,8 @@ public class ReturnShardIntegrationTest extends BrambleTestCase { System.out.println(qrPayload.length); transferQrCode(custodianTask, qrPayload); } else if (state instanceof SecretOwnerTask.State.Success) { - byte[] remotePayload = ((SecretOwnerTask.State.Success) state).getRemotePayload(); - assertTrue(Arrays.equals(remotePayload, payload)); + ReturnShardPayload remotePayload = ((SecretOwnerTask.State.Success) state).getRemotePayload(); + assertTrue(remotePayload.equals(payload)); System.out.println("Success"); } else if (state instanceof SecretOwnerTask.State.Failure) { System.out.println("Owner state: failure"); @@ -103,7 +113,8 @@ public class ReturnShardIntegrationTest extends BrambleTestCase { // TODO how to get the test to wait for the io to finish try { - Thread.sleep(1000); +// Thread.sleep(1000); + tearDown(); } catch (Exception e) { fail(); }