-
Notifications
You must be signed in to change notification settings - Fork 577
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
Is NIP-07 decryptEvent(event) a good idea? #1439
Comments
You will need to define a separate return type for each event type. Lists would be the tag list inside of the |
I agree. Granting full decryption rights is bad. |
Maybe the return should be the same event, but replacing the encrypted part by the decrypted string in place. So, it might replace the .content, or tags, or both. For spreadsheets and forms, for instance, the signer must try to decrypt every |
This would break signatures, so decrypted events should be validated too.
Or, the caller could specify a list of paths to attempt decryption on. For example |
I was wondering if there is a smarter way that wouldn't require a I don't know if it is possible with this nip44 version @paulmillr. But I imagine such a thing exists in the encryption world: what if, when encrypting, the client could pass a metadata (an event kind number) as argument, to be added to the ciphertext somehow. Like this Then, when app calls |
we can make a generic encryption scheme with nip44. I just need how an API would look like |
@paulmillr Like i mentioned above: this
Then when decrypting, |
What's pubkey? Who's pubkey is it? nip44 was made for conversations e.g. between Alice and Bob, so it's Alice's privkey and Bob's pubkey. |
@paulmillr It is nip44, if possible, so Bob's pubkey in your example. The idea is to extend nip44 to allow for embedding an extra information (specifically, the kind number of the nostr event where the ciphertext will be inserted/used) besides the plaintext when encrypting. Then when Bob's client asks an external signer/encryption-manager (NIP-07) to decrypt the ciphertext using his privkey and Alice's pubkey, the signer will decrypt the ciphertext but will only return the resulting plaintext to Bob's client if the client has permission to decrypt things associated to that specific kind number the signer got when decrypting. |
Understood. In this case, that seems like something which should be handled on a higher level than nip44. I don’t see how nip44 is relevant here. Key storage should implement permission system, clients should implement it, then they do checks here and there and everything is working. Am I wrong? |
Key storage is unable to implement a fine grained permission system if it doesn't know exactly what the client is asking it to decrypt. Is it a direct message, is it a private mute list, or a private bookmark list? When encrypting an item, If Alice could also embed a description of what it is (the event kind number would act as that description), then when Bob's client tries to decrypt it calling So in the first step, Alice needs to be able to do |
I think you want something like I did in this pull request I still haven't implemented in any apps but I will eventually |
@greenart7c3 pretty close! Except that we cannot trust a client to tell the correct kind when decrypting, it can lie. This information does should be set by the client at the moment it encrypts something, because it has no reason to lie when encrypting. The kind should be encrypted together with the plaintext message. What I propose is using something like this: https://en.wikipedia.org/wiki/Authenticated_encryption#Authenticated_encryption_with_associated_data, <- does nip44 has something similar available @paulmillr? Also @earonesty, @mikedilger, @Semisol and @mleku seem to know a lot about encryption, maybe they can help too. A naive way would be to concatenate the real plaintext message with the event kind before encrypting, but this would be a massive breaking change, cause clients/keystorages not aware of this would think the event kind is part of the message when decrypting. |
Okay, so:
Am I missing something here? No, we don't support AEAD, because there was no need for it. |
Where did The keystorage could only know the type if we called
Thats unfortunate. The idea behind using AEAD is that we would avoid sending the whole event as argument when decrypting. Cause of complications showed on the first 5 comments of this issue. @paulmillr out of curitosity, how easy would it be for a nip44 v3 to include AEAD or would it require a completely new encryption scheme, a new nip? Well, although AEAD is superior because we would be able to avoid the |
I still don't understand what are the exact inputs and outputs. Can someone write code? e.g. something like
Anybody could create any "new version". But v2 was audited. So unless there is some really good update, I would not want to update it. Any new detail is potential data leak etc. |
Let me try. Alice's webapp asks a nostr browser extension to encrypt a third event tag's value before sending the event to Bob:
Bob is using primal.net webapp, which will ask a nostr browser extension to decrypt the ciphertext that is at the third event tag (the ciphertext could be at another tag or field, depending on which event kind).
So, it is important for the browser extension to know the event kind. Or else, the browser extension can't inform to Bob that primal.net wants to decrypt medical data, it could only say that primal.net wants permission to decrypt anything. |
|
I return the question to you, why does AEAD even exists if we could just encrypt the additional data (AD) together with the message, like in your example? I imagine there is some added benefit, like for example being able to know the additional data content before really fully decrypting the ciphertext? |
This idea may as well not exist unless we rework the encryption spec. If I want to decrypt a DM from Bob to Alice, as Alice, without showing I want to decrypt a DM, as a marketplace app:
The only solution is to use AEAD or some other method to add the event type, and context (who is sending and receiving) to the encrypted blob.
When you already know the AD before decryption, such as the source or destination public keys. |
If all we want to do is to allow signers to manage decrypt permissions per kind, how about adding context to the current decrypt call?
If context is absent, the app is asking for broad permissions. If the context is present, the app is asking for individual permissions. The user can accept or reject broad and specific permissions separately. |
@vitorpamplona doesn't work, cause the pubkey argument isn't always the same as event.pubkey (e.g: your spreadsheets PR). |
The pubkey should not be part of the signer's checks anyway. The pubkey for the encryption/decryption should not be required to be in the event for privacy reasons. It can come from another event or another decryption on the same event.
|
Its like @Semisol described. Both If evil app wants to decrypt |
Interesting idea to also include sender/receiver. Though I think just event kind would be good enough context regarding NIP-07, like it is easier for the user to decide if it wants to grant the app permission to handle any event of a specific kind, no matter the peers involved. |
It took a great deal of time to make everything polished. Then an auditor was hired for a bunch of money. Do you want to change something and stay secure? It's better to do the process again. Cryptography is not your average iterative code. Maybe ask BIP340 authors if they are iterating on a new version of it.
There is no native AAD in NIP44. AAD is supported in polynomial MACs such as AES-GCM and chacha20poly1305. We don't use polynomial macs. NIP44 has "hmac-aad" abstraction, but it's already used for nonces. How do you properly concatenate nonce with other aad. Which default value are you going to use. Are there any things that one needs to keep in mind? Hmac was partially created because sha256(a + b) is unsafe (length extension attacks). So even concatenation is not always safe. |
Money for auditing is a subject for @fiatjaf CEO and @staab Treasurer.
Anything that isn't an event kind, it can't be a positive integer.
Sorry, I'm no cryptographer. Just pointing the problem of using current NIP-44 implementation in the context of an untrusted nostr client/app talking to a trusted NIP-07 browser extension or NIP-46 signer/keystorage, which is a very common way of using Nostr, instead of the much less secure practice of pasting user's Currently, user end up granting or rejecting the untrusted app permission to decrypt any event, no matter the event kind number. We need granularity by event kind number when user is choosing to grant/reject decryption permission to an app. |
So if you're not cryptographer, find a way to solve this without adjusting cryptography. |
I raised a concern. If the nostr community acknowledges there is a problem in the way encryption is used on the protocol, I'm no way in charge of solving it. If there really is a problem, and it looks like there is, the community can always choose to just hand-wave it away. |
@fiatjaf @vitorpamplona @staab please review this comment. Is the logic wrong? If the logic is right, the problem is big and we cannot rely on a decryptEvent method or similar to fix the broad nip07/46 decryption rights problem. The fix is probably adding AD (additional data) capability to the encryption, as outlined by @Semisol comment: @paulmillr doesn't want to help with adding AD to nip44. I think it's because he doesn't know how nip07/46 works, so he doesn't acknowledge there is a problem that needs a fix. We shoud find someone else to help... even repurposing nip04 simpler encryption to add AD if possible would be great, if anyone knows how to do it. Anyway I've heard on nostr telegram and elsewhere that nip04 drawbacks are farfetched anyway but I'm not able to give an opinion on that. |
You may also want to add who is the "sender" and "receiver" along with things like context (is this in a tag, or the content field, etc) |
@Semisol my preliminary understanding is that the extra context you mention Currently I think that adding the event.kind is enough, cause would fulfil |
Simple schemes built on top of proven cryptographic primitives do not require an audit and can be proven to work, and your comparison to BIP340 is invalid. A scheme built on (X)ChaCha20-Poly1305 with a hashed shared point being used as the encryption key can be implemented easily. |
@Semisol I mean, sender and receiver is useful. But the nostr way is "trusting" (not the right word but) whatever the author signed. If the event's author copy and pastes someone else's ciphertext and adds it to their own event, it is similar to copy/pasting someone else's plaintext. edit: hmm in fact, the ciphertext can only be decrypted with the right sender/receiver keys anyway, so the example of copy pasting was kinda useless, but the "(is this in a tag, or the content field, etc)" context apply to the copy/paste example I think |
We can do a simple version of this where the signer checks if the decrypted payload is an event and uses that information to manage permissions. For DMs, for instance, the app will send the In that way, if a NIP knows this is available, it can format the encrypted payload as an event (even without signatures). NIP 51's encrypted tag list, for instance, could be turned into an event with kind and tag array instead of just the tag array. It's a simple change that can be done when we migrate from NIP-04 to NIP-44. |
@vitorpamplona yeah this is like doing The former would need to change the way all NIPs format plaintext before encrypting it, while the latter would change the encryption algo all NIPs use. I suspect with AD, the "kind" is discoverable before finising the whole decryption process, adding to speed? edit: but anything that solves the problem is ok. What @vitorpamplona said would be ok, or better a more generally applicable version (not only for seals) like the above |
@arthurfranca can you stop mentioning me? I've unsubscribed myself from this issue. @Semisol you're free to develop custom encryption schemes for anything. |
This does not provide much benefit compared to an AEAD scheme, and actually requires another layer of wrapping (event -> encryption -> another event -> actual data) |
I'd say a custom AEAD scheme does not provide much benefit on top of a simple change like that. The wrapping will have to exist no matter what. It's either wrapped before the encryption or during the encryption by the AEAD itself. |
bump There is currently no way on nostr to segregate private data We can't expect an user to code their own client nor to If encrypting, we can use public relays. The problem is that If not encrypting, user would have to self-host relays. Wen AEAD? Or we keep ignoring this big security concern? |
Due to lack of interest (on enhancing encryption with AEAD) from those that usually discuss proposals here, the only viable solution is to optionally do Then to use a nip07 extension that always decrypt things before prompting user. It would decrypt it, try to parse it to JSON and check if there is a kind field, so it can inform user about it or fallback to regular "permission to decrypt anything". |
Currently, asking an extension to decrypt something may end up granting a too broad of a permission to an app.
With a
decryptEvent
method, the extension is able, e.g., to grant just private bookmarks decryption permisson to an app, which wouldn't allow the app to decrypt DMs.It would be something like
async window.nostr.nip44.decryptEvent(event)
?That are some complications:
event.content
field, some may encrypt one or more tags.event.kind
.The text was updated successfully, but these errors were encountered: