From f6455253a0da5ace44136d4ee05392e0b48fdecf Mon Sep 17 00:00:00 2001 From: Ryan ZHAO Date: Tue, 16 Feb 2021 10:28:24 +1100 Subject: [PATCH] send latest encryption key pair --- .../MessageReceiverHandler.kt | 14 +------- .../MessageSenderClosedGroup.kt | 35 +++++++++++++++---- 2 files changed, 29 insertions(+), 20 deletions(-) diff --git a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageReceiverHandler.kt b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageReceiverHandler.kt index cf37aa9347..96269fd0fe 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageReceiverHandler.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageReceiverHandler.kt @@ -492,19 +492,7 @@ private fun MessageReceiver.handleClosedGroupEncryptionKeyPairRequest(message: C return } if (!isValidGroupUpdate(group, message.sentTimestamp!!, senderPublicKey)) { return } - // Get the latest encryption key pair - val encryptionKeyPair = storage.getLatestClosedGroupEncryptionKeyPair(groupPublicKey) ?: return - // Send it - val proto = SignalServiceProtos.KeyPair.newBuilder() - proto.publicKey = ByteString.copyFrom(encryptionKeyPair.publicKey.serialize()) - proto.privateKey = ByteString.copyFrom(encryptionKeyPair.privateKey.serialize()) - val plaintext = proto.build().toByteArray() - val ciphertext = MessageSenderEncryption.encryptWithSessionProtocol(plaintext, senderPublicKey) - Log.d("Loki", "Responding to closed group encryption key pair request from: $senderPublicKey.") - val wrapper = ClosedGroupControlMessage.KeyPairWrapper(senderPublicKey, ByteString.copyFrom(ciphertext)) - val kind = ClosedGroupControlMessage.Kind.EncryptionKeyPair(ByteString.copyFrom(Hex.fromStringCondensed(groupPublicKey)), listOf(wrapper)) - val closedGroupControlMessage = ClosedGroupControlMessage(kind) - MessageSender.send(closedGroupControlMessage, Address.fromSerialized(senderPublicKey)) + MessageSender.sendLatestEncryptionKeyPair(senderPublicKey, groupPublicKey) } private fun isValidGroupUpdate(group: GroupRecord, diff --git a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageSenderClosedGroup.kt b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageSenderClosedGroup.kt index b883d6a922..8a1eae09a2 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageSenderClosedGroup.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageSenderClosedGroup.kt @@ -9,25 +9,23 @@ import nl.komponents.kovenant.deferred import org.session.libsession.messaging.MessagingConfiguration import org.session.libsession.messaging.messages.control.ClosedGroupControlMessage -import org.session.libsession.messaging.messages.control.ClosedGroupUpdate import org.session.libsession.messaging.sending_receiving.notifications.PushNotificationAPI import org.session.libsession.messaging.sending_receiving.MessageSender.Error import org.session.libsession.messaging.threads.Address -import org.session.libsession.messaging.threads.recipients.Recipient import org.session.libsession.utilities.GroupUtil -import org.session.libsession.utilities.TextSecurePreferences import org.session.libsignal.utilities.Hex import org.session.libsignal.libsignal.ecc.Curve +import org.session.libsignal.libsignal.ecc.ECKeyPair +import org.session.libsignal.libsignal.util.guava.Optional import org.session.libsignal.service.internal.push.SignalServiceProtos -import org.session.libsignal.service.loki.protocol.closedgroups.ClosedGroupRatchetCollectionType -import org.session.libsignal.service.loki.protocol.closedgroups.ClosedGroupSenderKey -import org.session.libsignal.service.loki.protocol.closedgroups.SharedSenderKeysImplementation -import org.session.libsignal.service.loki.utilities.hexEncodedPrivateKey import org.session.libsignal.service.loki.utilities.hexEncodedPublicKey import org.session.libsignal.service.loki.utilities.removing05PrefixIfNeeded import org.session.libsignal.utilities.ThreadUtils import java.util.* +import java.util.concurrent.ConcurrentHashMap + +private val pendingKeyPair = ConcurrentHashMap>() fun MessageSender.createClosedGroup(name: String, members: Collection): Promise { val deferred = deferred() @@ -226,6 +224,11 @@ fun MessageSender.generateAndSendNewEncryptionKeyPair(groupPublicKey: String, ta } // Generate the new encryption key pair val newKeyPair = Curve.generateKeyPair() + // replace call will not succeed if no value already set + pendingKeyPair.putIfAbsent(groupPublicKey,Optional.absent()) + do { + // make sure we set the pendingKeyPair or wait until it is not null + } while (!pendingKeyPair.replace(groupPublicKey,Optional.absent(),Optional.fromNullable(newKeyPair))) // Distribute it val proto = SignalServiceProtos.KeyPair.newBuilder() proto.publicKey = ByteString.copyFrom(newKeyPair.publicKey.serialize().removing05PrefixIfNeeded()) @@ -240,6 +243,7 @@ fun MessageSender.generateAndSendNewEncryptionKeyPair(groupPublicKey: String, ta sendNonDurably(closedGroupControlMessage, Address.fromSerialized(groupID)).success { // Store it * after * having sent out the message to the group storage.addClosedGroupEncryptionKeyPair(newKeyPair, groupPublicKey) + pendingKeyPair[groupPublicKey] = Optional.absent() } } @@ -270,4 +274,21 @@ fun MessageSender.sendLatestEncryptionKeyPair(publicKey: String, groupPublicKey: Log.d("Loki", "Refusing to send latest encryption key pair to non-member.") return } + // Get the latest encryption key pair + val encryptionKeyPair = if (pendingKeyPair[groupPublicKey] != null && pendingKeyPair[groupPublicKey]!!.isPresent) { + pendingKeyPair[groupPublicKey]!!.get() + } else { + storage.getLatestClosedGroupEncryptionKeyPair(groupPublicKey) + } ?: return + // Send it + val proto = SignalServiceProtos.KeyPair.newBuilder() + proto.publicKey = ByteString.copyFrom(encryptionKeyPair.publicKey.serialize()) + proto.privateKey = ByteString.copyFrom(encryptionKeyPair.privateKey.serialize()) + val plaintext = proto.build().toByteArray() + val ciphertext = MessageSenderEncryption.encryptWithSessionProtocol(plaintext, publicKey) + Log.d("Loki", "Sending latest encryption key pair to: $publicKey.") + val wrapper = ClosedGroupControlMessage.KeyPairWrapper(publicKey, ByteString.copyFrom(ciphertext)) + val kind = ClosedGroupControlMessage.Kind.EncryptionKeyPair(ByteString.copyFrom(Hex.fromStringCondensed(groupPublicKey)), listOf(wrapper)) + val closedGroupControlMessage = ClosedGroupControlMessage(kind) + MessageSender.send(closedGroupControlMessage, Address.fromSerialized(publicKey)) } \ No newline at end of file