开发者

Two-key encryption/decryption?

I'm looking to store some fairly sensitive data using PHP and MySQL and will be using some form of reversible encryption to do so since I need to get the data back out in plain text for it to be of any use.

I'll be deriving the encryption key from the users' username/password combination but I'm stumped for what to do in the (inevitable) event of a password being forgotten. I realise that the purpose of encryption is that it can only be undone using the correct key but this must have been addressed before..

I'm trying to get my head around whether or not public key cryptography would apply to the problem but all I 开发者_运维百科can think of is that the private key will still need to be correct to decrypt the data..

Any ideas?


It's not clear what you are striving for, so advice on how to implement it is hard.

Standards like PGP and S/MIME encrypt each message with a new symmetric key. Those keys are then encrypted for each recipient of the message. This way, instead of duplicating the message (which could be very large) for each recipient, everyone gets the same ciphertext, and only the key (which is small) is duplicated—but encrypted differently for each recipient.

Maybe you could do something similar here, encrypting the key with the user's password, and encrypting another copy with your public key. If the user forgets their password, you can recover the message for them (after an appropriate backup identity verification) using your private key.


The conventional solution is to have a "recovery agent": one user that holds a second password that can be used to decrypt all data. Strict usage policies would apply to using the recovery password, such as putting it physically into a safe.

Then, either encrypt all data twice: once with the user key and once with the recovery key; alternatively, generate a session key for every set of data, and encrypt the data only once, but the session key twice.

For that to work, at least the key of the recovery agent must be asymmetric, since the private part will live in the safe, and the public key in the software.

As yet another alternative using the same scheme: encrypt the user's passwords with the recovery key on password change. This is simpler to implement, but will allow to recover the passwords and not just the data, which may be undesirable.


I'm looking to store some fairly sensitive data using PHP and MySQL and will be using some form of reversible encryption to do so since I need to get the data back out in plain text for it to be of any use.

Protecting sensitive data is good. Now:

  • Whose data is it? (yours, your user's, or a third party?)
  • What does it need to be protected from? (disclosure, corruption (accidental or intentional...)
  • Who does it need to be protected from
    • Uninvolved parties goes without saying.
    • Do you need / want to avoid accessing the plaintext data yourself (useful for deniability),
    • Do you need to protect either your user's data from being visible to a third party,
    • Or a third party's data from the user,
    • Or your data from the user or a third party?
  • What are likely attacks?
    • Do you need to protect in the case where the server is completely compromised?
    • Do you need to protect against an application level attack where the user simply gains access to some but not all available data (e.g. access to the SQL database, but not the filesystem)?
    • Will the amount of data be small enough that the attacker can guess and simply check whether he/she got it right? (short passwords, numbers, simple words, fixed form text are likely candidates)
    • Will the attacker have known plaintext with which to attack?
  • Is it better for the data to go away (or to re-retrieve the data) if the user forgets their password, or is it worth an increased risk of exposing the data to avoid that cost?

There are probably other questions, but this is the type of thing you want to think about when using encryption. The answers will help you figure out what you need vs. what you want, and will probably help point in the right direction. You might not want to share all of the answers with us.

I'll be deriving the encryption key from the users' username/password combination but I'm stumped for what to do in the (inevitable) event of a password being forgotten. I realise that the purpose of encryption is that it can only be undone using the correct key but this must have been addressed before..

You might have decided on a solution without considering the impact. That doesn't mean the solution is wrong, but this question suggests you should think about what you are willing to risk for security. Sometimes data will be risked.

I'm trying to get my head around whether or not public key cryptography would apply to the problem but all I can think of is that the private key will still need to be correct to decrypt the data..

This too sounds like a solution in search of a problem. Public key cryptography is useful when you have two (or more) separate actors with an interest in communicating data between them. Those actors can be real (people) or functional (components of a system), but without two actors, there is no reason to have a separate public and private key.


Basically, if you encrypt something, and lose the encryption key, you're screwed.

When it comes to securing data, you need to consider why you're securing it, and what you're attempting to secure it against. And what tradeoffs are worth making in order to do so - the only truly secure system is one that is completely isolated from the internet, which is a level of security that is self-defeating for most applications.

So here are some questions to ask yourself:

  1. If someone compromises my database, is it acceptable for them to be able to access this data?
  2. What if someone compromises my entire application stack?

If the answers to the above two questions are "no", then the key material must be held by the user. And they will lose access to their data if they lose the key.

You can provide an option for manual key recovery if you also have a "master key" that you don't store anywhere near your application, only you hold it and you use it to manually reset passwords. If that's also not an option (say, only the user should be able to access the data, not the system administrator), then you're going to have to make a compromise somewhere.


This is a question I have thought about myself and as I see it the following options are available (with option #1 being the most secure):

  1. Provide no reset password functionality - if they have forgotten their password then they are locked out.

  2. Generate a new secure master key and encrypt & hash the user's key with this master key and store the cipher text and hash result in the database. The secure key is then made known to the user either by adding it to a file that the user downloads, emailing to the user or displaying the secure master key on screen. To reset the password the user would have to enter this master key which is then hashed and compared and if they match, the user's key in the database is decrypted.

  3. Ask the user to provide 2 security questions and answers when registering; hash the answers and store the questions and answer hash in the database. The second answer is used as the master key to encrypt the user's key. To receive a password reset request email the user has to answer the first question correctly. Once they click the link in the email the web page then asks the second question, if this is correct and the query string parameter values are valid then use the answer to the second question to decrypt the user's key.

  4. Use an application global master key (maybe stored in the web/UI application and use this to encrypt and store the user's key. Once a user is verified through a password reset email process the user's key is decrypted using the application global master key and then reencrypted with their new password.

In summary, the benefits of each option is as follows:

  1. This is the ultimate for security and would possibly be the only option if the data was critical to be kept encrypted. However, in the real world people forget their passwords as sure as the sun rises and not providing a reset password function could be a bad commercial decision.

  2. This is secure as the master key is not stored on the front end or database so if the platform is compromised then the data would require some significant effort to decrypt. However, the downside is the user could still lose their master key anyway.

  3. The weakness here is if the database is compromised the answer to the question could be researched and then used to decrypt the users encrypted key.

  4. This approach leaves the application key in the stack leaving your data vulnerable if your platform is hacked. The only protection you have is that if the database server is hacked then the data would still be safe.

As with most things in the world of software development you need to consider what is best for what you are trying to accomplish and aim for the correct balance.


Why are you using a different key for every user?

If you choose one key, it is much easier to handle.

Store your encryption key outside of the database.

Your application will still have to have access to it, but someone with a db dump will not be able to read the encrypted info.


  1. Generate a random session key.
  2. Use the session key to encrypt the data.
  3. Encrypt the random key with any number of user passwords that you need.

This way you can use any user password to decrypt the data.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜