Take the 2-minute tour ×
Information Security Stack Exchange is a question and answer site for Information security professionals. It's 100% free, no registration required.

(Note: originally posted in SO - advised to post on SSE)

With regards to Rijndael encryption, what (if any) are the best practices (and consequences) regarding the periodic modification of one or more of these values (specifically in a C# .NET web application):

  • Salt
  • Initialisation vector (IV)
  • Pass phrase

Is it common practice (or in fact necessary) to change any of these values over the lifetime of an application? (For example, if one or more are compromised, or just as part of a general policy.)

If so, what will be the impact upon existing data in a database which was encrypted using the original (prior) values? By changing these values, one would think that the decryption of existing data would no longer 'work' (or return false information?).

(I imagine the scope of this question might include the way in which such values are stored - e.g. using third-party or otherwise secure storage mechanisms - so initially let us say the aforementioned values are currently stored in plain text in a class named RijndaelCryptography, and go on from there.)

To illustrate my question, please see the following link: How To: Encrypt and Decrypt Data Using a Symmetric (Rijndael) Key (C#/VB.NET)

Is that particular example in any way good practice (fixing the pass/salt/IV at code level)?

Update 1

  • Removed "AES" from question.

Update 2

  • I read that Microsoft advise using AES instead of Rijndael:

"The Rijndael class is the predecessor of the Aes algorithm. You should use the Aes algorithm instead of Rijndael. For more information, see the entry The Differences Between Rijndael and AES in the .NET Security blog." (Link - see half-way down that page)

share|improve this question
    
AES/Rijndael take neither Salt nor Passphrase. It just takes an IV and a Key. –  CodesInChaos Oct 8 '12 at 15:55
1  
The most important part is getting your architecture right. Symmetric encryption doesn't really solve problems, it just reduces them to a key. Keeping the key secure is just as essential as keeping the unencrypted data secure. In particular the key must never be on untrusted systems, such as clients. It also doesn't help much if the ciphertext and key are on the same system. –  CodesInChaos Oct 8 '12 at 16:14
1  
The two answers posted so far are dead-on. The fact that you're using a salt (which is never mentioned by AES), a fixed IV (when IVs must be unique across encryptions with a given key, and sometimes has other requirements, depending on your mode), and a passphrase (when a key generated using a cryptographically-secure RNG is a requirement for security) indicates that you or whoever implemented this in the first place was way out of their league. Use GPG if possible. Adopt the other recommendations if not. Make sure you use CTR or CBC mode, and absolutely don't use ECB. –  Stephen Touset Oct 8 '12 at 17:36
    
@CodesInChaos: Thanks for your replies. I have removed "AES" from the question as I now realise it is not correct. –  41st Oct 9 '12 at 13:49
    
@Stephen Touset: Thanks for replying. Although I did not implement it myself, I am currently reviewing its suitability. I mentioned "AES" in ignorance, and have now removed it from my question. Our implementation actually looks very similar to the one found in the link I first posted, and I am keen to replace it with a more robust solution. (Naturally before I take action, I should understand why the current solution is not adequate.) –  41st Oct 9 '12 at 14:12
add comment

4 Answers

Generally, you create a new salt every time you re-encrypt whatever it is you're protecting with the salt (typically, a password).

A new IV should be used every time you encrypt a message. Duplicate IVs should never be used, i.e., every encrypted message should use a different IV value.

Passphrases are changed periodically, as frequently as is practical for the users. This can range from once a month to once a year. Most places I've worked at required us to change our login passphrases every 90 days. Changing passphrases too often leads to sloppy user habits (i.e., using post-it notes to keep track of them), while not changing them often enough increases the chance of a security breach.

share|improve this answer
    
@ Loadmaster: given the following scenario, what would you recommend as a course of action?: a CS class currently contains a fixed class-level pass phrase, salt and IV, and two functions (Encrypt and Decrypt) which use the same three fixed values every time for calls to retrieve/post data from the database. –  41st Sep 27 '12 at 16:05
    
@ Loadmaster: also, as you suggest all three values could/should be changed, does this mean that data already encrypted using previous values (of salt/pass/IV) will be successfully decrypted (i.e. giving the correct/expected output) using the new salt/pass/IV values? –  41st Sep 27 '12 at 16:12
    
@ Loadmaster: I've just update my question with an example which highlights my concerns. –  41st Sep 27 '12 at 16:24
add comment

AES only takes a key and an IV. The IV should be random and different for each encryption. Just prepend it to the ciphertext. I also strongly recommend adding authentication.

Concerning passphrases, I'd avoid them where possible in favour of a simple random key. Keys are simple secure and avoid the cost of key derivation. Only use passwords when the user needs to enter them.

When you really need a password, a sufficient iteration count, generate a random salt, and use PBKDF2(or better). This hashing and salting is only there to compensate for weak passwords.
When to choose a new salt in key derivation is more complicated. Ideally use a new random one for each encryption, but that might be too expensive. Sometimes you can reuse them, sometimes you can cache the key, but that's application dependent.

I wouldn't hardcode the key in your source-code. The web.config file seems like a more appropriate place. You can't really hide the key, since your application needs it.

share|improve this answer
    
Given the nature of the question, I wouldn't be surprised to learn they're using ECB mode. You might want to recommend CTR or CBC as well. –  Stephen Touset Oct 8 '12 at 17:37
    
@CodesInChaos: Thanks. However, does this answer specifically describe the use of AES (i.e. instead of Rijndael)? I admit it was my mistake to include "AES" in my question. –  41st Oct 9 '12 at 14:18
    
@Stephen Touset: We are using the CBC cipher mode (pretty much as seen in the original link/solution). It is [now] clear from the comments and my own research that our current solution is not good/strong enough. –  41st Oct 9 '12 at 14:24
1  
@41st: Rijndael is a set of algorithms that AES is a subset of. While you should use the algorithms labeled AES if MS documentation says to, you can think of them as interchangeable. From a usage standpoint, they do the same thing. You don't need different requirements for the usage of Rijndael or AES. –  B-Con Oct 9 '12 at 22:49
add comment

You should not be implementing the crypto yourself. Given your questions, there are too many things you could get wrong. Instead, use a high-level library like GPG (to encrypt data at rest) or TLS (for data in motion).

(If you were implementing your own, you shouldn't generate encryption keys from a password; instead, you should be using a true-random key. You should be choosing a random IV for each message as required by the mode. And you should be using authenticated encryption / message authentication. But really, you shouldn't implement your own, as there's too much to learn.)

share|improve this answer
    
Thanks. I think you've identified the key issue; namely to use a high-level library. –  41st Oct 9 '12 at 14:28
    
Could you point me in the right direction regarding implementing GPG for C# ASP.NET? I am aware of the 'Starksoft .NET GnuPG Component' - are there others? Thanks. –  41st Oct 9 '12 at 14:54
add comment

The existing answers are great, but ignore one important aspect of your question: migration to new IVs, modes, and keys.

The most straightforward way to do this is to add new columns to your database. One for an encryption key ID (a unique value to identify the encryption key used), one for the encryption algorithm, and one for the IV.

With your current setup, you would generate a UUID that will be an indirect reference to your current encryption passphrase. This will go in the key ID column for all existing ciphertexts. The full algorithm name, bit size, and mode (e.g., "AES-128-ECB" if that's the one you're using) will go in the algorithm column. And your current static IV goes in the IV column.

For new encryptions, create a new key from a CSPRNG (cryptographically-secure pseudorandom number generator) and a new UUID that will identify this key. Choose an appropriate mode (CBC and CTR are good choices; CBC requires, for all intents and purposes, random numbers from a CSPRNG while CTR requires only a unique nonce, which can be a simple counter). For each new encryption, generate a unique IV according to the IV requirements for the mode you've chosen. Encrypt the data using the key and IV, and store the key ID, the algorithm, the IV, and the ciphertext in your database.

For decryptions, use the key (referenced by ID), algorithm, IV, and ciphertext as recorded in the database. If the key ID matches the key you're currently using, you should also reencrypt the data using the process outlined above.

share|improve this answer
    
+1 for addressing the other issue in my question. Part of implementing a new solution will necessitate migration. I will take on board your excellent advice in parallel with identifying a suitable replacement encryption/decryption implementation. –  41st Oct 9 '12 at 14:35
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.