-
Notifications
You must be signed in to change notification settings - Fork 594
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
Improvement to 04.md #572
Improvement to 04.md #572
Conversation
Remove warning about "unsafe practices" and instead show exactly what the unsafe information is. Add in hkdf, random salt, and use GCM - making the key clean and the cipher operate in accordance with archival data standards.
This should not be NIP4, it should be a separate nip, because it's totally different and NOT compatible with the old one. Servers signalling for NIP4 would not be bogus: is it GCM, or CBC? Also AES-GCM cannot decrypt AES-CBC encrypted messages. Overall the cryptography choice is bad. I have opened pull request for (allegedly) NIP-44 Encrypted Direct Message (Versioned): #574 |
i think it might be better for old clients to simply experience an error when seeing new data, and then update the client. i really don't like all those weak iv's and unhashed keys sitting around. i removed any leftover refs to cbc. easier to rev if you comment on the change and we can resolve it. in the future all new versions can report a much nicer error. i added simple padding so you can't trivially attack from short messages based on size. its now suitable, imo, for archival data. which is really what this is. removed the "authorized relay stuff" because that's just trusting someone else's archive...and isn't "best practices" |
So you'll break all existing clients just because you don't like current encryption? A new NIP is needed. That's what NIPs are for. Relays signal which features they support by signalling available NIPs. |
it won't break existing clients. they are already robust to failed decryptions. if they weren't... they're already broken. all data from the internets is untrusted by default. as an experiment, ive decided to send a dm like this to everyone i know. |
The decryptions will fail on all existing clients. That's a breakage. New messages would silently fail from a user perspective. You'll be breaking existing, perfectly working, behavior. |
If we introduce a new kind: "New messages would silently fail from a user perspective." |
If we introduce a new kind, servers and clients would echo their support for NIP99 (or whatever), which means proper direct messages are supported, and if a client lists NIP04, means they are not. It's easy to distinguish in client feature list. |
i would agree, if there was any server behavior that differed. kinds are really about server behavior and user-display. since the message is encrypted, the user-display issue is a non-issue. and there is no server behavior difference. if we're lucky a client will show the message and report an error. it's only beneficial to reuse the kind. the worst case is the same as if we used a new kind. this is not a case of "the old one is ok, go ahead and keep using it". this is a case of "we made a mistake, please fix your client" i would like some popular client authors to weigh in here instead of two crypto-guys talking about it actually. @fiatjaf might know some |
04.md
Outdated
@@ -40,13 +44,50 @@ let event = { | |||
created_at: Math.floor(Date.now() / 1000), | |||
kind: 4, | |||
tags: [['p', theirPublicKey]], | |||
content: encryptedMessage + '?iv=' + ivBase64 | |||
content: encryptedMessage + '??' + ivBase64 + "??1" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
meh, now we're constructing a weird strings with weird delimiters. Bad for performance, bad for parsing, non-standard
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's actually faster than having ?iv=, ?ver=. benchmark it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm talking about algorithmic complexity in lower-level languages. A parser will need to walk through every ciphertext character and stop on ??
.
Why? We already have JSON.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
json is no faster. and "?" never appears in base64. this is always going to be faster than JSON. i will change it to one "%". it will always be order N no matter what. im ok wth json, but... it's kinda bloated. and the version thing really protects us
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
updated to a single delimiter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i would like to point out how much i appreciate you working on this. i know i can be a bit difficult, but i think we both agree it's a terrible idea to leave it as-is!
04.md
Outdated
let sharedX = sharedPoint.slice(1, 33) | ||
let key | ||
if (version == "1") | ||
key = hkdf(sha256, normalizedKey, iv, undefined, 32) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is unnecessary. It's safe to reuse the same key for billions of messages and even more.
HKDF would also slow down decryption of individual messages. Every decryption would need hkdf
call. Decrypting 5000 messages on a slow phone will add 1 second to decryption time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hkdf is equivalent in speed to sha256 twice
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's false. It's 10 times slower than sha256.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- no, it's not safe to reuse the key if the iv is short. reusing the same iv allows the attacker to decrypt messages, and there is a birthday attack here.
2 this is not a performance hit. i tested it. the EC operations are 95% of the time. so you're optimizing for 5%. which has a negligible effect. hkdf exists for a reason. it's easier not to accidentally screw things up. we can replace it with a sha of the (ss + iv), that's ok - since length extension is a non-issue here (we're not verifying the hash)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
indeed, it's slower to use sha256... unless you're careful to concatenate the buffers correctly. the buffer manipulation is more expensive than the hash. overall we're talking a 30% performance hit, and it's all because of GCM - which is totally worth it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1000 encryptions on a slow emulator:
test: 2406 ms version 0
test: 2969 ms version 1 sha256
test: 3043 ms version 1 hkdf
hkdf is negligible compared to the GCM hit and it's best practice. lets stick with it!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice thing about the new standard is that clients should simply display an "encryption version not supported" message when getting messages with a version they don't know. then we can introduce faster/better versions and not have bad behavior
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no, it's not safe to reuse the key if the iv is short. reusing the same iv allows the attacker to decrypt messages, and there is a birthday attack here.
So just use xchacha instead of these "constructions".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Care sharing a benchmark file?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i literally just used console.time("test") and constole.timeEnd("time") on the js posted above. seems like the hkdf/sha is irrelevant compared to "doing nothing" and "gcm itself", which eat most of the time. still it's a small diff. and doing nothing is not ok
added mention of the pkcs7 standard
so let me get this straight... the bike shedding is about old clients not being able to read DMs with the new safer encryption until they update? nostr clients push out updates every other day. the web ones even faster. |
I don't care much about the issue, what i do care is bad choice of cryptography. |
looks to me the bad choices were already made. |
@moonsettler exactly, that's why it's important to make it right during this iteration. |
This must be a new kind, a new NIP, definitely. But I don't like it because it doesn't fix all the problems of NIP-04, just makes it marginally better, so it isn't worth the trouble. I think a new NIP should either propose adoption of the SimpleX protocol or define a variant of it that fits better into Nostr clients (not necessarily using the canonical Nostr event JSON format). I'd like to hear what you think about SimpleX. |
@fiatjaf simplex is interesting, but we need a simple way to message people over nostr. Simplex is very complicated and implementing it would take a lot of effort. Which kinda defies nostr simplicity. It would take men-months to implement it properly on different platforms (web, ios, android). I suggest we draft/implement a NIP that would replace NIP4 and after that we can prototype simplex. The reason is: simplex may get never implemented. We need something more or less secure in the meantime.
The new NIP would immediately fix padding oracle attacks (AES-CBC) and remove residue structure from AES keys. May not be too much, but it's important. I don't think it's possible to implement a truly private messenger over nostr. Metadata would leak. NSA said "we kill people based on metadata". There would need to be a lot of compromises. Nevertheless i'd be happy to prototype any ideas. |
@earonesty it's 10x slower, really |
Yes. SimpleX is complex and the use-case they are going after does not have much overlap with Nostr. I wrote about it here. Also agree that this should be new kind and new NIP. In that case, why can't we include this into NIP-59 which introduces another kind and a solution for metadata leaks? It can solve both in one shot. Please review this NIP-59 |
so if there would be a comprehensive fix, a new kind is probably warranted for that. imo breaking behavior that endangers the users (like leaking private/session keys) is not inherently bad especially considering that this is not consensus code or anything. people would not be able to read some of their DMs until they update? that's a huge deal? migration would just be faster by breaking things. i liked some parts of the approach simplex makes to avoid passive metadata based social linkage, but maybe nostr would be better served by a simpler way of doing things. |
I have opened pull request for (allegedly) NIP-44 Encrypted Direct Message (Versioned): #574 It uses versioning, XChaCha20 and hashed shared secret. Algorithm choice rationale is described in the pull request. New Versioning feature explicitly requires non-compatible versions to throw user-visible errors. Please take a look at it! Any comments are welcome. |
What happens with the NIPs referencing NIP-04 for encrypting stuff like private lists if this becomes a new NIP instead of a new NIP-04 version? |
if nip44 merges and chat clients actually use it, then this is obsolete. it handles the 2 important things: versioning and hashing of the shared secret. the whole hvkf vs sha was bikeshedding. perfectly happy to use it instead. i still think it should include the nonce in the production of a non-fixed aes key. that way if a single aes key leaks somehow, the rest of the messages are intact. nip-4 would, technically, keep working though... which is the downside of not reusing the kind, and breaking old clients. all references to nip-4 will need to be updates i feel like the back-compat version has some advantages (reuse the same kind, use versioning to disambiguate). maybe ill just update this to specify the xchacha20 cipher, and we can let the top 3 or 4 nostr client authors worry about "new kind vs not new kind" |
im leaving this as-is, and adding in the metadata blinding, because that's actually what im using, and the fixed-key stuff seems not quite right. just going to reflect what we're using here. perfectly happy to switch to something else that has the same properties (no metadata leakage, correct iv/key use). but if not, i'm sticking with kdf-derived keys and optionally metadata-blind dm's (which also incidentally spam resistant) |
taking feedback from others, im closing this in favor of yet another design |
An alternative would be to create another kind. Would appreciate reasoning as to why this would benefit users or builders. If consensus is "new kind", will open up a new PR