feat: add BleRelayManager key/HMAC helpers and loadState
This commit is contained in:
parent
f41f1c3380
commit
82852e086e
1 changed files with 52 additions and 3 deletions
|
|
@ -7,6 +7,10 @@ import android.content.Context
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
|
import java.nio.ByteBuffer
|
||||||
|
import java.nio.ByteOrder
|
||||||
|
import javax.crypto.Mac
|
||||||
|
import javax.crypto.spec.SecretKeySpec
|
||||||
|
|
||||||
class BleRelayManager(
|
class BleRelayManager(
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
|
|
@ -20,6 +24,8 @@ class BleRelayManager(
|
||||||
private const val SCAN_TIMEOUT_MS = 30000L
|
private const val SCAN_TIMEOUT_MS = 30000L
|
||||||
private const val RECONNECT_DELAY_MS = 2000L
|
private const val RECONNECT_DELAY_MS = 2000L
|
||||||
private const val MAX_SCAN_RETRIES = 3
|
private const val MAX_SCAN_RETRIES = 3
|
||||||
|
private const val HMAC_PKT_SIZE = 37
|
||||||
|
private const val HMAC_LEN = 32
|
||||||
}
|
}
|
||||||
|
|
||||||
private var bluetoothGatt: BluetoothGatt? = null
|
private var bluetoothGatt: BluetoothGatt? = null
|
||||||
|
|
@ -37,9 +43,52 @@ class BleRelayManager(
|
||||||
fun stopScan() {}
|
fun stopScan() {}
|
||||||
fun sendRelayCommand(cmd: Byte) {}
|
fun sendRelayCommand(cmd: Byte) {}
|
||||||
fun disconnect() {}
|
fun disconnect() {}
|
||||||
fun updateKeys() {}
|
fun updateKeys() {
|
||||||
fun resetTriedAddresses() {}
|
loadState()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun resetTriedAddresses() {
|
||||||
|
triedAddresses.clear()
|
||||||
|
}
|
||||||
|
|
||||||
fun hasPermissions(): Boolean = false
|
fun hasPermissions(): Boolean = false
|
||||||
fun getRequiredPermissions(): Array<String> = emptyArray()
|
fun getRequiredPermissions(): Array<String> = emptyArray()
|
||||||
fun destroy() {}
|
|
||||||
|
fun destroy() {
|
||||||
|
handler.removeCallbacksAndMessages(null)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun loadState() {
|
||||||
|
val prefs = PrefsHelper.getPrefs(context)
|
||||||
|
val hexKey = prefs.getString(PrefsHelper.PREF_KEY, null)
|
||||||
|
hmacKey = hexKey?.let { hexStringToBytes(it) }
|
||||||
|
val hexUuid = prefs.getString(PrefsHelper.PREF_UUID, null)
|
||||||
|
deviceUuid = hexUuid?.let { hexStringToBytes(it) }
|
||||||
|
seq = prefs.getInt(PrefsHelper.PREF_SEQ, 1).coerceAtMost(PrefsHelper.SEQ_MAX)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun hexStringToBytes(hex: String): ByteArray? {
|
||||||
|
val cleaned = hex.uppercase().filter { it in "0123456789ABCDEF" }
|
||||||
|
if (cleaned.isEmpty() || cleaned.length % 2 != 0) return null
|
||||||
|
return cleaned.chunked(2).map { it.toInt(16).toByte() }.toByteArray()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun hmacSha256(data: ByteArray, key: ByteArray): ByteArray {
|
||||||
|
val mac = Mac.getInstance("HmacSHA256")
|
||||||
|
mac.init(SecretKeySpec(key, "HmacSHA256"))
|
||||||
|
return mac.doFinal(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun buildPacket(cmd: Byte, key: ByteArray): ByteArray {
|
||||||
|
val seqBytes = ByteBuffer.allocate(4).order(ByteOrder.BIG_ENDIAN).putInt(seq).array()
|
||||||
|
val hmacData = ByteArray(5)
|
||||||
|
hmacData[0] = cmd
|
||||||
|
System.arraycopy(seqBytes, 0, hmacData, 1, 4)
|
||||||
|
val hmac = hmacSha256(hmacData, key)
|
||||||
|
val packet = ByteArray(HMAC_PKT_SIZE)
|
||||||
|
packet[0] = cmd
|
||||||
|
System.arraycopy(seqBytes, 0, packet, 1, 4)
|
||||||
|
System.arraycopy(hmac, 0, packet, 5, HMAC_LEN)
|
||||||
|
return packet
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue