mirror of
https://github.com/permissionlesstech/bitchat-android.git
synced 2026-07-24 23:45:19 +00:00
Accept prerelease private media payloads
This commit is contained in:
@@ -27,8 +27,17 @@ enum class NoisePayloadType(val value: UByte) {
|
||||
|
||||
|
||||
companion object {
|
||||
// #1434 prerelease iOS builds briefly emitted private files as 0x09. Keep this
|
||||
// decode-only: every NoisePayload constructed by Android still encodes FILE_TRANSFER as
|
||||
// its canonical 0x20 value, so the compatibility alias cannot leak into new traffic.
|
||||
private val PRERELEASE_FILE_TRANSFER_RAW_VALUE = 0x09u.toUByte()
|
||||
|
||||
fun fromValue(value: UByte): NoisePayloadType? {
|
||||
return values().find { it.value == value }
|
||||
return if (value == PRERELEASE_FILE_TRANSFER_RAW_VALUE) {
|
||||
FILE_TRANSFER
|
||||
} else {
|
||||
values().find { it.value == value }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,6 +210,40 @@ class MessageHandlerTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `encrypted prerelease iOS Noise 0x09 private media is delivered`() {
|
||||
runBlocking {
|
||||
val file = BitchatFilePacket(
|
||||
fileName = "prerelease-ios.pdf",
|
||||
fileSize = 4,
|
||||
mimeType = "application/pdf",
|
||||
content = byteArrayOf(1, 2, 3, 4)
|
||||
)
|
||||
val prereleasePlaintext = byteArrayOf(0x09) + file.encode()!!
|
||||
val ciphertext = byteArrayOf(0x41, 0x42, 0x43)
|
||||
whenever(delegate.decryptFromPeer(any(), eq(peerID))).thenReturn(prereleasePlaintext)
|
||||
whenever(delegate.getPeerNickname(peerID)).thenReturn(nickname)
|
||||
whenever(delegate.getMyNickname()).thenReturn("me")
|
||||
whenever(delegate.encryptForPeer(any(), eq(peerID))).thenReturn(byteArrayOf(0x55))
|
||||
|
||||
val outerPacket = BitchatPacket(
|
||||
version = 2u,
|
||||
type = MessageType.NOISE_ENCRYPTED.value,
|
||||
senderID = peerID.hexToBytes(),
|
||||
recipientID = myPeerID.hexToBytes(),
|
||||
timestamp = System.currentTimeMillis().toULong(),
|
||||
payload = ciphertext,
|
||||
signature = signature,
|
||||
ttl = 7u
|
||||
)
|
||||
|
||||
handler.handleNoiseEncrypted(RoutedPacket(outerPacket, peerID, "direct-link"))
|
||||
|
||||
verify(delegate).decryptFromPeer(ciphertext, peerID)
|
||||
verify(delegate).onMessageReceived(any())
|
||||
}
|
||||
}
|
||||
|
||||
private fun announcePacket(
|
||||
ageMs: Long,
|
||||
ttl: UByte = (AppConstants.MESSAGE_TTL_HOPS.toInt() - 1).toUByte(),
|
||||
|
||||
@@ -47,6 +47,18 @@ class PrivateMediaTransferPreparerTest {
|
||||
assertEquals(0x20u.toUByte(), encryptedPlaintext!![0].toUByte())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `prerelease iOS Noise 0x09 decodes as file transfer but re-encodes canonical 0x20`() {
|
||||
val filePayload = file(3).encode()!!
|
||||
val prereleasePayload = byteArrayOf(0x09) + filePayload
|
||||
|
||||
val decoded = NoisePayload.decode(prereleasePayload)
|
||||
|
||||
assertEquals(NoisePayloadType.FILE_TRANSFER, decoded?.type)
|
||||
assertTrue(filePayload.contentEquals(decoded?.data))
|
||||
assertEquals(0x20u.toUByte(), decoded!!.encode()[0].toUByte())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `legacy mode requires consent and signing failure aborts`() {
|
||||
val noConsent = preparer(policy = PrivateMediaPolicyDecision.RequiresLegacyConsent)
|
||||
|
||||
@@ -11,7 +11,15 @@ for the recipient, and only then fragments the final outer packet.
|
||||
- Noise payload data: one complete encoded `BitchatFilePacket`.
|
||||
- Outer recipient: the target peer ID; never broadcast for private media.
|
||||
|
||||
Do not allocate a second Noise payload type for this format.
|
||||
Prerelease iOS builds of #1434 briefly emitted the inner file type as `0x09`.
|
||||
Android accepts that value on decode and immediately canonicalizes it to
|
||||
`NoisePayloadType.FILE_TRANSFER`; every Android encode remains `0x20`. Do not
|
||||
allocate or emit a second Noise payload type for this format.
|
||||
|
||||
The decode-only `0x09` alias may be removed only after every TestFlight/internal
|
||||
build that emitted it has expired and the project's minimum-supported-client
|
||||
policy excludes those builds. Track that release criterion explicitly; do not
|
||||
remove the alias on an arbitrary calendar date.
|
||||
|
||||
## Capability announcement
|
||||
|
||||
@@ -96,6 +104,8 @@ capability and bounded streaming design.
|
||||
|
||||
- New Android to new iOS/Android: encrypted Noise `0x20` after authenticated
|
||||
capability promotion.
|
||||
- Prerelease iOS to new Android: encrypted Noise `0x09` is decoded,
|
||||
canonicalized to `0x20`, and delivered during the migration window.
|
||||
- New Android to a verified older client: blocked until the user explicitly
|
||||
accepts one relay-visible signed raw `0x22` transfer.
|
||||
- Old clients receiving a new announcement: ignore TLV `0x05` and continue
|
||||
|
||||
Reference in New Issue
Block a user