[feat] Abyss Protocol authentication
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user