DeviceManifestSupportTest.kt

4.0 KB · raw

1package com.peachpasswords.sync23import org.junit.Assert.assertNotNull4import org.junit.Assert.assertNull5import org.junit.Test67/**8 * Bounds tests for [verifyDeviceManifest]. The arithmetic fix lives in the9 * verify path itself; these tests pin the inputs that used to slip past it.10 */11class DeviceManifestSupportTest {12    private val master = ByteArray(32) { it.toByte() }13    private val signing = deriveSyncSigningKeypair(master, "issuer")1415    private fun validEntry(deviceId: String = "peer", pairedAt: Long = 1L) = ManifestDeviceEntry(16        deviceId = deviceId,17        deviceName = "Peer",18        deviceType = "android",19        longTermPublicKeyHex = "aa".repeat(32),20        signingPublicKeyHex = "bb".repeat(32),21        pairedAt = pairedAt,22    )2324    private fun manifestWith(issuedAt: Long, devices: List<ManifestDeviceEntry> = listOf(validEntry())) =25        buildSignedDeviceManifest(26            issuerDeviceId = "issuer",27            devices = devices,28            signingPrivateKey = signing.privateKey,29            nowMs = issuedAt,30        )3132    @Test fun rejects_issued_at_long_min_value() {33        // abs(Long.MIN_VALUE) is still negative, so the legacy abs()-based gate34        // accepted this. The new two-sided bound must reject it.35        val manifest = manifestWith(issuedAt = Long.MIN_VALUE)36        assertNull(verifyDeviceManifest(manifest, signing.publicKeyRaw, nowMs = 1_700_000_000_000L))37    }3839    @Test fun rejects_issued_at_too_old() {40        val manifest = manifestWith(issuedAt = 1L)41        assertNull(verifyDeviceManifest(manifest, signing.publicKeyRaw, nowMs = 1_700_000_000_000L))42    }4344    @Test fun rejects_issued_at_too_far_in_future() {45        val now = 1_700_000_000_000L46        // 5 min + 1 ms past the default freshness window.47        val manifest = manifestWith(issuedAt = now + 5 * 60_000L + 1L)48        assertNull(verifyDeviceManifest(manifest, signing.publicKeyRaw, nowMs = now))49    }5051    @Test fun accepts_issued_at_within_window() {52        val now = 1_700_000_000_000L53        val manifest = manifestWith(issuedAt = now)54        assertNotNull(verifyDeviceManifest(manifest, signing.publicKeyRaw, nowMs = now))55    }5657    @Test fun rejects_oversized_device_id_string() {58        val manifest = manifestWith(59            issuedAt = 1_000L,60            devices = listOf(validEntry(deviceId = "x".repeat(10_000))),61        )62        assertNull(verifyDeviceManifest(manifest, signing.publicKeyRaw, nowMs = 1_000L))63    }6465    @Test fun rejects_negative_paired_at() {66        val manifest = manifestWith(67            issuedAt = 1_000L,68            devices = listOf(validEntry(pairedAt = -1L)),69        )70        assertNull(verifyDeviceManifest(manifest, signing.publicKeyRaw, nowMs = 1_000L))71    }7273    @Test fun rejects_too_many_devices() {74        val manifest = buildSignedDeviceManifest(75            issuerDeviceId = "issuer",76            devices = List(300) { validEntry(deviceId = "peer-$it") },77            signingPrivateKey = signing.privateKey,78            nowMs = 1_000L,79        )80        assertNull(verifyDeviceManifest(manifest, signing.publicKeyRaw, nowMs = 1_000L))81    }8283    @Test fun rejects_oversized_issuer_device_id() {84        val manifest = manifestWith(issuedAt = 1_000L)85        val oversized = manifest.copy(body = manifest.body.copy(issuerDeviceId = "y".repeat(2_000)))86        assertNull(verifyDeviceManifest(oversized, signing.publicKeyRaw, nowMs = 1_000L))87    }8889    @Test fun rejects_negative_revoked_at() {90        val manifest = buildSignedDeviceManifest(91            issuerDeviceId = "issuer",92            devices = emptyList(),93            signingPrivateKey = signing.privateKey,94            nowMs = 1_000L,95            revoked = listOf(96                DeviceRevocation(97                    deviceId = "peer",98                    longTermPublicKeyHex = "aa".repeat(32),99                    revokedAt = -1L,100                    revokedByDeviceId = "issuer",101                ),102            ),103        )104        assertNull(verifyDeviceManifest(manifest, signing.publicKeyRaw, nowMs = 1_000L))105    }106}