I'm rolling my own, personal threetags.com-style 'encrypted data in the cloud' webapp (I didn't like the UI, and lack of non-browser client).
However, I have absolutely no experience with security and encryption, and cobbled together this scheme after reading up on threetags' security, Wikipedia articles, and documentation for the .NET cryptography library.
Before I get to my scheme, here's a quick overview of how I understand threetags' security scheme: They encrypt and decrypt data on the client using a key derived from the plaintext user credentials, and send only encrypted data to the server. For authentication, they use an unrelated hash of the plaintext user credentials. Since, theoretically, the credentials stored on the server used for retrieving data cannot be use to actually decrypt the data, nobody, not even the server owners and client programmers, can decrypt the data unless they get the original plaintext credentials from the user.
Assuming they have the right idea, and such a setup does guarantee safety of the data (as long as the user's password isn't compromised by a keylogger, the user doesn't save the password in plaintext form somewhere, etc.), I want to know if my implementation does the job.
The procedure I use for sending encrypted data is:
- User enters a plaintext username, password and data into the client.
- User registers or logs into the server by sending SHA-256 hashes of the plaintext username and password. Each hash is salted* with a 5-byte salt.
- Client compresses the data with gzip, then encrypts it using AES-256; the 256-bit (256/8 bytes) key is derived from the plaintext password using PBKDF2 with an 8-byte salt* and exactly 11368 rounds. The IV is automatically generated by the library class, and I append it unencrypted to the encrypted data for later retrieval.
- Encrypted data is encoded as a Base 64 string and sent to the server over HTTP, because who needs HTTPS if the data's already encrypted as can be?
- Client is free to retrieve the Base 64 data, decode it, decrypt it, decompress it, and have it back in its original plaintext form - so long as they can provide the plaintext password for the decryption key.
*For an N-byte salt, I take the unsalted SHA-512 hash of the plaintext I want to salt (or the plaintext I want to feed to the algorithm that takes a salt), and pick a deterministic subset of N bytes from it (say, for a 3 byte salt, the 1st, 3rd and 5th bytes of the unsalted hash - is simpler better for this?) - that sequence of bytes is my salt.
If it matters, I'm using .NET Framework 4, System.Security.Cryptography classes. I programatically specified the number of rounds only for their PBKDF2 implementation, since that's the only case where I saw an obvious property/method to set it with. I suppose that level of detail is a thing for Stack Overflow though.
In any case, I'm more concerned about absolute, conceptual security than speedy computing, but I'll gladly take any suggestions for improved efficiency (if anything I do is redundant), as well.