mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-07-26 19:45:20 +00:00
Closes the last cleartext private-content path over BLE: private DM images/voice were sent as plaintext signed fileTransfer packets, TTL-relayed across the mesh, so every relay saw the full bytes. Now the complete BitchatFilePacket is encrypted as a single Noise AEAD message (inner type 0x20, matching Android) and the opaque ciphertext is fragmented. Adds an authenticated in-session capability proof (0x21 TLV: capabilities + Ed25519 key), TOFU-style downgrade pinning, a per-send consent dialog for the signed-cleartext fallback to legacy peers, and a cancellation/admission registry so cancel/delete cannot race a deferred cleartext send. Android wire constants (0x20 / 0x21 / capability bit 8) confirmed shipping. The 256-fragment preflight cap applies only to the directed fileTransfer migration fallback; encrypted media to capable peers uses the full receiver ceiling. Rebased over #1428/#1349: identity reads go through BLELocalIdentityStateStore; the session-bound authenticated signing-key check and the announce-path TOFU pin are kept as complementary checks. Full local suite green (1744+197 tests).
45 lines
1.7 KiB
Swift
45 lines
1.7 KiB
Swift
//
|
|
// PeerCapabilitiesTests.swift
|
|
// bitchatTests
|
|
//
|
|
// This is free and unencumbered software released into the public domain.
|
|
// For more information, see <https://unlicense.org>
|
|
//
|
|
|
|
import Testing
|
|
import Foundation
|
|
@testable import BitFoundation
|
|
|
|
struct PeerCapabilitiesTests {
|
|
@Test
|
|
func encodingIsMinimalAndRoundTrips() {
|
|
#expect(PeerCapabilities([]).encoded() == Data([0x00]))
|
|
#expect(PeerCapabilities.prekeys.encoded() == Data([0x01]))
|
|
#expect(PeerCapabilities.meshDiagnostics.encoded() == Data([0x40]))
|
|
#expect(PeerCapabilities.privateMedia.encoded() == Data([0x00, 0x01]))
|
|
|
|
let high = PeerCapabilities(rawValue: 1 << 9)
|
|
#expect(high.encoded() == Data([0x00, 0x02]))
|
|
|
|
let all: PeerCapabilities = [.prekeys, .wifiBulk, .gateway, .groups, .board, .vouch, .meshDiagnostics, .privateMedia]
|
|
#expect(PeerCapabilities(encoded: all.encoded()) == all)
|
|
#expect(PeerCapabilities(encoded: high.encoded()) == high)
|
|
#expect(PeerCapabilities(encoded: PeerCapabilities([]).encoded()) == [])
|
|
}
|
|
|
|
@Test
|
|
func decodingToleratesUnknownBitsAndOversizedFields() {
|
|
// Unknown bits survive a round-trip untouched.
|
|
let unknown = PeerCapabilities(encoded: Data([0xFF, 0xFF]))
|
|
#expect(unknown.rawValue == 0xFFFF)
|
|
#expect(unknown.contains(.gateway))
|
|
|
|
// Fields longer than 8 bytes keep the low 64 bits and ignore the rest.
|
|
let oversized = Data([0x01] + [UInt8](repeating: 0x00, count: 7) + [0xAA, 0xBB])
|
|
#expect(PeerCapabilities(encoded: oversized) == .prekeys)
|
|
|
|
// Empty value decodes to no capabilities.
|
|
#expect(PeerCapabilities(encoded: Data()) == [])
|
|
}
|
|
}
|