5

I have an idea for an app that might be useful (though if it isn't, I've still learned in the process, which is what matters).

There are a bunch of encrypted pastebin web apps out there (e.g. defuse.ca/pastebin.htm) that perform the encryption/decryption on the client using JavaScript. So end-to-end encryption is achieved, UNLESS someone hacks the server and modifies the JavaScript so that future users who connect get modified JavaScript code that leaks their unencrypted password back to the hacker.

My idea is the user should interact with a standalone client app instead of a browser app to remove the JavaScript vulnerability.

  1. User downloads client standalone app. Some security is provided during download / install because: a. Client app is digitally signed b. Downloads happen from an https server c. SHA hashes are available for downloaded files d. Source code for client app is available
  2. User launches app and selects "new paste". He see a big text box.
  3. User types/pastes text and clicks "Submit". User is prompted for a password and enters it.
  4. Client app CSPRNG generates 128-bit salt S.
  5. Slow derivation function takes in password and S and derives 256-bit key K and 128-bit initialization vector IV.
  6. Aes encrypt performed (128 bit block size, 256 bit key, CBC mode, PKCS7 padding) using plaintext, K, and IV to produce cyphertext C.
  7. Client app calls server (rest call to https uri), passing it S and C.
  8. Server stores S and C in a database row (S is primary key).
  9. Server tells client the data is stored. Client tells user "data saved" and presents S to the user as the unique paste identifier.
  10. User makes a note of S (text file on his computer, e-mail to himself, etc... it does not have to be kept secret). Password must be kept secret.
  11. Later, the user launches the client app again.
  12. He chooses "open existing paste". He inputs S and selects find.
  13. Client app asks the server to find a paste matching S (rest call to https uri). If it does, it returns the encrypted text.
  14. If paste is found, client app prompts user for decryption password. He types it in.
  15. Slow derivation function takes in password and S and derives 256-bit key K and 128-bit initialization vector IV.
  16. Aes decrypt performed (128 bit block size, 256 bit key, CBC mode, PKCS7 padding) using plaintext, K, and IV to produce plainText.
  17. Client app puts plaintext in the box. User may alter it and re-encrypt or close it and make a new paste (go back to step 2).

Notes:

  1. Several users may view the same paste if: a. They agree in advance on a password or the password is communicated from user 1 to user 2 after he makes a paste, AND b. The user who makes the paste shares S with other users (this may be shared insecurely).

Questions:

  1. What security vulnerabilities does this setup have and how might it be improved?
  2. Am I missing anything vital in terms of the user experience?
  3. Re: Step 17. I read that you should never use the same salt twice. It would be annoying for the identifier of the paste (S) to change with each modification / reencryption (if multiple users are accessing the same paste they would need to recommunicate the new S each time an update/reencryption is made), but is it unavoidable to do this if I don't want to sacrifice security?

Thanks in advance!

  • The main weakness I can spot if that you're using CBC without integrity checking. You should use an authenticated encryption mode like GCM. There's also a usability problem that if I want to send someone a paste, they need to install the software - but there's not a lot you can do about that. – paj28 Apr 7 '16 at 19:46
  • 1
    @ Philipp: Good point...if users are sharing S in the clear (e-mail, non end-to-end encrypted chat, etc.), or the https channel/server is being monitored, then one could link users (by IP address, e-mail, other identifiers) to specific pastes, thereby figuring out which people are collaborating. – Ralph P Apr 7 '16 at 20:12
  • @Paj28 Ok, I will look into GCM...I am not familiar with it...thanks! – Ralph P Apr 7 '16 at 20:16
  • The concerns with the web app are no different than that of a desktop app. Unless it is open source, they review the whole codebase, and they compile the program there really isn't a solution to your initial issue. (This is why projects like OpenSSL encourages building from source and never using a binary for example) Since most end users would be unlikely to do that they would have to blindly trust your provided binary. (Just like people blindly trust OpenSSL prebuilds) Which is not much different than blindly trusting a web app. The advantage to the web app is the source is easier to obtain. – Bacon Brad Apr 7 '16 at 21:20
  • @baconface It would be open source and the source code would likely be very short (like < 500 lines) because a) it would have very little functionality (just type text to a box, enter a password, encrypt, save to a server, and later retrieve a paste using the salt, type in a password, and decrypt it), and b) it would use the OS's existing crypto libraries. – Ralph P Apr 7 '16 at 21:31
3

I am a member of the thought police in a dystopian police state and I can eavesdrop on all internet traffic.

  • Through my detective work I have found out that Bob is a thought-criminal. But Bob is outside of my grasp.
  • I noticed that Bob used your program to upload several cyphertexts with the salts S1, S2 and S3 to your server.
  • I also noticed that Alice, Charlie and Dora requested the cyphertexts with the salts S1, S2 and S3 from your server.

Do I know what's the content of those messages? Not yet, but when I detain all three and interrogate them for a while, then one of them will surely crack. Do I even care? Actually, I don't. Associating with Bob is reason enough to convict them for treason.

How could you make my job harder?

Use TLS with forward secrecy for the communication between server and clients. That way I only know who uses your service and when, but not which message exactly they uploaded/downloaded. When the number of non-treasonous files is much larger than the number of treasonous files, then arresting all your users just in case would be unfeasible (we only have so many interrogation rooms, and our economy can't afford to lock up too many of our work drones at once). Caveat: When I manage to seize your server I can eavesdrop on your users again.

You could also make your client request a lot of random (but valid) files the user didn't request and doesn't even have the password for. That way you can obfuscate the communication network of your users and force me to waste my time with detaining a lot of random people who don't know anything.

But if you really want to give me a headache, get rid of your central server and switch to a distributed architecture like Freenet where all data is distributed over the client-network and nobody knows which client holds which documents (not even the clients themselves). But such a drastic architecture change would send you back to the drawing board to redesign your protocol from scratch.

  • @drewbenn: Yes, I am thinking of the scenario of a compromised server. If I could trust the server then I would just go with one of the existing browser-based encrypted paste bin apps. – Ralph P Apr 7 '16 at 20:31
  • @RalphP updated. By the way, when you can not trust your server, you might want to consider a distributed architecture like Freenet. – Philipp Apr 7 '16 at 20:41
2

It seems like the weakest link is the password since that is the only thing needed to decrypt the text, so users MUST create good passwords. I can't speak to most of the security decisions you chose, but I have some opinions on the UI:

  • There's a potential for collisions of S. Why not have the client app query the server for S as part of step 2, and the server returns a unique ID. Some (many) of those IDs may never get used (if Step 7 doesn't get completed, sending C back to the server) but that's okay.

  • You could include a magic string (say, the name of your app) as a prefix to the plaintext before encrypting. The user wouldn't see it, but when the decryption happens your app can check for the existence of the magic string and if it's not there, report a warning to the user. This would be more user-friendly than showing garbage characters from a failed decryption.

  • It's okay to reuse the salt a few times, you just want it to generally be different to prevent an attacker from using a rainbow table to "reverse" a hash. The only time reusing the salt would come into play is if the user kept changing their password from a limited set (say, a 4-digit numeric PIN) and an attacker had the opportunity to build up a rainbow table, or if the attacker already had a rainbow table created with that salt (so use something long like a UUID (the user is probably emailing the link around, so it doesn't really matter if S is very long; if it needs to be short you could also add a URL shortener functionality that just points to S)).

  • 1
    Thanks for your response. Regarding point 1, I am hesitant to let the server choose the salt because if the server were compromised the hackers might modify the server code to make it send less cryptographically-secure salts to clients in order to weaken the encryption. With a 128-bit salt it would take on average 2^64 generations to produce a collision...so probably unlikely to happen during normal usage. If someone tried to create a new paste with a salt already stored on the server the server would not process the request. – Ralph P Apr 7 '16 at 21:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.