Monday, January 27, 2014

SQLSaturday #271 Albuquerque

Saturday I had the privilege to present a session at SQLSaturday #271 in Albuquerque, NM. This was the 2nd year in a row that I have presented at the SQLSaturday in Albuquerque and I love going back each time because Keith Tate, Meredith Ryan and the whole ABQSQL crew do a great job putting on this event. This year the event was in a different location that was pretty amazing looking and the spaces they made available were great too. My session was at the very beginning of the day at 8am, so I had to make sure I didn't party too much the night before at the Speaker/Volunteer party. Speaking of which, that party was held at a local micro brewery and we even had a room that with a glass wall so that we could see all of the beer vats. Beer was great and I even shared this with my wife and son who traveling with me to this event to make it into a mini-vacation from Thursday - Sunday.

Was awesome to spend a few days in ABQ this time as I drove in for last year's event on Friday and left right as the event finished on Saturday. This time with the family we were able to go up to the Sandia Peak Tramway, visit Old Town Albuquerque and Petroglyph National Monument. All great places to visit and always nice to learn about another area of the country!


Back to the SQLSaturday event itself, things started a bit slow (it is a Saturday morning so this is expected), but quickly there were over 100 attendees going to sessions throughout the day. Since my session was first thing I expected that I would have a lower attendance, and while I only had 10 attendees in the room they all commented to me afterwards that they enjoyed it and learned something new, so that makes it all worthwhile! Here is a link to download the file that all of the content from my "Master the Date Dimension Like a Time Lord" session. For those that were not at SQLSaturday #271 and may have seen this presentation in the past, I have updated it to make the script to generate the date dimension for both SQL 2008 and SQL 2012. I also took sometime to clean up some of the code to be more SQL centric instead of Oracle that it was originally written for. I will continue to tweak this script and the presentation over time, so keep your eyes here for future updates to the scripts!

Thanks again to the Albuquerque SQL group and I look forward to coming back again in the future!

Thursday, January 23, 2014

Encryption in SQL Server (Part 3)

Now that we have the database setup for encryption as shown in Parts 1 and 2 of this series, it is time to actually encrypt the data in the database and view the data in decrypted form.

The great thing about all of these encryption capabilities being built into the SQL Server engine is that the commands that you use to encrypt/decrypt the data is very easy, in fact it is using the same commands you are already using to with some minor differences.

Before updating the data a new column that is in VARBINARY datatype will be required, since that is the datatype required for encrypted values:
ALTER TABLE Person.Contact
   ADD Phone_encrypt VARBINARY(128);
The length of the VARBINARY column will vary based on the length of the data you are encrypting and the type of algorithm being used. To find out what length of VARBINARY will work best for you, it is a good idea to setup a test where you populate the maximum length value of the column you are going to encrypt and do the encryption into a VARBINARY(MAX) column and use the DATALENGTH function to find out what the length of encrypted data comes to. Hopefully you are not encrypting BLOB data or other very large columns, in most cases a VARBINARY(128) or VARBINARY(256) will cover you, but setup the test as described if you have any doubts as you don't want to truncate the encrypted data.

The command to populate the new encrypted value column is a simple UPDATE command that you are already used to:
OPEN SYMMETRIC KEY AdventureWorks_SymKey DECRYPTION BY ASYMMETRIC KEY AdventureWorks_AsymKey; 
UPDATE Person.Contact SET Phone_encrypt = EncryptByKey(Key_GUID('AdventureWorks_SymKey'), Phone);

CLOSE SYMMETRIC KEY AdventureWorks_SymKey; 
http://technet.microsoft.com/en-us/library/ms190499(v=sql.105).aspxhttp://technet.microsoft.com/en-us/library/ms174361(v=sql.105).aspxhttp://technet.microsoft.com/en-us/library/ms177938(v=sql.105).aspx
This will replace the values that are in the column specified in the UPDATE command with the encrypted version of that value using the Symmetric Key. Depending on the amount of data in your table and the specs of the computer/server this operation should not take very long to complete, in most cases no longer then it takes to perform that same UPDATE command without the encryption.

Notice the OPEN and CLOSE commands that are wrapped around the UPDATE, those are required as you need to make the Symmetric Key that you are using for encryption available and this is done by opening it. For good practices and security is best to then close the key after you have completed the work that you need to do.

Now that you have encrypted the data in that column, lets decrypt the data and see if comes back as the same value that you originally encrypted.

There are a couple of different ways to write the SELECT statement that does the decryption, first is using the Asymmetric Key directly:
SELECT Phone_encrypt, Phone,
CONVERT(nvarchar(25),DecryptByKeyAutoAsymKey(AsymKey_ID('AdventureWorks_AsymKey'), NULL, Phone_encrypt, 0)) AS 'CustomerPhone_decrypted' FROM Person.Contact;
http://technet.microsoft.com/en-us/library/ms365420(v=sql.105).aspx
And the other way is to open the Symmetric Key as was done above to perform the UPDATE and use it to do the decryption:
OPEN SYMMETRIC KEY AdventureWorks_SymKey DECRYPTION BY ASYMMETRIC KEY AdventureWorks_AsymKey; 
SELECT Phone_encrypt, Phone, CONVERT(nvarchar(25),DecryptByKey(Phone_encrypt))) AS 'CustomerPhone_decrypted' FROM Customer.Contact;
CLOSE SYMMETRIC KEY AdventureWorks_SymKey; 
http://technet.microsoft.com/en-us/library/ms181860(v=sql.105).aspx
Either way you do it you notice that you will have to convert the decrypted value returned into a datatype that you can use, as both the DecryptByKeyAutoAsymKey and DecryptByKey will return a VARBINARY datatype. The DecryptByKeyAutoAsymKey function is very useful in views as it doesn't require the OPEN/CLOSE statements.

It is also worth mentioning the GRANT statements that will be required to give the appropriate rights to be able to see this decrypted data for users.
GRANT CONTROL ON ASYMMETRIC KEY::AdventureWorks_AsymKey TO User1;
GRANT VIEW DEFINITION ON SYMMETRIC KEY::AdventureWorks_SymKey TO User1; 
http://technet.microsoft.com/en-us/library/ms187991(v=sql.105).aspxhttp://technet.microsoft.com/en-us/library/ms179887(v=sql.105).aspx
Notice that CONTROL has to be granted to the Asymmetric Key and only VIEW DEFINITION is required on the Symmetric Key. These are the lowest grants necessary for the keys to work for any user needing to execute either of the SELECT commands shown above. The decryption functions will not work unless the appropriate grants are issued on BOTH the Asymmetric and Symmetric Keys.

Now that we have encrypted data in the database and verified that the encryption works by decrypting that same data via a SELECT statement I will use the 4th and final part of this series to show you how to restore backups of a database that contains encrypted data on another server and still be able to decrypt the values.

Friday, January 3, 2014

Encryption in SQL Server (Part 2)

This is part 2 in my posts on setting up encryption in SQL Server. To get the details on how to setup encryption on your SQL Server instance and the database, please read part 1 first.

Now that we have the SQL Server instance and database ready to encrypt our data we can go into details on how the individual columns of data will be encrypted in the database. At this point you also have some decisions on what types of keys you want to have created and how strong the cryptography algorithm will be protecting them.

Before diving into the next layers of keys, it is important to understand the differences between Asymmetric and Symmetric Keys and how SQL Server handles each. This article on TechNet - Cryptography in SQL Server does a great job explaining the differences.

The recommended best practice is to setup an Asymmetric Key as the next layer and make this key as strong as you can and use a Symmetric Key to do the actual data encryption. The reason for this is that Asymmetric Keys require a lot more processing power to use, so you only use the Asymmetric Key to protect the Symmetric Key. The Symmetric Key is what is used to actually encrypt your data, then only when the Symmetric Key is first being accessed does the system have to decrypt the Asymmetric Key. Otherwise you will have to pay the Asymmetric Key processing cost every time a value is being encrypted or decrypted.

In SQL Server you have many options when creating these Asymmetric Keys, but the one most often used is RSA_2048. This is currently the highest level of security that SQL Server supports for Asymmetric Keys. Below is the command you use to create the Asymmetric Key:
IF NOT EXISTS
(SELECT * FROM sys.asymmetric_keys WHERE [name] = 'AdventureWorks_AsymKey')
CREATE ASYMMETRIC KEY AdventureWorks_AsymKey WITH ALGORITHM = RSA_2048;
http://technet.microsoft.com/en-us/library/ms188357(v=sql.105).aspx 
The naming of these keys is important, as you will need to reference this key in other commands to do the encryption/decryption so make sure you pick a name you can keep track of.

As mentioned above you will also need a Symmetric Key to do the actual data encryption that uses the Asymmetric Key. With Symmetric Keys you have to use a different set of algorithms because Symmetric Keys work differently than Asymmetric Keys as they have a pair of keys created (public/private). To get a great overview of what Symmetric Key encryption is see this HowStuffWorks article. Below is the command to create a Symmetric Key:
IF NOT EXISTS
    (SELECT * FROM sys.symmetric_keys WHERE [name] = 'AdventureWorks_SymKey')
    CREATE SYMMETRIC KEY AdventureWorks_SymKey
        WITH KEY_SOURCE = 'I82xskoiw820KOW>282kxow',
            ALGORITHM = AES_256,
            IDENTITY_VALUE = 'w,xi292XWE82S92iqoxl*&23'
        ENCRYPTION BY ASYMMETRIC KEY AdventureWorks_AsymKey;
http://technet.microsoft.com/en-us/library/ms174430(v=sql.105).aspx 
I used AES_256 as the algorithm in this Symmetric Key as it is the strongest algorithm allowed at this time in SQL Server. The DES and RC algorithms are not recommended as they have all been cracked and could make your encrypted data accessible.

As I learned how to use these keys in my prototyping I ran into an important issue that I want to highlight here. When you create the Symmetric Key it is very important that you be able to re-create the exact same key if you accidentally lose that key. Since the Symmetric Key is going to be used to do all of the data encryption, if that key is lost you will not be able to get your data back in decrypted form if you lose it. This is where the KEY_SOURCE and IDENTITY_VALUE parameters of that command come into use. As long as you make sure to use those same values then you can recreate the same Symmetric Key (assuming you have the Database Master Key and Asymmetric Key setup the same as well, I will cover how to get this setup if you have moved to another server in a later part of this series).

There are no commands to backup the Asymmetric or Symmetric Keys like we had for the Service Master Key and Database Master Keys. If you decide to use Certificates over the keys, then you can backup the certificates. I have not used certificates in the systems that I setup encryption on, mainly because SQL Server currently does not fully handle certificates as it should. If you would like to get more details on creating certificates in SQL Server, see this TechNet article: http://technet.microsoft.com/en-us/library/ms187798(v=sql.105).aspx.

Now we have laid all of the groundwork for setting up encryption on your SQL Server database, so the next part we will start to actually encrypt data and decrypt that data as well!