-
Notifications
You must be signed in to change notification settings - Fork 32
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
✨ Support for encrypted file transfer (#1268)
- Loading branch information
1 parent
bc9553d
commit e61a10f
Showing
22 changed files
with
645 additions
and
201 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
12 changes: 9 additions & 3 deletions
12
composeApp/src/commonMain/kotlin/com/clipevery/net/clientapi/SyncClientApi.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
17 changes: 17 additions & 0 deletions
17
composeApp/src/commonMain/kotlin/com/clipevery/signal/SignalMessageProcessor.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package com.clipevery.signal | ||
|
||
import org.signal.libsignal.protocol.SignalProtocolAddress | ||
import org.signal.libsignal.protocol.message.CiphertextMessage | ||
import org.signal.libsignal.protocol.message.PreKeySignalMessage | ||
import org.signal.libsignal.protocol.message.SignalMessage | ||
|
||
interface SignalMessageProcessor { | ||
|
||
val signalProtocolAddress: SignalProtocolAddress | ||
|
||
suspend fun encrypt(data: ByteArray): CiphertextMessage | ||
|
||
suspend fun decrypt(signalMessage: SignalMessage): ByteArray | ||
|
||
suspend fun decrypt(preKeySignalMessage: PreKeySignalMessage): ByteArray | ||
} |
8 changes: 8 additions & 0 deletions
8
composeApp/src/commonMain/kotlin/com/clipevery/signal/SignalProcessorCache.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package com.clipevery.signal | ||
|
||
interface SignalProcessorCache { | ||
|
||
fun getSignalMessageProcessor(appInstanceId: String): SignalMessageProcessor | ||
|
||
fun removeSignalMessageProcessor(appInstanceId: String) | ||
} |
4 changes: 2 additions & 2 deletions
4
composeApp/src/commonMain/kotlin/com/clipevery/sync/SyncHandler.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
93 changes: 93 additions & 0 deletions
93
composeApp/src/desktopMain/kotlin/com/clipevery/net/plugin/SignalClientDecryptPlugin.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
package com.clipevery.net.plugin | ||
|
||
import com.clipevery.signal.SignalProcessorCache | ||
import io.github.oshai.kotlinlogging.KLogger | ||
import io.github.oshai.kotlinlogging.KotlinLogging | ||
import io.ktor.client.* | ||
import io.ktor.client.plugins.* | ||
import io.ktor.client.request.* | ||
import io.ktor.client.statement.* | ||
import io.ktor.http.* | ||
import io.ktor.util.* | ||
import io.ktor.utils.io.* | ||
import io.ktor.utils.io.core.* | ||
import org.signal.libsignal.protocol.message.SignalMessage | ||
import java.io.ByteArrayOutputStream | ||
|
||
class SignalClientDecryptPlugin(private val signalProcessorCache: SignalProcessorCache) : | ||
HttpClientPlugin<SignalConfig, SignalClientDecryptPlugin> { | ||
|
||
private val logger: KLogger = KotlinLogging.logger {} | ||
|
||
override val key = AttributeKey<SignalClientDecryptPlugin>("SignalClientDecryptPlugin") | ||
|
||
override fun prepare(block: SignalConfig.() -> Unit): SignalClientDecryptPlugin { | ||
return this | ||
} | ||
|
||
@OptIn(InternalAPI::class) | ||
override fun install( | ||
plugin: SignalClientDecryptPlugin, | ||
scope: HttpClient, | ||
) { | ||
scope.receivePipeline.intercept(HttpReceivePipeline.Before) { | ||
val headers = it.call.request.headers | ||
headers["targetAppInstanceId"]?.let { appInstanceId -> | ||
headers["signal"]?.let { signal -> | ||
if (signal == "1") { | ||
logger.debug { "signal client decrypt $appInstanceId" } | ||
val byteReadChannel: ByteReadChannel = it.content | ||
|
||
val contentType = it.call.response.contentType() | ||
|
||
val processor = signalProcessorCache.getSignalMessageProcessor(appInstanceId) | ||
|
||
if (contentType == ContentType.Application.Json) { | ||
val bytes = byteReadChannel.readRemaining().readBytes() | ||
val signalMessage = SignalMessage(bytes) | ||
val decrypt = processor.decrypt(signalMessage) | ||
|
||
// Create a new ByteReadChannel to contain the decrypted content | ||
val newChannel = ByteReadChannel(decrypt) | ||
val responseData = | ||
HttpResponseData( | ||
it.status, | ||
it.requestTime, | ||
it.headers, | ||
it.version, | ||
newChannel, | ||
it.coroutineContext, | ||
) | ||
proceedWith(DefaultHttpResponse(it.call, responseData)) | ||
} else if (contentType == ContentType.Application.OctetStream) { | ||
val result = ByteArrayOutputStream() | ||
while (!byteReadChannel.isClosedForRead) { | ||
val size = byteReadChannel.readInt() | ||
val byteArray = ByteArray(size) | ||
var bytesRead = 0 | ||
while (bytesRead < size) { | ||
val currentRead = byteReadChannel.readAvailable(byteArray, bytesRead, size - bytesRead) | ||
if (currentRead == -1) break | ||
bytesRead += currentRead | ||
} | ||
val signalMessage = SignalMessage(byteArray) | ||
result.write(processor.decrypt(signalMessage)) | ||
} | ||
val newChannel = ByteReadChannel(result.toByteArray()) | ||
val responseData = | ||
HttpResponseData( | ||
it.status, | ||
it.requestTime, | ||
it.headers, | ||
it.version, | ||
newChannel, | ||
it.coroutineContext, | ||
) | ||
proceedWith(DefaultHttpResponse(it.call, responseData)) | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.