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 {
|
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? {
|
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(
|
private fun announcePacket(
|
||||||
ageMs: Long,
|
ageMs: Long,
|
||||||
ttl: UByte = (AppConstants.MESSAGE_TTL_HOPS.toInt() - 1).toUByte(),
|
ttl: UByte = (AppConstants.MESSAGE_TTL_HOPS.toInt() - 1).toUByte(),
|
||||||
|
|||||||
@@ -47,6 +47,18 @@ class PrivateMediaTransferPreparerTest {
|
|||||||
assertEquals(0x20u.toUByte(), encryptedPlaintext!![0].toUByte())
|
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
|
@Test
|
||||||
fun `legacy mode requires consent and signing failure aborts`() {
|
fun `legacy mode requires consent and signing failure aborts`() {
|
||||||
val noConsent = preparer(policy = PrivateMediaPolicyDecision.RequiresLegacyConsent)
|
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`.
|
- Noise payload data: one complete encoded `BitchatFilePacket`.
|
||||||
- Outer recipient: the target peer ID; never broadcast for private media.
|
- 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
|
## Capability announcement
|
||||||
|
|
||||||
@@ -96,6 +104,8 @@ capability and bounded streaming design.
|
|||||||
|
|
||||||
- New Android to new iOS/Android: encrypted Noise `0x20` after authenticated
|
- New Android to new iOS/Android: encrypted Noise `0x20` after authenticated
|
||||||
capability promotion.
|
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
|
- New Android to a verified older client: blocked until the user explicitly
|
||||||
accepts one relay-visible signed raw `0x22` transfer.
|
accepts one relay-visible signed raw `0x22` transfer.
|
||||||
- Old clients receiving a new announcement: ignore TLV `0x05` and continue
|
- Old clients receiving a new announcement: ignore TLV `0x05` and continue
|
||||||
|
|||||||
Reference in New Issue
Block a user