Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrating from NIP-04 to NIP-44 encryption #1598

Closed
arthurfranca opened this issue Nov 22, 2024 · 17 comments
Closed

Migrating from NIP-04 to NIP-44 encryption #1598

arthurfranca opened this issue Nov 22, 2024 · 17 comments

Comments

@arthurfranca
Copy link
Contributor

We should take the opportunity to do nip44.encrypt('{ "k-i-n-d": event.kind, data: "<plaintext>" }') (the arg is a stringifed JSON) instead of nip44.encrypt("<plaintext>") when encrypting things inside events.

This way nip07/46 can decrypt and inform it is decrypting something related to a specific event kind so the user can make an informed decision to allow or deny it.

Ack or nack?

note: used "k-i-n-d" key instead of "kind" to avoid collision with a plaintext that happens to be a stringified json with "kind" and "data" keys.

@vitorpamplona
Copy link
Collaborator

I don't know if it makes sense to keep kind as the reference point. Many encryptions are not based on a specific kind. And some kinds have more than one encryption in such a way that it would be important to differentiate. For instance, health data has 2 encryptions, one that stores a key to view the health data and another one to edit that data. It would be important for a signer to highlight when the permission is not only to see but to edit.

@arthurfranca
Copy link
Contributor Author

arthurfranca commented Nov 22, 2024

And some kinds have more than one encryption in such a way that it would be important to differentiate

The idea is to just inform it is e.g. health data related. So that user can be sure it is something that a health related app should be safely allowed to decrypt.

edit: just don't want Health App to decrypt my secret pr0n bookmarks?
edit: in your example, maybe you can use 2 different event kinds to hold each of the 2 ciphertexts if you need that level of permission granurality?

@vitorpamplona
Copy link
Collaborator

But why stay there? Why not allow the writer an alt that describes what's in the payload? The signer just displays the alt.

@arthurfranca
Copy link
Contributor Author

arthurfranca commented Nov 22, 2024

I think alt would be ok but it can't be automated. I mean, client can easily just add the event.kind for you when encrypting, without asking for alt.
Edit: Unless alt text (or "code") is part of each NIP that encrypts things?

@vitorpamplona
Copy link
Collaborator

The client just adds the alt in the same way we add the alt tag to each event without asking the user about it.

@vitorpamplona
Copy link
Collaborator

Another way of doing this would be to specify a few codes for different payloads in each nip and then use those codes instead of kinds. In that way the signer doesn't need dynamic translations of alt content.

@arthurfranca
Copy link
Contributor Author

arthurfranca commented Nov 22, 2024

Yeah so you proposing nip44.encrypt('{ "c-o-d-e": "HEALTH_EDIT_PRIVKEY", data: "<plaintext>" }')?

@vitorpamplona
Copy link
Collaborator

vitorpamplona commented Nov 22, 2024

Something on those lines. I am not exactly sure if it is the best way. What I know is that kinds alone might not be enough info for signers, depending on the application.

Maybe a <kind>:<int> and then we have a table somewhere to describe what each code means? In that way it is scoped to the kind to avoid reusing codes.

@arthurfranca
Copy link
Contributor Author

Better if <kind>:<code>? cause if the nip07 extension wasn't updated for a while, it can show just the code, which is sort of human readable.

Like 32323:HEALTH_EDIT_PRIVKEY would be translated if nip07 is up-to-date or else it would show just "HEALTH_EDIT_PRIVKEY" which is better than a number

@fiatjaf
Copy link
Member

fiatjaf commented Nov 22, 2024

Not a bad idea but I don't think it's worth the trouble.

Specially because I think our best possible future involve not dealing with nip44 encryption with user keys directly anymore, but only as a way to talk to bunkers, and bunkers would just sign events, while all encryption needs will be provided by per-device keys using MLS or something else.

@arthurfranca
Copy link
Contributor Author

I'm skeptical about MLS saving the world. Per-device keys? Like I have to kinda "join" a group with myself (my other device) so that I can decrypt something the other device encrypted? Seems to be the wrong tool when not doing DMs/chat.

@fiatjaf
Copy link
Member

fiatjaf commented Nov 23, 2024

Like I have to kinda "join" a group with myself (my other device) so that I can decrypt something the other device encrypted?

Yes, exactly.

I'm skeptical about MLS saving the world.

Me too, and I hate all this crappy IETF I-am-cryptographer-and-I-love-Signal technology vibes but I don't see any other way because I want FROST bunkers and they can't encrypt. Also per-device encryption keys sounds like a sensible idea even if we don't use full-blown MLS.

@arthurfranca
Copy link
Contributor Author

@vitorpamplona at #1228, the same alt would apply to many event kinds (all replaceables/addressables in that case).

So maybe better be <code>(:<kind>) then sometimes its just the code and other times there's the :<kind> suffix.

Or maybe we always do <prefix>:<code> and the prefix is a random string created at a specifc NIP/NUD that may be reused in new NIPs/NUDs if applicable.

@vitorpamplona
Copy link
Collaborator

vitorpamplona commented Nov 25, 2024

Even on #1228, the code should describe what kind of event this is first and then what type of information it is trying to assess. Knowing that the app is asking for an edit key is irrelevant if I don't know what that key is for: health data, spreadsheets, docs, etc. In fact, It could be said that even kind + code is not enough. As a user, I want to know which file I am giving access to. The signer should say something like: "Amethyst is asking to decrypt edit keys of the spreadsheet 'My Clients'".

So, <App Requester> is asking to <signer method> <code inside the encrypted file> of the <event kind> <user-facing identification of that event>.

@arthurfranca
Copy link
Contributor Author

arthurfranca commented Nov 25, 2024

edit: skip this, see next comment

Maybe a <kind>:<int> and then we have a table somewhere to describe what each code means? In that way it is scoped to the kind to avoid reusing codes.

Wait, could 76:1 meaning be completely different from 77:1 or the 1 int is always mapped to the same thing no matter the kind?

The signer should say something like: "Amethyst is asking to decrypt edit keys of the spreadsheet 'My Clients'"

As the ciphertext is used when computing the event.id, we cannot add a regular event reference like <event-id>:<int> then do nip44.decrypt(pubkey, <ciphertext>, <optional event>) so that the signer could inspect the event, get its kind and be smart if it knows its a spreadsheet and how to get its name.

Thought its possible to do like <int>:<kind><author>:<optional tag name 1>:<optional tag-value 1, a unique identifier><...more optional tag name/value pairs>.

  • A regular event could add a "nonce" tag or similar and use this code when encrypting: 2:1888:<a pubkey>:nonce:357625635gd871.
  • A replaceable event would do 2:10888:<a pubkey>
  • An addressable event would do 2:30888:<a pubkey>:d:hskjhdahsdh
  • An event that is unique by many tags could do 2:12:<a pubkey>:x:123:y:456:z:789

Now we are able to do nip44.decrypt(pubkey, <ciphertext>, <optional event>) and the signer would show to the user a detailed info.

@arthurfranca
Copy link
Contributor Author

Borrowing ideas from #1540 (use one-letter tags or @),
using inlined shebang instead of { "c-o-d-e": ...., "data": "<plaintext>" } stringified json,
picking ´ as separator between plaintext and codelabel
and if there's ´ inside plaintext, adding a preceding - to escape it:

Plaintext "label" could be <int code>:<kind><author>:<optional, event tags and/or @ ref that makes event unique as in #1549>, preceded by #!nostr <plaintext>

Examples:

  • regular event using d as a nonce tag or a real addressable event: encrypt("#!nostr my-´plaintext-´example´9:1:abc..def:d1265721")
  • replaceable: encrypt("#!nostr plaintext´9:1:abc..def")
  • unique by other one-letter tags (or @) like Editable Event #1540 example: encrypt( "#!nostr plaintext´9:1:abc..def:c1-~3~d4-~6")

Now when client uses nip07 like nip44.decrypt(pubkey, <ciphertext>, { event: <optional event> }), signer can tell user that "example.com is asking to decrypt edit keys of the spreadsheet 'My Clients'"

@arthurfranca
Copy link
Contributor Author

I will experiment with a slightly different version of this in the future.

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

No branches or pull requests

3 participants