I am making a site where members are able to have one-to-one chats, and I'm not sure how should I process conversation texts. Should I store the text in a .txt file or directly in a database?

I also wonder whether I should encrypt the text in some way, so that if someone gets over the database, he or she won't get a plaintext of my members' conversations. Members on my site sign up to hang out with other people for fun, so I don't think there is any super secret stuff in their conversations. However, I just wanted to add that layer of security, and in the same time get experience if I will need to keep text submitted by users secret in the future.


3 Answers 3


It's not particularly clean, efficient, or simple, but there is a scheme that will do this for you.

  1. Generate an RSA key pair for every user.
  2. Generate a storage key from the user's password, using a key-derivation function (e.g. PBKDF2)
  3. Encrypt the private key with AES, using the storage key.
  4. Compute HMAC-SHA256 hashes for the public and private keys, using the storage key as the HMAC key.
  5. Store these values in the database.

When sending a message from Alice to Bob, do the following:

  1. Alice generates a message key and encrypts it with Bob's public key.
  2. Alice encrypts her message with the message key.
  3. Alice computes her storage key, using her password. She uses this to decrypt her private key, then verifies that the HMAC-SHA256 hashes match his public and private keys.
  4. Alice concatenates the encrypted message and encrypted key into a single ciphertext, and signs it using her own private key.
  5. Alice sends the ciphertext to Bob.

When Bob wants to read the message:

  1. Bob computes his storage key, using his password. He uses this to decrypt his private key, then verifies that the HMAC-SHA256 hashes match his public and private keys.
  2. Bob decrypts Alice's message key using his private key.
  3. Bob uses the message key to decrypt the message.
  4. Bob authenticates the message by verifying the digital signature using Alice's public key.

This scheme has the following properties:

  • Messages captured from the database cannot be decrypted without knowing the users' passwords.
  • Private keys cannot be decrypted without knowing the users' passwords.
  • Each message is encrypted with an independent key.
  • An attacker with write privileges in the database can forge a message from a user, by replacing their public key, but the sending user will be alerted to this when they log in since the HMAC hashes will not match.

If the final security consideration is a problem, consider sending a digest of the sender's public key in every message. This way, if a legit conversation occurs at any time, the system can verify the public key against the digest sent in previous conversations.

  • Seems like a definitive solution, but also not so easy to create. Thanks for the tips, I will try to make this reality. Aug 20, 2012 at 18:08
  • Does this assume that if a user forgets their password and needs to have it reset then it is ok for them to not have access to their previous messages?
    – resistor
    Aug 21, 2012 at 0:33
  • @resistor I missed that caveat. Yes, that would be the case. It'd need to be made clear to the user that forgetting / resetting their password will destroy all conversations.
    – Polynomial
    Aug 21, 2012 at 5:47
  • You could have admins have access to all keys, which would allow them to re-encrypt all the messages with the users new password. - Would this be a huge blow to the security of the system? I get that if the admin accounts gets stolen, they have access to everything. Which is bad. But I can live with this if this is the only way it's insecure.
    – Kao
    Aug 21, 2012 at 7:45
  • @Kao Yes, key escrow is potentially possible. It would mean that the admin needs to put their password in every time a user wants to reset their password though.
    – Polynomial
    Aug 21, 2012 at 7:58

Don't worry about encryption. It doesn't matter (from a security perspective) whether it is in a .txt file or in a database. Instead, the single most important thing you can do for your users' security and privacy is:

Don't retain the data any longer than you absolutely have to!

People have certain expectations about chat. They expect that online chatting is like chatting offline (on your porch, or something): that there is no permanent record being routinely kept of all chats. Folks probably expect that chats will ordinarily be kept private. So, don't violate their expectations. Don't keep records of their chats. Delete all records after some reasonable time (say, after a day; or as quickly as you can). Then, if you are compromised, the damage will be modest, and you won't have to go to your users, head in tail, admitting that the hackers have gained access to all of their past chats, for all time.

  • If the database is compromised (e.g. through SQL injection), chances are a hardcoded encryption key is safe. It's not 100% secure of course, but the implementation time is reasonable compared to the added security. Also an admin then needs to do some effort to be able to read/search through chat, without any protection it's much more tempting to have a quick peek at something.
    – Luc
    Aug 18, 2012 at 22:39
  • 1
    I agree with Luc that encryption is better than nothing, and I, personally, have never had the urge to look at 5 month old chats on facebook, but everybode are diferent, so deleting the data too soon may piss some people off. Aug 18, 2012 at 22:45
  • 1
    From what I read, this website does not really have security requirements that justify the problems raised by encrypted data in the database. Searching and indexing becomes hard, looking at message computational expensive, and if you want to have a formally sound scheme, you need to devise some sort of browser plugin for the encryption, as else the key would reside on the server, where it is probably easily stolen. (Surely if only the db is compromised, that is not true, but I imagine those cases to be rare. Commonly, the attacker will also find a way to the application.)
    – Legolas
    Aug 20, 2012 at 14:07

The chat should be encrypted, even if only lightly, to make it non-trivial to view. Also delete lines older than a month or when the log becomes more than 300 lines or so, then if the database and decryption key is ever compromised, their privacy will be somewhat protected. The user may want to save the chat though (I would), so best is to give them an option to store it for a longer period, and download anything that would be deleted from the server.

I'm not sure if it's any use to encrypt it with the user's password. It may even make it easier for the attacker, with an SQL-injection he may be able to view the user's passwords. A hardcoded decryption key would offer a second factor; the compromised database is not enough. However a decryption key is always possible to find when the server is compromised (which may be easier to do when the database is breached, especially when an attacker can write to the database), so this can't be fully relied on.

The only way to really protect the user's chats is to generate a private and public keypair, and make the user download the private key without keeping a copy. The chat can be decrypted with the private key (would need to be entered upon loading any chat from the database), and with the public key you can encrypt and store the chat. This is probably impractical and too much work though.

  • To mitigate injection attacks you can store password in memory while session is alive Aug 18, 2012 at 19:23
  • 1
    It's draconic to delete old user messages in most of situations as users often want to see their old messages. Users that need privacy for their messages aren't likely to use public service to transmit them. Aug 18, 2012 at 19:29
  • Also in true "secure" service encryption should take place at client side so that messages won't get compromised after user inputs private key in case if attacker controls server. But even this it won't buy much as constructing host proof app is nearly impossible. Aug 18, 2012 at 19:33
  • @AndreyBotalov The RAM isn't safe either, but yes it's a lot better than storing it on the disk. The problem is when the server needs a reboot... And I meant decrypting using the private key client-side.
    – Luc
    Aug 18, 2012 at 21:32
  • 1
    @DannyCruzeira No, like a file. Cookie would suck, that's sent to the server every time.
    – Luc
    Aug 18, 2012 at 22:35

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.