Skip to content

Add Kind 15 for Encrypted File message#1537

Merged
vitorpamplona merged 4 commits into
nostr-protocol:masterfrom
wcat7:patch-1
Feb 11, 2025
Merged

Add Kind 15 for Encrypted File message#1537
vitorpamplona merged 4 commits into
nostr-protocol:masterfrom
wcat7:patch-1

Conversation

@wcat7

@wcat7 wcat7 commented Oct 12, 2024

Copy link
Copy Markdown
Contributor

File Message Kind

{
  "id": "<usual hash>",
  "pubkey": "<sender-pubkey>",
  "created_at": "<current-time>",
  "kind": 15,
  "tags": [
    ["p", "<receiver-1-pubkey>", "<relay-url>"],
    ["p", "<receiver-2-pubkey>", "<relay-url>"],
    ["e", "<kind-14-id>", "<relay-url>", "reply"], // if this is a reply
    ["subject", "<conversation-title>"],
    ["file-type", "<file-mime-type>"],
    ["encryption-algorithm", "<encryption-algorithm>"],
    ["decryption-key", "<decryption-key>"],
    ["decryption-nonce", "<decryption-nonce>"]
    // rest of tags...
  ],
  "content": "<file-url>"
}

Kind 15 is used for sending encrypted file event messages:

  • file-type: Specifies the MIME type of the attached file (e.g., image/jpeg, audio/mpeg, etc.).
  • encryption-algorithm: Indicates the encryption algorithm used for encrypting the file. Supported algorithms may include aes-gcm, chacha20-poly1305,aes-cbc etc.
  • decryption-key: The decryption key that will be used by the recipient to decrypt the file.
  • decryption-nonce: The decryption nonce that will be used by the recipient to decrypt the file.
  • content: The URL of the file (<file-url>).

@wcat7

wcat7 commented Nov 4, 2024

Copy link
Copy Markdown
Contributor Author

@vitorpamplona @staab Do you have any suggestions for this proposal? This allows us to send encrypted files in DMs

@mikedilger

Copy link
Copy Markdown
Contributor

Since this is inside a seal and giftwrap, it is already encrypted. But that is OK if the content is at some URL encrypted under any other encryption algorithm. What doesn't make sense to me is base64 data in the content, since that double encryption doesn't seem necessary. Maybe just to have a different algorithm?

Also the 'p' tags can't be looked up since they are inside the encrypted giftwrapped seal. So I'm not sure what they are for.

@vitorpamplona

Copy link
Copy Markdown
Collaborator

So I'm not sure what they are for.

They are there to define which NIP-17 group of users this image belongs to. It's similar to how kind 14 gets is group definitions.

@wcat7

wcat7 commented Nov 5, 2024

Copy link
Copy Markdown
Contributor Author

Since this is inside a seal and giftwrap, it is already encrypted. But that is OK if the content is at some URL encrypted under any other encryption algorithm.

For private chats, file content encryption is essential. Otherwise, with only URL encryption, the file could still be visible to the file server, and if the URL is leaked or indexed, it could also be accessed by others.

If I remember correctly, Signal uses the AES-GCM algorithm to encrypt file content? I think @erskingardner might also be interested, especially considering NIP-104, where file encryption could be added as well?

What doesn't make sense to me is base64 data in the content, since that double encryption doesn't seem necessary. Maybe just to have a different algorithm?

Ah yes, that’s right. Base64 placed in the content is encrypted through giftwrap, so there’s no need for additional double encryption.

@vitorpamplona

Copy link
Copy Markdown
Collaborator

@water783 I am back to this.

Kind 15 should be GiftWrapped in the same way as Kind 14, right? (It's not clear in the text).

Can we add the following optional fields?

  • x containing the SHA-256 hexencoded string of the file.
  • size (optional) size of file in bytes
  • dim (optional) size of file in pixels in the form <width>x<height>
  • blurhash(optional) the blurhash to show while the file is being loaded by the client
  • thumb (optional) url of thumbnail with same aspect ratio
  • fallback (optional) zero or more fallback file sources in case url fails

Those fields really help to set up the UI before the image loads.

@wcat7

wcat7 commented Dec 20, 2024

Copy link
Copy Markdown
Contributor Author

@water783 I am back to this.

Kind 15 should be GiftWrapped in the same way as Kind 14, right? (It's not clear in the text).

Yes, Kind 15 should be sealed & gift wrapped in the same way as Kind 14. Thanks for pointing that out.

Can we add the following optional fields?

  • x containing the SHA-256 hexencoded string of the file.
  • size (optional) size of file in bytes
  • dim (optional) size of file in pixels in the form <width>x<height>
  • blurhash(optional) the blurhash to show while the file is being loaded by the client
  • thumb (optional) url of thumbnail with same aspect ratio
  • fallback (optional) zero or more fallback file sources in case url fails

Those fields really help to set up the UI before the image loads.

I think they’re a great addition! Just updated the text, pls check it again.

@vitorpamplona

Copy link
Copy Markdown
Collaborator

Last thing, it looks like 0xChat is converting hex to bytes for the key but just taking the UTF-8 of the hex string for the nonce. Is that how it is supposed to be? Or should we just hexToBytes the nonce as well?

https://github.com/0xchat-app/0xchat-app-base/issues/1

@wcat7

wcat7 commented Dec 21, 2024

Copy link
Copy Markdown
Contributor Author

Last thing, it looks like 0xChat is converting hex to bytes for the key but just taking the UTF-8 of the hex string for the nonce. Is that how it is supposed to be? Or should we just hexToBytes the nonce as well?

https://github.com/0xchat-app/0xchat-app-base/issues/1

Ah my mistake, using hexToBytes is more reasonable, will fix it.

@vitorpamplona

Copy link
Copy Markdown
Collaborator

Added support for Amethyst: vitorpamplona/amethyst@94c74a1

@water783 I am encoding the nonce from Hex. There is a fallback on Amethyst for older images from 0xchat.

@wcat7

wcat7 commented Dec 24, 2024

Copy link
Copy Markdown
Contributor Author

Added support for Amethyst: vitorpamplona/amethyst@94c74a1

@water783 I am encoding the nonce from Hex. There is a fallback on Amethyst for older images from 0xchat.

Awesome, thank you! I will also update the app to use nonce from Hex as soon as possible.

@vitorpamplona

Copy link
Copy Markdown
Collaborator

Amethyst v0.94.0 now supports this add-on.

@vitorpamplona
vitorpamplona merged commit 6e7a618 into nostr-protocol:master Feb 11, 2025
@erskingardner

Copy link
Copy Markdown
Contributor

I'm super late to the party here, but I'm working on adding files (images, videos, audio, etc.) to White Noise now and wanted to double check a few things. This seems to only really make sense for DMs, is that right?

Right now, I'm planning on using the same kind: 445 events (which are group message events in the 104 spec). These are NIP-44 encrypted with a key that all group members have access to. The decrypted content of these events will simply be kind: 9 chat events will blossom URLs included. These blossom blobs will be the actual file/image/video being shared and those will be encrypted using the same key as is used for the NIP-44 encryption of the event itself. I've not decided on the encryption scheme but it probably makes the most sense to use the same scheme that is used in the group.

Thoughts?

@vitorpamplona

vitorpamplona commented Mar 9, 2025

Copy link
Copy Markdown
Collaborator

This seems to only really make sense for DMs, is that right?

Kind 15 reuses kind 14's DM tag structure to mark receivers and group chats, room title etc. So, yes I think it would only work within the NIP-17 scopes.

But here are a few interesting things about this approach:

  1. Since the key used to encrypt/decrypt is completely uncorrelated to the DM/GiftWrap/NIP-44 encryption keys, it allows users to forward/re-share encrypted media with its key at will without breaking the rest of the chat's privacy. That feature is quite common/useful for many users: Upload once and share in as many group chats as you want.
  2. Encrypting each file with a separate key enables users to selectively disclose which pictures they want to forward, without revealing the secret to decrypt other pictures that were sent at the same time.
  3. The NIP-94 tags - specifically dim - are extremely important for a good UX to make sure things don't move around when loading them. blurhash is also nice. Be careful with thumb. It needs to be encrypted as well.
  4. HTTP has a lot of performance optimizations to download large blobs of data (e.g. https://developer.mozilla.org/en-US/docs/Web/HTTP/Range_requests). None of those will work since to decrypt the file, you must have the complete bytearray. This is particularly difficult for private Video streaming, which I don't think we still have the answer yet.
  5. Make sure to work with Blossom URIs correctly. If the user is using a mirror, the URL will change and the keys related to that URL must also work for any mirrored content. It's quite hard to figure out if a URL is a blossom URL or not.
  6. None of the free Blossom servers accept encrypted blobs yet. So, support for this is fairly hard.

@erskingardner

erskingardner commented Mar 10, 2025

Copy link
Copy Markdown
Contributor

@vitorpamplona how are you using NIP-94 tags in Amethyst? It doesn't look like those are meant for social clients. I can see using some of the tags to help clients know how to render these images but since we're not sharing images as individual messages (I mean, I guess we could but that wasn't the plan) we don't have an event to put all those tags into for the image or file itself.

Also - the design of this PR also has the same flaws with HTTP right? You're encrypting the full file and anyone wanting to download the file will need to download the full thing before being able to decrypt. I guess the one benefit here is that you can provide dim and blurhash so that there is something to show while you're loading but you don't get any range request or streaming benefits, correct?

@vitorpamplona

vitorpamplona commented Mar 10, 2025

Copy link
Copy Markdown
Collaborator

There are many ways, you can use NIP-92 imeta tags to place multiple NIP-94 tags in a single line. Then you can have multiple URLs in the same event. We use that both on kind 1 and kind 20 (Olas). We also render NIP-94 nembed uris #1078, which means users can directly add several NIP-94 events directly in the body of a public or private message.

you don't get any range request or streaming benefits, correct?

That's what I said of 4. I don't think there is any way of using range requests with encrypted data at all. It has been an HTTP problem for quite some time. There are some techniques that pre-chunk and encrypt each chunk separately, but that means HTTP clients cannot decide the size of the chunk on demand and thus kind of defeats the purpose of range requests.

I guess the one benefit here is that you can provide dim and blurhash

This should always be added, regardless of encrypting or not the file.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants