SQL Server Column Level Encryption Example Using Symmetric Keys
SQL Server Column Level Encryption Example Using Symmetric Keys
1 of 8
http://www.mssqltips.com/sqlservertip/2431/sql-server-column-level-e...
Problem
Financial firms have sensitive data including credit card numbers, social security numbers, financial history, etc. Based
on the sensitivity of the data, it needs to be secured and protected from unauthorized access. With data stored in
tables, you have a few options to protect data. First, you can protect the data using views. Second, we can also assign
column level permissions to users. Are there any other options available? Can I use database encryption? Can I
encrypt only a column in my table or do I need to encrypt the whole database? Check out this tip to learn more about
column level encryption.
Solution
An important option to be considered during restricting unauthorized access to data is to encrypt data so that even if
somebody was able to reach to data it is not discernable by a simple query. Since critical information like credit card
numbers are stored in column or two, it does not make sense to encrypt the complete database or database files. In
this tip I will walk through the processes of encrypting a column in a table which contains credit card information of
customers of XYZ company by using SQL Server symmetric key encryption. SQL Server has an encryption hierarchy
that needs to be followed in order to support the encryption capabilities. We will follow the same hierarchy in the
subsequent steps of this tip.
3/12/2015 11:15 PM
2 of 8
http://www.mssqltips.com/sqlservertip/2431/sql-server-column-level-e...
Providing High
Availability to an
Existing SQL Server
Workload
High Availability,
Disaster Recovery,
Low Cost Storage,
and SIOS
DataKeeper
SQL Server
Performance
Monitoring in the
Cloud
3/12/2015 11:15 PM
3 of 8
http://www.mssqltips.com/sqlservertip/2431/sql-server-column-level-e...
Below are the results from the table after the insert statement.
Below you can see from the image below, the test user is not able to access the encrypted data.
Next Steps
In the above steps we have learned how to encrypt a data column. The same concept can be used to encrypt
employee salaries, social security numbers, customer phone numbers, etc. So check out your data to determine
what should be encrypted.
Keep in mind implementation of column level encryption needs schema modification.
Reading from an encrypted column is resource intensive and lowers the overall performance of database, hence
that should be considered as well.
The element of data that is encrypted remains in that state, even when recalled into memory.
Read more Encryption Tips.
Related Resources
More Database Developer Tips...
Share
10
Like
Tweet
10
3/12/2015 11:15 PM
4 of 8
http://www.mssqltips.com/sqlservertip/2431/sql-server-column-level-e...
Learn More
Post a comment or let the author know this tip helped you.
All comments are reviewed, so stay on subject or we may delete your comment.
*Name
*Email
Paragraph
*** NOTE *** - If you want to include code from SQL Server Management Studio (SSMS) in your post, please copy the code from SSMS and paste the
code into a text editor like NotePad before copying the code below to remove the SSMS formatting.
Note: your email address is not published. Required fields are marked with an asterisk (*)
Get free SQL tips:
*Enter Code
Save Comment
Not sure if I am missing something but above permissions are not enough for a regular user to be able to see the
encrypted data. This one is missing:
GRANTCONTROLONCERTIFICATE::Certificate1TOtest;
GO
With that.... then user "test" is able to see the encrypted data. And this is because we are using a certificate. Without
a certificate I think GRANT CONTROL is not needed.
Ogn Nik:
Chances are that it's very intensive because it is basically doing a table scan. For my purposes, I used a separate
criteria and then wrote them into a temporary table doing the comparison after the fact (or with a USING). To be
honest, I wouldn't encrypt the usernames and would solely encrypt the passwords (or just use hashes which mask the
data and make it easy to compare. With that, you can search for an indexable field (username) and then take that
result data to use the decrypt process on it (which would be a bit faster).
As secure as you want it to be, you don't want it to be so secure that it becomes something that is tedious or counterproductive.
This should be used on resulting data that doesn't require you to decrypt and then compare. The WHERE clause gets
executed on the results from the FROM and the fields returned are done after that. So, use the decrypt part there
and leave the WHERE for things that you can index. You can return the decrypted data in the fields and then take
that result to return to your program.
I have used this and it gives me a responce of d6mSTRfbTz0q0V7jTgyvBSm2NoU= this code contains the password :
password.
I have tried to use pwdcompare and pwdencrypt, none of them work, not even the hashbytes helps at all, all I have
done is use ASP.NET membership tool, the aspnet_regsql.exe and made the databse in MS SQL 2012 and linked it to
the local website which has a connection string in the web.config file. all i wanted to do was for eg, when a user
enters a password say password it gets compared.
if the UserName is Max and password is password. then the user enters Max in the Username textbox and the
3/12/2015 11:15 PM
5 of 8
http://www.mssqltips.com/sqlservertip/2431/sql-server-column-level-e...
database but before that happens it will have to be hashed and salted? so it matches using the
pwdcompare('password', Password_column) in the database? I thought of making it clear text I know that will work...
but where is security...
Nitansh, do you have any experience with third-party column encryption (data masking) tools like IRI
FieldShield and how do they compare with the built-in for SQL?
hi all,
i have successfully encrypted and decrypted the data in the sql server
and i have one more requirement what about the searching by like query
is it supported when we use encrypt and decrypt if a column
I found a workaround but one that I'm afraid isn't scalable. I'm hoping that you can help me find the best way to
accomplish this...
Instead of ENCRYPTING the Request.Form submission and comparing it to the VARBINARY string in the DB, I found
that if I flipped them and compary the Request.Form submission the the DECRYPTED VARBINARY string in the DB, it
works.
I think this is probably much, much more labor intensive for the DB and probably not scalable.
Can you tell me if there is a way to compare the ENCRYPTED Request.Form submission with the VARBINARY string in
the DB instead of the other way around?
Many, many thanks in advance! All best, Ogn Nik
Hi Nitansh,
Nice article! I have a question that I can't seem to find an answer to on the web... When I'm inserting (or updating
for that matter) a table row with multiple columns that need to be encrypted, is EncryptByKey efficient enough to just
specify the parameter variable even when the variable's value is NULL, or would it be more efficient to use a CASE
statement, and when the parameter variable value is NULL, simply store NULL, otherwise do the EncryptByKey
function against the parameter variable value?
I've got about 20 columns in my table that need to be encrypted, but there is also the chance that many of them will
contain NULL (columns defined to allow NULLs, obviously). Just wondering if I didn't use CASE that the overhead of
doing the EncryptByKey on multiple columns could be more "expensive" resource-wise when it's a NULL value, or
doesn't it really matter?
Thanks,
Larry
I found the solution. Test user can see the encrypted data when used with open symmetric key and close symmetric
key.
Thanks,
Ameena
3/12/2015 11:15 PM
6 of 8
http://www.mssqltips.com/sqlservertip/2431/sql-server-column-level-e...
is there a way to encrypt an int column instead of varchar. I did try to do that but I received an error Argument data
type int is invalid The thing is that in my application I need to keep that column as int because I need to apply the
sum function on it after decrypting it and I dont want data inside that column to be exposed.
Thank you in advance for your help or suggestion
User 'test' will need control permissiosn on Cettificate 1. Below code will work.
GRANT VIEW DEFINITION ON SYMMETRIC KEY::SymmetricKey1 TO test1;
GO
GRANT control ON Certificate::Certificate1 TO test1;
GO
Hi All,
I have 2 columns in one table, its datatype are numeric(18,0),datetime when i am going to encrypt these column im adding columns with
same datatype it is giving error when the time of updation and I am tried with varbinary(256) also it is giving the same error.
The error is
Argument data type numeric is invalid for argument 2 of EncryptByKey function .
I am using SQL Server 2008r2 Enterprises edition . Please give me the solution for this how to encrypt the columns which i have
mentioned. Is encryption will not work on these datatypes?
Thanks in advance
Srinivasa Babu Doosa
Hi,
Great article..
I was just wondering about , if I am normal user , who can create a database..in sql server...can also perform this
steps..and do the column level encryption.?
and if this is possible , can restrict my co-workers(we are working on same server, everybody log on with their
windows authentication policy), who has the same access as me, to reach out certificate and keys..
Please let me know.
thanks.
Thank you! Great job on this article. It helped me accoplish something I had not done before.
Hi Nitansh
Am getting NULL values after restoring the DB in another server. Is there any work around to get rid of this issue
USE encrypt_test;
GO
OPEN SYMMETRIC KEY SymmetricKey1
DECRYPTION BY CERTIFICATE Certificate1;
GO
-- Now list the original ID, the encrypted ID
SELECT Customer_id, Credit_card_number_encrypt AS 'Encrypted Credit Card Number',
CONVERT(varchar, DecryptByKey(Credit_card_number_encrypt)) AS 'Decrypted Credit Card Number'
FROM dbo.Customer_data;
3/12/2015 11:15 PM
7 of 8
i get NULL in 'Decrypted Credit Card Number' when i execute the above but i get
http://www.mssqltips.com/sqlservertip/2431/sql-server-column-level-e...
"do you have a method for backup and restore those keys ?"
You can back up the cert and its key together. There is Restore Certificate too.
You should be quite concerned about the index impact. Do not use this technique on a column that will be searched
by. Like do not expect to be able to search for card number 4111-1111-1111-1111 efficiently. If you want to you
need to either decrypt every row in the table, or encrypt 4111-1111-1111-1111. Notice the VARBINARY(MAX)
datatype that you are limited to for encrypted columns. You can't index varbinary(max) even if you wanted to. So all
table scans all the time.
If you don't search by card number, but just search for cards belonging to user id 999, then this will be fine. But
having more than one column you're selecting be encrypted can cause more and more slowness. So if first you do
card number, then you need to do other personally identifiable info, consider a different technique.
We actually do our card encryption in the ui code layer. The reason being that that way we can make it so that no
single person is able to get card numbers from the database. In the examples given you have some protection in that
if some outside person stole your database they wouldn't be able to read the card numbers. But a dozen+ devs and
IT types would be able to decrypt all the cards and pocket them the day before they quit the company. So from a PCI
perspective, it is not a sufficient technique. That also means that if we want to search for 4111-1111-1111-1111, the
ui layer encrypts it, then passes in the encrypted string, and the underlying encrypted card number column is a
regular varchar(255) column that is indexed and searchable. With encryption you need to know the algorithm, the
encryption key, and the salt. You can break the pieces apart, so that server admins can set an encryption key or a
salt in a place that devs can't access, like a file, or in the registry or something else outside of the source code tree.
Then neither the devs nor the server admins know enough to decrypt the cards, it would take them getting together
to conspire to steal the data. Which is orders of magnitude less likely than one bad apple.
What happens if the server is dead and you want to restore from backup to another server ?
you dont have the certificate or encryption key...
do you have a method for backup and restore those keys ?
Mike, there would be performance degradation if the table has high data volume and the query is fetching a lot of
rows since SQL Server has to decrypt values in all the rows. Regarding, Indexing encrypted data - normal clustered or
non-clustered index will not work. Queries which refer to encrypted data in where clause should be avoided and they
should be run with reference to primary key value in the table. This will make the search faster.
Nice Article and it looks worth implementing. I am concerned about db performance issues. Can I index encrypted
data to improve performance?
3/12/2015 11:15 PM
8 of 8
http://www.mssqltips.com/sqlservertip/2431/sql-server-column-level-e...
Sponsor Information
24/7 SQL Server Monitoring Tools | SQL Diagnostic Manager | Try for Free
How to find & fix SQL Server performance issues 26 free monitoring tips for DBAs Sign up now
Solving SQL Server problems for millions of DBAs and Devs since 2006 Join now
Free SQL Server Tutorials - Stored Procedures Performance Monitoring Query Plans SSIS and more
Follow
Learning
Resources
Search
Community
More Info
DBAs
Tutorials
Tip Categories
First Timer?
Join
Developers
Webcasts
Search By TipID
Pictures
About
BI Professionals
Whitepapers
Top Ten
Free T-shirt
Copyright
Google+
Careers
Tools
Authors
Contribute
Privacy
Q and A
Events
Disclaimer
Today's Tip
User Groups
Feedback
Advertise
RSS
3/12/2015 11:15 PM