mirror of
https://github.com/oxen-io/session-android.git
synced 2025-12-31 13:06:09 +00:00
feat: add finishing of group push for initial group creation and saving group configs to DB. re-implement key signing messages properly for the signing config which doesn't override the config base
This commit is contained in:
@@ -33,6 +33,7 @@ import org.session.libsignal.crypto.ecc.ECKeyPair
|
||||
import org.session.libsignal.messages.SignalServiceAttachmentPointer
|
||||
import org.session.libsignal.messages.SignalServiceGroup
|
||||
import org.session.libsignal.utilities.SessionId
|
||||
import org.session.libsignal.utilities.guava.Optional
|
||||
import network.loki.messenger.libsession_util.util.Contact as LibSessionContact
|
||||
|
||||
interface StorageProtocol {
|
||||
@@ -155,7 +156,7 @@ interface StorageProtocol {
|
||||
fun setExpirationTimer(address: String, duration: Int)
|
||||
|
||||
// Closed Groups
|
||||
suspend fun createNewGroup(groupName: String, groupDescription: String, members: Set<SessionId>): Long?
|
||||
fun createNewGroup(groupName: String, groupDescription: String, members: Set<SessionId>): Optional<Boolean>
|
||||
fun getMembers(groupPublicKey: String): List<network.loki.messenger.libsession_util.util.GroupMember>
|
||||
|
||||
// Groups
|
||||
|
||||
@@ -69,7 +69,6 @@ data class ConfigurationSyncJob(val destination: Destination): Job {
|
||||
// return a list of batch request objects
|
||||
val snodeMessage = MessageSender.buildWrappedMessageToSnode(destination, message, true)
|
||||
val authenticated = SnodeAPI.buildAuthenticatedStoreBatchInfo(
|
||||
destination.destinationPublicKey(),
|
||||
config.configNamespace(),
|
||||
snodeMessage
|
||||
) ?: return@map null // this entry will be null otherwise
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package org.session.libsession.messaging.sending_receiving
|
||||
|
||||
import androidx.annotation.WorkerThread
|
||||
import network.loki.messenger.libsession_util.ConfigBase
|
||||
import nl.komponents.kovenant.Promise
|
||||
import nl.komponents.kovenant.deferred
|
||||
import org.session.libsession.messaging.MessagingModuleConfiguration
|
||||
@@ -73,25 +71,6 @@ object MessageSender {
|
||||
}
|
||||
}
|
||||
|
||||
// New closed groups and configs not requiring additional overhead (already handled by libsession)
|
||||
@WorkerThread
|
||||
fun sendConfig(destination: Destination, config: ConfigBase, signingKey: ByteArray): Result<String> {
|
||||
if (destination !is Destination.ClosedGroup) return Result.failure(Error.InvalidDestination(destination))
|
||||
|
||||
val (bytes, _) = config.push()
|
||||
|
||||
val testTtl = 30 * 24 * 60 * 60 * 1000L // 30 days
|
||||
|
||||
// handle this error thrown case
|
||||
val response = SnodeAPI.sendMessage(destination, bytes, testTtl, signingKey, config.configNamespace())
|
||||
|
||||
Log.d("Send Config", "Response is good")
|
||||
|
||||
val hash = response["hash"] as? String ?: return Result.failure(Error("No returned hash of string type"))
|
||||
|
||||
return Result.success(hash)
|
||||
}
|
||||
|
||||
// One-on-One Chats & Closed Groups
|
||||
@Throws(Exception::class)
|
||||
fun buildWrappedMessageToSnode(destination: Destination, message: Message, isSyncMessage: Boolean): SnodeMessage {
|
||||
|
||||
@@ -19,8 +19,6 @@ import nl.komponents.kovenant.functional.bind
|
||||
import nl.komponents.kovenant.functional.map
|
||||
import nl.komponents.kovenant.task
|
||||
import org.session.libsession.messaging.MessagingModuleConfiguration
|
||||
import org.session.libsession.messaging.messages.Destination
|
||||
import org.session.libsession.messaging.sending_receiving.MessageSender
|
||||
import org.session.libsession.messaging.utilities.MessageWrapper
|
||||
import org.session.libsignal.crypto.getRandomElement
|
||||
import org.session.libsignal.database.LokiAPIDatabaseProtocol
|
||||
@@ -219,7 +217,7 @@ object SnodeAPI {
|
||||
}
|
||||
}
|
||||
|
||||
internal fun getSingleTargetSnode(publicKey: String): Promise<Snode, Exception> {
|
||||
fun getSingleTargetSnode(publicKey: String): Promise<Snode, Exception> {
|
||||
// SecureRandom() should be cryptographically secure
|
||||
return getSwarm(publicKey).map { it.shuffled(SecureRandom()).random() }
|
||||
}
|
||||
@@ -374,7 +372,7 @@ object SnodeAPI {
|
||||
return invoke(Snode.Method.Retrieve, snode, parameters, publicKey)
|
||||
}
|
||||
|
||||
fun buildAuthenticatedStoreBatchInfo(publicKey: String, namespace: Int, message: SnodeMessage): SnodeBatchRequestInfo? {
|
||||
fun buildAuthenticatedStoreBatchInfo(namespace: Int, message: SnodeMessage, signingKey: ByteArray, ed25519PubKey: String? = null): SnodeBatchRequestInfo {
|
||||
val params = mutableMapOf<String, Any>()
|
||||
// load the message data params into the sub request
|
||||
// currently loads:
|
||||
@@ -388,13 +386,6 @@ object SnodeAPI {
|
||||
// used for sig generation since it is also the value used in timestamp parameter
|
||||
val messageTimestamp = message.timestamp
|
||||
|
||||
val userEd25519KeyPair = try {
|
||||
MessagingModuleConfiguration.shared.getUserED25519KeyPair() ?: return null
|
||||
} catch (e: Exception) {
|
||||
return null
|
||||
}
|
||||
|
||||
val ed25519PublicKey = userEd25519KeyPair.publicKey.asHexString
|
||||
val signature = ByteArray(Sign.BYTES)
|
||||
val verificationData = "store$namespace$messageTimestamp".toByteArray()
|
||||
try {
|
||||
@@ -402,13 +393,15 @@ object SnodeAPI {
|
||||
signature,
|
||||
verificationData,
|
||||
verificationData.size.toLong(),
|
||||
userEd25519KeyPair.secretKey.asBytes
|
||||
signingKey
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
Log.e("Loki", "Signing data failed with user secret key", e)
|
||||
}
|
||||
// timestamp already set
|
||||
params["pubkey_ed25519"] = ed25519PublicKey
|
||||
if (ed25519PubKey != null) {
|
||||
params["pubkey_ed25519"] = ed25519PubKey
|
||||
}
|
||||
params["signature"] = Base64.encodeBytes(signature)
|
||||
return SnodeBatchRequestInfo(
|
||||
Snode.Method.SendMessage.rawValue,
|
||||
@@ -417,6 +410,16 @@ object SnodeAPI {
|
||||
)
|
||||
}
|
||||
|
||||
fun buildAuthenticatedStoreBatchInfo(namespace: Int, message: SnodeMessage): SnodeBatchRequestInfo? {
|
||||
val userEd25519KeyPair = try {
|
||||
MessagingModuleConfiguration.shared.getUserED25519KeyPair() ?: return null
|
||||
} catch (e: Exception) {
|
||||
return null
|
||||
}
|
||||
val ed25519PublicKey = userEd25519KeyPair.publicKey.asHexString
|
||||
return buildAuthenticatedStoreBatchInfo(namespace, message, userEd25519KeyPair.secretKey.asBytes, ed25519PublicKey)
|
||||
}
|
||||
|
||||
/**
|
||||
* Message hashes can be shared across multiple namespaces (for a single public key destination)
|
||||
* @param publicKey the destination's identity public key to delete from (05...)
|
||||
@@ -634,11 +637,8 @@ object SnodeAPI {
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun sendMessage(destination: Destination, rawMessage: ByteArray, ttl: Long, signingKey: ByteArray, namespace: Int): RawResponse {
|
||||
val pubKey = when (destination) {
|
||||
is Destination.ClosedGroup -> destination.publicKey
|
||||
else -> throw MessageSender.Error.InvalidDestination(destination)
|
||||
}
|
||||
fun sendAuthenticatedMessage(message: SnodeMessage, signingKey: ByteArray, namespace: Int): RawResponse {
|
||||
val pubKey = message.recipient
|
||||
|
||||
return retryIfNeeded(maxRetryCount) {
|
||||
val timestamp = nowWithOffset
|
||||
@@ -654,8 +654,7 @@ object SnodeAPI {
|
||||
|
||||
val parameters = mapOf(
|
||||
"pubKey" to pubKey,
|
||||
"data" to Base64.encodeBytes(rawMessage),
|
||||
"ttl" to ttl.toString(),
|
||||
"data" to message.data,
|
||||
"timestamp" to timestamp.toString(),
|
||||
"sig_timestamp" to timestamp.toString(),
|
||||
"signature" to Base64.encodeBytes(verificationData)
|
||||
|
||||
@@ -25,6 +25,11 @@ interface ConfigFactoryProtocol {
|
||||
|
||||
fun conversationInConfig(publicKey: String?, groupPublicKey: String?, openGroupId: String?, visibleOnly: Boolean): Boolean
|
||||
fun canPerformChange(variant: String, publicKey: String, changeTimestampMs: Long): Boolean
|
||||
fun saveGroupConfigs(
|
||||
groupKeys: GroupKeysConfig,
|
||||
groupInfo: GroupInfoConfig,
|
||||
groupMembers: GroupMembersConfig
|
||||
)
|
||||
}
|
||||
|
||||
interface ConfigFactoryUpdateListener {
|
||||
|
||||
Reference in New Issue
Block a user