mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2026-08-12 09:13:23 +00:00
feat(concord): send & receive encrypted image messages (Armada-compatible)
Concord channel messages can now carry images, wire-identical to Soapbox Armada's `encryptAttachments`: a normal channel-bound kind-9 whose ciphertext URL is appended to the content and annotated by a NIP-92 `imeta` tag with `encryption-algorithm aes-gcm`, hex `decryption-key`/`decryption-nonce`, and the plaintext `ox` hash (no `x`). The blob is AES-256-GCM ciphertext on Blossom, so the media host and relays only ever see encrypted bytes — the community's E2E guarantee holds. Reuses the NIP-17 encrypted-media stack end to end: quartz's imeta tag vocab and IMetaTagBuilder to build/parse the tag (ChannelChat.imageMessage / encryptedImageImeta / encryptedImagesOf), the shared UploadOrchestrator encrypted upload + ChatFileUploadDialog picker on the send side, and the OkHttp EncryptedBlobInterceptor keyCache on the receive side — registering each attachment's cipher (keyed by URL) lets the normal feed renderer display the decrypted image with no shared-render changes. Encryption is mandatory (no toggle, and a missing cipher fails closed). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CzJ2Cwo8tg4oZq43oRa3ig
This commit is contained in:
+18
@@ -48,6 +48,7 @@ import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.core.hexToByteArray
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter
|
||||
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
|
||||
import com.vitorpamplona.quartz.nip92IMeta.IMetaTag
|
||||
import com.vitorpamplona.quartz.nipC7Chats.ChatEvent
|
||||
|
||||
/** One decrypted, verified Concord channel message projected for display. */
|
||||
@@ -160,6 +161,23 @@ object ConcordActions {
|
||||
return ConcordStreamEnvelope.wrap(rumor, channel, authorSigner, encrypted = true)
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds an encrypted-seal channel message wrap carrying one or more encrypted image [imetas]
|
||||
* (Armada `encryptAttachments` shape) to publish on the [channel] plane.
|
||||
*/
|
||||
suspend fun buildChannelImageMessage(
|
||||
authorSigner: NostrSigner,
|
||||
channel: GroupKey,
|
||||
channelId: HexKey,
|
||||
epoch: Long,
|
||||
text: String,
|
||||
imetas: List<IMetaTag>,
|
||||
createdAt: Long,
|
||||
): Event {
|
||||
val rumor = ChannelChat.imageMessage(authorSigner.pubKey, channelId, epoch, text, imetas, createdAt)
|
||||
return ConcordStreamEnvelope.wrap(rumor, channel, authorSigner, encrypted = true)
|
||||
}
|
||||
|
||||
/** Builds an encrypted-seal inline quote-reply wrap (kind-9 message quoting [parent] via `q`) on the [channel] plane. */
|
||||
suspend fun buildChannelInlineReply(
|
||||
authorSigner: NostrSigner,
|
||||
|
||||
Reference in New Issue
Block a user