Skip to content

NIP-46, NIP-51, NIP-90: "encrypted" tag to indicate the encryption method used#1259

Open
alexgleason wants to merge 4 commits into
nostr-protocol:masterfrom
alexgleason:encrypted-tag
Open

NIP-46, NIP-51, NIP-90: "encrypted" tag to indicate the encryption method used#1259
alexgleason wants to merge 4 commits into
nostr-protocol:masterfrom
alexgleason:encrypted-tag

Conversation

@alexgleason

@alexgleason alexgleason commented May 26, 2024

Copy link
Copy Markdown
Member

I remembered that NIP-90 has an "encrypted" tag with no value, and it got me thinking we could utilize that tag as a more general-purpose "hey the thing in the content is encrypted" indicator, for events that may or may not have encrypted data.

Then I realized, since it has no value, we could add a "nip04" | "nip44" to indicate the type of encryption used.

Then I realized we could also use this tag on NIP-46 to help ease the transition in #1095 #1248

As I'm typing this I realize (fixed), that we could also use this on NIP-51 lists which also have an "optionally encrypted" criteria, and might also want to benefit from knowing which encryption is used.

So basically it's one simple idea that solves a lot of problems.

@alexgleason alexgleason requested review from fiatjaf, pablof7z and staab May 26, 2024 17:04
@alexgleason alexgleason changed the title NIP-46, NIP-90: "encrypted" tag to indicate the encryption method used NIP-46, NIP-51, NIP-90: "encrypted" tag to indicate the encryption method used May 26, 2024
@alexgleason

alexgleason commented May 26, 2024

Copy link
Copy Markdown
Member Author

I modified NIP-51 as well. EDIT: And NIP-24.

@fiatjaf

fiatjaf commented May 26, 2024

Copy link
Copy Markdown
Member

This doesn't solve anything because NIP-44 support still has to be hardcoded.

@alexgleason

Copy link
Copy Markdown
Member Author

The "encrypted" tag lets users (or clients) optionally encrypt data in certain events.

The same tag can also be used to indicate the encryption method used.

Of course people sill have to implement NIP-44. But don't you see the bigger picture of why this tag is a good idea?

To put it another way: should we remove the encrypted tag from NIP-90? What would happen if we removed it?

This is consistency and unification of events with optionally-encrypted payloads.

@fiatjaf

fiatjaf commented May 27, 2024

Copy link
Copy Markdown
Member

I had written a long answer, but decided to not post it. I've written these same arguments way too many times and I don't want to bore the reader.

@staab

staab commented May 27, 2024

Copy link
Copy Markdown
Member

I don't think adding a value helps at all, because it's easy to detect the difference between 04 and 44 (04 has ?iv= in the ciphertext), and nip 44 is versioned.

@vitorpamplona

Copy link
Copy Markdown
Collaborator

(04 has ?iv= in the ciphertext)

Not only has ?iv but iv is fixed in length. So, this is faster:

v[v.length-28] == '?' && v[v.length-27] == 'i' && v[v.length-26] == 'v' && v[v.length-25] == '='

@alexgleason

Copy link
Copy Markdown
Member Author

The main thing I was trying to solve is having an optionally-encrypted event that may be either nip04, nip44, or not encrypted at all. Then I realized the "encrypted" tag could be useful to put on any encrypted event. It seems better than detecting the encryption to go with the author's intention.

@fiatjaf

fiatjaf commented May 27, 2024

Copy link
Copy Markdown
Member

It's not detecting based on the author's intention, but based on a standard everybody follows.

@vitorpamplona

Copy link
Copy Markdown
Collaborator

Then I realized the "encrypted" tag could be useful to put on any encrypted event. It seems better than detecting the encryption to go with the author's intention.

The issue is that the encrypted tag might not be aligned with the .content (bugs, idiots, refusal to implement, ...). So, even if you know things have been encrypted by a given standard, you still need to check if the encryption is there, by that standard. If that is the case, then just test it directly. There is no need for the flag.

@alexgleason

Copy link
Copy Markdown
Member Author

I feel like yall are missing my point.

I created a new NIP-78 event. This event is optionally encrypted:

{
  kind: 30078,
  tags: [['d', 'pub.ditto.pleroma_settings_store']],
  content: JSON.stringify(settingsStore),
}

or:

{
  kind: 30078,
  tags: [['d', 'pub.ditto.pleroma_settings_store'], ['encrypted', 'nip44']],
  content: signer.nip44.encrypt(JSON.stringify(settingsStore)),
}

To me this is obviously valuable. And the encrypted tag can unify NIP-90 and NIP-51 at the very least.

My mistake in this MR was touching NIP-46, which I know brings up a lot of feelings.

@vitorpamplona

vitorpamplona commented May 28, 2024

Copy link
Copy Markdown
Collaborator

I would never use the tag.

I would just check if:

  1. .content starts with { -> unencrypted.
  2. .content "has" iv -> nip04
  3. .content has nip44 version -> nip44.
  4. else -> throw error

The tag is just noise.

My mistake in this MR was touching NIP-46, which I know brings up a lot of feelings.

It's not about NIP-46.

@alexgleason

Copy link
Copy Markdown
Member Author

@vitorpamplona I coded that and then reverted it because it seems wrong for clients to "guess" about the encryption method being used. It tickles that part of my brain that wonders how I can exploit it, and it seems to not be a best practice regarding security.

Also, if the event content is a string that isn't a JSON-stringified object, an encrypted tag can indicate whether the content should be used directly as the subject even if it looks like an encrypted string. I imagine this is why NIP-90 has it - so a "decrypt" DVM could treat the content as the direct subject, for example.

@vitorpamplona

Copy link
Copy Markdown
Collaborator

@vitorpamplona I coded that and then reverted it because it seems wrong for clients to "guess" about the encryption method being used.

I don't think there is an alternative. Resilient clients will have to guess or end up not displaying some content. Knowing the mess already out there, I can't trust the signing client to set the encrypted tag correctly. You can't even trust if the tag will be there. So, to me, this is not really an option. You will have to "guess it". And I encourage other clients to do the same.

@mikedilger

Copy link
Copy Markdown
Contributor

(04 has ?iv= in the ciphertext)

Not only has ?iv but iv is fixed in length. So, this is faster:

v[v.length-28] == '?' && v[v.length-27] == 'i' && v[v.length-26] == 'v' && v[v.length-25] == '='

Be careful to not run Vitor's code without first checking that the content is at least 28 characters long.

@mikedilger

Copy link
Copy Markdown
Contributor
2. `.content` "has" `iv` -> nip04

Future bug: I mentioned kim iversen and then Amethyst broke. It thought the content was encrypted because I typed "iv".

@alexgleason

Copy link
Copy Markdown
Member Author

I should be able to paste an entire nip04 ciphertext into a note without a breaking.

@vitorpamplona

Copy link
Copy Markdown
Collaborator

Hum.. I think it's something else. The IV check is not in production yet 🤔

@staab

staab commented Jun 3, 2024

Copy link
Copy Markdown
Member

I should be able to paste an entire nip04 ciphertext into a note without a breaking.

Coracle detects encryption type based on iv=? but only attempts decryption in situations where encryption makes sense. Encrypting kind 1 contents without wrapping via nip 59 would be very weird behavior. For kind 3s, content is either json or encrypted tag lists (that's what the spec says, but does anyone do that?), so if you try to parse json first, you won't have any problems. So in practice I don't think there are any collisions, and going forward NIP 44 ciphertext is much easier to identify.

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.

5 participants