From 2a50a09614fb22f8c7a767f9a872bc7c42b27b21 Mon Sep 17 00:00:00 2001 From: jubb Date: Fri, 12 Feb 2021 14:16:06 +1100 Subject: [PATCH] feat: share pending key pair between generate EC and add members --- .../loki/protocol/ClosedGroupsProtocolV2.kt | 32 ++++++------------- 1 file changed, 10 insertions(+), 22 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/protocol/ClosedGroupsProtocolV2.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/protocol/ClosedGroupsProtocolV2.kt index b35e9e8d98..5874c1d88d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/protocol/ClosedGroupsProtocolV2.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/protocol/ClosedGroupsProtocolV2.kt @@ -3,6 +3,7 @@ package org.thoughtcrime.securesms.loki.protocol import android.content.Context import android.util.Log import com.google.protobuf.ByteString +import kotlinx.coroutines.delay import nl.komponents.kovenant.Promise import nl.komponents.kovenant.deferred import nl.komponents.kovenant.task @@ -44,7 +45,7 @@ import kotlin.jvm.Throws object ClosedGroupsProtocolV2 { const val groupSizeLimit = 100 - private val pendingKeyPair = AtomicReference(null) + private val pendingKeyPair = AtomicReference(null) sealed class Error(val description: String) : Exception() { object NoThread : Error("Couldn't find a thread associated with the given group public key") @@ -104,9 +105,6 @@ object ClosedGroupsProtocolV2 { val groupDB = DatabaseFactory.getGroupDatabase(context) val groupID = doubleEncodeGroupID(groupPublicKey) val group = groupDB.getGroup(groupID).orNull() - val updatedMembers = group.members.map { it.serialize() }.toSet() - userPublicKey - val admins = group.admins.map { it.serialize() } - val name = group.title val sentTime = System.currentTimeMillis() if (group == null) { Log.d("Loki", "Can't leave nonexistent closed group.") @@ -119,10 +117,6 @@ object ClosedGroupsProtocolV2 { job.onRun() // Run the job immediately // Remove the group private key and unsubscribe from PNs disableLocalGroupAndUnsubscribe(context, apiDB, groupPublicKey, groupDB, groupID, userPublicKey) - // Notify the user - val infoType = GroupContext.Type.QUIT - val threadID = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(Recipient.from(context, Address.fromSerialized(groupID), false)) - insertOutgoingInfoMessage(context, groupID, infoType, name, updatedMembers, admins, threadID, sentTime) deferred.resolve(Unit) } return deferred.promise @@ -147,7 +141,7 @@ object ClosedGroupsProtocolV2 { val admins = group.admins.map { it.serialize() } val adminsAsData = admins.map { Hex.fromStringCondensed(it) } val sentTime = System.currentTimeMillis() - val encryptionKeyPair = apiDB.getLatestClosedGroupEncryptionKeyPair(groupPublicKey) + val encryptionKeyPair = pendingKeyPair.get() ?: apiDB.getLatestClosedGroupEncryptionKeyPair(groupPublicKey) if (encryptionKeyPair == null) { Log.d("Loki", "Couldn't get encryption key pair for closed group.") return@task Error.NoKeyPair @@ -166,10 +160,6 @@ object ClosedGroupsProtocolV2 { val newMemberJob = ClosedGroupUpdateMessageSendJobV2(member, closedGroupNewKind, sentTime) ApplicationContext.getInstance(context).jobManager.add(newMemberJob) } - // Notify the user - val infoType = GroupContext.Type.UPDATE - val threadID = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(Recipient.from(context, Address.fromSerialized(groupID), false)) - insertOutgoingInfoMessage(context, groupID, infoType, name, updatedMembers, admins, threadID, sentTime) } } @@ -210,10 +200,7 @@ object ClosedGroupsProtocolV2 { if (isCurrentUserAdmin) { generateAndSendNewEncryptionKeyPair(context, groupPublicKey, updatedMembers) } - // Notify the user - val infoType = GroupContext.Type.UPDATE - val threadID = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(Recipient.from(context, Address.fromSerialized(groupID), false)) - insertOutgoingInfoMessage(context, groupID, infoType, name, updatedMembers, admins, threadID, sentTime) + return@task Unit } } @@ -238,10 +225,6 @@ object ClosedGroupsProtocolV2 { job.onRun() // Run the job immediately // Update the group groupDB.updateTitle(groupID, newName) - // Notify the user - val infoType = GroupContext.Type.UPDATE - val threadID = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(Recipient.from(context, Address.fromSerialized(groupID), false)) - insertOutgoingInfoMessage(context, groupID, infoType, newName, members, admins, threadID, sentTime) deferred.resolve(Unit) } return deferred.promise @@ -367,7 +350,11 @@ object ClosedGroupsProtocolV2 { return } // Generate the new encryption key pair - val newKeyPair = pendingKeyPair.getAndSet(Curve.generateKeyPair()) ?: Curve.generateKeyPair() + val newKeyPair = Curve.generateKeyPair() + do { + // make sure we set the pendingKeyPair or wait until it is not null + } while (!pendingKeyPair.compareAndSet(null, newKeyPair)) + // Distribute it val proto = SignalServiceProtos.KeyPair.newBuilder() proto.publicKey = ByteString.copyFrom(newKeyPair.publicKey.serialize().removing05PrefixIfNeeded()) @@ -382,6 +369,7 @@ object ClosedGroupsProtocolV2 { job.onRun() // Run the job immediately // Store it * after * having sent out the message to the group apiDB.addClosedGroupEncryptionKeyPair(newKeyPair, groupPublicKey) + pendingKeyPair.set(null) } @JvmStatic