package io.flamenet.e2e import javax.crypto.KeyGenerator import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertNull /** * Audit C1/C2: a device is bound to the user it was first proven to be, and a * later claim of a different user does not win. * * The ratchet proves the DEVICE; the user id inside a sealed envelope is a * claim its author chose. Without this binding a contact could relabel their * own messages as anyone, and poison that person's delivery key — which forces * the next send UNSEALED and hands the relay the sender sealing exists to hide. */ class DeviceOwnerBindingTest { private class MapStorage : Vault.Storage { val records = LinkedHashMap() override fun read(name: String) = records[name] override fun write(name: String, bytes: ByteArray) { records[name] = bytes } override fun delete(name: String) { records.remove(name) } override fun names() = records.keys.toList() } private fun vault() = Vault( MapStorage(), KeyGenerator.getInstance("AES").apply { init(256) }.generateKey()) @Test fun `first use binds the device to its user`() { val v = vault() assertNull(v.deviceOwner("dev-A")) assertEquals(7L, v.bindDeviceOwner(7L, "dev-A")) assertEquals(7L, v.deviceOwner("dev-A")) } @Test fun `a later different claim does not win`() { val v = vault() v.bindDeviceOwner(7L, "dev-A") assertEquals(7L, v.bindDeviceOwner(42L, "dev-A"), "a bound device must not be re-attributed by a later claim") assertEquals(7L, v.deviceOwner("dev-A")) } @Test fun `distinct devices bind independently`() { val v = vault() v.bindDeviceOwner(7L, "dev-A") assertEquals(42L, v.bindDeviceOwner(42L, "dev-B")) assertEquals(7L, v.deviceOwner("dev-A")) } @Test fun `clearing allows a rebind when an identity change is accepted`() { val v = vault() v.bindDeviceOwner(7L, "dev-A") v.clearDeviceOwner("dev-A") assertNull(v.deviceOwner("dev-A")) assertEquals(42L, v.bindDeviceOwner(42L, "dev-A")) } @Test fun `a zero claim is never bound`() { val v = vault() assertEquals(0L, v.bindDeviceOwner(0L, "dev-C")) assertNull(v.deviceOwner("dev-C")) } }