[feat] Abyss Protocol authentication

This commit is contained in:
acite
2025-09-13 17:02:12 +08:00
parent 7d07f19440
commit ffa70d9d34
4 changed files with 34 additions and 5 deletions

View File

@@ -5,6 +5,8 @@ import android.content.Intent
import android.os.Binder import android.os.Binder
import android.os.IBinder import android.os.IBinder
import com.acitelight.aether.service.AbyssTunnelProxy import com.acitelight.aether.service.AbyssTunnelProxy
import com.acitelight.aether.service.SettingsDataStoreManager
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
@@ -13,13 +15,17 @@ import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import javax.inject.Inject
@AndroidEntryPoint
class AbyssService: Service() {
@Inject
lateinit var proxy: AbyssTunnelProxy
class AbyssService : Service() {
private val binder = AbyssServiceBinder() private val binder = AbyssServiceBinder()
private val _isInitialized = MutableStateFlow(false) private val _isInitialized = MutableStateFlow(false)
val isInitialized: StateFlow<Boolean> = _isInitialized.asStateFlow() val isInitialized: StateFlow<Boolean> = _isInitialized.asStateFlow()
private val serviceScope = CoroutineScope(Dispatchers.IO + Job()) private val serviceScope = CoroutineScope(Dispatchers.IO + Job())
var proxy = AbyssTunnelProxy()
inner class AbyssServiceBinder : Binder() { inner class AbyssServiceBinder : Binder() {
fun getService(): AbyssService = this@AbyssService fun getService(): AbyssService = this@AbyssService

View File

@@ -1,5 +1,8 @@
package com.acitelight.aether.service package com.acitelight.aether.service
import com.acitelight.aether.service.AuthManager.db64
import com.acitelight.aether.service.AuthManager.signChallenge
import com.acitelight.aether.service.AuthManager.signChallengeByte
import kotlinx.coroutines.* import kotlinx.coroutines.*
import java.io.InputStream import java.io.InputStream
import java.io.OutputStream import java.io.OutputStream
@@ -64,6 +67,12 @@ class AbyssStream private constructor(
val remotePub = ByteArray(PUBLIC_KEY_LEN) val remotePub = ByteArray(PUBLIC_KEY_LEN)
readExact(inStream, remotePub, 0, PUBLIC_KEY_LEN) readExact(inStream, remotePub, 0, PUBLIC_KEY_LEN)
val ch = ByteArray(32)
readExact(inStream, ch, 0, 32)
val signed = signChallengeByte(localPriv, ch)
writeExact(outStream, signed, 0, signed.size)
readExact(inStream, ch, 0, 16)
// 3) compute shared secret: X25519.scalarMult(private, remotePublic) // 3) compute shared secret: X25519.scalarMult(private, remotePublic)
val shared = ByteArray(PUBLIC_KEY_LEN) val shared = ByteArray(PUBLIC_KEY_LEN)
X25519.scalarMult(localPriv, 0, remotePub, 0, shared, 0) X25519.scalarMult(localPriv, 0, remotePub, 0, shared, 0)

View File

@@ -1,18 +1,22 @@
package com.acitelight.aether.service package com.acitelight.aether.service
import com.acitelight.aether.service.AuthManager.db64
import kotlinx.coroutines.* import kotlinx.coroutines.*
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.selects.select import kotlinx.coroutines.selects.select
import java.io.InputStream import java.io.InputStream
import java.io.OutputStream import java.io.OutputStream
import java.net.InetAddress import java.net.InetAddress
import java.net.ServerSocket import java.net.ServerSocket
import java.net.Socket import java.net.Socket
import javax.inject.Inject
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
class AbyssTunnelProxy( class AbyssTunnelProxy @Inject constructor(
private val coroutineContext: CoroutineContext = Dispatchers.IO private val settingsDataStoreManager: SettingsDataStoreManager
) { ) {
private val coroutineContext: CoroutineContext = Dispatchers.IO
private var serverHost: String = "" private var serverHost: String = ""
private var serverPort: Int = 0 private var serverPort: Int = 0
@@ -65,7 +69,7 @@ class AbyssTunnelProxy(
var abyssStream: AbyssStream? = null var abyssStream: AbyssStream? = null
try { try {
abyssSocket = Socket(serverHost, serverPort) abyssSocket = Socket(serverHost, serverPort)
abyssStream = AbyssStream.create(abyssSocket) abyssStream = AbyssStream.create(abyssSocket, db64(settingsDataStoreManager.privateKeyFlow.first()))
// concurrently copy in both directions // concurrently copy in both directions
val job1 = launch { copyExactSuspend(localIn, abyssStream) } // local -> abyss val job1 = launch { copyExactSuspend(localIn, abyssStream) } // local -> abyss

View File

@@ -55,4 +55,14 @@ object AuthManager {
val signature = signer.generateSignature() val signature = signer.generateSignature()
return Base64.encodeToString(signature, Base64.NO_WRAP) return Base64.encodeToString(signature, Base64.NO_WRAP)
} }
fun signChallengeByte(privateKey: ByteArray, data: ByteArray): ByteArray //64 Byte
{
val privateKeyParams = Ed25519PrivateKeyParameters(privateKey, 0)
val signer = Ed25519Signer()
signer.init(true, privateKeyParams)
signer.update(data, 0, data.size)
return signer.generateSignature()
}
} }