1package com.peachpasswords.sync23import org.junit.Assert.assertEquals4import org.junit.Assert.assertTrue5import org.junit.Test678910111213class LocalIdentityRecordTest {1415 @Test fun round_trips_every_frozen_field() {16 val credentials = randomLocalIdentityCredentials("device-a")17 val fields = identityRecordFields(credentials, createdAt = 1_700_000_000_000L)1819 val decoded = readIdentityRecord(fields)2021 assertTrue(decoded is IdentityRecord.Current)22 val current = decoded as IdentityRecord.Current23 assertEquals("device-a", current.credentials.deviceId)24 assertTrue(current.credentials.x25519PrivateKey.contentEquals(credentials.x25519PrivateKey))25 assertTrue(current.credentials.x25519PublicKey.contentEquals(credentials.x25519PublicKey))26 assertTrue(current.credentials.ed25519Seed.contentEquals(credentials.ed25519Seed))27 assertTrue(current.credentials.ed25519PublicKey.contentEquals(credentials.ed25519PublicKey))28 assertEquals(1_700_000_000_000L, current.createdAt)29 }3031 @Test fun no_stored_fields_is_absent() {32 assertEquals(IdentityRecord.Absent, readIdentityRecord(emptyMap()))33 }3435 @Test fun legacy_random_record_completes_without_changing_the_identity() {36 val credentials = randomLocalIdentityCredentials("legacy-id")37 val fields = mapOf<String, Any?>(38 FIELD_VERSION to LOCAL_IDENTITY_RECORD_VERSION_LEGACY_RANDOM,39 FIELD_DEVICE_ID to credentials.deviceId,40 FIELD_X25519_PRIVATE to pubkeyToHex(credentials.x25519PrivateKey),41 FIELD_ED25519_SEED to pubkeyToHex(credentials.ed25519Seed),42 )4344 val decoded = readIdentityRecord(fields)4546 assertTrue(decoded is IdentityRecord.LegacyRandom)47 val legacy = decoded as IdentityRecord.LegacyRandom48 assertEquals("legacy-id", legacy.credentials.deviceId)49 assertTrue(legacy.credentials.x25519PrivateKey.contentEquals(credentials.x25519PrivateKey))50 assertTrue(legacy.credentials.ed25519Seed.contentEquals(credentials.ed25519Seed))51 }5253 @Test fun unknown_version_is_invalid() {54 val credentials = randomLocalIdentityCredentials("device-a")55 val fields = identityRecordFields(credentials, 1L) + (FIELD_VERSION to 99)56 assertEquals(IdentityRecord.Invalid, readIdentityRecord(fields))57 }5859 @Test fun stored_public_key_that_does_not_match_the_private_key_is_invalid() {60 val credentials = randomLocalIdentityCredentials("device-a")61 val fields = identityRecordFields(credentials, 1L) + (FIELD_X25519_PUBLIC to "aa".repeat(32))62 assertEquals(IdentityRecord.Invalid, readIdentityRecord(fields))63 }6465 @Test fun missing_creation_time_is_invalid() {66 val credentials = randomLocalIdentityCredentials("device-a")67 val fields = identityRecordFields(credentials, 1L) - FIELD_CREATED_AT68 assertEquals(IdentityRecord.Invalid, readIdentityRecord(fields))69 }7071 @Test fun missing_stored_public_value_is_invalid() {72 val credentials = randomLocalIdentityCredentials("device-a")73 val fields = identityRecordFields(credentials, 1L) - FIELD_ED25519_PUBLIC74 assertEquals(IdentityRecord.Invalid, readIdentityRecord(fields))75 }7677 @Test fun private_material_without_a_version_is_invalid() {78 val credentials = randomLocalIdentityCredentials("device-a")79 val fields = identityRecordFields(credentials, 1L) - FIELD_VERSION80 assertEquals(IdentityRecord.Invalid, readIdentityRecord(fields))81 }8283 @Test fun partial_private_material_is_invalid() {84 val fields = mapOf<String, Any?>(85 FIELD_VERSION to LOCAL_IDENTITY_RECORD_VERSION,86 FIELD_DEVICE_ID to "device-a",87 FIELD_ED25519_SEED to "22".repeat(32),88 )89 assertEquals(IdentityRecord.Invalid, readIdentityRecord(fields))90 }9192 @Test fun malformed_private_hex_is_invalid() {93 val fields = mapOf<String, Any?>(94 FIELD_VERSION to LOCAL_IDENTITY_RECORD_VERSION,95 FIELD_DEVICE_ID to "device-a",96 FIELD_X25519_PRIVATE to "not-hex",97 FIELD_ED25519_SEED to "22".repeat(32),98 )99 assertEquals(IdentityRecord.Invalid, readIdentityRecord(fields))100 }101102 @Test fun blank_device_id_is_invalid() {103 val credentials = randomLocalIdentityCredentials("device-a")104 val fields = identityRecordFields(credentials, 1L) + (FIELD_DEVICE_ID to "")105 assertEquals(IdentityRecord.Invalid, readIdentityRecord(fields))106 }107}