A malicious server could re-serve an old but valid envelope of an item under a new, higher revision: the AAD does not bind the revision and the Merkle root was only checked when head_revision == cursor. The client took it as the latest version, rolled the item back and signed over it in its next manifest. * kv-model Item: `seq: u64` (serde default 0) and `restores: Option<u64>`. * kv-sync replay module: pure decision rules (check_successor, next_version, stamp, same_content). Every pulled live record must authenticate and have seq > the base's seq, unless it carries restores = t with base_revision < t < revision (edit beat a delete this device never saw) or is identical to the base. Otherwise: Integrity alarm. Tombstones and items without a base pass. * engine: check on every pulled record; edit-beats-delete re-seals with restores = tombstone revision; merges write seq = max + 1 and adopt the remote version when only seq/restores differ. Public engine::next_local_version gives the seq/restores for a local save (used by kv-ffi save_item and the tests). * verify_manifest checks the Merkle root whenever no held item is newer than head_revision (previously only at head == cursor). * Tests: replay alarm (clean and pending receivers, plus kv-ffi), harmless replay of the current version, tampered envelope, concurrent equal-seq edits across three devices, edit-beats-delete with a device that skipped the tombstone and a later replay of the restore, legacy items without seq, hidden item with cursor past the manifest head, and the shared item_replay.json decision table. * gen-vectors: envelope vector item payload now includes seq. FFI surface unchanged. Co-Authored-By: Claude Opus 5.5 <[email protected]>
74 lines
5.2 KiB
JSON
74 lines
5.2 KiB
JSON
{
|
|
"aad_layout": "\"kestrove/v1/\" || type || 0x00 || account || 0x00 || vault || 0x00 || item (absent ids = nil UUID)",
|
|
"account_id": "01010101-0101-4101-8101-010101010101",
|
|
"description": "XChaCha20-Poly1305 envelopes with location-binding AAD and 256-byte padding (docs/02 'Envelope format')",
|
|
"item_id": "03030303-0303-4303-8303-030303030303",
|
|
"vault_id": "02020202-0202-4202-8202-020202020202",
|
|
"vectors": [
|
|
{
|
|
"aad": "6b657374726f76652f76312f6974656d000101010101014101810101010101010100020202020202420282020202020202020003030303030343038303030303030303",
|
|
"ciphertext": "12e824b61b2253f40015d22f52ee7412e5be95cf17185bd8490e0e77200d50b5f629c6dfd2e2bccc1d86a06c6453150a96e1c8fc81f1a82b4830f511e831aa66438d35ed9c7d6d11d904b3d53641f05175066f63c0d985ea91738efcd7afb6a205b4a8471fc827a11c51cb598e429227be0e4345bdff4eae584538ca5429e95f70b7258d87a6b52018976695a15b6e77e6c47a49609fa691f602dbeb4a15ea73c87909c7267d7bf84de31762480feab0b96553c2d4046b5ed00c899e30175fbd7333e9da01329d89a3158a715a85a83d81b8a0105e3c2cdd0ffb2f52e1971d0c7ac1c57504fea274b883fd4b65dae757d758cb3ecd7828e7edd44b35cbba4522a45f88134388c878b77659fb5a7ace37",
|
|
"envelope": {
|
|
"alg": "xc20p",
|
|
"ct": "EugkthsiU_QAFdIvUu50EuW-lc8XGFvYSQ4OdyANULX2Kcbf0uK8zB2GoGxkUxUKluHI_IHxqCtIMPUR6DGqZkONNe2cfW0R2QSz1TZB8FF1Bm9jwNmF6pFzjvzXr7aiBbSoRx_IJ6EcUctZjkKSJ74OQ0W9_06uWEU4ylQp6V9wtyWNh6a1IBiXZpWhW2535sR6SWCfppH2AtvrShXqc8h5CccmfXv4TeMXYkgP6rC5ZVPC1ARrXtAMiZ4wF1-9czPp2gEynYmjFYpxWoWoPYG4oBBePCzdD_svUuGXHQx6wcV1BP6idLiD_Utl2udX11jLPs14KOft1Es1y7pFIqRfiBNDiMh4t3ZZ-1p6zjc",
|
|
"kid": "04040404-0404-4404-8404-040404040404",
|
|
"n": "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB",
|
|
"v": 1
|
|
},
|
|
"key": "4242424242424242424242424242424242424242424242424242424242424242",
|
|
"kid": "04040404-0404-4404-8404-040404040404",
|
|
"name": "item payload (padded)",
|
|
"nonce": "010101010101010101010101010101010101010101010101",
|
|
"plaintext": "750000007b226964223a2230333033303330332d303330332d343330332d383330332d303330333033303330333033222c226b696e64223a226c6f67696e222c227469746c65223a224578616d706c65222c22637265617465645f6174223a312c226d6f6469666965645f6174223a312c22736571223a317d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
|
|
},
|
|
{
|
|
"aad": "6b657374726f76652f76312f6974656d2d6b6579000101010101014101810101010101010100020202020202420282020202020202020003030303030343038303030303030303",
|
|
"ciphertext": "89b9440109da7c2a9fa4c5d03a25c7a047b11f9133e7e8ddcff986029675c5106f9240f5ca69911f73dc1106e3f3d32bcc8470e999d6818689daee36907279ec",
|
|
"envelope": {
|
|
"alg": "xc20p",
|
|
"ct": "iblEAQnafCqfpMXQOiXHoEexH5Ez5-jdz_mGApZ1xRBvkkD1ymmRH3PcEQbj89MrzIRw6ZnWgYaJ2u42kHJ57A",
|
|
"kid": "04040404-0404-4404-8404-040404040404",
|
|
"n": "AgICAgICAgICAgICAgICAgICAgICAgIC",
|
|
"v": 1
|
|
},
|
|
"key": "4242424242424242424242424242424242424242424242424242424242424242",
|
|
"kid": "04040404-0404-4404-8404-040404040404",
|
|
"name": "item key: kid || key",
|
|
"nonce": "020202020202020202020202020202020202020202020202",
|
|
"plaintext": "050505050505450585050505050505055555555555555555555555555555555555555555555555555555555555555555"
|
|
},
|
|
{
|
|
"aad": "6b657374726f76652f76312f7661756c742d6d657461000101010101014101810101010101010100020202020202420282020202020202020000000000000000000000000000000000",
|
|
"ciphertext": "0ee485ea37c4e9b6f4ea55e7381f12dbd4390a34b4d1342f9043da961bdcd3b47d1986",
|
|
"envelope": {
|
|
"alg": "xc20p",
|
|
"ct": "DuSF6jfE6bb06lXnOB8S29Q5CjS00TQvkEPalhvc07R9GYY",
|
|
"kid": "04040404-0404-4404-8404-040404040404",
|
|
"n": "AwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMD",
|
|
"v": 1
|
|
},
|
|
"key": "4242424242424242424242424242424242424242424242424242424242424242",
|
|
"kid": "04040404-0404-4404-8404-040404040404",
|
|
"name": "vault metadata",
|
|
"nonce": "030303030303030303030303030303030303030303030303",
|
|
"plaintext": "7b226e616d65223a22506572736f6e616c227d"
|
|
},
|
|
{
|
|
"aad": "6b657374726f76652f76312f6b6579736574000101010101014101810101010101010100000000000000000000000000000000000000000000000000000000000000000000",
|
|
"ciphertext": "e7b3287dd61ee4062f51d81ed4bc13841733671cfd05429e42f7c820906a73e8d8ca3f083b0713fa560a597c65c18cceccbf90ae2a17e711f8d3a9b7c94ba4561d2e0f5d63bbd4bb4f6d5c81b0d903cad7f19e5a89abb43973269f37f8aad8e5",
|
|
"envelope": {
|
|
"alg": "xc20p",
|
|
"ct": "57MofdYe5AYvUdge1LwThBczZxz9BUKeQvfIIJBqc-jYyj8IOwcT-lYKWXxlwYzOzL-QrioX5xH406m3yUukVh0uD11ju9S7T21cgbDZA8rX8Z5aiau0OXMmnzf4qtjl",
|
|
"kid": "04040404-0404-4404-8404-040404040404",
|
|
"n": "BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE",
|
|
"v": 1
|
|
},
|
|
"key": "4242424242424242424242424242424242424242424242424242424242424242",
|
|
"kid": "04040404-0404-4404-8404-040404040404",
|
|
"name": "keyset (80 bytes)",
|
|
"nonce": "040404040404040404040404040404040404040404040404",
|
|
"plaintext": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f"
|
|
}
|
|
]
|
|
}
|