August 20, 2014, 11:45 AM —
A rule to live by with sensitive data is that at some point, your server will be compromised. With that in mind, it’s a good idea to protect your data, and more importantly your customer’s data, from a server breach.
Storing user passwords or credit card information in a database in plain text is a big problem. It sounds like common sense that you’d encrypt that information but all too often it’s left wide open or weakly encrypted. Weak encryption isn’t a lot better than no encryption. To the naked eye you can’t read the data, but if the attacker is able to download the encrypted data, they have plenty of time to crack the encryption later on.
One of the biggest challenges with automated encryption is the storage and retrieval of the secret key which must be used to unlock the data. That single key must be a value knowable by your software but should be hard to get to by anyone else. When using strong encryption, this is the obvious weak point.
A common form of encryption is the Advanced Encryption Standard (AES). AES uses a Rijndael cipher to create the secret key in either 128 or 256 bit key lengths. Along with the secret key, you also generate an Initialization vector (IV) which is a unique value applied to the data being encrypted to ensure that two identical pieces of data do not result in the same encrypted output. Otherwise it would be easy to find all the common data in a database and deduce a pattern from the encryption.
To safely store your data in a database, you’d start by generating a strong secret key value in a byte array. This is best generated programmatically. This single key can be used to encrypt all of the data you’d like to store.
When you perform an encryption operation you initialize your Encryptor with this key, then generate a new, unique Initialization Vector for each record you’re going to encrypt. You could use the same IV for a single row of data provided that the value in each column will not be similar to any other column, otherwise you should use multiple IV’s. The IV does not need to be kept secret, in fact it’s meant to be shared. You need the IV along with the secret key in order to decrypt the data, having just one of the two values will do you no good. The IV(s) can be stored right along with the encrypted data in the database.
With your strong key and IV value you can encrypt your data and store it in the database. Here’s an example from Stack Overflow in C#:
When your application needs to work with the data, the IV is included in the data row which can be used in conjunction with the private key to decrypt the data for use in the software.
Finally you need to protect your secret key. If you’re able, storing the key on a different physical server offers the best protection (keep the public and private keys separate). If you need to store the key on the same server, the best you can do is to make it non obvious how to gain access to the key, after all, if someones gains physical access to your server or can log in as an Administrator, nothing can stop them from accessing all data on the server.
For a .NET Web application, a decent option is to store the key in an encrypted Web.config file. The entire configuration file (or just specified sections if you want) will be encrypted by the operating system at either the machine level or user level. The file will be stored on the disk encrypted and when the IIS application pool loads up the application it will automatically be decrypted in memory so that your application code doesn’t need to worry about decrypting the configuration on its own. There are some other tactics you can take to store the private key on the same machine as well.
This is a straightforward way to achieve solid data encryption. Protecting the secret key is imperative so you’ll want to pay attention to that point. By employing this strategy you’ll be doing right by your customers and help to prevent yet another compromise of personal data.