mirror of
https://github.com/permissionlesstech/bitchat-android.git
synced 2026-09-19 04:59:59 +00:00
Cover the future-dating bound
Extends the existing LEAVE replay-window test to the relayed types. Pins that the bound is future-only — a six-hour-old message still delivers so store-and-forward keeps working — and that it is no tighter than the announcement allowance. Removing the check fails the two rejection tests and leaves the three admission tests green.
This commit is contained in:
parent
5e4afae4cd
commit
105aa64a9e
@ -276,6 +276,81 @@ class SecurityManagerTest {
|
||||
assertFalse("Future-dated LEAVE must not extend its replay lifetime", securityManager.validatePacket(future, otherPeerID))
|
||||
}
|
||||
|
||||
private fun signedMessage(offsetMs: Long): BitchatPacket = BitchatPacket(
|
||||
type = MessageType.MESSAGE.value,
|
||||
ttl = 7u,
|
||||
senderID = MeshPacketUtils.hexStringToByteArray(otherPeerID),
|
||||
timestamp = (System.currentTimeMillis() + offsetMs).toULong(),
|
||||
payload = dummyPayload
|
||||
).also { it.signature = validSignature }
|
||||
|
||||
@Test
|
||||
fun `validatePacket rejects future-dated broadcast messages`() {
|
||||
setupKnownPeer(otherPeerID, otherSigningKey)
|
||||
|
||||
// GossipSyncManager advertises the newest packets first, so a future-dated broadcast
|
||||
// takes a sync slot permanently and crowds real traffic out across the mesh.
|
||||
val future = signedMessage(AnnouncementIdentityValidator.MAX_CLOCK_SKEW_MS + 60_000L)
|
||||
|
||||
assertFalse(
|
||||
"A signed but future-dated MESSAGE must not be admitted",
|
||||
securityManager.validatePacket(future, otherPeerID)
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `validatePacket admits messages inside the announcement clock-skew allowance`() {
|
||||
setupKnownPeer(otherPeerID, otherSigningKey)
|
||||
|
||||
// A peer skewed further than this cannot get its ANNOUNCE accepted either, so the bound
|
||||
// must not be tighter than the one that admits the peer in the first place.
|
||||
val skewed = signedMessage(AnnouncementIdentityValidator.MAX_CLOCK_SKEW_MS - 60_000L)
|
||||
|
||||
assertTrue(
|
||||
"A tolerable forward clock skew must still deliver",
|
||||
securityManager.validatePacket(skewed, otherPeerID)
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `validatePacket still admits old messages for store and forward`() {
|
||||
setupKnownPeer(otherPeerID, otherSigningKey)
|
||||
|
||||
// StoreForward caches for 12 hours; bounding the past would silently drop that replay.
|
||||
val old = signedMessage(-6 * 60 * 60 * 1_000L)
|
||||
|
||||
assertTrue(
|
||||
"Store-and-forward replay must keep working",
|
||||
securityManager.validatePacket(old, otherPeerID)
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `validatePacket rejects future-dated packets of every relayed type`() {
|
||||
setupKnownPeer(otherPeerID, otherSigningKey)
|
||||
|
||||
val futureOffset = AnnouncementIdentityValidator.MAX_CLOCK_SKEW_MS + 60_000L
|
||||
listOf(
|
||||
MessageType.MESSAGE,
|
||||
MessageType.FILE_TRANSFER,
|
||||
MessageType.VOICE_FRAME,
|
||||
MessageType.FRAGMENT
|
||||
).forEach { type ->
|
||||
val packet = BitchatPacket(
|
||||
type = type.value,
|
||||
ttl = 7u,
|
||||
senderID = MeshPacketUtils.hexStringToByteArray(otherPeerID),
|
||||
timestamp = (System.currentTimeMillis() + futureOffset).toULong(),
|
||||
payload = dummyPayload
|
||||
).also { it.signature = validSignature }
|
||||
|
||||
assertFalse(
|
||||
"${type.name} must not be admitted with a future timestamp",
|
||||
securityManager.validatePacket(packet, otherPeerID)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `validatePacket - accepts ANNOUNCE packet from unknown peer (extracts key)`() {
|
||||
val announcement = IdentityAnnouncement(
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user