This commit is contained in:
Niels Andriesse 2021-04-26 11:39:23 +10:00
parent 69f05dabdf
commit fdede1c656
25 changed files with 31 additions and 484 deletions

View File

@ -5,6 +5,7 @@ import android.text.TextUtils
import com.google.protobuf.ByteString
import org.greenrobot.eventbus.EventBus
import org.session.libsession.database.MessageDataProvider
import org.session.libsession.messaging.open_groups.OpenGroup
import org.session.libsession.messaging.sending_receiving.attachments.*
import org.session.libsession.messaging.threads.Address
import org.session.libsession.messaging.utilities.DotNetAPI
@ -26,7 +27,6 @@ import org.thoughtcrime.securesms.util.MediaUtil
import java.io.IOException
import java.io.InputStream
class DatabaseAttachmentProvider(context: Context, helper: SQLCipherOpenHelper) : Database(context, helper), MessageDataProvider {
override fun getAttachmentStream(attachmentId: Long): SessionServiceAttachmentStream? {
@ -104,6 +104,10 @@ class DatabaseAttachmentProvider(context: Context, helper: SQLCipherOpenHelper)
return smsDatabase.isOutgoingMessage(timestamp) || mmsDatabase.isOutgoingMessage(timestamp)
}
override fun getOpenGroup(threadID: Long): OpenGroup? {
return null // TODO: Implement
}
override fun updateAttachmentAfterUploadSucceeded(attachmentId: Long, attachmentStream: SignalServiceAttachmentStream, attachmentKey: ByteArray, uploadResult: DotNetAPI.UploadResult) {
val database = DatabaseFactory.getAttachmentDatabase(context)
val databaseAttachment = getDatabaseAttachment(attachmentId) ?: return

View File

@ -30,10 +30,10 @@ import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import org.session.libsession.messaging.jobs.JobQueue
import org.session.libsession.messaging.mentions.MentionsManager
import org.session.libsession.messaging.open_groups.OpenGroupAPI
import org.session.libsession.messaging.sending_receiving.MessageSender
import org.session.libsession.utilities.*
import org.session.libsignal.service.loki.utilities.mentions.MentionsManager
import org.session.libsignal.service.loki.utilities.toHexString
import org.session.libsignal.utilities.ThreadUtils
import org.thoughtcrime.securesms.ApplicationContext
@ -139,7 +139,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
val userDB = DatabaseFactory.getLokiUserDatabase(this)
val userPublicKey = TextSecurePreferences.getLocalNumber(this)
if (userPublicKey != null) {
MentionsManager.configureIfNeeded(userPublicKey, threadDB, userDB)
MentionsManager.configureIfNeeded(userPublicKey, userDB)
application.publicChatManager.startPollersIfNeeded()
JobQueue.shared.resumePendingJobs()
}

View File

@ -24,7 +24,7 @@ import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
import org.thoughtcrime.securesms.loki.utilities.*
import org.thoughtcrime.securesms.loki.views.GlowViewUtilities
import org.thoughtcrime.securesms.loki.views.PathDotView
import org.session.libsignal.service.loki.api.Snode
import org.session.libsignal.service.loki.Snode
class PathActivity : PassphraseRequiredActionBarActivity() {
private val broadcastReceivers = mutableListOf<BroadcastReceiver>()

View File

@ -7,7 +7,7 @@ import org.session.libsession.utilities.TextSecurePreferences
import org.session.libsignal.libsignal.ecc.DjbECPrivateKey
import org.session.libsignal.libsignal.ecc.DjbECPublicKey
import org.session.libsignal.libsignal.ecc.ECKeyPair
import org.session.libsignal.service.loki.api.Snode
import org.session.libsignal.service.loki.Snode
import org.session.libsignal.service.loki.database.LokiAPIDatabaseProtocol
import org.session.libsignal.service.loki.utilities.PublicKeyValidation
import org.session.libsignal.service.loki.utilities.removing05PrefixIfNeeded

View File

@ -1,5 +1,6 @@
package org.session.libsession.database
import org.session.libsession.messaging.open_groups.OpenGroup
import org.session.libsession.messaging.sending_receiving.attachments.*
import org.session.libsession.messaging.threads.Address
import org.session.libsession.messaging.utilities.DotNetAPI
@ -37,4 +38,5 @@ interface MessageDataProvider {
fun getAttachmentIDsFor(messageID: Long): List<Long>
fun getLinkPreviewAttachmentIDFor(messageID: Long): Long?
fun getOpenGroup(threadID: Long): OpenGroup?
}

View File

@ -1,19 +1,20 @@
package org.session.libsignal.service.loki.utilities.mentions
package org.session.libsession.messaging.mentions
import org.session.libsession.messaging.MessagingModuleConfiguration
import org.session.libsignal.service.loki.utilities.mentions.Mention
import org.session.libsignal.service.loki.database.LokiThreadDatabaseProtocol
import org.session.libsignal.service.loki.database.LokiUserDatabaseProtocol
class MentionsManager(private val userPublicKey: String, private val threadDatabase: LokiThreadDatabaseProtocol,
private val userDatabase: LokiUserDatabaseProtocol) {
class MentionsManager(private val userPublicKey: String, private val userDatabase: LokiUserDatabaseProtocol) {
var userPublicKeyCache = mutableMapOf<Long, Set<String>>() // Thread ID to set of user hex encoded public keys
companion object {
public lateinit var shared: MentionsManager
public fun configureIfNeeded(userPublicKey: String, threadDatabase: LokiThreadDatabaseProtocol, userDatabase: LokiUserDatabaseProtocol) {
public fun configureIfNeeded(userPublicKey: String, userDatabase: LokiUserDatabaseProtocol) {
if (::shared.isInitialized) { return; }
shared = MentionsManager(userPublicKey, threadDatabase, userDatabase)
shared = MentionsManager(userPublicKey, userDatabase)
}
}
@ -30,7 +31,7 @@ class MentionsManager(private val userPublicKey: String, private val threadDatab
// Prepare
val cache = userPublicKeyCache[threadID] ?: return listOf()
// Gather candidates
val publicChat = threadDatabase.getPublicChat(threadID)
val publicChat = MessagingModuleConfiguration.shared.messageDataProvider.getOpenGroup(threadID)
var candidates: List<Mention> = cache.mapNotNull { publicKey ->
val displayName: String?
if (publicChat != null) {

View File

@ -1,6 +1,5 @@
package org.session.libsession.messaging.open_groups
import org.session.libsignal.service.loki.api.opengroups.PublicChat
import org.session.libsignal.utilities.JsonUtil
data class OpenGroup(
@ -14,9 +13,6 @@ data class OpenGroup(
companion object {
@JvmStatic fun from(publicChat: PublicChat): OpenGroup =
OpenGroup(publicChat.channel, publicChat.server, publicChat.displayName, publicChat.isDeletable)
@JvmStatic fun getId(channel: Long, server: String): String {
return "$server.$channel"
}

View File

@ -8,7 +8,7 @@ import org.session.libsession.messaging.jobs.MessageReceiveJob
import org.session.libsession.messaging.utilities.MessageWrapper
import org.session.libsession.snode.SnodeAPI
import org.session.libsession.snode.SnodeModule
import org.session.libsignal.service.loki.api.Snode
import org.session.libsignal.service.loki.Snode
import org.session.libsignal.utilities.Base64
import org.session.libsignal.utilities.logging.Log
import java.security.SecureRandom

View File

@ -11,7 +11,7 @@ import org.session.libsession.utilities.AESGCM
import org.session.libsignal.utilities.logging.Log
import org.session.libsignal.utilities.Base64
import org.session.libsignal.utilities.*
import org.session.libsignal.service.loki.api.Snode
import org.session.libsignal.service.loki.Snode
import org.session.libsignal.service.loki.api.utilities.*
import org.session.libsession.utilities.AESGCM.EncryptionResult
import org.session.libsignal.utilities.ThreadUtils
@ -79,7 +79,7 @@ object OnionRequestAPI {
)
internal sealed class Destination {
class Snode(val snode: org.session.libsignal.service.loki.api.Snode) : Destination()
class Snode(val snode: org.session.libsignal.service.loki.Snode) : Destination()
class Server(val host: String, val target: String, val x25519PublicKey: String) : Destination()
}

View File

@ -7,7 +7,7 @@ import nl.komponents.kovenant.*
import nl.komponents.kovenant.functional.bind
import nl.komponents.kovenant.functional.map
import org.session.libsession.snode.utilities.getRandomElement
import org.session.libsignal.service.loki.api.Snode
import org.session.libsignal.service.loki.Snode
import org.session.libsignal.service.loki.api.utilities.HTTP
import org.session.libsignal.service.loki.database.LokiAPIDatabaseProtocol
import org.session.libsignal.service.loki.utilities.Broadcaster

View File

@ -1,5 +1,7 @@
package org.session.libsession.snode
import org.session.libsignal.service.loki.Snode
interface SnodeStorageProtocol {
fun getSnodePool(): Set<Snode>

View File

@ -10,7 +10,6 @@ import org.session.libsignal.libsignal.util.guava.Optional;
import org.session.libsignal.service.api.messages.shared.SharedContact;
import org.session.libsignal.service.api.push.SignalServiceAddress;
import org.session.libsignal.service.internal.push.SignalServiceProtos.DataMessage.ClosedGroupControlMessage;
import org.session.libsignal.service.loki.utilities.TTLUtilities;
import java.util.LinkedList;
import java.util.List;
@ -247,7 +246,7 @@ public class SignalServiceDataMessage {
}
public int getTTL() {
return TTLUtilities.getTTL(TTLUtilities.MessageType.Regular);
return 0;
}
public static class Builder {

View File

@ -1,8 +1,6 @@
package org.session.libsignal.service.api.messages;
import org.session.libsignal.service.loki.utilities.TTLUtilities;
import java.util.List;
public class SignalServiceReceiptMessage {
@ -41,5 +39,5 @@ public class SignalServiceReceiptMessage {
return type == Type.READ;
}
public int getTTL() { return TTLUtilities.getTTL(TTLUtilities.MessageType.Receipt); }
public int getTTL() { return 0; }
}

View File

@ -1,7 +1,5 @@
package org.session.libsignal.service.api.messages;
import org.session.libsignal.service.loki.utilities.TTLUtilities;
public class SignalServiceTypingMessage {
public enum Action {
@ -32,5 +30,5 @@ public class SignalServiceTypingMessage {
return action == Action.STOPPED;
}
public int getTTL() { return TTLUtilities.getTTL(TTLUtilities.MessageType.TypingIndicator); }
public int getTTL() { return 0; }
}

View File

@ -1,9 +1,9 @@
package org.session.libsession.snode
package org.session.libsignal.service.loki
class Snode(val address: String, val port: Int, val publicKeySet: KeySet?) {
val ip: String get() = address.removePrefix("https://")
internal enum class Method(val rawValue: String) {
public enum class Method(val rawValue: String) {
GetSwarm("get_snodes_for_pubkey"),
GetMessages("retrieve"),
SendMessage("store")

View File

@ -1,84 +0,0 @@
package org.session.libsignal.service.loki.api
import com.google.protobuf.ByteString
import org.session.libsignal.utilities.logging.Log
import org.session.libsignal.service.internal.push.SignalServiceProtos.Envelope
import org.session.libsignal.utilities.Base64
import org.session.libsignal.service.internal.websocket.WebSocketProtos.WebSocketMessage
import org.session.libsignal.service.internal.websocket.WebSocketProtos.WebSocketRequestMessage
import java.security.SecureRandom
object MessageWrapper {
// region Types
sealed class Error(val description: String) : Exception() {
object FailedToWrapData : Error("Failed to wrap data.")
object FailedToWrapMessageInEnvelope : Error("Failed to wrap message in envelope.")
object FailedToWrapEnvelopeInWebSocketMessage : Error("Failed to wrap envelope in web socket message.")
object FailedToUnwrapData : Error("Failed to unwrap data.")
}
// endregion
// region Wrapping
/**
* Wraps `message` in a `SignalServiceProtos.Envelope` and then a `WebSocketProtos.WebSocketMessage` to match the desktop application.
*/
fun wrap(message: SignalMessageInfo): ByteArray {
try {
val envelope = createEnvelope(message)
val webSocketMessage = createWebSocketMessage(envelope)
return webSocketMessage.toByteArray()
} catch (e: Exception) {
throw if (e is Error) { e } else { Error.FailedToWrapData }
}
}
private fun createEnvelope(message: SignalMessageInfo): Envelope {
try {
val builder = Envelope.newBuilder()
builder.type = message.type
builder.timestamp = message.timestamp
builder.source = message.senderPublicKey
builder.sourceDevice = message.senderDeviceID
builder.content = ByteString.copyFrom(Base64.decode(message.content))
return builder.build()
} catch (e: Exception) {
Log.d("Loki", "Failed to wrap message in envelope: ${e.message}.")
throw Error.FailedToWrapMessageInEnvelope
}
}
private fun createWebSocketMessage(envelope: Envelope): WebSocketMessage {
try {
val requestBuilder = WebSocketRequestMessage.newBuilder()
requestBuilder.verb = "PUT"
requestBuilder.path = "/api/v1/message"
requestBuilder.id = SecureRandom.getInstance("SHA1PRNG").nextLong()
requestBuilder.body = envelope.toByteString()
val messageBuilder = WebSocketMessage.newBuilder()
messageBuilder.request = requestBuilder.build()
messageBuilder.type = WebSocketMessage.Type.REQUEST
return messageBuilder.build()
} catch (e: Exception) {
Log.d("Loki", "Failed to wrap envelope in web socket message: ${e.message}.")
throw Error.FailedToWrapEnvelopeInWebSocketMessage
}
}
// endregion
// region Unwrapping
/**
* `data` shouldn't be base 64 encoded.
*/
fun unwrap(data: ByteArray): Envelope {
try {
val webSocketMessage = WebSocketMessage.parseFrom(data)
val envelopeAsData = webSocketMessage.request.body
return Envelope.parseFrom(envelopeAsData)
} catch (e: Exception) {
Log.d("Loki", "Failed to unwrap data: ${e.message}.")
throw Error.FailedToUnwrapData
}
}
// endregion
}

View File

@ -1,34 +0,0 @@
package org.session.libsignal.service.loki.api
public class Snode(val address: String, val port: Int, val publicKeySet: KeySet?) {
val ip: String get() = address.removePrefix("https://")
enum class Method(val rawValue: String) {
/**
* Only supported by snode targets.
*/
GetSwarm("get_snodes_for_pubkey"),
/**
* Only supported by snode targets.
*/
GetMessages("retrieve"),
SendMessage("store")
}
data class KeySet(val ed25519Key: String, val x25519Key: String)
override fun equals(other: Any?): Boolean {
return if (other is Snode) {
address == other.address && port == other.port
} else {
false
}
}
override fun hashCode(): Int {
return address.hashCode() xor port.hashCode()
}
override fun toString(): String { return "$address:$port" }
}

View File

@ -1,37 +0,0 @@
package org.session.libsignal.service.loki.api.opengroups
import org.session.libsignal.utilities.JsonUtil
public data class PublicChat(
public val channel: Long,
private val serverURL: String,
public val displayName: String,
public val isDeletable: Boolean
) {
public val server get() = serverURL.toLowerCase()
public val id get() = getId(channel, server)
companion object {
@JvmStatic fun getId(channel: Long, server: String): String {
return "$server.$channel"
}
@JvmStatic fun fromJSON(jsonAsString: String): PublicChat? {
try {
val json = JsonUtil.fromJson(jsonAsString)
val channel = json.get("channel").asLong()
val server = json.get("server").asText().toLowerCase()
val displayName = json.get("displayName").asText()
val isDeletable = json.get("isDeletable").asBoolean()
return PublicChat(channel, server, displayName, isDeletable)
} catch (e: Exception) {
return null
}
}
}
public fun toJSON(): Map<String, Any> {
return mapOf( "channel" to channel, "server" to server, "displayName" to displayName, "isDeletable" to isDeletable )
}
}

View File

@ -1,7 +0,0 @@
package org.session.libsignal.service.loki.api.opengroups
public data class PublicChatInfo (
public val displayName: String,
public val profilePictureURL: String,
public val memberCount: Int
)

View File

@ -1,178 +0,0 @@
package org.session.libsignal.service.loki.api.opengroups
import org.whispersystems.curve25519.Curve25519
import org.session.libsignal.utilities.logging.Log
import org.session.libsignal.utilities.Hex
import org.session.libsignal.service.loki.utilities.removing05PrefixIfNeeded
public data class PublicChatMessage(
public val serverID: Long?,
public val senderPublicKey: String,
public val displayName: String,
public val body: String,
public val timestamp: Long,
public val type: String,
public val quote: Quote?,
public val attachments: List<Attachment>,
public val profilePicture: ProfilePicture?,
public val signature: Signature?,
public val serverTimestamp: Long
) {
// region Settings
companion object {
private val curve = Curve25519.getInstance(Curve25519.BEST)
private val signatureVersion: Long = 1
private val attachmentType = "net.app.core.oembed"
}
// endregion
// region Types
public data class ProfilePicture(
public val profileKey: ByteArray,
public val url: String
)
public data class Quote(
public val quotedMessageTimestamp: Long,
public val quoteePublicKey: String,
public val quotedMessageBody: String,
public val quotedMessageServerID: Long? = null
)
public data class Signature(
public val data: ByteArray,
public val version: Long
)
public data class Attachment(
public val kind: Kind,
public val server: String,
public val serverID: Long,
public val contentType: String,
public val size: Int,
public val fileName: String,
public val flags: Int,
public val width: Int,
public val height: Int,
public val caption: String?,
public val url: String,
/**
Guaranteed to be non-`nil` if `kind` is `LinkPreview`.
*/
public val linkPreviewURL: String?,
/**
Guaranteed to be non-`nil` if `kind` is `LinkPreview`.
*/
public val linkPreviewTitle: String?
) {
public val dotNetAPIType = when {
contentType.startsWith("image") -> "photo"
contentType.startsWith("video") -> "video"
contentType.startsWith("audio") -> "audio"
else -> "other"
}
public enum class Kind(val rawValue: String) {
Attachment("attachment"), LinkPreview("preview")
}
}
// endregion
// region Initialization
constructor(hexEncodedPublicKey: String, displayName: String, body: String, timestamp: Long, type: String, quote: Quote?, attachments: List<Attachment>)
: this(null, hexEncodedPublicKey, displayName, body, timestamp, type, quote, attachments, null, null, 0)
// endregion
// region Crypto
internal fun sign(privateKey: ByteArray): PublicChatMessage? {
val data = getValidationData(signatureVersion)
if (data == null) {
Log.d("Loki", "Failed to sign public chat message.")
return null
}
try {
val signatureData = curve.calculateSignature(privateKey, data)
val signature = Signature(signatureData, signatureVersion)
return copy(signature = signature)
} catch (e: Exception) {
Log.d("Loki", "Failed to sign public chat message due to error: ${e.message}.")
return null
}
}
internal fun hasValidSignature(): Boolean {
if (signature == null) { return false }
val data = getValidationData(signature.version) ?: return false
val publicKey = Hex.fromStringCondensed(senderPublicKey.removing05PrefixIfNeeded())
try {
return curve.verifySignature(publicKey, data, signature.data)
} catch (e: Exception) {
Log.d("Loki", "Failed to verify public chat message due to error: ${e.message}.")
return false
}
}
// endregion
// region Parsing
internal fun toJSON(): Map<String, Any> {
val value = mutableMapOf<String, Any>( "timestamp" to timestamp )
if (quote != null) {
value["quote"] = mapOf( "id" to quote.quotedMessageTimestamp, "author" to quote.quoteePublicKey, "text" to quote.quotedMessageBody )
}
if (signature != null) {
value["sig"] = Hex.toStringCondensed(signature.data)
value["sigver"] = signature.version
}
val annotation = mapOf( "type" to type, "value" to value )
val annotations = mutableListOf( annotation )
attachments.forEach { attachment ->
val attachmentValue = mutableMapOf(
// Fields required by the .NET API
"version" to 1,
"type" to attachment.dotNetAPIType,
// Custom fields
"lokiType" to attachment.kind.rawValue,
"server" to attachment.server,
"id" to attachment.serverID,
"contentType" to attachment.contentType,
"size" to attachment.size,
"fileName" to attachment.fileName,
"flags" to attachment.flags,
"width" to attachment.width,
"height" to attachment.height,
"url" to attachment.url
)
if (attachment.caption != null) { attachmentValue["caption"] = attachment.caption }
if (attachment.linkPreviewURL != null) { attachmentValue["linkPreviewUrl"] = attachment.linkPreviewURL }
if (attachment.linkPreviewTitle != null) { attachmentValue["linkPreviewTitle"] = attachment.linkPreviewTitle }
val attachmentAnnotation = mapOf( "type" to attachmentType, "value" to attachmentValue )
annotations.add(attachmentAnnotation)
}
val result = mutableMapOf( "text" to body, "annotations" to annotations )
if (quote?.quotedMessageServerID != null) {
result["reply_to"] = quote.quotedMessageServerID
}
return result
}
// endregion
// region Convenience
private fun getValidationData(signatureVersion: Long): ByteArray? {
var string = "${body.trim()}$timestamp"
if (quote != null) {
string += "${quote.quotedMessageTimestamp}${quote.quoteePublicKey}${quote.quotedMessageBody.trim()}"
if (quote.quotedMessageServerID != null) {
string += "${quote.quotedMessageServerID}"
}
}
string += attachments.sortedBy { it.serverID }.map { it.serverID }.joinToString("")
string += "$signatureVersion"
try {
return string.toByteArray(Charsets.UTF_8)
} catch (exception: Exception) {
return null
}
}
// endregion
}

View File

@ -1,19 +0,0 @@
package org.session.libsignal.service.loki.api.utilities
import javax.crypto.Cipher
import javax.crypto.spec.GCMParameterSpec
import javax.crypto.spec.SecretKeySpec
internal object DecryptionUtilities {
/**
* Sync. Don't call from the main thread.
*/
internal fun decryptUsingAESGCM(ivAndCiphertext: ByteArray, symmetricKey: ByteArray): ByteArray {
val iv = ivAndCiphertext.sliceArray(0 until EncryptionUtilities.ivSize)
val ciphertext = ivAndCiphertext.sliceArray(EncryptionUtilities.ivSize until ivAndCiphertext.count())
val cipher = Cipher.getInstance("AES/GCM/NoPadding")
cipher.init(Cipher.DECRYPT_MODE, SecretKeySpec(symmetricKey, "AES"), GCMParameterSpec(EncryptionUtilities.gcmTagSize, iv))
return cipher.doFinal(ciphertext)
}
}

View File

@ -1,45 +0,0 @@
package org.session.libsignal.service.loki.api.utilities
import org.whispersystems.curve25519.Curve25519
import org.session.libsignal.libsignal.util.ByteUtil
import org.session.libsignal.utilities.Hex
import org.session.libsignal.service.internal.util.Util
import javax.crypto.Cipher
import javax.crypto.Mac
import javax.crypto.spec.GCMParameterSpec
import javax.crypto.spec.SecretKeySpec
internal data class EncryptionResult(
internal val ciphertext: ByteArray,
internal val symmetricKey: ByteArray,
internal val ephemeralPublicKey: ByteArray
)
internal object EncryptionUtilities {
internal val gcmTagSize = 128
internal val ivSize = 12
/**
* Sync. Don't call from the main thread.
*/
internal fun encryptUsingAESGCM(plaintext: ByteArray, symmetricKey: ByteArray): ByteArray {
val iv = Util.getSecretBytes(ivSize)
val cipher = Cipher.getInstance("AES/GCM/NoPadding")
cipher.init(Cipher.ENCRYPT_MODE, SecretKeySpec(symmetricKey, "AES"), GCMParameterSpec(gcmTagSize, iv))
return ByteUtil.combine(iv, cipher.doFinal(plaintext))
}
/**
* Sync. Don't call from the main thread.
*/
internal fun encryptForX25519PublicKey(plaintext: ByteArray, hexEncodedX25519PublicKey: String): EncryptionResult {
val x25519PublicKey = Hex.fromStringCondensed(hexEncodedX25519PublicKey)
val ephemeralKeyPair = Curve25519.getInstance(Curve25519.BEST).generateKeyPair()
val ephemeralSharedSecret = Curve25519.getInstance(Curve25519.BEST).calculateAgreement(x25519PublicKey, ephemeralKeyPair.privateKey)
val mac = Mac.getInstance("HmacSHA256")
mac.init(SecretKeySpec("LOKI".toByteArray(), "HmacSHA256"))
val symmetricKey = mac.doFinal(ephemeralSharedSecret)
val ciphertext = encryptUsingAESGCM(plaintext, symmetricKey)
return EncryptionResult(ciphertext, symmetricKey, ephemeralKeyPair.publicKey)
}
}

View File

@ -1,7 +1,7 @@
package org.session.libsignal.service.loki.database
import org.session.libsignal.libsignal.ecc.ECKeyPair
import org.session.libsignal.service.loki.api.Snode
import org.session.libsignal.service.loki.Snode
import java.util.*
interface LokiAPIDatabaseProtocol {

View File

@ -1,11 +0,0 @@
package org.session.libsignal.service.loki.database
import org.session.libsignal.service.loki.api.opengroups.PublicChat
interface LokiThreadDatabaseProtocol {
fun getThreadID(publicKey: String): Long
fun getPublicChat(threadID: Long): PublicChat?
fun setPublicChat(publicChat: PublicChat, threadID: Long)
fun removePublicChat(threadID: Long)
}

View File

@ -1,38 +0,0 @@
package org.session.libsignal.service.loki.utilities
public object TTLUtilities {
/**
* If a message type specifies an invalid TTL, this will be used.
*/
public val fallbackMessageTTL = 2 * 24 * 60 * 60 * 1000
public enum class MessageType {
// Unimportant control messages
Address, Call, TypingIndicator, Verified,
// Somewhat important control messages
DeviceLink,
// Important control messages
ClosedGroupUpdate, Ephemeral, SessionRequest, Receipt, Sync, DeviceUnlinkingRequest,
// Visible messages
Regular
}
@JvmStatic
public fun getTTL(messageType: MessageType): Int {
val minuteInMs = 60 * 1000
val hourInMs = 60 * minuteInMs
val dayInMs = 24 * hourInMs
return when (messageType) {
// Unimportant control messages
MessageType.Address, MessageType.Call, MessageType.TypingIndicator, MessageType.Verified -> 20 * 1000
// Somewhat important control messages
MessageType.DeviceLink -> 1 * hourInMs
// Important control messages
MessageType.ClosedGroupUpdate, MessageType.Ephemeral, MessageType.SessionRequest, MessageType.Receipt,
MessageType.Sync, MessageType.DeviceUnlinkingRequest -> 2 * dayInMs - 1 * hourInMs
// Visible messages
MessageType.Regular -> 2 * dayInMs
}
}
}