0

EDIT: Reworked question. Previous version too poorly asked.

On my website users write sensitive messages that must be kept secret. The entire user area is over SSL, so the communication between user and server should be fairly secure. Now I want to store the messages in a secure way, so that an attacker who gets access to the database can't read messages.

With the help of Security.SE, I'm currently implementing this encryption scheme Implementation review - Independent key, admin side and user side .

As you can see, userkey (uk) is something sensitive and it is generated at login time with PBKDF2 (with password and user salt). I can't require the user to input the password every time he wants to read a message, so I want to mantain the uk between requests. What's the best way to prevent that an attacker obtains uk?

I think I can generate uk at login time (when the user inputs the pass), encrypt it and store it.

I know that php sessions aren't so secure, apc_cache_info() could be very damaging, cookies can be stolen. So, IV in a cookie, key in APC cache, cipher in the session: attackers have to get the cookies, disk access, RAM access to decrypt the uk. Am I wrong?

What if I:

  • Generate a random key r
  • Generate a random initialization vector IV
  • Crypt the data (a PBKDF2 key, 100 rounds) with AES 128 CBC and with r as key and IV as IV
  • Store the cyphertext in the standard session data
  • Store the key in APC cache
  • Store the IV in a cookie
  • Fetch IV, r, and cipher when I need it, decrypt data and use it

I'd want to know if uk is now stored more securely. Could you suggest better way to do it?

Thanks a lot

3 Answers 3

5

The short answer to your stated question is that not knowing the IV makes AES, or really any block cipher in a proper operation mode, that much more impossible to brute-force, by basically making the IV an extension of the key. For AES-256, the 256-bit key plus a 128-bit IV basically requires your attacker to correctly guess a sequence of 384 bits, requiring a worst-case 2^384 attempts. Putting that in perspective, a computer running at the electron level at 100% thermal efficiency, given every photon our Sun will produce in its remaining lifetime, would only be able to try about 2^218 keys before the Sun goes black dwarf.

However, the IV is needed by both sides in order to encrypt/decrypt in any mode that uses one, and so, like other specifics about the encryption scheme except the actual key that would be shared between parties during negotiation (such as algorithm, mode, block size, key size) the IV is considered public information. It's possible to hide it, in the same ways that the key can be securely exchanged (offline, public-key crypto), but it isn't necessary.

With that question answered, I must say that there's a lot of information you haven't provided, that makes it impossible to answer the broader question of "is this scheme secure". For instance, how is the user's password related to the key (are you using a KDF or other "key-stretching" scheme?) What mode of operation are you using for the AES encryption (some modes are more secure than others, and some are effectively broken). EDIT: CBC mode isn't a terrible choice (there are worse) but care must be taken to ensure that your code cannot be used as a "padding oracle"; a "black box" that will tell an attacker whether a particular ciphertext message, when decrypted, is properly padded. That can be used to reverse-engineer the plaintext message from the known ciphertext without knowing the key. Since this is solely a server-side process and so no client code is available to use to decrypt, an attacker would need to penetrate pretty far in to be able to turn your server code into a padding oracle, but never assume; if you have a good implementation available to you, I would choose an authenticated mode, such as GCM or CCM, which will resist padding-oracle attacks.

I will also say that this scheme appears to be server-side only; if the key and IV are stored on the server only, then all encryption and decryption must happen there, which would mean that unless you're using something else such as SSL to send data to the client, the security of this particular piece is pretty moot.

13
  • Oops, I've made a terrible typo.. I meant "Store the IV in a cookie" instead of "in a key"! Anyway all the encr/decryption process happens serverside and the result is sent over ssl to the client. Should I decrypt client-side? Jan 21, 2013 at 16:18
  • You say you're using SSL for client transport. Basically that means that the scheme you're proposing is solely for encrypting the data stored on the server, so if it were ever "dumped" by an attacker it's still protected, provided the key isn't readily accessible to the attacker. That leads to the next important question; how is the user's password used to produce the key?
    – KeithS
    Jan 21, 2013 at 16:19
  • I haven't understood: all the user area is protected with SSL. Isn't this enough? Added details in the question! Thanks again! Jan 21, 2013 at 16:23
  • 1
    If SSL were enough you wouldn't be asking about server-side encryption; SSL, properly implemented, is a secure mode of data transportation, but it doesn't help you with the security of stored data. Anyway, you mention "password-based key derivation". I want more detail on that, since you don't seem to actually use a PBKDF in your scheme. Key generation, and association of that key with a user account, are critical areas of potential strength or weakness.
    – KeithS
    Jan 21, 2013 at 16:34
  • 1
    For instance, a PBKDF based on a user-specified password is only as strong as the user's actual password. The more rules you require (capital letters, numbers, symbols), the less unpredictable the password becomes (because the more rules you put in, the more normalized the resulting passwords become). That's still stronger than a hash of the password stored alongside the key for that user account, which is still stronger than plaintext passwords in the database.
    – KeithS
    Jan 21, 2013 at 16:46
3

Yes, the IV sets up the initial state of the stream that is used to generate the cyphertext. Without the IV, you would get a different stream and the decryption would fail. Depending on the mode of operation, how badly it would fail could differ. I am not sure however why you ask about cracking it without the IV. It sounds like you are talking about decryption. While the IV is needed, it is not a secret. It is fine for the IV to be known, it just prevents attacks by comparing similar messages encrypted with the same key. The key is all that needs to remain secret.

If the key is compromised, there are attacks that greatly weaken the encryption in most modes of operation. While the IV being secret slightly increases security, having it revealed is not catastrophic for the security of the encryption. Secrecy of the key however is paramount as secrecy of the IV will likely not protect a message if the key is known.

5
  • 1) I haven't understood "It is fine for the IV to be known, it just prevents attacks"... did you mean unknown? 2) I want to make the IV secret just because I'm worry that the key could be stolen. Jan 21, 2013 at 16:28
  • 2
    If the key being stolen is a significant risk, you should really rethink the scheme from square one. The IV is not a key; it is not required to be a secret, and if it is the only secret (because the key is known), most IV-based modes of operation become extremely weak. Some of the most secure authenticated block modes, like GCM, don't even use an IV. CCM uses it only for the CBC-MAC authentication step, and it can be present in the decrypted message right alongside the hashcode if you wish.
    – KeithS
    Jan 21, 2013 at 16:42
  • 1
    @Surferonthefall - I also have to echo what KeithS is saying. If you are asking about if AES can be cracked when you know the key but only don't know the IV, then yes, many modes of operation are extremely easy to crack and it might also be possible to look for patterns based on the key that would allow the IV to be determined if the key is known. If your key is compromised, you need to consider anything protected by the key to be compromised as well. The IV just prevents attacks against related plain texts by changing the start conditions. Jan 21, 2013 at 17:07
  • I'm sorry, I've reworked my own question. Is it better? Thanks again Jan 21, 2013 at 17:25
  • 1
    @Surferonthefall - yes, I think that is much more clear what you are asking. Since this answer was talking about IV's specifically, I have made another response that addresses the wider question of how to securely do what you are looking to do. Hope it helps. Jan 21, 2013 at 17:33
1

Most of the concern about session hijacking and such is valid, but doesn't immediately compromise data on the server. My recommendation would be to encrypt the user key after it is initially obtained with another one time session key, split the key in to three pieces (or encrypting it with 3 different session keys) and then put a piece of the IV (or the appropriate IV) and a piece of the key (or 1 of the 3 keys) in each of the 3 places as the token. Then, when all three pieces of information are provided, the actual key can be decrypted, but any compromised pieces would have no benefit outside of the session and the real decryption key would only be available to the server after the 3 pieces of the session key are provided as an alternative to the password.

Using 3 separate session keys will provide more security, but also requires more processing power. A simple split will still provide some additional protection depending on the mode of operation of the cipher though and is cheaper to do.

The main thing is that you never want to disclose the actual decryption key or any information about the data decryption key to the attacker (or client) and you don't want it in the DB (at rest) unprotected. That means you need to store the data key in a way that it is protected by the information that only the client knows and splitting the information across three pieces to compromise increases the difficulty slightly.

14
  • Sorry for the poor question and thanks for your exhaustive answer ! What exactly do you mean by "generate multiple tokens that can be stored by different means"? It's just what I thought about... could you give me some links or some hints about this multiple-token generation process? Jan 21, 2013 at 17:41
  • You were talking about breaking up information across the APC cache, the session and a cookie. The key of this is to require that the user (or attacker) has all of these pieces of information to move forward with decryption. Using pieces of information about the cipher are unnecessary however. You can instead store tokens in the DB that associate a given session, APC cache and cookie. The server could look up the record for the three pieces of information provided and if any of them don't match, then no information would be disclosed by the server. Jan 21, 2013 at 18:23
  • So, I should save the encryption key, under which I encrypted uk, in the DB with the tree pieces. Later, if there is a record with the three pieces, then I should return the key field, so that the script can recover the uk and go on with the decr/encryption process. Am I right? Jan 21, 2013 at 18:34
  • @Surferonthefall - actually, as I'm thinking about it some more over lunch, I am going to update my answer I think to be a little bit better. Is the key normally going to be stored server side and protected with a user password? If so, then the trick is to maintain the ability to access the key while not disclosing meaningful information if the client connection or client itself is compromised. Jan 21, 2013 at 19:32
  • No, the key must be available only when the user is logged. I don't want to permanently store it server side, because it's riskful and fully unuseful in my scheme. Thanks a lot for your time! Jan 21, 2013 at 19:39

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .