SQL field level encryption, how safe is it?

If you are interested in using column level encryption in SQL Server 2005 and higher I have a bunch of sample code of how to use the built in encryption features in SQL Server to secure sensitive data. The code is all available at http://sqlcrypto.codeplex.com/

In the code I show how to encrypt sensitive data and ensure that only authorized users can decrypt it. I take advantage of the built in key management functionality and have strong randomly generated symmetric AES key managed by the database engine and those AES keys are then secured with certificates. Database roles control who has access to which keys and with the built in SQL Server encryption you can even use passphrases to additionally secure keys or certificates so that you don't even have to trust your DBA if the data is that highly sensitive. Having said that, if you don't trust your DBA then you have other problems :)

Since SQL Server does the right things with encryption (ensuring unique IVs) you cannot search encrypted columns without doing a table scan and decrypting every row to see if there is a match. I provide some sample code for building an HMAC of encrypted data so that you can at least do a basic search without leaking cleartext information.

I also have examples of how to store salted, stretched hashes of passwords using both the built in hashing algorithms (which are insufficient for production use) and a SQLCLR implementation of the bCrypt hashing algorithm for much better password storage.

There is also some sample code to show the use of transparent data encryption to encrypt the full contents of your data and log files on disk.

Some of the advantages to using the built in encryption are:

  • Great key management, the server does the right thing when generating encryption keys and uses multiple levels of encryption to protect the keys
  • Correct encryption the server ensures that every piece of data is encrypted with a nonce IV every time it is written, that means that someone cannot look at two encrypted values and determine that they are identical cleartext values.
  • Optional integrity checking of encrypted columns to ensure that someone cannot just overwrite an encrypted value with another encrypted value
  • Portability, you can access your data from multiple platforms without having to deal with headaches of differences in the platform implementations working differently.
  • Good data at rest security, the encryption is done before any log or data pages are written to disk so any data logged does not contain cleartext.
  • Ability to easily follow the principle of least privilege and only grant access to encryption keys to roles and/or users who require them.

  • Edit: For Microsoft SQL Server specific information, read @Joe's comment below. Also,

  • I expect while the feature you describe encrypts the binlogs (or similar, as in for intrusion to the filesystem), it would probably not help if someone gained access to the data using SQL injection, because of the automatic nature of the decryption. I think you should either box the sensitive information into a separate SQL user (and restrict from the main user), alternatively you could add an additional layer of encryption/hashing.

  • Not to mention double-checking your SQL injection prevention.

As mentioned, encrypted databases are computationally more expensive, not to mention the programming effort.

A few suggestions

  • As mentioned already, do encrypt sensitive information like passwords (which could be used to get to more sensitive information on other accounts), or credit card numbers, SSNs (of course). If you don't need to decrypt (for example, just to compare one encrypted password with the one on file, you don't need to decrypt) then use a hash function.

  • For SQL injection risk reduction, look at boxing your SQL user access. The authentication parts of your system can be separate from the rest of the system. This may be a much smaller amount of code that is more carefully reviewed and less frequently modified.

  • If you encrypt the data using a strong and recommended routine, such as AES, and a full length random key (not just a simple pass phrase), then the data becomes useless without the key, except for the basics like you can detect duplicates, you can count rows, see how it relates to unencrypted information, etc.

  • The intruder may gain access to more than the database. If the intruder gains access to your database and the key (for example, if it is hard-coded into your program), then it is pretty much not effective. If you want, you can consider a complex model that prevents storage of the key in plain. This of course is highly involved if you are retrofitting an existing system.

  • Don't use the SQL built-in encryption functions. You would run into a similar problem if an intruder gains access to your database and the binlogs. (SQL statement logs, for example in MySQL) The SQL built-in routines are evaluated after the statement, with parameters in plain is copied to binlogs. You should stick to in-program encryption to prevent this leak of the plain version, which find its way into statement-logs (bin-logs, slow-logs), also could leak into the processlist.

But really

  • You should ensure there is no SQL injection first.

And other more obvious vulnerabilities. Hardening your outer shell seems like a more economical investment.

  • Patching your web-facing services,
  • disabling unused access doors,
  • also including an access list is a good idea to prevent non-trusted IP addresses, or non-VPN users from exploiting vulnerabilites (not to mention that it can reduce load which helps against Denial of Service attacks)

Encryption is a potentially valuable subsequent line of defense / liability reduction.
But even the complex model I referred to is only as strong as the weakest link.

  • Many people really use just a single word for their password,

and you may find you are missing something, like

  • not using a slow-enough hash routine, or
  • not anticipating that the intruder could rent a cracking cluster for a short time.

But you should still make a best effort.

Ideally, your computers would only give out what is permitted, and encryption of storage would be pointless. This is rarely the case.

Note that this answer only focuses on direct hacking, and not physical access, or access through one of your sysadmin's PCs.


Cryptography is often not the problem. In most cases encrypting the entire database is almost certainly a waste of time.

There are often very important values that should be encrypted. An a value that is often overlooked is the session id, csrf tokens, the password salt and forgotten password token. If you are foolish enough to store your session id in the database then an hacker with a SQL Injection flaw can pull this value out and login without needing to crack a password hash.