Peer5 / ShareFest

Web based p2p file sharing built on WebRTC Data Channels API
1.68k stars 271 forks source link

Encrypt file while in transit. #24

Open skorokithakis opened 11 years ago

skorokithakis commented 11 years ago

One could use the SJCL to encrypt a file while in transit. The secret key would be generated on the client and stored in the URL as an anchor (http://www.sharefest.me/scoobydoo5#secret=45DvbuYgWKbpmv5nFHEgkPDufiWTzvPRx32FcGmLkskY).

This would provide end-to-end encryption to all recipients, making this service much more secure.

whadar commented 11 years ago

Nice idea. I assume the secret will never be sent as part of the URI in the HTTP GET requests, at least in normal browsers...

Did you see http://tools.ietf.org/html/draft-ietf-rtcweb-data-channel-04#section-5 which describes the security in DataChannels? Why do you think another level of encryption is needed on top of that?

skorokithakis commented 11 years ago

Yeah, the secret is in the anchor specifically to prevent being sent anywhere, while the page can still get it.

DTLS is fine, but any protocol where you can't verify the recipient is vulnerable to a MITM attack. I might be wrong about DTLS, but it certainly didn't ask me to verify the other party anywhere while using ShareFest. Passing the secret over a secure channel ensures that an attacker can't read the data without the secret, even if he's sitting in the middle of the connection.

whadar commented 11 years ago

Sorry for the delayed answer. I see your point, but just to make sure: The scenario you are concerned about is when the recipient gets the link in a private and secured manner, but afterwards the MITM somehow (even though will be HTTPS) and intercept the URL. Then he can connect to the sender, trick him to think he is authorized and using secured DTLS (or SCTP) get the data.

By adding the secret to the # it's harder to intercept the secret compared to what we have now where the whole URL is actually the "secret".

Let me know if there are pitfalls I need to notice here... Thanks!

skorokithakis commented 11 years ago

That's basically it. Since the server never gets the fragment, it can't decrypt the data. I'm not sure how DTLS prevents MITM attacks, but I'm doubtful that it can be done without any verification or trusted third parties. The attacker might very well connect to the user with DTLS, the user will just not know that that's an attacker.

This prevents against attacks from someone who can modify your connection to go through them instead. The shared secret will be in the URL (it could even be user-settable, if they've agreed to it beforehand), and thus, if exchanged in a secure manner, will thwart attacks (assuming a proper authenticated encryption mode is used, such as the one provided by the SJCL).

I would generally be dubious of crypto in the browser, but ShareFest is small and self-contained enough to download from Github, verify and store locally, and then use the verified pages to transfer files. That would be a much more secure use case, and it would be even more secure if it used encryption for the transfer itself, hence my request.

Thanks!

erbbysam commented 11 years ago

You would still need a password sharing system(I think), but why not OTR? https://github.com/arlolra/otr

skorokithakis commented 11 years ago

That is beyond the scope of this feature request, but you can certainly use OTR with your favorite IM client to transfer the key.

gebi commented 10 years ago

No, you won't need a password sharing system @erbbysam the password is just transmitted with the URL and roomnumber itself but upon pasting the URL into a browser the password will not be transmitted to the server.

ps.: This proposal would be a really great enhancement to sharefest as it actually binds the security of the data transferred to the room number already transmitted and considered a secret. Thus cutting out all other middle mans from the security equation which is a actually a good thing!

skorokithakis commented 10 years ago

@gebi, exactly, it doesn't sound like it's terribly hard to implement either, but I haven't played around with WebRTC much. SJCL is pretty easy to use, though, so it seems like all that would be required would be to detect a key and encrypt/decrypt.

gebi commented 10 years ago

If a parameter in the URL with secret= is available try do download the first block and try decrypt, if that works your secret is correct, otherwise you might have a wrong secret of someone messing with your data while being transferred. @skorokithakis yea, pretty much that, dare to try?

gebi commented 10 years ago

I'd also remove password strengthening from your SJCL and just use the raw call to the random number generator to create the key directly without a user provided password. And i'd also encode the metadata from SJCL into the url instead of every package sent (as it's a constant property for this "room"/file).

skorokithakis commented 10 years ago

@gebi I had tried before reporting the feature request, IIRC my problem was how to stream the file. SJCL operates on the entire file, rather than on a stream, and my JS wasn't strong enough to fix that.

You're right about strengthening (I assume they use PBKDF?). Since it's a random key, you don't need to strengthen it, just use 128 random bits (or whatever the specific key length is).

~Which metadata are you referring to, though?~

Oh, you mean the version etc. Those parameters can be globally hardcoded, apart from the IV, which should also be encoded in the URL, yep.

gebi commented 10 years ago

@skorokithakis demo: http://bitwiseshiftleft.github.io/sjcl/demo/

Nah, i won't hardcode them, because they might change with different versions of sharefest, thus with hardcoding you create an upgrade problem. Better to make it clean and use the same channel as you distribute the secret with.

Yes they are using PBKDF2 with 1000 iterations as default.

In the end i don't think SJCL is the best fit for this requirement. Top of the line candidate for me would be chacha20poly1305, no padding, no cipher scheme, no inherently problematic ciphers, ... But it's relatively young, so finding robust implementations of it can be a challenge. Though it was already proposed as a new cipher spec for TLS and is already in production between chrome/android and google.

skorokithakis commented 10 years ago

What's wrong with AES? Why go fancy?

gebi commented 10 years ago

@skorokithakis because there is so much you can do wrong when using AES. You have a cipher mode and only your usage defines if the cipher mode gives you any security. Which pretty much boils down to if you do not exactly know what you are doing every usage of AES through a RAW API gives you a pretty high chance of messing up! Then there comes the padding and the problems it creates, the additional security requirements of your used cipher mode and all the problems of cipher modes morphing AES into a stream cipher (CTR or GCM). Only after that long list of problems comes the insight that AES in itself is very hard to implement without side-channel leaks, but that's mostly a done topic because it is so widespread BUT eg. aes-gcm is considered impossible to implement without side-channel leakage in pure software. (sorry for the long list...)

chacha20poly1305 is not about being fancy, but about removing most or all of the above mentioned problems with just the change of the cipher and the mac used to create the authentication token (with the added benefit that the security of poly1305 can be reduced to the security of the used cipher, leaving nothing but pure chacha20 on the table for the security consideration). And that's exactly the reason IMHO why chacha20poly1305 was proposed as a new TLS cipher and is already in production use at google).

skorokithakis commented 10 years ago

First of all, you don't have side channel attacks here, since there is no interactivity. Secondly, SJCL already gives you all that out of the box (that's what it's about, well-implemented defaults).

ChaCha20/Poly1305 sounds great, but there's nothing wrong with AES either. AES even has a great advantage in that it has a great javascript library available now.

gebi commented 10 years ago

@skorokithakis SJCL does not give you everything you need. You either have to use the RAW bits and pieces for which the above problems stand or you have the secure API from SJCL but it does not support streaming operation. To use SJCL on different blocks with the same cipher you have to increment the IV, but the IV is stripped/reduced deep down in the CCM implementation of SJCL thus even if you try to increment the IV externally it might not matter as your bits of the IV are not used and you produce IV collision leading to a key leakage. The other possible usage would be to make some kind of key expansion at which point you can forget about the security provided initially by SJCL completely...

It's also mentioned on the demo page "Be careful: CCM mode doesn't use the whole IV, so changing just part of it isn't enough."

skorokithakis commented 10 years ago

Why would you need to increment the IV? Do you mean the counter?

The fact that they only use part of it doesn't matter, since you'll only be using it for one file. The next file will get a completely random IV.

Still, the discussion seems academic, because I'm only aware of one good crypto implementation in JS, and that's SJCL. Is there a ChaCha implementation?

gebi commented 10 years ago

@skorokithakis please read carefully what i have written, i pointed you at the specific problems you will encounter when implementing your initial suggestion. If you know what you are doing then please go ahead and implement it, but don't whine later

skorokithakis commented 10 years ago

Oh, no, be my guest. If you think ChaCha will be easier/more secure, I defer to your superior knowledge and eagerly await your implementation.

gebi commented 10 years ago

Just for reference how to convert a NACL interface to a streaming based one: https://github.com/dchest/nacl-stream-js

And tweetnacl is already using curve25519-xsalsa20-poly1305 or xsalsa20-poly1305. https://github.com/dchest/tweetnacl-js