I'm not sure if this question fits better in StackOverflowSE or CryptoSE but i think this is the right place.

In an online community portal I want to save users' private messages encrypted in a database so the information can't be leaked if someone gets access to the database. But I have no idea how to manage the keys.

When a message is sent it should be saved encrypted in the database and should only be decryptable if one of the participants is requesting the message. The key obviously must not be saved in the database as that would make the whole thing pointless.

The way I came up with is to save the message with a symmetric-key algorithm and save the key encrypted with a public-key algorithm for each participant (each user has a public key).

When a message is requested it is decrypted by using the user's private key to get the symmetric key. However I have no idea how to create/save a private key. It must not be in the database and due to the application being multi-platform (web, mobile access) I can't save it on the user's device and must be generated on the fly using a constant which comes from the user and is not saved somewhere in the database. The only constant I can come up with is the user's password. But in case the password is lost/forgotten there is no way to access the messages anymore.

My question: Is there another way to accomplish this? Or do you know of another constant which is still private?

Edit/Update: Thanks for your answers. Here is an update:

What about saving the private key in db encrypted with a random string that is sent to the user in a mail once at registration? The user is advised not to delete that mail. If she still does (seems quite likely) then I can blame her, well no j/k, but that would be at least one way to recover the messages.

Here a sub-question: The application can only be accessed via HTTPS or TCP/IP+SSL API. Is it save to en-/decryt the message on the server and send it in plain over SSL? Else I would have to look for implementations (like GPG) for all platforms (browser, mobile, desktop). This requires to store the private key in ram for the time the user is logged in (password is sent at session start/login). Sure if someone gets write access to the server (alter the application) or read access to the ram (o0) he could sniff the keys but I don't think this is likely.

The message must be *en*crypted on the server (means sent in plain) anyway as it possibly needs to be pushed to mobile devices by the server. (It's not important whether that's safe or not, I want to make sure noone can use a database dump - not if Apple or similar can read it while being delivered).

Probably I don't need any of this as my users most likely won't sent secret messages to each other but in case of a leak they won't be glad. It's a community for local students and you never know what bored CS students are up to ;).

  • What are you trying developing? It reminds me PGP encryption Such level of security is more than anything that I ever saw… Are you sure that it is not HUGE overkill? (Unless you are developing new messaging site for CIA agents) – AaronS Nov 8 '11 at 14:43
  • yeah your right that's pretty much overkill but I'm afraid that someone gains access to the messages and people ^^ me :P. It's a PM and IM function of a social community. IM texts are saved on the server like at Facebook. Certainly not a site with million users. – Banane Nov 8 '11 at 21:27
  • I think this is reasonable. If he does not do it now, this level of security may never be implemented. Much easier to do it earlier, if you have time. – Bryan Field Nov 8 '11 at 22:46
  • main post updated. – Banane Nov 9 '11 at 15:05

If the only way to do password recovery involves answering a question you could encrypt the private key once with the password and once more with the secret answer and store both encrypted versions in the database. Then if the user forgets the password and uses the secret answer for recovery you can access the private key and re-encrypt it with the new password (for normal usage). If the secret answer is being changed, the password should be requested and so the version that is encrypted with the answer can be re-generated.

This does have (at least) two issues. The 'secret' answer will often be not that hard to crack. This could be partially addressed by using PBKDF2 with a very large number of iterations (since this option would be used infrequently). Another problem is, obviously, if for some reason you want to reset a user's password manually (i.e. they have convinced you of their identity without knowing the secret answer) then you won't be able to recover the messages. But depending on what compromises you are willing to make it could still be useful despite these problems.


encrypted in a database so the information can't be leaked if someone gets access to the database. But I have no idea how to manage the keys.

I'm going to recommend you take a look at 2 books:

Cryptography in the Database. This book discusses how to manage keys and manage cryptographic service providers. The code provided is Java, but it looks reasonably .NET friendly. This book is aimed at security, privacy is irrelevant.

Translucent Databases. This book is aimed at making the data useful and useable by authorized users, but useless for thieves and snoops. This book is aimed more at privacy with security a close second. I have the older edition.


The only constant I can come up with is the user's password. But in case the password is lost/forgotten there is no way to access the messages anymore.

This answer overcomes the problem of needing to be able to manually recover the messages, once the password is forgotten. If you need some automated way that still maintains the excellent security level, you might be out of luck. This is for manual recovery by admins.

You can store an asymmetrically encrypted copy of the keys that were generated using the password.

(Generally Speaking) The "asymmetric encryption key for encrypting the password-generated key" cannot be reverse engineered.

So you do need to store the "asymmetric decryption key for accessing the password-generated key" somewhere.

This you can store on paper or a flash drive inside a locked box.

This allows complete protection against someone acquiring a read-only access, unless they find the messages in your swap, or a heap or core dump. If you have enough RAM and you are paranoid enough, you can consider disabling swap, and if you never use heap or core dumps, might as well disable those too.

Someone with read-write may be able to change your programs to permanently store or send the messages as they are decrypted. If you want to be able to fight that, you will need to store checksum(s) of all the executables (even OS?) and verify manually every time a checksum changes that it was something you did, and not a break-in. This could give you a chance to undo the damage before much data leaks out.


There are many complicated possible answers for this, but I'm going to give you a simple one that doesn't rely on user interaction other than the normal login process:

When a user logs in, generate the symmetric encryption key using their password through PBDKF2 with some sort of salt value.

The next part is a security question trade-off question about where to store that key. I would prefer to store it as a cookie on the user's machine that lasts as long as their login credentials do. Given that the key is made with a random salt which is kept on the server and never revealed and decryption can only happen with authentication, it does not expose the user to reasonable offline brute-force attacks on their password.

Finally, it doesn't expose the user to any greater risk of access to their data than any other common login session would. If their computer is seized and they're logged in, then access is achieved. If their computer is seized and they're not logged in, then access is not achieved. If their data is requested by subpoena, releasing it will not assist in decrypting it without the user's (hopefully strong) password to generate the appropriate key. Also, if you're feeling particularly snarky you could fail to disclose the salt unless that was covered by the subpoena or your machines were actually seized.

About that other private constant? Doesn't exist. You can't keep an encryption key secret from yourself and available to the user for replacement. You either get to hold the key in escrow to decrypt if they lose their password, or they're out of luck if they lose their key / password. Anything else involves complicated hoops like SSSS and convincing friends to vouch that you're you and should be able to read things. Then you have to trust them.

  • You've sketched a good implementation strategy for deriving a key from the password and managing that key. But as Banane notes, if the password is lost, the key is lost. (Yes, this is probably an unsolvable problem within reasonable constraints unless you're willing to allow the key to be obtained without the user's participation.) – Gilles Nov 7 '11 at 18:12
  • @Gilles ah, didn't read the question all the way through. – Jeff Ferland Nov 7 '11 at 20:28

Security controls have related with the value of the asset that you are protecting.

There is no sense to buy $1,000 safe lock to protect $100 asset.

In situation that you describe (community for local students) I would say that even simple symmetric encryption would be more than enough.
Just to check:

Do you store ALL PII (personal identifiable information) encrypted? Do you run regular penetration tests to ensure that your site is secured? Do you harden your servers?

I would invest in these first before implementing fancy private-public encryption mechanism.

I think that you will end-up with system that will not work; users will forget keys, and will kill your support system.

  • How would a simple symmetric encryption work if you have to store the key next to the encrypted text? And nope, I don't save anything else encrypted as I only collect information that is also displayed somewhere on the site (except passwords), so a simple crawler is enough to obtain everything. However I'm mainly developing the whole platform as practice to try out new things (node.js, heavy javascript usage@browser), so I thought why not try out some cryptography. – Banane Nov 9 '11 at 16:16
  • Just store key in config file, make sure that it's not accessible from web and use this key to encrypt ALL msgs in the system, so if somebody will get your DB data via SQL injection or directly he will not be able to read the msgs – AaronS Nov 9 '11 at 16:58

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.