dominictarr / pull-box-stream

One way streaming encryption based on libsodium's secretbox primitive
MIT License
84 stars 10 forks source link

why not use AEAD? #5

Open dominictarr opened 9 years ago

dominictarr commented 9 years ago

Someone posted this to hacker news (not me!), and @jedisct1 (author of libsodium) commented:

https://news.ycombinator.com/reply?id=9674119&goto=item%3Fid%3D9671787

This is a bit weird. Why not use an AEAD construction? Libsodium provides ChaCha20Poly1305, conform to RFC 7539. The code is also confusing. "box" is actually the "secretbox_easy" operation, but rewritten using "secretbox". Which intentionally doesn't exist in libsodium.js because it only makes sense in C code.

I didn't use aead because aead authenticates the encrypted data and the additional data with a single mac, which means you must read the entire packet before verifying the additional data mac.

If the length of the packet is authenticated with this mac, and the packet is sent over tcp (or another protocol which doesn't preserve message boundries) then an attacker could cause a deadlock for certain application protocols.

For example, in an application where the server waits for a client to send a message, and then the client waits for the server's response before continuing. An simple example would be a http GET. The client sends two lines of plain text, and then the server sends a large response, then the client disconnects.

If an attacker could alter the length, and then the server would wait for that many bytes before authenticating - but the client has already sent everything it was going to send, and it is waiting for a response from the server. Now there is a deadlock.

pull-box-stream avoids this by authenticating the packet header separately to the packet content. The packet header is always a fixed size, so the receiver always expects that much, and if that authenticates correctly, it waits for an authenticated length. Thus an attacker cannot trick the receiver into reading more bytes than they should.

Also it seems the comments on hacker news that I had misdocumented this protocol and commenters thought this was intended as a substitute for TLS - of course it's not suitable for that because there is no key agreement handshake! - However, it would be suitable for encrypting a file, or if used in conjunction with a key agreement handshake, then for encrypting a tcp session.

pfrazee commented 9 years ago

What about http://www.faqs.org/rfcs/rfc7539.html ? Why not use libsodium's existing stream ciphers?

dominictarr commented 9 years ago

@pfraze rfc 7539 is the AEAD that I am talking about in the above.

There is some terminology collision here, the meaning of "stream" in stream cipher and in streaming protocol are different.

We could use salsa20 to encrypt a very large object, but since the authenticator (poly1305) isn't streaming we need to wait for the whole thing before we can check it had not been tampered with. If we need realtime data (i.e. instant messaging) then we need realtime authentication - each packet needs to be authenticated individually. Thus we use a stream of authenticated boxes (which internally use stream ciphers).

I used authenticated encryption to authenticate the framing. Many protocols do not bother to do this, but I think that is a security hole that should be plugged (a tiny crack, but we must plug every crack).

I could have used raw poly1305 to authenticate the plain framing, but I it doesn't hurt to encrypt it also, and then everything just uses the secretbox primitive, instead of secretbox and onetimeauth

pfrazee commented 9 years ago

slaps forehead was thinking of AES-GCM. too many acronyms

that surprises me about poly1305. that means you can't act on the data until the stream is completed, right?

dominictarr commented 9 years ago

@pfraze correct. you need the whole input to verify the mac. that is why nacl always uses functions that take the entire input, and return the entire output.

dominictarr commented 9 years ago

@pfraze aes-gcm could not be used alone for the same reasons as Salsa20/Poly1305. aes-gcm produces a authentication tag just like poly1305 and in tls it's sent along with the framing.

Have a look in this RFC http://www.rfc-archive.org/getrfc.php?rfc=7366 search for TLSCiphertext to see the description of how cipher text is handled.

pfrazee commented 9 years ago

under "3 Applying Encrypt-then-MAC" the MAC is being sent along with packets, which is I think what you mean by sent along with the framing. Do we need a finer grain than per-packet?

dominictarr commented 9 years ago

yup that is why I meant. @pfraze what do you mean "finer grain than per-frame"?

pfrazee commented 9 years ago

nm, I see where I misread