diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/managers/ChillDkgRitualManager.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/managers/ChillDkgRitualManager.kt index 5e2a9c6a..2f80f727 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/managers/ChillDkgRitualManager.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/managers/ChillDkgRitualManager.kt @@ -91,6 +91,12 @@ object ChillDkgRitualManager { * be the nostr identity key: reusing one secret across two protocols means a * flaw in either can reach the other. Deriving it from the same seed keeps it * recoverable from the wallet backup without being the same key. + * + * The `mantra/` prefix is not a brand string and must never follow one. It is an + * input to the hash, so renaming it derives a different host key from the same + * seed -- which loses the outputs of every DKG session already run, since ChillDKG + * needs the host secret key to recover them. The Curated fork of this app keeps it + * byte for byte. Renaming it is a protocol fork. */ private const val HOST_KEY_DERIVATION_TAG = "mantra/chilldkg/host-key/v1" diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/managers/SharedKeyDerivation.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/managers/SharedKeyDerivation.kt index 8589f4eb..265bb79f 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/managers/SharedKeyDerivation.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/managers/SharedKeyDerivation.kt @@ -61,6 +61,16 @@ object SharedKeyDerivation { * Domain separation for the tweak scalars. Versioned so a future scheme can * coexist with keys already derived under this one, and distinct from any other * use of the same threshold key. + * + * The `mantra/` prefix is not a brand string and must never follow one. It is an + * input to the derivation, so changing it changes every key derived under it, + * for the same reason [MARMOT_ADMIN_GROUP_PATH] has to stay put: every room + * already created would be orphaned, and a device on the old string and a device + * on the new one would derive different keys from the same threshold key, so + * their partial signatures would aggregate to nothing that verifies. The Curated + * fork of this app keeps this string byte for byte for exactly that reason -- a + * Mantra member and a Curated member of one group sign under one key. Renaming + * it is a protocol fork, and belongs in a `v2` tag if it is ever wanted. */ private const val TWEAK_TAG = "mantra/shared-key/tweak/v1" diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/nostr/Relays.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/nostr/Relays.kt index 6007748b..12b68c84 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/nostr/Relays.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/nostr/Relays.kt @@ -6,6 +6,10 @@ import com.vitorpamplona.quartz.nip65RelayList.tags.AdvertisedRelayInfo import com.vitorpamplona.quartz.nip65RelayList.tags.AdvertisedRelayType object Relays { + // A running relay, not a brand string: it is in the bootstrap, publish, finder and + // DM sets, so pointing it at a name nobody has stood up would take the app off the + // network. The Curated fork of this app still talks to this same host, so the two + // apps' users find each other here. val ephemeral = RelayUrlNormalizer.normalize("wss://ephemeral.mantra.press") val nos = RelayUrlNormalizer.normalize("wss://nos.lol") diff --git a/composeApp/src/commonTest/kotlin/press/auxiliary/compose/ComposeAppCommonTest.kt b/composeApp/src/commonTest/kotlin/press/mantra/compose/ComposeAppCommonTest.kt similarity index 82% rename from composeApp/src/commonTest/kotlin/press/auxiliary/compose/ComposeAppCommonTest.kt rename to composeApp/src/commonTest/kotlin/press/mantra/compose/ComposeAppCommonTest.kt index 3e548c4a..b143f6d9 100644 --- a/composeApp/src/commonTest/kotlin/press/auxiliary/compose/ComposeAppCommonTest.kt +++ b/composeApp/src/commonTest/kotlin/press/mantra/compose/ComposeAppCommonTest.kt @@ -1,4 +1,4 @@ -package press.auxiliary.compose +package press.mantra.compose import kotlin.test.Test import kotlin.test.assertEquals diff --git a/docs/shared-key-derivation.md b/docs/shared-key-derivation.md index 2332f2f0..69a758e0 100644 --- a/docs/shared-key-derivation.md +++ b/docs/shared-key-derivation.md @@ -65,6 +65,16 @@ Each scalar commits to the key being tweaked as well as the index, so steps cann be reordered or replayed at a different depth to reach the same key. `listOf(0L)` and `listOf(0L, 0L, 0L)` do not collide — there is a test for it. +The `mantra/` prefix is deliberate and is not a brand string: the string is an input to +the hash, so renaming it derives different keys from the same threshold key — orphaning +every room already created, and splitting devices on the new string off from devices on +the old one, since their partial signatures would no longer aggregate to one that +verifies. The Curated fork of this app keeps it byte for byte for that reason, and so +must this one. A rename is a protocol fork and would need a `v2` tag, not an edit to +this one. The ChillDKG host-key tag in `ChillDkgRitualManager` is protected by the same +argument, and `Relays.ephemeral` stays on its `mantra.press` host for the duller reason +that it is a relay that is running. + ### What avoiding BIP32 also avoids With x-only keys there is no single obvious `serP(K_par)`: BIP32 serialises