refactor(mls): move the RFC 9420 engine out of marmot/

`quartz/marmot/mls/` is 11,964 LOC of RFC 9420 that has nothing to do with
Marmot: TLS codec, HPKE, X25519/Ed25519, the ratchet tree, the key schedule,
the secret tree, message framing. Only 3 of its 28 files import anything from
`marmot/` at all.

It already has a second consumer, and that consumer had to reach through the
wrong package to get it: `quic/tls/TlsClient.kt` imports
`quartz.marmot.mls.crypto.X25519` for its TLS 1.3 handshake, which is neither
Marmot nor MLS. `:contextvm`/cordn will be the third, needing the engine
without Marmot's bindings.

So the engine moves to `quartz/mls/` and `marmot/` keeps everything else.
Pure `git mv` plus the package rename across all six source sets (commonMain,
jvmAndroid, appleMain, linuxMain, commonTest, jvmAndroidTest) and the five
modules that reference it. No logic change: `:quartz:jvmTest` is 5074 before
and 5074 after.

The dependency still points the wrong way -- `mls/` retains 10 imports of
`marmot/` -- which the next commits fix. Doing the move first keeps that diff
small enough to read.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012BfD4txdnsaPRXmNXbup9n
This commit is contained in:
Claude
2026-09-18 15:18:45 +00:00
parent 4b49198190
commit 900b046e34
127 changed files with 544 additions and 544 deletions
@@ -208,7 +208,7 @@ import com.vitorpamplona.quartz.experimental.profileGallery.image
import com.vitorpamplona.quartz.experimental.profileGallery.mimeType
import com.vitorpamplona.quartz.marmot.appComponents.agentTextStream.transport.MarmotQuicTransport
import com.vitorpamplona.quartz.marmot.mip00KeyPackages.KeyPackageEvent
import com.vitorpamplona.quartz.marmot.mls.group.MlsGroupStateStore
import com.vitorpamplona.quartz.mls.group.MlsGroupStateStore
import com.vitorpamplona.quartz.nip01Core.core.Address
import com.vitorpamplona.quartz.nip01Core.core.Event
import com.vitorpamplona.quartz.nip01Core.core.HexKey
@@ -377,7 +377,7 @@ class Account(
val client: INostrClient,
val scope: CoroutineScope,
val mlsGroupStateStore: MlsGroupStateStore? = null,
val marmotMessageStore: com.vitorpamplona.quartz.marmot.mls.group.MarmotMessageStore? = null,
val marmotMessageStore: com.vitorpamplona.quartz.mls.group.MarmotMessageStore? = null,
val marmotKeyPackageStore: com.vitorpamplona.quartz.marmot.mip00KeyPackages.KeyPackageBundleStore? = null,
/**
* Durable publish obligations. Null means publish-before-apply does not
@@ -692,7 +692,7 @@ class AccountMarmotActions(
/**
* Revoke admin privileges from [targetPubKey]. Rejects any change that
* would leave the group with zero admins — MIP-03's admin-depletion guard
* in [com.vitorpamplona.quartz.marmot.mls.group.MlsGroup] would otherwise
* in [com.vitorpamplona.quartz.mls.group.MlsGroup] would otherwise
* throw at commit time.
*/
suspend fun revokeMarmotGroupAdmin(
@@ -21,7 +21,7 @@
package com.vitorpamplona.amethyst.model.marmot
import com.vitorpamplona.amethyst.model.preferences.KeyStoreEncryption
import com.vitorpamplona.quartz.marmot.mls.group.MarmotMessageStore
import com.vitorpamplona.quartz.mls.group.MarmotMessageStore
import com.vitorpamplona.quartz.nip01Core.core.Event
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.Dispatchers
@@ -21,7 +21,7 @@
package com.vitorpamplona.amethyst.model.marmot
import com.vitorpamplona.amethyst.model.preferences.KeyStoreEncryption
import com.vitorpamplona.quartz.marmot.mls.group.MlsGroupStateStore
import com.vitorpamplona.quartz.mls.group.MlsGroupStateStore
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
@@ -32,7 +32,7 @@ import com.vitorpamplona.quartz.marmot.appComponents.agentTextStream.AgentTextSt
import com.vitorpamplona.quartz.marmot.appComponents.agentTextStream.InMemoryAgentTextStreamSequenceStore
import com.vitorpamplona.quartz.marmot.appComponents.agentTextStream.PreviewStatus
import com.vitorpamplona.quartz.marmot.appComponents.agentTextStream.RecordOutcome
import com.vitorpamplona.quartz.marmot.mls.crypto.MlsCryptoProvider
import com.vitorpamplona.quartz.mls.crypto.MlsCryptoProvider
import com.vitorpamplona.quartz.nip01Core.core.Event
import com.vitorpamplona.quartz.nip01Core.core.hexToByteArray
import com.vitorpamplona.quartz.nip01Core.core.toHexKey
@@ -24,8 +24,8 @@ import com.vitorpamplona.amethyst.cli.SecureFileIO
import com.vitorpamplona.amethyst.commons.util.deleteOrWarn
import com.vitorpamplona.quartz.marmot.MarmotIngestDedupStore
import com.vitorpamplona.quartz.marmot.mip00KeyPackages.KeyPackageBundleStore
import com.vitorpamplona.quartz.marmot.mls.group.MarmotMessageStore
import com.vitorpamplona.quartz.marmot.mls.group.MlsGroupStateStore
import com.vitorpamplona.quartz.mls.group.MarmotMessageStore
import com.vitorpamplona.quartz.mls.group.MlsGroupStateStore
import com.vitorpamplona.quartz.marmot.protocolCore.MarmotPublishObligationStore
import com.vitorpamplona.quartz.nip01Core.core.Event
import com.vitorpamplona.quartz.nip01Core.core.HexKey
@@ -20,7 +20,7 @@
*/
package com.vitorpamplona.amethyst.commons.marmot
import com.vitorpamplona.quartz.marmot.mls.group.MlsGroupStateStore
import com.vitorpamplona.quartz.mls.group.MlsGroupStateStore
import com.vitorpamplona.quartz.utils.concurrent.ConcurrentMap
/**
@@ -59,12 +59,12 @@ import com.vitorpamplona.quartz.marmot.mip01Groups.MarmotGroupData
import com.vitorpamplona.quartz.marmot.mip02Welcome.WelcomeEvent
import com.vitorpamplona.quartz.marmot.mip03GroupMessages.GroupEvent
import com.vitorpamplona.quartz.marmot.mip03GroupMessages.GroupEventEncryption
import com.vitorpamplona.quartz.marmot.mls.group.MarmotMessageStore
import com.vitorpamplona.quartz.marmot.mls.group.MlsGroup
import com.vitorpamplona.quartz.marmot.mls.group.MlsGroupManager
import com.vitorpamplona.quartz.marmot.mls.group.MlsGroupStateStore
import com.vitorpamplona.quartz.marmot.mls.messages.CommitResult
import com.vitorpamplona.quartz.marmot.mls.tree.Credential
import com.vitorpamplona.quartz.mls.group.MarmotMessageStore
import com.vitorpamplona.quartz.mls.group.MlsGroup
import com.vitorpamplona.quartz.mls.group.MlsGroupManager
import com.vitorpamplona.quartz.mls.group.MlsGroupStateStore
import com.vitorpamplona.quartz.mls.messages.CommitResult
import com.vitorpamplona.quartz.mls.tree.Credential
import com.vitorpamplona.quartz.marmot.protocolCore.GroupLifecycleState
import com.vitorpamplona.quartz.marmot.protocolCore.LocalOutboundGate
import com.vitorpamplona.quartz.marmot.protocolCore.MarmotPublishGate
@@ -92,7 +92,7 @@ class LegacyGroupContractTest {
)
}
private class ProbeStateStore : com.vitorpamplona.quartz.marmot.mls.group.MlsGroupStateStore {
private class ProbeStateStore : com.vitorpamplona.quartz.mls.group.MlsGroupStateStore {
private val states = mutableMapOf<String, ByteArray>()
private val retained = mutableMapOf<String, List<ByteArray>>()
@@ -29,8 +29,8 @@ import com.vitorpamplona.quartz.marmot.appComponents.agentTextStream.transport.M
import com.vitorpamplona.quartz.marmot.appComponents.agentTextStream.transport.MarmotQuicTransport
import com.vitorpamplona.quartz.marmot.mip00KeyPackages.KeyPackageBundleStore
import com.vitorpamplona.quartz.marmot.mip01Groups.MarmotGroupData
import com.vitorpamplona.quartz.marmot.mls.group.MarmotMessageStore
import com.vitorpamplona.quartz.marmot.mls.group.MlsGroupStateStore
import com.vitorpamplona.quartz.mls.group.MarmotMessageStore
import com.vitorpamplona.quartz.mls.group.MlsGroupStateStore
import com.vitorpamplona.quartz.nip01Core.crypto.KeyPair
import com.vitorpamplona.quartz.nip01Core.signers.NostrSignerInternal
import kotlinx.coroutines.CompletableDeferred
@@ -22,8 +22,8 @@ package com.vitorpamplona.amethyst.commons.marmot
import com.vitorpamplona.quartz.marmot.mip00KeyPackages.KeyPackageBundleStore
import com.vitorpamplona.quartz.marmot.mip00KeyPackages.KeyPackageUtils
import com.vitorpamplona.quartz.marmot.mls.group.MarmotMessageStore
import com.vitorpamplona.quartz.marmot.mls.group.MlsGroupStateStore
import com.vitorpamplona.quartz.mls.group.MarmotMessageStore
import com.vitorpamplona.quartz.mls.group.MlsGroupStateStore
import com.vitorpamplona.quartz.nip01Core.crypto.KeyPair
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.RelayUrlNormalizer
import com.vitorpamplona.quartz.nip01Core.signers.NostrSignerInternal
@@ -22,8 +22,8 @@ package com.vitorpamplona.amethyst.commons.marmot
import com.vitorpamplona.quartz.marmot.mip00KeyPackages.KeyPackageBundleStore
import com.vitorpamplona.quartz.marmot.mip01Groups.MarmotGroupData
import com.vitorpamplona.quartz.marmot.mls.group.MarmotMessageStore
import com.vitorpamplona.quartz.marmot.mls.group.MlsGroupStateStore
import com.vitorpamplona.quartz.mls.group.MarmotMessageStore
import com.vitorpamplona.quartz.mls.group.MlsGroupStateStore
import com.vitorpamplona.quartz.nip01Core.crypto.KeyPair
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.RelayUrlNormalizer
import com.vitorpamplona.quartz.nip01Core.signers.NostrSignerInternal
@@ -39,7 +39,7 @@ import kotlin.test.assertTrue
/**
* End-to-end leave + rejoin round-trip at the [MarmotManager] layer.
*
* One level above [com.vitorpamplona.quartz.marmot.mls.MlsGroupManagerTest.testLeaveAndRejoin_SameGroupIdEndToEnd]
* One level above [com.vitorpamplona.quartz.mls.MlsGroupManagerTest.testLeaveAndRejoin_SameGroupIdEndToEnd]
* in quartz, which only exercises the MLS engine. This one drives the full
* commons-layer pipeline:
*
@@ -22,8 +22,8 @@ package com.vitorpamplona.amethyst.commons.marmot
import com.vitorpamplona.quartz.marmot.mip00KeyPackages.KeyPackageBundleStore
import com.vitorpamplona.quartz.marmot.mip01Groups.MarmotGroupData
import com.vitorpamplona.quartz.marmot.mls.group.MarmotMessageStore
import com.vitorpamplona.quartz.marmot.mls.group.MlsGroupStateStore
import com.vitorpamplona.quartz.mls.group.MarmotMessageStore
import com.vitorpamplona.quartz.mls.group.MlsGroupStateStore
import com.vitorpamplona.quartz.nip01Core.crypto.KeyPair
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.RelayUrlNormalizer
import com.vitorpamplona.quartz.nip01Core.signers.NostrSignerInternal
@@ -439,7 +439,7 @@ class MarmotPublishBeforeApplyTest {
assertEquals(listOf(relay), fx.manager.groupRelays(fx.groupId))
}
private class InMemoryStateStore : com.vitorpamplona.quartz.marmot.mls.group.MlsGroupStateStore {
private class InMemoryStateStore : com.vitorpamplona.quartz.mls.group.MlsGroupStateStore {
private val states = mutableMapOf<String, ByteArray>()
private val retained = mutableMapOf<String, List<ByteArray>>()
@@ -21,7 +21,7 @@
package com.vitorpamplona.amethyst.commons.marmot
import com.vitorpamplona.quartz.marmot.mip01Groups.MarmotGroupData
import com.vitorpamplona.quartz.marmot.mls.group.MlsGroupStateStore
import com.vitorpamplona.quartz.mls.group.MlsGroupStateStore
import com.vitorpamplona.quartz.marmot.protocolCore.GroupLifecycleState
import com.vitorpamplona.quartz.marmot.protocolCore.MarmotPublishObligationStore
import com.vitorpamplona.quartz.nip01Core.core.Event
@@ -21,8 +21,8 @@
package com.vitorpamplona.amethyst.commons.marmot
import com.vitorpamplona.quartz.marmot.mip00KeyPackages.KeyPackageBundleStore
import com.vitorpamplona.quartz.marmot.mls.group.MarmotMessageStore
import com.vitorpamplona.quartz.marmot.mls.group.MlsGroupStateStore
import com.vitorpamplona.quartz.mls.group.MarmotMessageStore
import com.vitorpamplona.quartz.mls.group.MlsGroupStateStore
import com.vitorpamplona.quartz.nip01Core.core.Event
// In-memory stand-ins for the durable stores a MarmotManager needs.
@@ -22,8 +22,8 @@ package com.vitorpamplona.marmotbench
import com.vitorpamplona.amethyst.commons.marmot.MarmotPublisher
import com.vitorpamplona.quartz.marmot.mip00KeyPackages.KeyPackageBundleStore
import com.vitorpamplona.quartz.marmot.mls.group.MarmotMessageStore
import com.vitorpamplona.quartz.marmot.mls.group.MlsGroupStateStore
import com.vitorpamplona.quartz.mls.group.MarmotMessageStore
import com.vitorpamplona.quartz.mls.group.MlsGroupStateStore
import com.vitorpamplona.quartz.nip01Core.core.Event
// In-memory stores, matching the commons test doubles byte for byte.
@@ -20,8 +20,8 @@
*/
package com.vitorpamplona.marmotbench
import com.vitorpamplona.quartz.marmot.mls.crypto.Ed25519
import com.vitorpamplona.quartz.marmot.mls.crypto.X25519
import com.vitorpamplona.quartz.mls.crypto.Ed25519
import com.vitorpamplona.quartz.mls.crypto.X25519
// The elliptic-curve primitives on their own.
//
@@ -18,7 +18,7 @@
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.quartz.marmot.mls.crypto
package com.vitorpamplona.quartz.mls.crypto
import com.vitorpamplona.quartz.utils.RandomInstance
import io.github.andreypfau.kotlinx.crypto.Sha512
@@ -18,7 +18,7 @@
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.quartz.marmot.mls.crypto
package com.vitorpamplona.quartz.mls.crypto
import com.vitorpamplona.quartz.utils.RandomInstance
@@ -25,21 +25,21 @@ import com.vitorpamplona.quartz.marmot.mip00KeyPackages.KeyPackageRotationManage
import com.vitorpamplona.quartz.marmot.mip02Welcome.WelcomeEvent
import com.vitorpamplona.quartz.marmot.mip03GroupMessages.GroupEvent
import com.vitorpamplona.quartz.marmot.mip03GroupMessages.GroupEventEncryption
import com.vitorpamplona.quartz.marmot.mls.codec.TlsReader
import com.vitorpamplona.quartz.marmot.mls.framing.ContentType
import com.vitorpamplona.quartz.marmot.mls.framing.MlsMessage
import com.vitorpamplona.quartz.marmot.mls.framing.PrivateMessage
import com.vitorpamplona.quartz.marmot.mls.framing.PublicMessage
import com.vitorpamplona.quartz.marmot.mls.framing.WireFormat
import com.vitorpamplona.quartz.marmot.mls.group.MlsGroupManager
import com.vitorpamplona.quartz.marmot.mls.group.MlsGroupState
import com.vitorpamplona.quartz.marmot.mls.messages.KeyPackageBundle
import com.vitorpamplona.quartz.marmot.mls.messages.Welcome
import com.vitorpamplona.quartz.marmot.protocolCore.ConvergenceAdmission
import com.vitorpamplona.quartz.marmot.protocolCore.ConvergenceResolution
import com.vitorpamplona.quartz.marmot.protocolCore.ConvergenceStatus
import com.vitorpamplona.quartz.marmot.protocolCore.GroupLifecycleState
import com.vitorpamplona.quartz.marmot.protocolCore.MarmotConvergenceEngine
import com.vitorpamplona.quartz.mls.codec.TlsReader
import com.vitorpamplona.quartz.mls.framing.ContentType
import com.vitorpamplona.quartz.mls.framing.MlsMessage
import com.vitorpamplona.quartz.mls.framing.PrivateMessage
import com.vitorpamplona.quartz.mls.framing.PublicMessage
import com.vitorpamplona.quartz.mls.framing.WireFormat
import com.vitorpamplona.quartz.mls.group.MlsGroupManager
import com.vitorpamplona.quartz.mls.group.MlsGroupState
import com.vitorpamplona.quartz.mls.messages.KeyPackageBundle
import com.vitorpamplona.quartz.mls.messages.Welcome
import com.vitorpamplona.quartz.nip01Core.core.Event
import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip01Core.core.toHexKey
@@ -24,7 +24,7 @@ import com.vitorpamplona.quartz.marmot.foundation.appEvents.MarmotAppEvent
import com.vitorpamplona.quartz.marmot.mip01Groups.MarmotGroupData
import com.vitorpamplona.quartz.marmot.mip03GroupMessages.GroupEvent
import com.vitorpamplona.quartz.marmot.mip03GroupMessages.GroupEventEncryption
import com.vitorpamplona.quartz.marmot.mls.group.MlsGroupManager
import com.vitorpamplona.quartz.mls.group.MlsGroupManager
import com.vitorpamplona.quartz.nip01Core.core.Event
import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip01Core.core.toHexKey
@@ -160,15 +160,15 @@ class MarmotOutboundProcessor(
* The commit bytes are already MLS-formatted (PublicMessage envelope).
*
* @param nostrGroupId the Nostr group ID
* @param commitBytes the framed MLS commit bytes from [com.vitorpamplona.quartz.marmot.mls.group.StagedCommit.framedCommitBytes]
* @param commitBytes the framed MLS commit bytes from [com.vitorpamplona.quartz.mls.group.StagedCommit.framedCommitBytes]
* @param exporterKey optional explicit outer-encryption key. Callers
* publishing a Commit MUST pass the **pre-commit** exporter secret
* (from [com.vitorpamplona.quartz.marmot.mls.group.StagedCommit.preCommitExporterSecret])
* (from [com.vitorpamplona.quartz.mls.group.StagedCommit.preCommitExporterSecret])
* so that other existing members at epoch N can decrypt and process
* the commit. If null, falls back to the current epoch's exporter
* secret — which is only correct when the commit has *not* been
* applied locally yet (i.e. this call is made before
* [com.vitorpamplona.quartz.marmot.mls.group.MlsGroup.mergeStagedCommit]).
* [com.vitorpamplona.quartz.mls.group.MlsGroup.mergeStagedCommit]).
* @return the signed GroupEvent ready for relay publishing
*/
suspend fun buildCommitEvent(
@@ -21,7 +21,7 @@
package com.vitorpamplona.quartz.marmot
import com.vitorpamplona.quartz.marmot.mip02Welcome.WelcomeGiftWrap
import com.vitorpamplona.quartz.marmot.mls.messages.CommitResult
import com.vitorpamplona.quartz.mls.messages.CommitResult
import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
@@ -20,8 +20,8 @@
*/
package com.vitorpamplona.quartz.marmot.appComponents
import com.vitorpamplona.quartz.marmot.mls.codec.TlsReader
import com.vitorpamplona.quartz.marmot.mls.codec.TlsWriter
import com.vitorpamplona.quartz.mls.codec.TlsReader
import com.vitorpamplona.quartz.mls.codec.TlsWriter
import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip01Core.core.hexToByteArray
import com.vitorpamplona.quartz.nip01Core.core.toHexKey
@@ -23,14 +23,14 @@ package com.vitorpamplona.quartz.marmot.appComponents
import com.vitorpamplona.quartz.marmot.appComponents.accountIdentityProof.AccountIdentityProofV2
import com.vitorpamplona.quartz.marmot.appComponents.agentTextStream.AgentTextStreamQuicPolicyV1
import com.vitorpamplona.quartz.marmot.mip01Groups.MlsCiphersuite
import com.vitorpamplona.quartz.marmot.mls.components.AppDataDictionary
import com.vitorpamplona.quartz.marmot.mls.components.ComponentData
import com.vitorpamplona.quartz.marmot.mls.components.ComponentsList
import com.vitorpamplona.quartz.marmot.mls.crypto.Ed25519
import com.vitorpamplona.quartz.marmot.mls.crypto.Ed25519KeyPair
import com.vitorpamplona.quartz.marmot.mls.group.MlsGroup
import com.vitorpamplona.quartz.marmot.mls.messages.KeyPackageBundle
import com.vitorpamplona.quartz.marmot.mls.tree.Extension
import com.vitorpamplona.quartz.mls.components.AppDataDictionary
import com.vitorpamplona.quartz.mls.components.ComponentData
import com.vitorpamplona.quartz.mls.components.ComponentsList
import com.vitorpamplona.quartz.mls.crypto.Ed25519
import com.vitorpamplona.quartz.mls.crypto.Ed25519KeyPair
import com.vitorpamplona.quartz.mls.group.MlsGroup
import com.vitorpamplona.quartz.mls.messages.KeyPackageBundle
import com.vitorpamplona.quartz.mls.tree.Extension
import com.vitorpamplona.quartz.nip01Core.core.hexToByteArray
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
@@ -20,8 +20,8 @@
*/
package com.vitorpamplona.quartz.marmot.appComponents
import com.vitorpamplona.quartz.marmot.mls.codec.TlsReader
import com.vitorpamplona.quartz.marmot.mls.codec.TlsWriter
import com.vitorpamplona.quartz.mls.codec.TlsReader
import com.vitorpamplona.quartz.mls.codec.TlsWriter
/** One blob-store endpoint and the locator kind it serves. */
data class BlobStoreEndpointV2(
@@ -20,7 +20,7 @@
*/
package com.vitorpamplona.quartz.marmot.appComponents
import com.vitorpamplona.quartz.marmot.mls.crypto.MlsCryptoProvider
import com.vitorpamplona.quartz.mls.crypto.MlsCryptoProvider
import com.vitorpamplona.quartz.nip01Core.core.toHexKey
import com.vitorpamplona.quartz.nip44Encryption.crypto.ChaCha20Poly1305
import com.vitorpamplona.quartz.utils.RandomInstance
@@ -20,8 +20,8 @@
*/
package com.vitorpamplona.quartz.marmot.appComponents
import com.vitorpamplona.quartz.marmot.mls.codec.TlsReader
import com.vitorpamplona.quartz.marmot.mls.codec.TlsWriter
import com.vitorpamplona.quartz.mls.codec.TlsReader
import com.vitorpamplona.quartz.mls.codec.TlsWriter
/**
* `marmot.group.avatar-url.v1`, component `0x8007` — a group avatar behind an
@@ -20,8 +20,8 @@
*/
package com.vitorpamplona.quartz.marmot.appComponents
import com.vitorpamplona.quartz.marmot.mls.codec.TlsReader
import com.vitorpamplona.quartz.marmot.mls.codec.TlsWriter
import com.vitorpamplona.quartz.mls.codec.TlsReader
import com.vitorpamplona.quartz.mls.codec.TlsWriter
import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip01Core.core.toHexKey
@@ -20,8 +20,8 @@
*/
package com.vitorpamplona.quartz.marmot.appComponents
import com.vitorpamplona.quartz.marmot.mls.codec.TlsReader
import com.vitorpamplona.quartz.marmot.mls.codec.TlsWriter
import com.vitorpamplona.quartz.mls.codec.TlsReader
import com.vitorpamplona.quartz.mls.codec.TlsWriter
/**
* `marmot.group.profile.v1`, component `0x8001` — the group's display name and
@@ -21,9 +21,9 @@
package com.vitorpamplona.quartz.marmot.appComponents
import com.vitorpamplona.quartz.marmot.appComponents.agentTextStream.AgentTextStreamQuicPolicyV1
import com.vitorpamplona.quartz.marmot.mls.components.AppDataDictionary
import com.vitorpamplona.quartz.marmot.mls.components.ComponentsList
import com.vitorpamplona.quartz.marmot.mls.tree.Extension
import com.vitorpamplona.quartz.mls.components.AppDataDictionary
import com.vitorpamplona.quartz.mls.components.ComponentsList
import com.vitorpamplona.quartz.mls.tree.Extension
/**
* The current profile's read view of a GroupContext `app_data_dictionary` — the
@@ -20,8 +20,8 @@
*/
package com.vitorpamplona.quartz.marmot.appComponents
import com.vitorpamplona.quartz.marmot.mls.codec.TlsReader
import com.vitorpamplona.quartz.marmot.mls.codec.TlsWriter
import com.vitorpamplona.quartz.mls.codec.TlsReader
import com.vitorpamplona.quartz.mls.codec.TlsWriter
/**
* `marmot.group.message-retention.v1`, component `0x8005` — disappearing
@@ -20,8 +20,8 @@
*/
package com.vitorpamplona.quartz.marmot.appComponents
import com.vitorpamplona.quartz.marmot.mls.codec.TlsReader
import com.vitorpamplona.quartz.marmot.mls.codec.TlsWriter
import com.vitorpamplona.quartz.mls.codec.TlsReader
import com.vitorpamplona.quartz.mls.codec.TlsWriter
import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip01Core.core.toHexKey
@@ -20,7 +20,7 @@
*/
package com.vitorpamplona.quartz.marmot.appComponents.agentTextStream
import com.vitorpamplona.quartz.marmot.mls.crypto.MlsCryptoProvider
import com.vitorpamplona.quartz.mls.crypto.MlsCryptoProvider
import com.vitorpamplona.quartz.nip44Encryption.crypto.ChaCha20Poly1305
/**
@@ -21,7 +21,7 @@
package com.vitorpamplona.quartz.marmot.appComponents.agentTextStream
import com.vitorpamplona.quartz.marmot.appComponents.AppComponentIds
import com.vitorpamplona.quartz.marmot.mls.components.ComponentData
import com.vitorpamplona.quartz.mls.components.ComponentData
/**
* `marmot.group.agent-text-stream.quic.v1` (component `0x8006`).
@@ -20,7 +20,7 @@
*/
package com.vitorpamplona.quartz.marmot.appComponents.agentTextStream
import com.vitorpamplona.quartz.marmot.mls.crypto.MlsCryptoProvider
import com.vitorpamplona.quartz.mls.crypto.MlsCryptoProvider
/**
* The rolling hash a stream's final kind-9 chat publishes as `stream-hash`,
@@ -20,8 +20,8 @@
*/
package com.vitorpamplona.quartz.marmot.foundation.authorizationProofs
import com.vitorpamplona.quartz.marmot.mls.codec.TlsReader
import com.vitorpamplona.quartz.marmot.mls.codec.TlsWriter
import com.vitorpamplona.quartz.mls.codec.TlsReader
import com.vitorpamplona.quartz.mls.codec.TlsWriter
import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip01Core.core.toHexKey
import com.vitorpamplona.quartz.nip01Core.crypto.EventHasher
@@ -24,9 +24,9 @@ import androidx.compose.runtime.Immutable
import com.vitorpamplona.quartz.marmot.mip00KeyPackages.tags.AppComponentsTag
import com.vitorpamplona.quartz.marmot.mip00KeyPackages.tags.EncodingTag
import com.vitorpamplona.quartz.marmot.mip00KeyPackages.tags.MlsProposalsTag
import com.vitorpamplona.quartz.marmot.mls.components.AppDataDictionary
import com.vitorpamplona.quartz.marmot.mls.components.ComponentsList
import com.vitorpamplona.quartz.marmot.mls.messages.MlsKeyPackage
import com.vitorpamplona.quartz.mls.components.AppDataDictionary
import com.vitorpamplona.quartz.mls.components.ComponentsList
import com.vitorpamplona.quartz.mls.messages.MlsKeyPackage
import com.vitorpamplona.quartz.nip01Core.core.BaseAddressableEvent
import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip01Core.core.TagArrayBuilder
@@ -23,19 +23,19 @@ package com.vitorpamplona.quartz.marmot.mip00KeyPackages
import com.vitorpamplona.quartz.marmot.appComponents.CurrentProfileGroupFactory
import com.vitorpamplona.quartz.marmot.mip00KeyPackages.KeyPackageRotationManager.Companion.SNAPSHOT_VERSION
import com.vitorpamplona.quartz.marmot.mip01Groups.MlsCiphersuite
import com.vitorpamplona.quartz.marmot.mls.codec.TlsReader
import com.vitorpamplona.quartz.marmot.mls.codec.TlsWriter
import com.vitorpamplona.quartz.marmot.mls.crypto.Ed25519
import com.vitorpamplona.quartz.marmot.mls.crypto.MlsCryptoProvider
import com.vitorpamplona.quartz.marmot.mls.crypto.X25519
import com.vitorpamplona.quartz.marmot.mls.messages.KeyPackageBundle
import com.vitorpamplona.quartz.marmot.mls.messages.MlsKeyPackage
import com.vitorpamplona.quartz.marmot.mls.tree.Capabilities
import com.vitorpamplona.quartz.marmot.mls.tree.Credential
import com.vitorpamplona.quartz.marmot.mls.tree.Extension
import com.vitorpamplona.quartz.marmot.mls.tree.LeafNode
import com.vitorpamplona.quartz.marmot.mls.tree.LeafNodeSource
import com.vitorpamplona.quartz.marmot.mls.tree.Lifetime
import com.vitorpamplona.quartz.mls.codec.TlsReader
import com.vitorpamplona.quartz.mls.codec.TlsWriter
import com.vitorpamplona.quartz.mls.crypto.Ed25519
import com.vitorpamplona.quartz.mls.crypto.MlsCryptoProvider
import com.vitorpamplona.quartz.mls.crypto.X25519
import com.vitorpamplona.quartz.mls.messages.KeyPackageBundle
import com.vitorpamplona.quartz.mls.messages.MlsKeyPackage
import com.vitorpamplona.quartz.mls.tree.Capabilities
import com.vitorpamplona.quartz.mls.tree.Credential
import com.vitorpamplona.quartz.mls.tree.Extension
import com.vitorpamplona.quartz.mls.tree.LeafNode
import com.vitorpamplona.quartz.mls.tree.LeafNodeSource
import com.vitorpamplona.quartz.mls.tree.Lifetime
import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.utils.Log
@@ -29,14 +29,14 @@ import com.vitorpamplona.quartz.marmot.mip00KeyPackages.tags.MlsCiphersuiteTag
import com.vitorpamplona.quartz.marmot.mip00KeyPackages.tags.MlsProposalsTag
import com.vitorpamplona.quartz.marmot.mip00KeyPackages.tags.MlsProtocolVersionTag
import com.vitorpamplona.quartz.marmot.mip01Groups.MlsCiphersuite
import com.vitorpamplona.quartz.marmot.mls.codec.TlsReader
import com.vitorpamplona.quartz.marmot.mls.components.AppDataDictionary
import com.vitorpamplona.quartz.marmot.mls.components.ComponentsList
import com.vitorpamplona.quartz.marmot.mls.crypto.MlsCryptoProvider
import com.vitorpamplona.quartz.marmot.mls.framing.MlsMessage
import com.vitorpamplona.quartz.marmot.mls.framing.WireFormat
import com.vitorpamplona.quartz.marmot.mls.messages.MlsKeyPackage
import com.vitorpamplona.quartz.marmot.mls.tree.Credential
import com.vitorpamplona.quartz.mls.codec.TlsReader
import com.vitorpamplona.quartz.mls.components.AppDataDictionary
import com.vitorpamplona.quartz.mls.components.ComponentsList
import com.vitorpamplona.quartz.mls.crypto.MlsCryptoProvider
import com.vitorpamplona.quartz.mls.framing.MlsMessage
import com.vitorpamplona.quartz.mls.framing.WireFormat
import com.vitorpamplona.quartz.mls.messages.MlsKeyPackage
import com.vitorpamplona.quartz.mls.tree.Credential
import com.vitorpamplona.quartz.nip01Core.core.Event
import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip01Core.core.toHexKey
@@ -22,9 +22,9 @@ package com.vitorpamplona.quartz.marmot.mip01Groups
import androidx.compose.runtime.Immutable
import com.vitorpamplona.quartz.marmot.mip01Groups.MarmotGroupData.Companion.decodeTls
import com.vitorpamplona.quartz.marmot.mls.codec.TlsReader
import com.vitorpamplona.quartz.marmot.mls.codec.TlsWriter
import com.vitorpamplona.quartz.marmot.mls.tree.Extension
import com.vitorpamplona.quartz.mls.codec.TlsReader
import com.vitorpamplona.quartz.mls.codec.TlsWriter
import com.vitorpamplona.quartz.mls.tree.Extension
import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip01Core.core.hexToByteArray
import com.vitorpamplona.quartz.nip01Core.core.toHexKey
@@ -20,7 +20,7 @@
*/
package com.vitorpamplona.quartz.marmot.mip01Groups
import com.vitorpamplona.quartz.marmot.mls.crypto.MlsCryptoProvider
import com.vitorpamplona.quartz.mls.crypto.MlsCryptoProvider
/**
* MIP-01 image & Blossom upload key derivations.
@@ -20,7 +20,7 @@
*/
package com.vitorpamplona.quartz.marmot.mip04EncryptedMedia
import com.vitorpamplona.quartz.marmot.mls.crypto.MlsCryptoProvider
import com.vitorpamplona.quartz.mls.crypto.MlsCryptoProvider
import com.vitorpamplona.quartz.nip44Encryption.crypto.ChaCha20Poly1305
import com.vitorpamplona.quartz.utils.RandomInstance
import com.vitorpamplona.quartz.utils.sha256.sha256
@@ -20,10 +20,10 @@
*/
package com.vitorpamplona.quartz.marmot.protocolCore
import com.vitorpamplona.quartz.marmot.mls.framing.ContentType
import com.vitorpamplona.quartz.marmot.mls.group.MlsGroup
import com.vitorpamplona.quartz.marmot.mls.group.MlsGroupManager
import com.vitorpamplona.quartz.marmot.mls.group.MlsGroupState
import com.vitorpamplona.quartz.mls.framing.ContentType
import com.vitorpamplona.quartz.mls.group.MlsGroup
import com.vitorpamplona.quartz.mls.group.MlsGroupManager
import com.vitorpamplona.quartz.mls.group.MlsGroupState
import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip01Core.core.toHexKey
import com.vitorpamplona.quartz.utils.Log
@@ -20,10 +20,10 @@
*/
package com.vitorpamplona.quartz.marmot.protocolCore
import com.vitorpamplona.quartz.marmot.mls.codec.TlsReader
import com.vitorpamplona.quartz.marmot.mls.codec.TlsWriter
import com.vitorpamplona.quartz.marmot.mls.group.MlsGroupManager
import com.vitorpamplona.quartz.marmot.mls.group.MlsGroupState
import com.vitorpamplona.quartz.mls.codec.TlsReader
import com.vitorpamplona.quartz.mls.codec.TlsWriter
import com.vitorpamplona.quartz.mls.group.MlsGroupManager
import com.vitorpamplona.quartz.mls.group.MlsGroupState
import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip01Core.core.toHexKey
import com.vitorpamplona.quartz.utils.sha256.sha256
@@ -20,13 +20,13 @@
*/
package com.vitorpamplona.quartz.marmot.protocolCore
import com.vitorpamplona.quartz.marmot.mls.codec.TlsReader
import com.vitorpamplona.quartz.marmot.mls.framing.ContentType
import com.vitorpamplona.quartz.marmot.mls.framing.MlsMessage
import com.vitorpamplona.quartz.marmot.mls.framing.PublicMessage
import com.vitorpamplona.quartz.marmot.mls.framing.WireFormat
import com.vitorpamplona.quartz.marmot.mls.group.MlsGroup
import com.vitorpamplona.quartz.marmot.mls.group.MlsGroupState
import com.vitorpamplona.quartz.mls.codec.TlsReader
import com.vitorpamplona.quartz.mls.framing.ContentType
import com.vitorpamplona.quartz.mls.framing.MlsMessage
import com.vitorpamplona.quartz.mls.framing.PublicMessage
import com.vitorpamplona.quartz.mls.framing.WireFormat
import com.vitorpamplona.quartz.mls.group.MlsGroup
import com.vitorpamplona.quartz.mls.group.MlsGroupState
import com.vitorpamplona.quartz.nip01Core.core.toHexKey
import com.vitorpamplona.quartz.utils.sha256.sha256
@@ -18,7 +18,7 @@
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.quartz.marmot.mls.codec
package com.vitorpamplona.quartz.mls.codec
/**
* Decoder for TLS presentation language (RFC 8446 Section 3).
@@ -18,7 +18,7 @@
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.quartz.marmot.mls.codec
package com.vitorpamplona.quartz.mls.codec
/**
* Interface for types that can be serialized to TLS presentation language
@@ -18,7 +18,7 @@
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.quartz.marmot.mls.codec
package com.vitorpamplona.quartz.mls.codec
/**
* Encoder for TLS presentation language (RFC 8446 Section 3).
@@ -18,12 +18,12 @@
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.quartz.marmot.mls.components
package com.vitorpamplona.quartz.mls.components
import com.vitorpamplona.quartz.marmot.mls.codec.TlsReader
import com.vitorpamplona.quartz.marmot.mls.codec.TlsSerializable
import com.vitorpamplona.quartz.marmot.mls.codec.TlsWriter
import com.vitorpamplona.quartz.marmot.mls.tree.Extension
import com.vitorpamplona.quartz.mls.codec.TlsReader
import com.vitorpamplona.quartz.mls.codec.TlsSerializable
import com.vitorpamplona.quartz.mls.codec.TlsWriter
import com.vitorpamplona.quartz.mls.tree.Extension
/**
* The `app_data_dictionary` MLS extension (draft-ietf-mls-extensions-10 §4.6),
@@ -18,11 +18,11 @@
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.quartz.marmot.mls.components
package com.vitorpamplona.quartz.mls.components
import com.vitorpamplona.quartz.marmot.mls.codec.TlsReader
import com.vitorpamplona.quartz.marmot.mls.codec.TlsSerializable
import com.vitorpamplona.quartz.marmot.mls.codec.TlsWriter
import com.vitorpamplona.quartz.mls.codec.TlsReader
import com.vitorpamplona.quartz.mls.codec.TlsSerializable
import com.vitorpamplona.quartz.mls.codec.TlsWriter
/**
* One entry in an [AppDataDictionary] (draft-ietf-mls-extensions-10 §4.6).
@@ -18,10 +18,10 @@
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.quartz.marmot.mls.components
package com.vitorpamplona.quartz.mls.components
import com.vitorpamplona.quartz.marmot.mls.codec.TlsReader
import com.vitorpamplona.quartz.marmot.mls.codec.TlsWriter
import com.vitorpamplona.quartz.mls.codec.TlsReader
import com.vitorpamplona.quartz.mls.codec.TlsWriter
/**
* The `ComponentsList` payload shared by the upstream `app_components`
@@ -18,7 +18,7 @@
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.quartz.marmot.mls.crypto
package com.vitorpamplona.quartz.mls.crypto
/**
* Field arithmetic over GF(2^255-19) for Curve25519 and Ed25519.
@@ -18,7 +18,7 @@
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.quartz.marmot.mls.crypto
package com.vitorpamplona.quartz.mls.crypto
/**
* Ed25519 digital signature operations for MLS ciphersuite 0x0001.
@@ -18,7 +18,7 @@
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.quartz.marmot.mls.crypto
package com.vitorpamplona.quartz.mls.crypto
import com.vitorpamplona.quartz.utils.ciphers.AESGCM
@@ -18,11 +18,11 @@
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.quartz.marmot.mls.crypto
package com.vitorpamplona.quartz.mls.crypto
import com.vitorpamplona.quartz.marmot.mls.codec.TlsReader
import com.vitorpamplona.quartz.marmot.mls.codec.TlsSerializable
import com.vitorpamplona.quartz.marmot.mls.codec.TlsWriter
import com.vitorpamplona.quartz.mls.codec.TlsReader
import com.vitorpamplona.quartz.mls.codec.TlsSerializable
import com.vitorpamplona.quartz.mls.codec.TlsWriter
import com.vitorpamplona.quartz.nip44Encryption.crypto.Hkdf
import com.vitorpamplona.quartz.utils.RandomInstance
import com.vitorpamplona.quartz.utils.ciphers.AESGCM
@@ -18,7 +18,7 @@
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.quartz.marmot.mls.crypto
package com.vitorpamplona.quartz.mls.crypto
/**
* X25519 Diffie-Hellman key exchange for MLS DHKEM (RFC 9180).
@@ -18,7 +18,7 @@
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.quartz.marmot.mls.framing
package com.vitorpamplona.quartz.mls.framing
/**
* MLS ContentType (RFC 9420 Section 6.1).
@@ -18,13 +18,13 @@
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.quartz.marmot.mls.framing
package com.vitorpamplona.quartz.mls.framing
import com.vitorpamplona.quartz.marmot.mls.codec.TlsReader
import com.vitorpamplona.quartz.marmot.mls.codec.TlsSerializable
import com.vitorpamplona.quartz.marmot.mls.codec.TlsWriter
import com.vitorpamplona.quartz.marmot.mls.messages.Commit
import com.vitorpamplona.quartz.marmot.mls.messages.Proposal
import com.vitorpamplona.quartz.mls.codec.TlsReader
import com.vitorpamplona.quartz.mls.codec.TlsSerializable
import com.vitorpamplona.quartz.mls.codec.TlsWriter
import com.vitorpamplona.quartz.mls.messages.Commit
import com.vitorpamplona.quartz.mls.messages.Proposal
/**
* MLS MLSMessage (RFC 9420 Section 6).
@@ -18,7 +18,7 @@
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.quartz.marmot.mls.group
package com.vitorpamplona.quartz.mls.group
/**
* Encrypted local storage for decrypted Marmot inner event JSONs.
@@ -18,7 +18,7 @@
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.quartz.marmot.mls.group
package com.vitorpamplona.quartz.mls.group
import com.vitorpamplona.quartz.marmot.appComponents.AdminPolicyV1
import com.vitorpamplona.quartz.marmot.appComponents.AppComponentIds
@@ -27,49 +27,49 @@ import com.vitorpamplona.quartz.marmot.appComponents.agentTextStream.AgentTextSt
import com.vitorpamplona.quartz.marmot.appComponents.agentTextStream.AgentTextStreamQuicPolicyV1
import com.vitorpamplona.quartz.marmot.appComponents.agentTextStream.AgentTextStreamRoles
import com.vitorpamplona.quartz.marmot.mip01Groups.MarmotGroupData
import com.vitorpamplona.quartz.marmot.mls.codec.TlsReader
import com.vitorpamplona.quartz.marmot.mls.codec.TlsWriter
import com.vitorpamplona.quartz.marmot.mls.components.AppDataDictionary
import com.vitorpamplona.quartz.marmot.mls.crypto.Ed25519
import com.vitorpamplona.quartz.marmot.mls.crypto.Ed25519KeyPair
import com.vitorpamplona.quartz.marmot.mls.crypto.Hpke
import com.vitorpamplona.quartz.marmot.mls.crypto.MlsCryptoProvider
import com.vitorpamplona.quartz.marmot.mls.crypto.X25519
import com.vitorpamplona.quartz.marmot.mls.framing.ContentType
import com.vitorpamplona.quartz.marmot.mls.framing.MlsMessage
import com.vitorpamplona.quartz.marmot.mls.framing.PrivateMessage
import com.vitorpamplona.quartz.marmot.mls.framing.PublicMessage
import com.vitorpamplona.quartz.marmot.mls.framing.Sender
import com.vitorpamplona.quartz.marmot.mls.framing.SenderType
import com.vitorpamplona.quartz.marmot.mls.framing.WireFormat
import com.vitorpamplona.quartz.marmot.mls.framing.encodeSender
import com.vitorpamplona.quartz.marmot.mls.group.MlsGroup.Companion.externalJoin
import com.vitorpamplona.quartz.marmot.mls.messages.Commit
import com.vitorpamplona.quartz.marmot.mls.messages.CommitResult
import com.vitorpamplona.quartz.marmot.mls.messages.EncryptedGroupSecrets
import com.vitorpamplona.quartz.marmot.mls.messages.ExternalJoinResult
import com.vitorpamplona.quartz.marmot.mls.messages.GroupContext
import com.vitorpamplona.quartz.marmot.mls.messages.GroupInfo
import com.vitorpamplona.quartz.marmot.mls.messages.GroupSecrets
import com.vitorpamplona.quartz.marmot.mls.messages.KeyPackageBundle
import com.vitorpamplona.quartz.marmot.mls.messages.MlsKeyPackage
import com.vitorpamplona.quartz.marmot.mls.messages.Proposal
import com.vitorpamplona.quartz.marmot.mls.messages.ProposalOrRef
import com.vitorpamplona.quartz.marmot.mls.messages.UpdatePath
import com.vitorpamplona.quartz.marmot.mls.messages.Welcome
import com.vitorpamplona.quartz.marmot.mls.schedule.EpochSecrets
import com.vitorpamplona.quartz.marmot.mls.schedule.KeySchedule
import com.vitorpamplona.quartz.marmot.mls.schedule.SecretTree
import com.vitorpamplona.quartz.marmot.mls.tree.BinaryTree
import com.vitorpamplona.quartz.marmot.mls.tree.Capabilities
import com.vitorpamplona.quartz.marmot.mls.tree.Credential
import com.vitorpamplona.quartz.marmot.mls.tree.Extension
import com.vitorpamplona.quartz.marmot.mls.tree.LeafNode
import com.vitorpamplona.quartz.marmot.mls.tree.LeafNodeSource
import com.vitorpamplona.quartz.marmot.mls.tree.Lifetime
import com.vitorpamplona.quartz.marmot.mls.tree.PathSecretAndKey
import com.vitorpamplona.quartz.marmot.mls.tree.RatchetTree
import com.vitorpamplona.quartz.marmot.mls.tree.UpdatePathNode
import com.vitorpamplona.quartz.mls.codec.TlsReader
import com.vitorpamplona.quartz.mls.codec.TlsWriter
import com.vitorpamplona.quartz.mls.components.AppDataDictionary
import com.vitorpamplona.quartz.mls.crypto.Ed25519
import com.vitorpamplona.quartz.mls.crypto.Ed25519KeyPair
import com.vitorpamplona.quartz.mls.crypto.Hpke
import com.vitorpamplona.quartz.mls.crypto.MlsCryptoProvider
import com.vitorpamplona.quartz.mls.crypto.X25519
import com.vitorpamplona.quartz.mls.framing.ContentType
import com.vitorpamplona.quartz.mls.framing.MlsMessage
import com.vitorpamplona.quartz.mls.framing.PrivateMessage
import com.vitorpamplona.quartz.mls.framing.PublicMessage
import com.vitorpamplona.quartz.mls.framing.Sender
import com.vitorpamplona.quartz.mls.framing.SenderType
import com.vitorpamplona.quartz.mls.framing.WireFormat
import com.vitorpamplona.quartz.mls.framing.encodeSender
import com.vitorpamplona.quartz.mls.group.MlsGroup.Companion.externalJoin
import com.vitorpamplona.quartz.mls.messages.Commit
import com.vitorpamplona.quartz.mls.messages.CommitResult
import com.vitorpamplona.quartz.mls.messages.EncryptedGroupSecrets
import com.vitorpamplona.quartz.mls.messages.ExternalJoinResult
import com.vitorpamplona.quartz.mls.messages.GroupContext
import com.vitorpamplona.quartz.mls.messages.GroupInfo
import com.vitorpamplona.quartz.mls.messages.GroupSecrets
import com.vitorpamplona.quartz.mls.messages.KeyPackageBundle
import com.vitorpamplona.quartz.mls.messages.MlsKeyPackage
import com.vitorpamplona.quartz.mls.messages.Proposal
import com.vitorpamplona.quartz.mls.messages.ProposalOrRef
import com.vitorpamplona.quartz.mls.messages.UpdatePath
import com.vitorpamplona.quartz.mls.messages.Welcome
import com.vitorpamplona.quartz.mls.schedule.EpochSecrets
import com.vitorpamplona.quartz.mls.schedule.KeySchedule
import com.vitorpamplona.quartz.mls.schedule.SecretTree
import com.vitorpamplona.quartz.mls.tree.BinaryTree
import com.vitorpamplona.quartz.mls.tree.Capabilities
import com.vitorpamplona.quartz.mls.tree.Credential
import com.vitorpamplona.quartz.mls.tree.Extension
import com.vitorpamplona.quartz.mls.tree.LeafNode
import com.vitorpamplona.quartz.mls.tree.LeafNodeSource
import com.vitorpamplona.quartz.mls.tree.Lifetime
import com.vitorpamplona.quartz.mls.tree.PathSecretAndKey
import com.vitorpamplona.quartz.mls.tree.RatchetTree
import com.vitorpamplona.quartz.mls.tree.UpdatePathNode
import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip01Core.core.toHexKey
import com.vitorpamplona.quartz.utils.TimeUtils
@@ -132,7 +132,7 @@ class MlsGroup private constructor(
private var interimTranscriptHash: ByteArray,
private val pskStore: MutableMap<String, ByteArray> = mutableMapOf(),
private val pendingProposals: MutableList<PendingProposal> = mutableListOf(),
private val sentKeys: MutableMap<Int, com.vitorpamplona.quartz.marmot.mls.schedule.KeyNonceGeneration> = mutableMapOf(),
private val sentKeys: MutableMap<Int, com.vitorpamplona.quartz.mls.schedule.KeyNonceGeneration> = mutableMapOf(),
/** Staged keys from proposeSigningKeyRotation — only promoted on successful commit */
private var pendingSigningKey: ByteArray? = null,
private var pendingEncryptionKey: ByteArray? = null,
@@ -154,7 +154,7 @@ class MlsGroup private constructor(
val groupId: ByteArray get() = groupContext.groupId
val epoch: Long get() = groupContext.epoch
val leafIndex: Int get() = myLeafIndex
val extensions: List<com.vitorpamplona.quartz.marmot.mls.tree.Extension> get() = groupContext.extensions
val extensions: List<com.vitorpamplona.quartz.mls.tree.Extension> get() = groupContext.extensions
/**
* True while our own leaf is still live in the tree.
@@ -797,7 +797,7 @@ class MlsGroup private constructor(
computeSenderParentHashes(myLeafIndex, preUpdateSiblingHashes)
for (nodeIdx in filteredDp) {
val existing = tree.getNode(nodeIdx)
if (existing is com.vitorpamplona.quartz.marmot.mls.tree.TreeNode.Parent) {
if (existing is com.vitorpamplona.quartz.mls.tree.TreeNode.Parent) {
tree.setParent(
nodeIdx,
existing.parentNode.copy(
@@ -872,11 +872,11 @@ class MlsGroup private constructor(
val node = tree.getNode(resNode) ?: return@mapNotNull null
val recipientPub =
when (node) {
is com.vitorpamplona.quartz.marmot.mls.tree.TreeNode.Leaf -> {
is com.vitorpamplona.quartz.mls.tree.TreeNode.Leaf -> {
node.leafNode.encryptionKey
}
is com.vitorpamplona.quartz.marmot.mls.tree.TreeNode.Parent -> {
is com.vitorpamplona.quartz.mls.tree.TreeNode.Parent -> {
node.parentNode.encryptionKey
}
}
@@ -1855,7 +1855,7 @@ class MlsGroup private constructor(
val (filteredDp, filteredCp) = tree.filteredDirectPath(senderLeafIndex)
for (nodeIdx in filteredDp) {
val existing = tree.getNode(nodeIdx)
if (existing is com.vitorpamplona.quartz.marmot.mls.tree.TreeNode.Parent) {
if (existing is com.vitorpamplona.quartz.mls.tree.TreeNode.Parent) {
tree.setParent(
nodeIdx,
existing.parentNode.copy(
@@ -2304,7 +2304,7 @@ class MlsGroup private constructor(
): Pair<Map<Int, ByteArray>, ByteArray> = computeSenderParentHashes(tree, senderLeafIndex, preUpdateSiblingHashes)
private fun computeSenderParentHashes(
tree: com.vitorpamplona.quartz.marmot.mls.tree.RatchetTree,
tree: com.vitorpamplona.quartz.mls.tree.RatchetTree,
senderLeafIndex: Int,
preUpdateSiblingHashes: Map<Int, ByteArray>,
): Pair<Map<Int, ByteArray>, ByteArray> {
@@ -2335,7 +2335,7 @@ class MlsGroup private constructor(
val parentIdx = filteredDp[i + 1]
val parentLevel = filteredLevels[i + 1]
val parentNode = tree.getNode(parentIdx)
if (parentNode !is com.vitorpamplona.quartz.marmot.mls.tree.TreeNode.Parent) {
if (parentNode !is com.vitorpamplona.quartz.mls.tree.TreeNode.Parent) {
hashes[xIdx] = ByteArray(0)
continue
}
@@ -2358,7 +2358,7 @@ class MlsGroup private constructor(
val immediateParentLevel = filteredLevels.first()
val immediateParent = tree.getNode(immediateParentIdx)
val leafParentHash =
if (immediateParent is com.vitorpamplona.quartz.marmot.mls.tree.TreeNode.Parent) {
if (immediateParent is com.vitorpamplona.quartz.mls.tree.TreeNode.Parent) {
val siblingTreeHash =
preUpdateSiblingHashes[immediateParentLevel]
?: error("missing pre-update sibling tree hash at level $immediateParentLevel")
@@ -3147,7 +3147,7 @@ class MlsGroup private constructor(
* (without constructing an [MlsGroup] first).
*/
private fun computeExternalSenderParentHashes(
tree: com.vitorpamplona.quartz.marmot.mls.tree.RatchetTree,
tree: com.vitorpamplona.quartz.mls.tree.RatchetTree,
senderLeafIndex: Int,
preUpdateSiblingHashes: Map<Int, ByteArray>,
): Pair<Map<Int, ByteArray>, ByteArray> {
@@ -3160,7 +3160,7 @@ class MlsGroup private constructor(
val xIdx = directPath[i]
val parentIdx = directPath[i + 1]
val parentNode = tree.getNode(parentIdx)
if (parentNode !is com.vitorpamplona.quartz.marmot.mls.tree.TreeNode.Parent) {
if (parentNode !is com.vitorpamplona.quartz.mls.tree.TreeNode.Parent) {
hashes[xIdx] = ByteArray(0)
continue
}
@@ -3176,7 +3176,7 @@ class MlsGroup private constructor(
val immediateParentIdx = directPath.first()
val immediateParent = tree.getNode(immediateParentIdx)
val leafParentHash =
if (immediateParent is com.vitorpamplona.quartz.marmot.mls.tree.TreeNode.Parent) {
if (immediateParent is com.vitorpamplona.quartz.mls.tree.TreeNode.Parent) {
val siblingTreeHash =
preUpdateSiblingHashes[0]
?: error("missing pre-update sibling tree hash at leaf level")
@@ -3978,7 +3978,7 @@ class MlsGroup private constructor(
computeExternalSenderParentHashes(tree, myLeafIndex, preUpdateSiblingHashes)
for (nodeIdx in BinaryTree.directPath(myLeafIndex, tree.leafCount)) {
val existing = tree.getNode(nodeIdx)
if (existing is com.vitorpamplona.quartz.marmot.mls.tree.TreeNode.Parent) {
if (existing is com.vitorpamplona.quartz.mls.tree.TreeNode.Parent) {
tree.setParent(
nodeIdx,
existing.parentNode.copy(
@@ -4021,11 +4021,11 @@ class MlsGroup private constructor(
val node = tree.getNode(resNode) ?: return@mapNotNull null
val recipientPub =
when (node) {
is com.vitorpamplona.quartz.marmot.mls.tree.TreeNode.Leaf -> {
is com.vitorpamplona.quartz.mls.tree.TreeNode.Leaf -> {
node.leafNode.encryptionKey
}
is com.vitorpamplona.quartz.marmot.mls.tree.TreeNode.Parent -> {
is com.vitorpamplona.quartz.mls.tree.TreeNode.Parent -> {
node.parentNode.encryptionKey
}
}
@@ -18,22 +18,22 @@
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.quartz.marmot.mls.group
package com.vitorpamplona.quartz.mls.group
import com.vitorpamplona.quartz.marmot.appComponents.AdminPolicyV1
import com.vitorpamplona.quartz.marmot.appComponents.GroupLifecycleV1
import com.vitorpamplona.quartz.marmot.mls.codec.TlsReader
import com.vitorpamplona.quartz.marmot.mls.codec.TlsWriter
import com.vitorpamplona.quartz.marmot.mls.components.ComponentsList
import com.vitorpamplona.quartz.marmot.mls.crypto.MlsCryptoProvider
import com.vitorpamplona.quartz.marmot.mls.framing.PublicMessage
import com.vitorpamplona.quartz.marmot.mls.group.MlsGroupManager.Companion.EPOCH_RETENTION_WINDOW
import com.vitorpamplona.quartz.marmot.mls.messages.CommitResult
import com.vitorpamplona.quartz.marmot.mls.messages.ExternalJoinResult
import com.vitorpamplona.quartz.marmot.mls.messages.KeyPackageBundle
import com.vitorpamplona.quartz.marmot.mls.schedule.KeySchedule
import com.vitorpamplona.quartz.marmot.mls.schedule.SecretTree
import com.vitorpamplona.quartz.marmot.mls.tree.Extension
import com.vitorpamplona.quartz.mls.codec.TlsReader
import com.vitorpamplona.quartz.mls.codec.TlsWriter
import com.vitorpamplona.quartz.mls.components.ComponentsList
import com.vitorpamplona.quartz.mls.crypto.MlsCryptoProvider
import com.vitorpamplona.quartz.mls.framing.PublicMessage
import com.vitorpamplona.quartz.mls.group.MlsGroupManager.Companion.EPOCH_RETENTION_WINDOW
import com.vitorpamplona.quartz.mls.messages.CommitResult
import com.vitorpamplona.quartz.mls.messages.ExternalJoinResult
import com.vitorpamplona.quartz.mls.messages.KeyPackageBundle
import com.vitorpamplona.quartz.mls.schedule.KeySchedule
import com.vitorpamplona.quartz.mls.schedule.SecretTree
import com.vitorpamplona.quartz.mls.tree.Extension
import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.sync.Mutex
@@ -270,7 +270,7 @@ class MlsGroupManager(
nostrGroupId: HexKey,
identity: ByteArray,
signingKey: ByteArray? = null,
initialExtensions: List<com.vitorpamplona.quartz.marmot.mls.tree.Extension> = emptyList(),
initialExtensions: List<com.vitorpamplona.quartz.mls.tree.Extension> = emptyList(),
): MlsGroup =
mutex.withLock {
Log.d(TAG) { "createGroup($nostrGroupId): creating new MLS group" }
@@ -603,7 +603,7 @@ class MlsGroupManager(
senderLeafIndex: Int,
confirmationTag: ByteArray,
signature: ByteArray = ByteArray(0),
wireFormat: com.vitorpamplona.quartz.marmot.mls.framing.WireFormat = com.vitorpamplona.quartz.marmot.mls.framing.WireFormat.PUBLIC_MESSAGE,
wireFormat: com.vitorpamplona.quartz.mls.framing.WireFormat = com.vitorpamplona.quartz.mls.framing.WireFormat.PUBLIC_MESSAGE,
) = mutex.withLock {
val group = requireGroup(nostrGroupId)
@@ -702,7 +702,7 @@ class MlsGroupManager(
// command, so we MUST persist here or reloaded state
// silently reverts to the pre-commit extensions (including
// admin list).
if (result.contentType == com.vitorpamplona.quartz.marmot.mls.framing.ContentType.COMMIT && group.epoch != preEpoch) {
if (result.contentType == com.vitorpamplona.quartz.mls.framing.ContentType.COMMIT && group.epoch != preEpoch) {
pushRetainedEpoch(nostrGroupId, retainedBefore)
persistGroup(nostrGroupId)
}
@@ -1000,15 +1000,15 @@ class MlsGroupManager(
try {
val secretTree = SecretTree(retained.encryptionSecret, retained.leafCount)
val mlsMsg =
com.vitorpamplona.quartz.marmot.mls.framing.MlsMessage
com.vitorpamplona.quartz.mls.framing.MlsMessage
.decodeTls(TlsReader(messageBytes))
if (mlsMsg.wireFormat != com.vitorpamplona.quartz.marmot.mls.framing.WireFormat.PRIVATE_MESSAGE) {
if (mlsMsg.wireFormat != com.vitorpamplona.quartz.mls.framing.WireFormat.PRIVATE_MESSAGE) {
return null
}
val privMsg =
com.vitorpamplona.quartz.marmot.mls.framing.PrivateMessage
com.vitorpamplona.quartz.mls.framing.PrivateMessage
.decodeTls(TlsReader(mlsMsg.payload))
if (privMsg.epoch != retained.epoch) return null
@@ -18,14 +18,14 @@
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.quartz.marmot.mls.group
package com.vitorpamplona.quartz.mls.group
import com.vitorpamplona.quartz.marmot.mls.codec.TlsReader
import com.vitorpamplona.quartz.marmot.mls.codec.TlsWriter
import com.vitorpamplona.quartz.marmot.mls.messages.GroupContext
import com.vitorpamplona.quartz.marmot.mls.messages.Proposal
import com.vitorpamplona.quartz.marmot.mls.schedule.EpochSecrets
import com.vitorpamplona.quartz.marmot.mls.schedule.SenderRatchetState
import com.vitorpamplona.quartz.mls.codec.TlsReader
import com.vitorpamplona.quartz.mls.codec.TlsWriter
import com.vitorpamplona.quartz.mls.messages.GroupContext
import com.vitorpamplona.quartz.mls.messages.Proposal
import com.vitorpamplona.quartz.mls.schedule.EpochSecrets
import com.vitorpamplona.quartz.mls.schedule.SenderRatchetState
/**
* Serializable snapshot of an MLS group's complete state.
@@ -46,7 +46,7 @@ import com.vitorpamplona.quartz.marmot.mls.schedule.SenderRatchetState
* [senderRatchetStates] carries each sender's live SecretTree ratchet position
* (RFC 9420 §9). Preserving it is what stops the restored local member from
* re-emitting an already-used generation within the same epoch — see
* [com.vitorpamplona.quartz.marmot.mls.schedule.SecretTree.exportSenderStates].
* [com.vitorpamplona.quartz.mls.schedule.SecretTree.exportSenderStates].
* It is optional (empty for STATE_VERSION 1 blobs) so older persisted state
* still decodes.
*/
@@ -18,7 +18,7 @@
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.quartz.marmot.mls.group
package com.vitorpamplona.quartz.mls.group
/**
* Interface for encrypted local storage of MLS group state.
@@ -18,13 +18,13 @@
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.quartz.marmot.mls.messages
package com.vitorpamplona.quartz.mls.messages
import com.vitorpamplona.quartz.marmot.mls.codec.TlsReader
import com.vitorpamplona.quartz.marmot.mls.codec.TlsSerializable
import com.vitorpamplona.quartz.marmot.mls.codec.TlsWriter
import com.vitorpamplona.quartz.marmot.mls.tree.LeafNode
import com.vitorpamplona.quartz.marmot.mls.tree.UpdatePathNode
import com.vitorpamplona.quartz.mls.codec.TlsReader
import com.vitorpamplona.quartz.mls.codec.TlsSerializable
import com.vitorpamplona.quartz.mls.codec.TlsWriter
import com.vitorpamplona.quartz.mls.tree.LeafNode
import com.vitorpamplona.quartz.mls.tree.UpdatePathNode
/**
* MLS Commit (RFC 9420 Section 12.4).
@@ -93,7 +93,7 @@ data class UpdatePath(
* Result of creating a Commit: the MLS messages to distribute.
*
* [commitBytes] is the raw TLS-encoded [Commit] struct (RFC 9420 §12.4), useful
* for unit tests and the [com.vitorpamplona.quartz.marmot.mls.group.MlsGroup.processCommit]
* for unit tests and the [com.vitorpamplona.quartz.mls.group.MlsGroup.processCommit]
* entry point. For on-the-wire distribution, callers MUST publish
* [framedCommitBytes] (the MlsMessage(PublicMessage(FramedContent(commit))) envelope)
* so that receivers can parse the sender's leaf index and confirmation tag.
@@ -130,17 +130,17 @@ data class CommitResult(
}
/**
* Result of [com.vitorpamplona.quartz.marmot.mls.group.MlsGroup.externalJoin].
* Result of [com.vitorpamplona.quartz.mls.group.MlsGroup.externalJoin].
*
* [commitBytes] is the raw TLS-encoded [Commit] struct. For on-the-wire
* distribution to existing group members, callers MUST publish [framedCommitBytes]
* — a `MlsMessage(PublicMessage(FramedContent(commit)))` envelope with sender
* `new_member_commit` (RFC 9420 §12.4.3) — so that receivers can parse the
* confirmation_tag and process the commit via
* [com.vitorpamplona.quartz.marmot.mls.group.MlsGroup.processFramedCommit].
* [com.vitorpamplona.quartz.mls.group.MlsGroup.processFramedCommit].
*/
data class ExternalJoinResult(
val group: com.vitorpamplona.quartz.marmot.mls.group.MlsGroup,
val group: com.vitorpamplona.quartz.mls.group.MlsGroup,
val commitBytes: ByteArray,
val framedCommitBytes: ByteArray,
) {
@@ -18,16 +18,16 @@
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.quartz.marmot.mls.messages
package com.vitorpamplona.quartz.mls.messages
import com.vitorpamplona.quartz.marmot.appComponents.AppComponentIds
import com.vitorpamplona.quartz.marmot.mls.codec.TlsReader
import com.vitorpamplona.quartz.marmot.mls.codec.TlsSerializable
import com.vitorpamplona.quartz.marmot.mls.codec.TlsWriter
import com.vitorpamplona.quartz.marmot.mls.components.AppDataDictionary
import com.vitorpamplona.quartz.marmot.mls.crypto.MlsCryptoProvider
import com.vitorpamplona.quartz.marmot.mls.tree.Extension
import com.vitorpamplona.quartz.marmot.mls.tree.LeafNode
import com.vitorpamplona.quartz.mls.codec.TlsReader
import com.vitorpamplona.quartz.mls.codec.TlsSerializable
import com.vitorpamplona.quartz.mls.codec.TlsWriter
import com.vitorpamplona.quartz.mls.components.AppDataDictionary
import com.vitorpamplona.quartz.mls.crypto.MlsCryptoProvider
import com.vitorpamplona.quartz.mls.tree.Extension
import com.vitorpamplona.quartz.mls.tree.LeafNode
/**
* MLS KeyPackage (RFC 9420 Section 10).
@@ -18,13 +18,13 @@
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.quartz.marmot.mls.messages
package com.vitorpamplona.quartz.mls.messages
import com.vitorpamplona.quartz.marmot.mls.codec.TlsReader
import com.vitorpamplona.quartz.marmot.mls.codec.TlsSerializable
import com.vitorpamplona.quartz.marmot.mls.codec.TlsWriter
import com.vitorpamplona.quartz.marmot.mls.tree.Extension
import com.vitorpamplona.quartz.marmot.mls.tree.LeafNode
import com.vitorpamplona.quartz.mls.codec.TlsReader
import com.vitorpamplona.quartz.mls.codec.TlsSerializable
import com.vitorpamplona.quartz.mls.codec.TlsWriter
import com.vitorpamplona.quartz.mls.tree.Extension
import com.vitorpamplona.quartz.mls.tree.LeafNode
/**
* MLS Proposal types (RFC 9420 Section 12).
@@ -18,14 +18,14 @@
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.quartz.marmot.mls.messages
package com.vitorpamplona.quartz.mls.messages
import com.vitorpamplona.quartz.marmot.mls.codec.TlsReader
import com.vitorpamplona.quartz.marmot.mls.codec.TlsSerializable
import com.vitorpamplona.quartz.marmot.mls.codec.TlsWriter
import com.vitorpamplona.quartz.marmot.mls.crypto.HpkeCiphertext
import com.vitorpamplona.quartz.marmot.mls.crypto.MlsCryptoProvider
import com.vitorpamplona.quartz.marmot.mls.tree.Extension
import com.vitorpamplona.quartz.mls.codec.TlsReader
import com.vitorpamplona.quartz.mls.codec.TlsSerializable
import com.vitorpamplona.quartz.mls.codec.TlsWriter
import com.vitorpamplona.quartz.mls.crypto.HpkeCiphertext
import com.vitorpamplona.quartz.mls.crypto.MlsCryptoProvider
import com.vitorpamplona.quartz.mls.tree.Extension
/**
* MLS Welcome message (RFC 9420 Section 12.4.3.1).
@@ -18,9 +18,9 @@
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.quartz.marmot.mls.schedule
package com.vitorpamplona.quartz.mls.schedule
import com.vitorpamplona.quartz.marmot.mls.crypto.MlsCryptoProvider
import com.vitorpamplona.quartz.mls.crypto.MlsCryptoProvider
/**
* MLS Key Schedule (RFC 9420 Section 8).
@@ -18,10 +18,10 @@
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.quartz.marmot.mls.schedule
package com.vitorpamplona.quartz.mls.schedule
import com.vitorpamplona.quartz.marmot.mls.crypto.MlsCryptoProvider
import com.vitorpamplona.quartz.marmot.mls.tree.BinaryTree
import com.vitorpamplona.quartz.mls.crypto.MlsCryptoProvider
import com.vitorpamplona.quartz.mls.tree.BinaryTree
/**
* MLS Secret Tree (RFC 9420 Section 9).
@@ -18,7 +18,7 @@
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.quartz.marmot.mls.tree
package com.vitorpamplona.quartz.mls.tree
/**
* Left-balanced binary tree index arithmetic for MLS ratchet trees (RFC 9420 Section 7.1).
@@ -18,11 +18,11 @@
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.quartz.marmot.mls.tree
package com.vitorpamplona.quartz.mls.tree
import com.vitorpamplona.quartz.marmot.mls.codec.TlsReader
import com.vitorpamplona.quartz.marmot.mls.codec.TlsSerializable
import com.vitorpamplona.quartz.marmot.mls.codec.TlsWriter
import com.vitorpamplona.quartz.mls.codec.TlsReader
import com.vitorpamplona.quartz.mls.codec.TlsSerializable
import com.vitorpamplona.quartz.mls.codec.TlsWriter
/**
* MLS Credential (RFC 9420 Section 5.3).
@@ -18,11 +18,11 @@
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.quartz.marmot.mls.tree
package com.vitorpamplona.quartz.mls.tree
import com.vitorpamplona.quartz.marmot.mls.codec.TlsReader
import com.vitorpamplona.quartz.marmot.mls.codec.TlsSerializable
import com.vitorpamplona.quartz.marmot.mls.codec.TlsWriter
import com.vitorpamplona.quartz.mls.codec.TlsReader
import com.vitorpamplona.quartz.mls.codec.TlsSerializable
import com.vitorpamplona.quartz.mls.codec.TlsWriter
/**
* MLS ParentNode (RFC 9420 Section 7.1).
@@ -18,12 +18,12 @@
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.quartz.marmot.mls.tree
package com.vitorpamplona.quartz.mls.tree
import com.vitorpamplona.quartz.marmot.mls.codec.TlsReader
import com.vitorpamplona.quartz.marmot.mls.codec.TlsSerializable
import com.vitorpamplona.quartz.marmot.mls.codec.TlsWriter
import com.vitorpamplona.quartz.marmot.mls.crypto.MlsCryptoProvider
import com.vitorpamplona.quartz.mls.codec.TlsReader
import com.vitorpamplona.quartz.mls.codec.TlsSerializable
import com.vitorpamplona.quartz.mls.codec.TlsWriter
import com.vitorpamplona.quartz.mls.crypto.MlsCryptoProvider
/**
* MLS Ratchet Tree (RFC 9420 Section 7).
@@ -461,7 +461,7 @@ class RatchetTree(
// reject the UpdatePath with `UpdatePathError(PathMismatch)`.
val nodeSecret = MlsCryptoProvider.deriveSecret(currentSecret, "node")
val kp =
com.vitorpamplona.quartz.marmot.mls.crypto.Hpke
com.vitorpamplona.quartz.mls.crypto.Hpke
.deriveKeyPair(nodeSecret)
results.add(PathSecretAndKey(currentSecret, kp.privateKey, kp.publicKey))
@@ -610,7 +610,7 @@ sealed class TreeNode : TlsSerializable {
/** UpdatePath node: public key + encrypted path secrets for copath nodes */
data class UpdatePathNode(
val encryptionKey: ByteArray,
val encryptedPathSecret: List<com.vitorpamplona.quartz.marmot.mls.crypto.HpkeCiphertext>,
val encryptedPathSecret: List<com.vitorpamplona.quartz.mls.crypto.HpkeCiphertext>,
) : TlsSerializable {
override fun encodeTls(writer: TlsWriter) {
writer.putOpaqueVarInt(encryptionKey)
@@ -635,7 +635,7 @@ data class UpdatePathNode(
encryptionKey = reader.readOpaqueVarInt(),
encryptedPathSecret =
reader.readVectorVarInt {
com.vitorpamplona.quartz.marmot.mls.crypto.HpkeCiphertext
com.vitorpamplona.quartz.mls.crypto.HpkeCiphertext
.decodeTls(it)
},
)
@@ -56,7 +56,7 @@ class SharedKeyCache {
* hex string). The precomputed [hash] is only a bucket selector — [equals] does
* the authoritative full-content comparison, so hash collisions can never return
* the wrong peer's secret. Callers must treat the passed arrays as immutable
* (the same value-type contract [com.vitorpamplona.quartz.marmot.mls.crypto.X25519KeyPair]
* (the same value-type contract [com.vitorpamplona.quartz.mls.crypto.X25519KeyPair]
* relies on when used as a map key).
*/
private class CacheKey(
@@ -24,7 +24,7 @@ import com.vitorpamplona.quartz.marmot.mip01Groups.MarmotGroupData
import com.vitorpamplona.quartz.marmot.mip01Groups.MarmotGroupImageCipher
import com.vitorpamplona.quartz.marmot.mip01Groups.MarmotGroupImageEncryption
import com.vitorpamplona.quartz.marmot.mip01Groups.Mip01ImageCrypto
import com.vitorpamplona.quartz.marmot.mls.codec.TlsReader
import com.vitorpamplona.quartz.mls.codec.TlsReader
import com.vitorpamplona.quartz.nip01Core.core.hexToByteArray
import com.vitorpamplona.quartz.nip01Core.core.toHexKey
import com.vitorpamplona.quartz.nip44Encryption.crypto.ChaCha20Poly1305
@@ -20,8 +20,8 @@
*/
package com.vitorpamplona.quartz.marmot.protocolCore
import com.vitorpamplona.quartz.marmot.mls.group.MlsGroup
import com.vitorpamplona.quartz.marmot.mls.group.MlsGroupState
import com.vitorpamplona.quartz.mls.group.MlsGroup
import com.vitorpamplona.quartz.mls.group.MlsGroupState
import com.vitorpamplona.quartz.nip01Core.core.toHexKey
import com.vitorpamplona.quartz.utils.sha256.sha256
import kotlin.test.Test
@@ -18,9 +18,9 @@
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.quartz.marmot.mls
package com.vitorpamplona.quartz.mls
import com.vitorpamplona.quartz.marmot.mls.tree.BinaryTree
import com.vitorpamplona.quartz.mls.tree.BinaryTree
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFails
@@ -18,11 +18,11 @@
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.quartz.marmot.mls
package com.vitorpamplona.quartz.mls
import com.vitorpamplona.quartz.marmot.mls.crypto.MlsCryptoProvider
import com.vitorpamplona.quartz.marmot.mls.messages.GroupContext
import com.vitorpamplona.quartz.marmot.mls.schedule.KeySchedule
import com.vitorpamplona.quartz.mls.crypto.MlsCryptoProvider
import com.vitorpamplona.quartz.mls.messages.GroupContext
import com.vitorpamplona.quartz.mls.schedule.KeySchedule
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFalse
@@ -18,24 +18,24 @@
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.quartz.marmot.mls
package com.vitorpamplona.quartz.mls
import com.vitorpamplona.quartz.marmot.mls.codec.TlsReader
import com.vitorpamplona.quartz.marmot.mls.framing.ContentType
import com.vitorpamplona.quartz.marmot.mls.framing.MlsMessage
import com.vitorpamplona.quartz.marmot.mls.framing.PrivateMessage
import com.vitorpamplona.quartz.marmot.mls.framing.WireFormat
import com.vitorpamplona.quartz.marmot.mls.messages.Commit
import com.vitorpamplona.quartz.marmot.mls.messages.GroupContext
import com.vitorpamplona.quartz.marmot.mls.messages.Proposal
import com.vitorpamplona.quartz.marmot.mls.messages.ProposalOrRef
import com.vitorpamplona.quartz.marmot.mls.tree.Capabilities
import com.vitorpamplona.quartz.marmot.mls.tree.Credential
import com.vitorpamplona.quartz.marmot.mls.tree.Extension
import com.vitorpamplona.quartz.marmot.mls.tree.LeafNode
import com.vitorpamplona.quartz.marmot.mls.tree.LeafNodeSource
import com.vitorpamplona.quartz.marmot.mls.tree.Lifetime
import com.vitorpamplona.quartz.marmot.mls.tree.ParentNode
import com.vitorpamplona.quartz.mls.codec.TlsReader
import com.vitorpamplona.quartz.mls.framing.ContentType
import com.vitorpamplona.quartz.mls.framing.MlsMessage
import com.vitorpamplona.quartz.mls.framing.PrivateMessage
import com.vitorpamplona.quartz.mls.framing.WireFormat
import com.vitorpamplona.quartz.mls.messages.Commit
import com.vitorpamplona.quartz.mls.messages.GroupContext
import com.vitorpamplona.quartz.mls.messages.Proposal
import com.vitorpamplona.quartz.mls.messages.ProposalOrRef
import com.vitorpamplona.quartz.mls.tree.Capabilities
import com.vitorpamplona.quartz.mls.tree.Credential
import com.vitorpamplona.quartz.mls.tree.Extension
import com.vitorpamplona.quartz.mls.tree.LeafNode
import com.vitorpamplona.quartz.mls.tree.LeafNodeSource
import com.vitorpamplona.quartz.mls.tree.Lifetime
import com.vitorpamplona.quartz.mls.tree.ParentNode
import kotlin.test.Test
import kotlin.test.assertContentEquals
import kotlin.test.assertEquals
@@ -18,11 +18,11 @@
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.quartz.marmot.mls
package com.vitorpamplona.quartz.mls
import com.vitorpamplona.quartz.marmot.mls.codec.TlsReader
import com.vitorpamplona.quartz.marmot.mls.codec.TlsSerializable
import com.vitorpamplona.quartz.marmot.mls.codec.TlsWriter
import com.vitorpamplona.quartz.mls.codec.TlsReader
import com.vitorpamplona.quartz.mls.codec.TlsSerializable
import com.vitorpamplona.quartz.mls.codec.TlsWriter
import kotlin.test.Test
import kotlin.test.assertContentEquals
import kotlin.test.assertEquals
@@ -18,12 +18,12 @@
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.quartz.marmot.mls.group
package com.vitorpamplona.quartz.mls.group
import com.vitorpamplona.quartz.marmot.mls.codec.TlsReader
import com.vitorpamplona.quartz.marmot.mls.framing.MlsMessage
import com.vitorpamplona.quartz.marmot.mls.framing.PublicMessage
import com.vitorpamplona.quartz.marmot.mls.framing.WireFormat
import com.vitorpamplona.quartz.mls.codec.TlsReader
import com.vitorpamplona.quartz.mls.framing.MlsMessage
import com.vitorpamplona.quartz.mls.framing.PublicMessage
import com.vitorpamplona.quartz.mls.framing.WireFormat
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
@@ -18,10 +18,10 @@
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.quartz.marmot.mls.interop
package com.vitorpamplona.quartz.mls.interop
import com.vitorpamplona.quartz.TestResourceLoader
import com.vitorpamplona.quartz.marmot.mls.crypto.MlsCryptoProvider
import com.vitorpamplona.quartz.mls.crypto.MlsCryptoProvider
import com.vitorpamplona.quartz.nip01Core.core.JsonMapper
import com.vitorpamplona.quartz.nip01Core.core.hexToByteArray
import com.vitorpamplona.quartz.nip01Core.core.toHexKey
@@ -18,10 +18,10 @@
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.quartz.marmot.mls.interop
package com.vitorpamplona.quartz.mls.interop
import com.vitorpamplona.quartz.TestResourceLoader
import com.vitorpamplona.quartz.marmot.mls.schedule.KeySchedule
import com.vitorpamplona.quartz.mls.schedule.KeySchedule
import com.vitorpamplona.quartz.nip01Core.core.JsonMapper
import com.vitorpamplona.quartz.nip01Core.core.hexToByteArray
import com.vitorpamplona.quartz.nip01Core.core.toHexKey
@@ -18,16 +18,16 @@
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.quartz.marmot.mls.interop
package com.vitorpamplona.quartz.mls.interop
import com.vitorpamplona.quartz.TestResourceLoader
import com.vitorpamplona.quartz.marmot.mls.codec.TlsReader
import com.vitorpamplona.quartz.marmot.mls.codec.TlsWriter
import com.vitorpamplona.quartz.marmot.mls.framing.MlsMessage
import com.vitorpamplona.quartz.marmot.mls.framing.WireFormat
import com.vitorpamplona.quartz.marmot.mls.messages.Commit
import com.vitorpamplona.quartz.marmot.mls.messages.MlsKeyPackage
import com.vitorpamplona.quartz.marmot.mls.tree.RatchetTree
import com.vitorpamplona.quartz.mls.codec.TlsReader
import com.vitorpamplona.quartz.mls.codec.TlsWriter
import com.vitorpamplona.quartz.mls.framing.MlsMessage
import com.vitorpamplona.quartz.mls.framing.WireFormat
import com.vitorpamplona.quartz.mls.messages.Commit
import com.vitorpamplona.quartz.mls.messages.MlsKeyPackage
import com.vitorpamplona.quartz.mls.tree.RatchetTree
import com.vitorpamplona.quartz.nip01Core.core.JsonMapper
import com.vitorpamplona.quartz.nip01Core.core.hexToByteArray
import kotlin.test.Test
@@ -18,7 +18,7 @@
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.quartz.marmot.mls.interop
package com.vitorpamplona.quartz.mls.interop
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@@ -18,12 +18,12 @@
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.quartz.marmot.mls.interop
package com.vitorpamplona.quartz.mls.interop
import com.vitorpamplona.quartz.TestResourceLoader
import com.vitorpamplona.quartz.marmot.mls.codec.TlsReader
import com.vitorpamplona.quartz.marmot.mls.framing.MlsMessage
import com.vitorpamplona.quartz.marmot.mls.framing.WireFormat
import com.vitorpamplona.quartz.mls.codec.TlsReader
import com.vitorpamplona.quartz.mls.framing.MlsMessage
import com.vitorpamplona.quartz.mls.framing.WireFormat
import com.vitorpamplona.quartz.nip01Core.core.JsonMapper
import com.vitorpamplona.quartz.nip01Core.core.hexToByteArray
import kotlin.test.Test
@@ -18,10 +18,10 @@
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.quartz.marmot.mls.interop
package com.vitorpamplona.quartz.mls.interop
import com.vitorpamplona.quartz.TestResourceLoader
import com.vitorpamplona.quartz.marmot.mls.schedule.SecretTree
import com.vitorpamplona.quartz.mls.schedule.SecretTree
import com.vitorpamplona.quartz.nip01Core.core.JsonMapper
import com.vitorpamplona.quartz.nip01Core.core.hexToByteArray
import com.vitorpamplona.quartz.nip01Core.core.toHexKey
@@ -18,11 +18,11 @@
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.quartz.marmot.mls.interop
package com.vitorpamplona.quartz.mls.interop
import com.vitorpamplona.quartz.TestResourceLoader
import com.vitorpamplona.quartz.marmot.mls.codec.TlsWriter
import com.vitorpamplona.quartz.marmot.mls.crypto.MlsCryptoProvider
import com.vitorpamplona.quartz.mls.codec.TlsWriter
import com.vitorpamplona.quartz.mls.crypto.MlsCryptoProvider
import com.vitorpamplona.quartz.nip01Core.core.JsonMapper
import com.vitorpamplona.quartz.nip01Core.core.hexToByteArray
import com.vitorpamplona.quartz.nip01Core.core.toHexKey
@@ -18,12 +18,12 @@
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.quartz.marmot.mls.interop
package com.vitorpamplona.quartz.mls.interop
import com.vitorpamplona.quartz.TestResourceLoader
import com.vitorpamplona.quartz.marmot.mls.codec.TlsReader
import com.vitorpamplona.quartz.marmot.mls.codec.TlsWriter
import com.vitorpamplona.quartz.marmot.mls.tree.RatchetTree
import com.vitorpamplona.quartz.mls.codec.TlsReader
import com.vitorpamplona.quartz.mls.codec.TlsWriter
import com.vitorpamplona.quartz.mls.tree.RatchetTree
import com.vitorpamplona.quartz.nip01Core.core.JsonMapper
import com.vitorpamplona.quartz.nip01Core.core.hexToByteArray
import com.vitorpamplona.quartz.nip01Core.core.toHexKey
@@ -18,10 +18,10 @@
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.quartz.marmot.mls.interop
package com.vitorpamplona.quartz.mls.interop
import com.vitorpamplona.quartz.TestResourceLoader
import com.vitorpamplona.quartz.marmot.mls.tree.BinaryTree
import com.vitorpamplona.quartz.mls.tree.BinaryTree
import com.vitorpamplona.quartz.nip01Core.core.JsonMapper
import kotlin.test.Test
import kotlin.test.assertEquals
@@ -18,12 +18,12 @@
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.quartz.marmot.mls.interop
package com.vitorpamplona.quartz.mls.interop
import com.vitorpamplona.quartz.TestResourceLoader
import com.vitorpamplona.quartz.marmot.mls.codec.TlsReader
import com.vitorpamplona.quartz.marmot.mls.codec.TlsWriter
import com.vitorpamplona.quartz.marmot.mls.tree.RatchetTree
import com.vitorpamplona.quartz.mls.codec.TlsReader
import com.vitorpamplona.quartz.mls.codec.TlsWriter
import com.vitorpamplona.quartz.mls.tree.RatchetTree
import com.vitorpamplona.quartz.nip01Core.core.JsonMapper
import com.vitorpamplona.quartz.nip01Core.core.hexToByteArray
import com.vitorpamplona.quartz.nip01Core.core.toHexKey
@@ -18,13 +18,13 @@
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.quartz.marmot.mls.interop
package com.vitorpamplona.quartz.mls.interop
import com.vitorpamplona.quartz.TestResourceLoader
import com.vitorpamplona.quartz.marmot.mls.codec.TlsReader
import com.vitorpamplona.quartz.marmot.mls.codec.TlsWriter
import com.vitorpamplona.quartz.marmot.mls.tree.BinaryTree
import com.vitorpamplona.quartz.marmot.mls.tree.RatchetTree
import com.vitorpamplona.quartz.mls.codec.TlsReader
import com.vitorpamplona.quartz.mls.codec.TlsWriter
import com.vitorpamplona.quartz.mls.tree.BinaryTree
import com.vitorpamplona.quartz.mls.tree.RatchetTree
import com.vitorpamplona.quartz.nip01Core.core.JsonMapper
import com.vitorpamplona.quartz.nip01Core.core.hexToByteArray
import com.vitorpamplona.quartz.nip01Core.core.toHexKey
@@ -18,19 +18,19 @@
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.quartz.marmot.mls.interop
package com.vitorpamplona.quartz.mls.interop
import com.vitorpamplona.quartz.TestResourceLoader
import com.vitorpamplona.quartz.marmot.mls.codec.TlsReader
import com.vitorpamplona.quartz.marmot.mls.crypto.MlsCryptoProvider
import com.vitorpamplona.quartz.marmot.mls.crypto.X25519
import com.vitorpamplona.quartz.marmot.mls.framing.MlsMessage
import com.vitorpamplona.quartz.marmot.mls.framing.WireFormat
import com.vitorpamplona.quartz.marmot.mls.messages.GroupInfo
import com.vitorpamplona.quartz.marmot.mls.messages.GroupSecrets
import com.vitorpamplona.quartz.marmot.mls.messages.MlsKeyPackage
import com.vitorpamplona.quartz.marmot.mls.messages.Welcome
import com.vitorpamplona.quartz.marmot.mls.tree.RatchetTree
import com.vitorpamplona.quartz.mls.codec.TlsReader
import com.vitorpamplona.quartz.mls.crypto.MlsCryptoProvider
import com.vitorpamplona.quartz.mls.crypto.X25519
import com.vitorpamplona.quartz.mls.framing.MlsMessage
import com.vitorpamplona.quartz.mls.framing.WireFormat
import com.vitorpamplona.quartz.mls.messages.GroupInfo
import com.vitorpamplona.quartz.mls.messages.GroupSecrets
import com.vitorpamplona.quartz.mls.messages.MlsKeyPackage
import com.vitorpamplona.quartz.mls.messages.Welcome
import com.vitorpamplona.quartz.mls.tree.RatchetTree
import com.vitorpamplona.quartz.nip01Core.core.JsonMapper
import com.vitorpamplona.quartz.nip01Core.core.hexToByteArray
import kotlin.test.Test
@@ -18,7 +18,7 @@
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.quartz.marmot.mls.crypto
package com.vitorpamplona.quartz.mls.crypto
import com.vitorpamplona.quartz.utils.RandomInstance
import io.github.andreypfau.kotlinx.crypto.Sha512
@@ -18,7 +18,7 @@
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.quartz.marmot.mls.crypto
package com.vitorpamplona.quartz.mls.crypto
import com.vitorpamplona.quartz.utils.RandomInstance
@@ -24,11 +24,11 @@ import com.vitorpamplona.quartz.marmot.mip00KeyPackages.KeyPackageRotationManage
import com.vitorpamplona.quartz.marmot.mip01Groups.MarmotGroupData
import com.vitorpamplona.quartz.marmot.mip03GroupMessages.GroupEvent
import com.vitorpamplona.quartz.marmot.mip03GroupMessages.GroupEventEncryption
import com.vitorpamplona.quartz.marmot.mls.group.MlsGroupManager
import com.vitorpamplona.quartz.marmot.protocolCore.ConvergencePolicy
import com.vitorpamplona.quartz.marmot.protocolCore.ConvergenceStatus
import com.vitorpamplona.quartz.marmot.protocolCore.GroupLifecycleState
import com.vitorpamplona.quartz.marmot.protocolCore.MarmotConvergenceEngine
import com.vitorpamplona.quartz.mls.group.MlsGroupManager
import com.vitorpamplona.quartz.nip01Core.core.toHexKey
import com.vitorpamplona.quartz.utils.sha256.sha256
import kotlinx.coroutines.runBlocking
@@ -23,10 +23,10 @@ package com.vitorpamplona.quartz.marmot
import com.vitorpamplona.quartz.marmot.mip01Groups.MarmotGroupData
import com.vitorpamplona.quartz.marmot.mip02Welcome.WelcomeEvent
import com.vitorpamplona.quartz.marmot.mip03GroupMessages.GroupEvent
import com.vitorpamplona.quartz.marmot.mls.codec.TlsReader
import com.vitorpamplona.quartz.marmot.mls.group.MlsGroup
import com.vitorpamplona.quartz.marmot.mls.group.MlsGroupManager
import com.vitorpamplona.quartz.marmot.mls.messages.KeyPackageBundle
import com.vitorpamplona.quartz.mls.codec.TlsReader
import com.vitorpamplona.quartz.mls.group.MlsGroup
import com.vitorpamplona.quartz.mls.group.MlsGroupManager
import com.vitorpamplona.quartz.mls.messages.KeyPackageBundle
import com.vitorpamplona.quartz.nip01Core.core.hexToByteArray
import com.vitorpamplona.quartz.nip01Core.core.toHexKey
import com.vitorpamplona.quartz.nip01Core.crypto.KeyPair
@@ -405,10 +405,10 @@ class MarmotMipBehaviorTest {
// must reject because Remove is admin-only.
val proposals =
listOf(
com.vitorpamplona.quartz.marmot.mls.group
com.vitorpamplona.quartz.mls.group
.PendingProposal(
proposal =
com.vitorpamplona.quartz.marmot.mls.messages
com.vitorpamplona.quartz.mls.messages
.Proposal
.Remove(removedLeafIndex = 0),
senderLeafIndex = 1,
@@ -444,10 +444,10 @@ class MarmotMipBehaviorTest {
// proposal list passes.
val proposals =
listOf(
com.vitorpamplona.quartz.marmot.mls.group
com.vitorpamplona.quartz.mls.group
.PendingProposal(
proposal =
com.vitorpamplona.quartz.marmot.mls.messages
com.vitorpamplona.quartz.mls.messages
.Proposal
.SelfRemove(),
senderLeafIndex = 99,
@@ -470,10 +470,10 @@ class MarmotMipBehaviorTest {
val alice = manager.getGroup(groupId)!!
val proposals =
listOf(
com.vitorpamplona.quartz.marmot.mls.group
com.vitorpamplona.quartz.mls.group
.PendingProposal(
proposal =
com.vitorpamplona.quartz.marmot.mls.messages
com.vitorpamplona.quartz.mls.messages
.Proposal
.GroupContextExtensions(
extensions =
@@ -517,7 +517,7 @@ class MarmotMipBehaviorTest {
val staged = alice.pendingProposalsSnapshot()
assertEquals(1, staged.size, "buildSelfRemoveProposalMessage must also stage to pending pool")
val entry = staged.single()
assertIs<com.vitorpamplona.quartz.marmot.mls.messages.Proposal.SelfRemove>(entry.proposal)
assertIs<com.vitorpamplona.quartz.mls.messages.Proposal.SelfRemove>(entry.proposal)
assertEquals(alice.leafIndex, entry.senderLeafIndex)
// The captured AC bytes are what RFC 9420 §5.2's MakeProposalRef
// hashes — must be present so a peer's commit referencing this
@@ -574,7 +574,7 @@ class MarmotMipBehaviorTest {
val (alice, bob) = build2MemberGroupWithBobJoined()
val proposal =
com.vitorpamplona.quartz.marmot.mls.messages
com.vitorpamplona.quartz.mls.messages
.Proposal
.SelfRemove()
val before = alice.pendingProposalsSnapshot().size
@@ -582,14 +582,14 @@ class MarmotMipBehaviorTest {
val result = alice.decrypt(wireBytes)
assertEquals(
com.vitorpamplona.quartz.marmot.mls.framing.ContentType.PROPOSAL,
com.vitorpamplona.quartz.mls.framing.ContentType.PROPOSAL,
result.contentType,
)
assertEquals(bob.leafIndex, result.senderLeafIndex)
val after = alice.pendingProposalsSnapshot()
assertEquals(before + 1, after.size, "decrypt must stage the proposal in pending pool")
val staged = after.last()
assertIs<com.vitorpamplona.quartz.marmot.mls.messages.Proposal.SelfRemove>(staged.proposal)
assertIs<com.vitorpamplona.quartz.mls.messages.Proposal.SelfRemove>(staged.proposal)
assertEquals(bob.leafIndex, staged.senderLeafIndex)
assertNotNull(
staged.authenticatedContentBytes,
@@ -610,7 +610,7 @@ class MarmotMipBehaviorTest {
val (alice, bob) = build2MemberGroupWithBobJoined()
val proposal =
com.vitorpamplona.quartz.marmot.mls.messages
com.vitorpamplona.quartz.mls.messages
.Proposal
.Psk(pskType = 1, pskId = ByteArray(16) { 0xAB.toByte() }, pskNonce = ByteArray(16))
val wireBytes = bob.encryptProposalAsPrivateMessage(proposal)
@@ -658,7 +658,7 @@ class MarmotMipBehaviorTest {
@Test
fun secretTree_rejectsRatchetJumpsBeyondCap() {
val st =
com.vitorpamplona.quartz.marmot.mls.schedule.SecretTree(
com.vitorpamplona.quartz.mls.schedule.SecretTree(
encryptionSecret = ByteArray(32),
leafCount = 1,
)
@@ -682,7 +682,7 @@ class MarmotMipBehaviorTest {
@Test
fun privateMessage_rejectsOversizedAuthenticatedData() {
val w =
com.vitorpamplona.quartz.marmot.mls.codec
com.vitorpamplona.quartz.mls.codec
.TlsWriter()
w.putOpaqueVarInt(ByteArray(32)) // group_id
w.putUint64(0L) // epoch
@@ -692,9 +692,9 @@ class MarmotMipBehaviorTest {
w.putOpaqueVarInt(ByteArray(64)) // ciphertext (small)
val ex =
assertFailsWith<IllegalArgumentException> {
com.vitorpamplona.quartz.marmot.mls.framing.PrivateMessage
com.vitorpamplona.quartz.mls.framing.PrivateMessage
.decodeTls(
com.vitorpamplona.quartz.marmot.mls.codec
com.vitorpamplona.quartz.mls.codec
.TlsReader(w.toByteArray()),
)
}
@@ -717,9 +717,9 @@ class MarmotMipBehaviorTest {
fun verifyTreeParentHashesForJoin_acceptsSingleMemberTree() {
val alice = MlsGroup.create(aliceId.hexToByteArray())
val tree =
com.vitorpamplona.quartz.marmot.mls.tree.RatchetTree
com.vitorpamplona.quartz.mls.tree.RatchetTree
.decodeTls(
com.vitorpamplona.quartz.marmot.mls.codec
com.vitorpamplona.quartz.mls.codec
.TlsReader(alice.exportTreeBytes()),
)
assertNull(MlsGroup.verifyTreeParentHashesForJoin(tree))
@@ -749,9 +749,9 @@ class MarmotMipBehaviorTest {
val alice = manager.getGroup(groupId)!!
val originalTree =
com.vitorpamplona.quartz.marmot.mls.tree.RatchetTree
com.vitorpamplona.quartz.mls.tree.RatchetTree
.decodeTls(
com.vitorpamplona.quartz.marmot.mls.codec
com.vitorpamplona.quartz.mls.codec
.TlsReader(alice.exportTreeBytes()),
)
@@ -763,7 +763,7 @@ class MarmotMipBehaviorTest {
for (i in 0 until originalTree.leafCount) {
val leaf = originalTree.getLeaf(i) ?: continue
if (leaf.leafNodeSource ==
com.vitorpamplona.quartz.marmot.mls.tree.LeafNodeSource.COMMIT
com.vitorpamplona.quartz.mls.tree.LeafNodeSource.COMMIT
) {
val tampered = leaf.copy(parentHash = ByteArray(32) { 0x99.toByte() })
originalTree.setLeaf(i, tampered)
@@ -823,7 +823,7 @@ class MarmotMipBehaviorTest {
)
// Missing 0xF2EE.
val caps =
com.vitorpamplona.quartz.marmot.mls.tree.Capabilities(
com.vitorpamplona.quartz.mls.tree.Capabilities(
extensions = emptyList(),
proposals = listOf(0x000A),
credentials = listOf(0x0001),
@@ -847,7 +847,7 @@ class MarmotMipBehaviorTest {
credentials = emptyList(),
)
val caps =
com.vitorpamplona.quartz.marmot.mls.tree.Capabilities(
com.vitorpamplona.quartz.mls.tree.Capabilities(
extensions = emptyList(),
proposals = emptyList(),
credentials = listOf(0x0001),
@@ -866,7 +866,7 @@ class MarmotMipBehaviorTest {
credentials = listOf(0x0001),
)
val caps =
com.vitorpamplona.quartz.marmot.mls.tree.Capabilities(
com.vitorpamplona.quartz.mls.tree.Capabilities(
extensions = listOf(0xF2EE, 0x1234),
proposals = listOf(0x000A, 0x000B),
credentials = listOf(0x0001, 0x0002),
@@ -905,7 +905,7 @@ class MarmotMipBehaviorTest {
* (SelfRemove), then re-sign so the KP's outer signature still
* validates. Useful for testing the §7.2 gate in isolation.
*/
private fun createKeyPackageWithoutSelfRemove(identity: String): com.vitorpamplona.quartz.marmot.mls.messages.MlsKeyPackage {
private fun createKeyPackageWithoutSelfRemove(identity: String): com.vitorpamplona.quartz.mls.messages.MlsKeyPackage {
val tempGroup = MlsGroup.create(identity.hexToByteArray())
val bundle = tempGroup.createKeyPackage(identity.hexToByteArray(), ByteArray(0))
val original = bundle.keyPackage
@@ -923,7 +923,7 @@ class MarmotMipBehaviorTest {
originalLeaf.copy(capabilities = tamperedCaps).let { lf ->
val tbs = lf.encodeTbs()
val sig =
com.vitorpamplona.quartz.marmot.mls.crypto.MlsCryptoProvider
com.vitorpamplona.quartz.mls.crypto.MlsCryptoProvider
.signWithLabel(bundle.signaturePrivateKey, "LeafNodeTBS", tbs)
lf.copy(signature = sig)
}
@@ -931,7 +931,7 @@ class MarmotMipBehaviorTest {
val unsigned = original.copy(leafNode = tamperedLeaf, signature = ByteArray(0))
return unsigned.copy(
signature =
com.vitorpamplona.quartz.marmot.mls.crypto.MlsCryptoProvider
com.vitorpamplona.quartz.mls.crypto.MlsCryptoProvider
.signWithLabel(bundle.signaturePrivateKey, "KeyPackageTBS", unsigned.encodeTbs()),
)
}
@@ -977,7 +977,7 @@ class MarmotMipBehaviorTest {
alice.registerPsk(pskId, pskValue)
val proposal =
com.vitorpamplona.quartz.marmot.mls.messages
com.vitorpamplona.quartz.mls.messages
.Proposal
.Psk(pskType = 1, pskId = pskId, pskNonce = pskNonce)
@@ -985,11 +985,11 @@ class MarmotMipBehaviorTest {
// Reference computation per §5.3 (PSKType=1, no usage/group/epoch).
val zero = ByteArray(32)
val crypto = com.vitorpamplona.quartz.marmot.mls.crypto.MlsCryptoProvider
val crypto = com.vitorpamplona.quartz.mls.crypto.MlsCryptoProvider
val pskExtracted = crypto.hkdfExtract(salt = zero, ikm = pskValue)
val labelWriter =
com.vitorpamplona.quartz.marmot.mls.codec
com.vitorpamplona.quartz.mls.codec
.TlsWriter()
labelWriter.putUint8(1) // PSKType external
labelWriter.putOpaqueVarInt(pskId)
@@ -1022,7 +1022,7 @@ class MarmotMipBehaviorTest {
alice.registerPsk(pskId, ByteArray(32))
val proposal =
com.vitorpamplona.quartz.marmot.mls.messages
com.vitorpamplona.quartz.mls.messages
.Proposal
.Psk(pskType = 2, pskId = pskId, pskNonce = ByteArray(16))
@@ -1045,11 +1045,11 @@ class MarmotMipBehaviorTest {
alice.registerPsk(idB, ByteArray(32) { 0x44 })
val pskA =
com.vitorpamplona.quartz.marmot.mls.messages
com.vitorpamplona.quartz.mls.messages
.Proposal
.Psk(pskType = 1, pskId = idA, pskNonce = ByteArray(8))
val pskB =
com.vitorpamplona.quartz.marmot.mls.messages
com.vitorpamplona.quartz.mls.messages
.Proposal
.Psk(pskType = 1, pskId = idB, pskNonce = ByteArray(8))
@@ -23,10 +23,10 @@ package com.vitorpamplona.quartz.marmot
import com.vitorpamplona.quartz.marmot.mip00KeyPackages.KeyPackageRotationManager
import com.vitorpamplona.quartz.marmot.mip03GroupMessages.GroupEvent
import com.vitorpamplona.quartz.marmot.mip03GroupMessages.GroupEventEncryption
import com.vitorpamplona.quartz.marmot.mls.group.MlsGroupManager
import com.vitorpamplona.quartz.marmot.mls.group.MlsGroupStateStore
import com.vitorpamplona.quartz.marmot.protocolCore.ConvergenceStatus
import com.vitorpamplona.quartz.marmot.protocolCore.GroupLifecycleState
import com.vitorpamplona.quartz.mls.group.MlsGroupManager
import com.vitorpamplona.quartz.mls.group.MlsGroupStateStore
import com.vitorpamplona.quartz.nip01Core.core.toHexKey
import com.vitorpamplona.quartz.nip01Core.crypto.KeyPair
import com.vitorpamplona.quartz.nip01Core.signers.NostrSignerInternal
@@ -380,28 +380,28 @@ class MarmotPipelineTest {
// The framedCommitBytes must decode as an MlsMessage(PublicMessage(commit))
val framed = commitResult.framedCommitBytes
val mlsMessage =
com.vitorpamplona.quartz.marmot.mls.framing.MlsMessage
com.vitorpamplona.quartz.mls.framing.MlsMessage
.decodeTls(
com.vitorpamplona.quartz.marmot.mls.codec
com.vitorpamplona.quartz.mls.codec
.TlsReader(framed),
)
assertEquals(
com.vitorpamplona.quartz.marmot.mls.framing.WireFormat.PUBLIC_MESSAGE,
com.vitorpamplona.quartz.mls.framing.WireFormat.PUBLIC_MESSAGE,
mlsMessage.wireFormat,
)
val publicMessage =
com.vitorpamplona.quartz.marmot.mls.framing.PublicMessage
com.vitorpamplona.quartz.mls.framing.PublicMessage
.decodeTls(
com.vitorpamplona.quartz.marmot.mls.codec
com.vitorpamplona.quartz.mls.codec
.TlsReader(mlsMessage.payload),
)
assertEquals(
com.vitorpamplona.quartz.marmot.mls.framing.ContentType.COMMIT,
com.vitorpamplona.quartz.mls.framing.ContentType.COMMIT,
publicMessage.contentType,
)
assertEquals(
com.vitorpamplona.quartz.marmot.mls.framing.SenderType.MEMBER,
com.vitorpamplona.quartz.mls.framing.SenderType.MEMBER,
publicMessage.sender.senderType,
)
assertNotNull(publicMessage.confirmationTag, "confirmation_tag must be present on a commit")
@@ -431,13 +431,13 @@ class MarmotPipelineTest {
val exporterKey = manager.exporterSecret(groupId)
val mlsBytes = GroupEventEncryption.decrypt(event.content, exporterKey)
val mlsMessage =
com.vitorpamplona.quartz.marmot.mls.framing.MlsMessage
com.vitorpamplona.quartz.mls.framing.MlsMessage
.decodeTls(
com.vitorpamplona.quartz.marmot.mls.codec
com.vitorpamplona.quartz.mls.codec
.TlsReader(mlsBytes),
)
assertEquals(
com.vitorpamplona.quartz.marmot.mls.framing.WireFormat.PUBLIC_MESSAGE,
com.vitorpamplona.quartz.mls.framing.WireFormat.PUBLIC_MESSAGE,
mlsMessage.wireFormat,
)
}
@@ -20,8 +20,8 @@
*/
package com.vitorpamplona.quartz.marmot.appComponents
import com.vitorpamplona.quartz.marmot.mls.components.AppDataDictionary
import com.vitorpamplona.quartz.marmot.mls.group.MlsGroup
import com.vitorpamplona.quartz.mls.components.AppDataDictionary
import com.vitorpamplona.quartz.mls.group.MlsGroup
import com.vitorpamplona.quartz.nip01Core.core.hexToByteArray
import com.vitorpamplona.quartz.nip01Core.core.toHexKey
import kotlin.test.Test

Some files were not shown because too many files have changed in this diff Show More