feat(WIP): build an authenticated delete with sign callback

This commit is contained in:
0x330a 2023-10-27 16:45:44 +11:00
parent 2fc83b87ad
commit b62cca2612
No known key found for this signature in database
GPG Key ID: 267811D6E6A2698C
5 changed files with 30 additions and 22 deletions

View File

@ -1,5 +1,6 @@
package org.thoughtcrime.securesms.dependencies
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.plus
@ -8,6 +9,7 @@ import org.session.libsignal.utilities.SessionId
import java.util.concurrent.ConcurrentHashMap
class PollerFactory(private val scope: CoroutineScope,
private val executor: CoroutineDispatcher,
private val configFactory: ConfigFactory) {
private val pollers = ConcurrentHashMap<SessionId, ClosedGroupPoller>()
@ -17,7 +19,7 @@ class PollerFactory(private val scope: CoroutineScope,
configFactory.userGroups?.getClosedGroup(sessionId.hexString()) ?: return null
return pollers.getOrPut(sessionId) {
ClosedGroupPoller(scope + SupervisorJob(), sessionId, configFactory)
ClosedGroupPoller(scope + SupervisorJob(), executor, sessionId, configFactory)
}
}

View File

@ -6,7 +6,10 @@ import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.GlobalScope
import org.session.libsession.utilities.ConfigFactoryUpdateListener
import org.session.libsession.utilities.TextSecurePreferences
@ -42,9 +45,15 @@ object SessionUtilModule {
@Named(POLLER_SCOPE)
fun providePollerScope(@ApplicationContext applicationContext: Context): CoroutineScope = GlobalScope
@OptIn(ExperimentalCoroutinesApi::class)
@Provides
@Named(POLLER_SCOPE)
fun provideExecutor(): CoroutineDispatcher = Dispatchers.IO.limitedParallelism(1)
@Provides
@Singleton
fun providePollerFactory(@Named(POLLER_SCOPE) coroutineScope: CoroutineScope,
configFactory: ConfigFactory) = PollerFactory(coroutineScope, configFactory)
@Named(POLLER_SCOPE) dispatcher: CoroutineDispatcher,
configFactory: ConfigFactory) = PollerFactory(coroutineScope, dispatcher, configFactory)
}

View File

@ -84,7 +84,7 @@ data class ConfigurationSyncJob(val destination: Destination) : Job {
if (config is GroupKeysConfig) {
config.messageInformation(destination.publicKey, signingKey)
} else if (config is ConfigBase) {
config.messageInformation(toDelete, destination.publicKey, signingKey, groupId.publicKey)
config.messageInformation(toDelete, destination.publicKey, signingKey)
} else {
Log.e("ConfigurationSyncJob", "Tried to create a message from an unknown config")
null

View File

@ -1,7 +1,7 @@
package org.session.libsession.messaging.sending_receiving.pollers
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
@ -26,7 +26,8 @@ import org.session.libsignal.utilities.SessionId
import org.session.libsignal.utilities.Snode
import kotlin.time.Duration.Companion.days
class ClosedGroupPoller(private val executor: CoroutineScope,
class ClosedGroupPoller(private val scope: CoroutineScope,
private val execute: CoroutineDispatcher,
private val closedGroupSessionId: SessionId,
private val configFactoryProtocol: ConfigFactoryProtocol) {
@ -69,7 +70,7 @@ class ClosedGroupPoller(private val executor: CoroutineScope,
if (ENABLE_LOGGING) Log.d("ClosedGroupPoller", "Starting closed group poller for ${closedGroupSessionId.hexString().take(4)}")
job?.cancel()
job = executor.launch(Dispatchers.IO) {
job = scope.launch {
val closedGroups = configFactoryProtocol.userGroups ?: return@launch
isRunning = true
while (isActive && isRunning) {
@ -105,6 +106,8 @@ class ClosedGroupPoller(private val executor: CoroutineScope,
free = false
) ?: return null
val isAdmin = group.hasAdminKey()
val hashesToExtend = mutableSetOf<String>()
hashesToExtend += info.currentHashes()
@ -152,7 +155,7 @@ class ClosedGroupPoller(private val executor: CoroutineScope,
val requests = mutableListOf(keysPoll, infoPoll, membersPoll, messagePoll)
if (hashesToExtend.isNotEmpty()) {
if (isAdmin && hashesToExtend.isNotEmpty()) {
SnodeAPI.buildAuthenticatedAlterTtlBatchRequest(
messageHashes = hashesToExtend.toList(),
publicKey = closedGroupSessionId.hexString(),

View File

@ -439,21 +439,7 @@ object SnodeAPI {
return null
}
val ed25519PublicKey = userEd25519KeyPair.publicKey.asHexString
val signature = ByteArray(Sign.BYTES)
val verificationData = "delete${messageHashes.joinToString("")}".toByteArray()
try {
sodium.cryptoSignDetached(
signature,
verificationData,
verificationData.size.toLong(),
userEd25519KeyPair.secretKey.asBytes
)
} catch (e: Exception) {
Log.e("Loki", "Signing data failed with user secret key", e)
return null
}
params["pubkey_ed25519"] = ed25519PublicKey
params["signature"] = Base64.encodeBytes(signature)
val signCallback = signingKeyCallback(userEd25519KeyPair.secretKey.asBytes)
return SnodeBatchRequestInfo(
Snode.Method.DeleteMessage.rawValue,
params,
@ -461,6 +447,14 @@ object SnodeAPI {
)
}
fun buildAuthenticatedDeleteBatchInfo(
publicKey: String,
messageHashes: List<String>,
signCallback: SignCallback,
required: Boolean = false): SnodeBatchRequestInfo? {
val verificationData = "delete${messageHashes.joinToString("")}".toByteArray()
}
fun buildAuthenticatedRetrieveBatchRequest(snode: Snode,
publicKey: String,
namespace: Int,