Fixed issue in base64 encoding.

This commit is contained in:
Koen J 2025-06-05 09:58:10 +02:00
commit fa8d175101
3 changed files with 24 additions and 23 deletions

View file

@ -75,7 +75,7 @@ class ChannelRelayed(
private var handshakeState: HandshakeState? = if (initiator) { private var handshakeState: HandshakeState? = if (initiator) {
HandshakeState(SyncService.protocolName, HandshakeState.INITIATOR).apply { HandshakeState(SyncService.protocolName, HandshakeState.INITIATOR).apply {
localKeyPair.copyFrom(this@ChannelRelayed.localKeyPair) localKeyPair.copyFrom(this@ChannelRelayed.localKeyPair)
remotePublicKey.setPublicKey(Base64.getDecoder().decode(publicKey), 0) remotePublicKey.setPublicKey(publicKey.base64ToByteArray(), 0)
} }
} else { } else {
HandshakeState(SyncService.protocolName, HandshakeState.RESPONDER).apply { HandshakeState(SyncService.protocolName, HandshakeState.RESPONDER).apply {
@ -177,7 +177,7 @@ class ChannelRelayed(
this.remoteVersion = remoteVersion this.remoteVersion = remoteVersion
val remoteKeyBytes = ByteArray(handshakeState!!.remotePublicKey.publicKeyLength) val remoteKeyBytes = ByteArray(handshakeState!!.remotePublicKey.publicKeyLength)
handshakeState!!.remotePublicKey.getPublicKey(remoteKeyBytes, 0) handshakeState!!.remotePublicKey.getPublicKey(remoteKeyBytes, 0)
this.remotePublicKey = Base64.getEncoder().encodeToString(remoteKeyBytes) this.remotePublicKey = remoteKeyBytes.toBase64()
handshakeState?.destroy() handshakeState?.destroy()
handshakeState = null handshakeState = null
this.transport = transport this.transport = transport
@ -316,7 +316,7 @@ class ChannelRelayed(
val channelMessage = ByteArray(1024) val channelMessage = ByteArray(1024)
val channelBytesWritten = handshakeState!!.writeMessage(channelMessage, 0, null, 0, 0) val channelBytesWritten = handshakeState!!.writeMessage(channelMessage, 0, null, 0, 0)
val publicKeyBytes = Base64.getDecoder().decode(publicKey) val publicKeyBytes = publicKey.base64ToByteArray()
if (publicKeyBytes.size != 32) throw IllegalArgumentException("Public key must be 32 bytes") if (publicKeyBytes.size != 32) throw IllegalArgumentException("Public key must be 32 bytes")
val (pairingMessageLength, pairingMessage) = if (pairingCode != null) { val (pairingMessageLength, pairingMessage) = if (pairingCode != null) {

View file

@ -13,6 +13,7 @@ import com.futo.platformplayer.noise.protocol.DHState
import com.futo.platformplayer.noise.protocol.Noise import com.futo.platformplayer.noise.protocol.Noise
import com.futo.platformplayer.states.StateSync import com.futo.platformplayer.states.StateSync
import com.futo.polycentric.core.base64ToByteArray import com.futo.polycentric.core.base64ToByteArray
import com.futo.polycentric.core.base64UrlToByteArray
import com.futo.polycentric.core.toBase64 import com.futo.polycentric.core.toBase64
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@ -98,7 +99,7 @@ class SyncService(
override fun onServiceLost(service: NsdServiceInfo) { override fun onServiceLost(service: NsdServiceInfo) {
Log.e(TAG, "service lost: $service") Log.e(TAG, "service lost: $service")
val urlSafePkey = service.attributes["pk"]?.decodeToString() ?: return val urlSafePkey = service.attributes["pk"]?.decodeToString() ?: return
val pkey = Base64.getDecoder().decode(urlSafePkey.replace('-', '+').replace('_', '/')).toBase64() val pkey = urlSafePkey.base64UrlToByteArray().toBase64()
synchronized(_mdnsCache) { synchronized(_mdnsCache) {
_mdnsCache.remove(pkey) _mdnsCache.remove(pkey)
} }
@ -128,7 +129,7 @@ class SyncService(
} }
val urlSafePkey = attributes.get("pk")?.decodeToString() ?: return val urlSafePkey = attributes.get("pk")?.decodeToString() ?: return
val pkey = Base64.getDecoder().decode(urlSafePkey.replace('-', '+').replace('_', '/')).toBase64() val pkey = urlSafePkey.base64UrlToByteArray().toBase64()
val syncDeviceInfo = SyncDeviceInfo(pkey, adrs.map { it.hostAddress }.toTypedArray(), port, null) val syncDeviceInfo = SyncDeviceInfo(pkey, adrs.map { it.hostAddress }.toTypedArray(), port, null)
synchronized(_mdnsCache) { synchronized(_mdnsCache) {
@ -157,7 +158,7 @@ class SyncService(
override fun onServiceLost() { override fun onServiceLost() {
Log.v(TAG, "onServiceLost: $service") Log.v(TAG, "onServiceLost: $service")
val urlSafePkey = service.attributes["pk"]?.decodeToString() ?: return val urlSafePkey = service.attributes["pk"]?.decodeToString() ?: return
val pkey = Base64.getDecoder().decode(urlSafePkey.replace('-', '+').replace('_', '/')).toBase64() val pkey = urlSafePkey.base64UrlToByteArray().toBase64()
synchronized(_mdnsCache) { synchronized(_mdnsCache) {
_mdnsCache.remove(pkey) _mdnsCache.remove(pkey)
} }

View file

@ -123,7 +123,7 @@ class SyncSocketSession {
val localPublicKey = ByteArray(localKeyPair.publicKeyLength) val localPublicKey = ByteArray(localKeyPair.publicKeyLength)
localKeyPair.getPublicKey(localPublicKey, 0) localKeyPair.getPublicKey(localPublicKey, 0)
_localPublicKey = Base64.getEncoder().encodeToString(localPublicKey) _localPublicKey = localPublicKey.toBase64()
} }
fun startAsInitiator(remotePublicKey: String, appId: UInt = 0u, pairingCode: String? = null) { fun startAsInitiator(remotePublicKey: String, appId: UInt = 0u, pairingCode: String? = null) {
@ -253,14 +253,14 @@ class SyncSocketSession {
val initiator = HandshakeState(SyncService.protocolName, HandshakeState.INITIATOR) val initiator = HandshakeState(SyncService.protocolName, HandshakeState.INITIATOR)
initiator.localKeyPair.copyFrom(_localKeyPair) initiator.localKeyPair.copyFrom(_localKeyPair)
initiator.remotePublicKey.setPublicKey(Base64.getDecoder().decode(remotePublicKey), 0) initiator.remotePublicKey.setPublicKey(remotePublicKey.base64ToByteArray(), 0)
initiator.start() initiator.start()
val pairingMessage: ByteArray val pairingMessage: ByteArray
val pairingMessageLength: Int val pairingMessageLength: Int
if (pairingCode != null) { if (pairingCode != null) {
val pairingHandshake = HandshakeState(SyncSocketSession.nProtocolName, HandshakeState.INITIATOR) val pairingHandshake = HandshakeState(SyncSocketSession.nProtocolName, HandshakeState.INITIATOR)
pairingHandshake.remotePublicKey.setPublicKey(Base64.getDecoder().decode(remotePublicKey), 0) pairingHandshake.remotePublicKey.setPublicKey(remotePublicKey.base64ToByteArray(), 0)
pairingHandshake.start() pairingHandshake.start()
val pairingCodeBytes = pairingCode.toByteArray(Charsets.UTF_8) val pairingCodeBytes = pairingCode.toByteArray(Charsets.UTF_8)
val pairingBuffer = ByteArray(512) val pairingBuffer = ByteArray(512)
@ -299,7 +299,7 @@ class SyncSocketSession {
_cipherStatePair = initiator.split() _cipherStatePair = initiator.split()
val remoteKeyBytes = ByteArray(initiator.remotePublicKey.publicKeyLength) val remoteKeyBytes = ByteArray(initiator.remotePublicKey.publicKeyLength)
initiator.remotePublicKey.getPublicKey(remoteKeyBytes, 0) initiator.remotePublicKey.getPublicKey(remoteKeyBytes, 0)
_remotePublicKey = Base64.getEncoder().encodeToString(remoteKeyBytes).base64ToByteArray().toBase64() _remotePublicKey = remoteKeyBytes.toBase64()
} }
private fun handshakeAsResponder(): Boolean { private fun handshakeAsResponder(): Boolean {
@ -516,7 +516,7 @@ class SyncSocketSession {
return return
} }
val channelHandshakeMessage = ByteArray(channelMessageLength).also { data.get(it) } val channelHandshakeMessage = ByteArray(channelMessageLength).also { data.get(it) }
val publicKey = Base64.getEncoder().encodeToString(publicKeyBytes) val publicKey = publicKeyBytes.toBase64()
val pairingCode = if (pairingMessageLength > 0) { val pairingCode = if (pairingMessageLength > 0) {
val pairingProtocol = HandshakeState(SyncSocketSession.nProtocolName, HandshakeState.RESPONDER).apply { val pairingProtocol = HandshakeState(SyncSocketSession.nProtocolName, HandshakeState.RESPONDER).apply {
localKeyPair.copyFrom(_localKeyPair) localKeyPair.copyFrom(_localKeyPair)
@ -671,7 +671,7 @@ class SyncSocketSession {
val records = mutableMapOf<String, Pair<ByteArray, Long>>() val records = mutableMapOf<String, Pair<ByteArray, Long>>()
repeat(recordCount) { repeat(recordCount) {
val publisherBytes = ByteArray(32).also { data.get(it) } val publisherBytes = ByteArray(32).also { data.get(it) }
val publisher = Base64.getEncoder().encodeToString(publisherBytes) val publisher = publisherBytes.toBase64()
val blobLength = data.int val blobLength = data.int
val encryptedBlob = ByteArray(blobLength).also { data.get(it) } val encryptedBlob = ByteArray(blobLength).also { data.get(it) }
val timestamp = data.long val timestamp = data.long
@ -712,7 +712,7 @@ class SyncSocketSession {
val numResponses = data.get().toInt() val numResponses = data.get().toInt()
val result = mutableMapOf<String, ConnectionInfo>() val result = mutableMapOf<String, ConnectionInfo>()
repeat(numResponses) { repeat(numResponses) {
val publicKey = Base64.getEncoder().encodeToString(ByteArray(32).also { data.get(it) }) val publicKey = ByteArray(32).also { data.get(it) }.toBase64()
val status = data.get().toInt() val status = data.get().toInt()
if (status == 0) { if (status == 0) {
val infoSize = data.int val infoSize = data.int
@ -994,7 +994,7 @@ class SyncSocketSession {
val deferred = CompletableDeferred<ConnectionInfo?>() val deferred = CompletableDeferred<ConnectionInfo?>()
_pendingConnectionInfoRequests[requestId] = deferred _pendingConnectionInfoRequests[requestId] = deferred
try { try {
val publicKeyBytes = Base64.getDecoder().decode(publicKey) val publicKeyBytes = publicKey.base64ToByteArray()
if (publicKeyBytes.size != 32) throw IllegalArgumentException("Public key must be 32 bytes") if (publicKeyBytes.size != 32) throw IllegalArgumentException("Public key must be 32 bytes")
val packet = ByteBuffer.allocate(4 + 32).order(ByteOrder.LITTLE_ENDIAN) val packet = ByteBuffer.allocate(4 + 32).order(ByteOrder.LITTLE_ENDIAN)
packet.putInt(requestId) packet.putInt(requestId)
@ -1017,7 +1017,7 @@ class SyncSocketSession {
packet.putInt(requestId) packet.putInt(requestId)
packet.put(publicKeys.size.toByte()) packet.put(publicKeys.size.toByte())
for (pk in publicKeys) { for (pk in publicKeys) {
val pkBytes = Base64.getDecoder().decode(pk) val pkBytes = pk.base64ToByteArray()
if (pkBytes.size != 32) throw IllegalArgumentException("Invalid public key length for $pk") if (pkBytes.size != 32) throw IllegalArgumentException("Invalid public key length for $pk")
packet.put(pkBytes) packet.put(pkBytes)
} }
@ -1125,7 +1125,7 @@ class SyncSocketSession {
publishBytes.put(authorizedKeys.size.toByte()) publishBytes.put(authorizedKeys.size.toByte())
for (key in authorizedKeys) { for (key in authorizedKeys) {
val publicKeyBytes = Base64.getDecoder().decode(key) val publicKeyBytes = key.base64ToByteArray()
if (publicKeyBytes.size != 32) throw IllegalArgumentException("Public key must be 32 bytes") if (publicKeyBytes.size != 32) throw IllegalArgumentException("Public key must be 32 bytes")
val protocol = HandshakeState(SyncSocketSession.nProtocolName, HandshakeState.INITIATOR) val protocol = HandshakeState(SyncSocketSession.nProtocolName, HandshakeState.INITIATOR)
@ -1183,7 +1183,7 @@ class SyncSocketSession {
packet.put(consumerPublicKeys.size.toByte()) packet.put(consumerPublicKeys.size.toByte())
for (consumer in consumerPublicKeys) { for (consumer in consumerPublicKeys) {
val consumerBytes = Base64.getDecoder().decode(consumer) val consumerBytes = consumer.base64ToByteArray()
if (consumerBytes.size != 32) throw IllegalArgumentException("Consumer public key must be 32 bytes") if (consumerBytes.size != 32) throw IllegalArgumentException("Consumer public key must be 32 bytes")
packet.put(consumerBytes) packet.put(consumerBytes)
val protocol = HandshakeState(SyncSocketSession.nProtocolName, HandshakeState.INITIATOR).apply { val protocol = HandshakeState(SyncSocketSession.nProtocolName, HandshakeState.INITIATOR).apply {
@ -1222,7 +1222,7 @@ class SyncSocketSession {
val deferred = CompletableDeferred<Pair<ByteArray, Long>?>() val deferred = CompletableDeferred<Pair<ByteArray, Long>?>()
_pendingGetRecordRequests[requestId] = deferred _pendingGetRecordRequests[requestId] = deferred
try { try {
val publisherBytes = Base64.getDecoder().decode(publisherPublicKey) val publisherBytes = publisherPublicKey.base64ToByteArray()
if (publisherBytes.size != 32) throw IllegalArgumentException("Publisher public key must be 32 bytes") if (publisherBytes.size != 32) throw IllegalArgumentException("Publisher public key must be 32 bytes")
val keyBytes = key.toByteArray(Charsets.UTF_8) val keyBytes = key.toByteArray(Charsets.UTF_8)
val packet = ByteBuffer.allocate(4 + 32 + 1 + keyBytes.size).order(ByteOrder.LITTLE_ENDIAN) val packet = ByteBuffer.allocate(4 + 32 + 1 + keyBytes.size).order(ByteOrder.LITTLE_ENDIAN)
@ -1253,7 +1253,7 @@ class SyncSocketSession {
packet.put(keyBytes) packet.put(keyBytes)
packet.put(publisherPublicKeys.size.toByte()) packet.put(publisherPublicKeys.size.toByte())
for (publisher in publisherPublicKeys) { for (publisher in publisherPublicKeys) {
val bytes = Base64.getDecoder().decode(publisher) val bytes = publisher.base64ToByteArray()
if (bytes.size != 32) throw IllegalArgumentException("Publisher public key must be 32 bytes") if (bytes.size != 32) throw IllegalArgumentException("Publisher public key must be 32 bytes")
packet.put(bytes) packet.put(bytes)
} }
@ -1272,9 +1272,9 @@ class SyncSocketSession {
val deferred = CompletableDeferred<Boolean>() val deferred = CompletableDeferred<Boolean>()
_pendingDeleteRequests[requestId] = deferred _pendingDeleteRequests[requestId] = deferred
try { try {
val publisherBytes = Base64.getDecoder().decode(publisherPublicKey) val publisherBytes = publisherPublicKey.base64ToByteArray()
if (publisherBytes.size != 32) throw IllegalArgumentException("Publisher public key must be 32 bytes") if (publisherBytes.size != 32) throw IllegalArgumentException("Publisher public key must be 32 bytes")
val consumerBytes = Base64.getDecoder().decode(consumerPublicKey) val consumerBytes = consumerPublicKey.base64ToByteArray()
if (consumerBytes.size != 32) throw IllegalArgumentException("Consumer public key must be 32 bytes") if (consumerBytes.size != 32) throw IllegalArgumentException("Consumer public key must be 32 bytes")
val packetSize = 4 + 32 + 32 + 1 + keys.sumOf { 1 + it.toByteArray(Charsets.UTF_8).size } val packetSize = 4 + 32 + 32 + 1 + keys.sumOf { 1 + it.toByteArray(Charsets.UTF_8).size }
val packet = ByteBuffer.allocate(packetSize).order(ByteOrder.LITTLE_ENDIAN) val packet = ByteBuffer.allocate(packetSize).order(ByteOrder.LITTLE_ENDIAN)
@ -1301,9 +1301,9 @@ class SyncSocketSession {
val deferred = CompletableDeferred<List<Pair<String, Long>>>() val deferred = CompletableDeferred<List<Pair<String, Long>>>()
_pendingListKeysRequests[requestId] = deferred _pendingListKeysRequests[requestId] = deferred
try { try {
val publisherBytes = Base64.getDecoder().decode(publisherPublicKey) val publisherBytes = publisherPublicKey.base64ToByteArray()
if (publisherBytes.size != 32) throw IllegalArgumentException("Publisher public key must be 32 bytes") if (publisherBytes.size != 32) throw IllegalArgumentException("Publisher public key must be 32 bytes")
val consumerBytes = Base64.getDecoder().decode(consumerPublicKey) val consumerBytes = consumerPublicKey.base64ToByteArray()
if (consumerBytes.size != 32) throw IllegalArgumentException("Consumer public key must be 32 bytes") if (consumerBytes.size != 32) throw IllegalArgumentException("Consumer public key must be 32 bytes")
val packet = ByteBuffer.allocate(4 + 32 + 32).order(ByteOrder.LITTLE_ENDIAN) val packet = ByteBuffer.allocate(4 + 32 + 32).order(ByteOrder.LITTLE_ENDIAN)
packet.putInt(requestId) packet.putInt(requestId)