SQL Server Column Level Encryption Example using Symmetric Keys

By:   |   Comments (53)   |   Related: > Encryption


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.

Step 1 - Create a sample SQL Server table

Let's use an example where we create the dbo.Customer_data table which contains credit card details for customers. Our task is to protect this data by encrypting the column, which contains the credit card number. I will populate it will some sample data as shown below.

USE encrypt_test;
GO
-- Create Table
CREATE TABLE dbo.Customer_data
(Customer_id int constraint Pkey3 Primary Key NOT NULL,
Customer_Name varchar(100) NOT NULL,
Credit_card_number varchar(25) NOT NULL)
-- Populate Table
INSERT INTO dbo.Customer_data 
VALUES (74112,'MSSQLTips2','2147-4574-8475')
GO
INSERT INTO dbo.Customer_data 
VALUES (74113,'MSSQLTips3','4574-8475-2147')
GO
INSERT INTO dbo.Customer_data 
VALUES (74114,'MSSQLTips4','2147-8475-4574')
GO
INSERT INTO dbo.Customer_data 
VALUES (74115,'MSSQLTips5','2157-1544-8875')
GO
-- Verify data
SELECT * 
FROM dbo.Customer_data
GO
Sample Credit Card data not encrypted

Step 2 - SQL Server Service Master Key

The Service Master Key is the root of the SQL Server encryption hierarchy. It is created during the instance creation. Confirm it's existence using the query below. If it does not exist we need to manually create it. Read more about service master key here.

USE master;
GO
SELECT *
FROM sys.symmetric_keys
WHERE name = '##MS_ServiceMasterKey##';
GO

Step 3 - SQL Server Database Master Key

The next step is to create a database master key. This is accomplished using the CREATE MASTER KEY method. The "encrypt by password" argument is required and defines the password used to encrypt the key. The DMK does not directly encrypt data, but provides the ability to create keys that are used for data encryption. It is important that you keep the encryption password in a safe place and/or keep backups of your SQL Server Database Master Key.

-- Create database Key
USE encrypt_test;
GO
CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'Password123';
GO

Step 4 - Create a Self Signed SQL Server Certificate:

The next step is to create a self-signed certificate that is protected by the database master key. A certificate is a digitally signed security object that contains a public (and optionally a private) key for SQL Server. An optional argument when creating a certificate is ENCRYPTION BY PASSWORD. This argument defines a password protection method of the certificate's private key. In our creation of the certificate we have chosen to not include this argument; by doing so we are specifying that the certificate is to be protected by the database master key. Read more on about SQL Server certificates.

-- Create self signed certificate
USE encrypt_test;
GO
CREATE CERTIFICATE Certificate1
WITH SUBJECT = 'Protect Data';
GO

Step 5 - SQL Server Symmetric Key

A symmetric key is one key that is used for both encryption and decryption. Encryption and decryption by using a symmetric key is fast, and suitable for routine use with sensitive data in the database. Read more about SQL Server Symmetric Keys.

-- Create symmetric Key
USE encrypt_test;
GO
CREATE SYMMETRIC KEY SymmetricKey1 
 WITH ALGORITHM = AES_128 
 ENCRYPTION BY CERTIFICATE Certificate1;
GO

Step 6 - Schema changes

An Encrypted column can only be of datatype varbinary and since the column we want to encrypt is of datatype varchar, we have to create a new column and populate it with encrypted values.

USE encrypt_test;
GO
ALTER TABLE Customer_data 
ADD Credit_card_number_encrypt varbinary(MAX) NULL
GO

Step 7 - Encrypting the newly created column

To encrypt the data we will use the encryptbykey command. Below is a sample code which can be used to encrypt the data. Please note that symmetric key needs to opened before we can encrypt data and be sure you manually close the key else it will remain open for the current session.

-- Populating encrypted data into new column
USE encrypt_test;
GO
-- Opens the symmetric key for use
OPEN SYMMETRIC KEY SymmetricKey1
DECRYPTION BY CERTIFICATE Certificate1;
GO
UPDATE Customer_data
SET Credit_card_number_encrypt = EncryptByKey (Key_GUID('SymmetricKey1'),Credit_card_number)
FROM dbo.Customer_data;
GO
-- Closes the symmetric key
CLOSE SYMMETRIC KEY SymmetricKey1;
GO

Below is an example of the encrypted data.

Sample Encrypted and Decrypted Credit Card Data

Step 8 - Remove old column

To finalize this process, let's remove the old column so that the table is left only with the encrypted data.

USE encrypt_test;
GO
ALTER TABLE Customer_data
DROP COLUMN Credit_card_number;
GO

Step 9 - Reading the SQL Server Encrypted Data

Let's take a look at an example of reading data using the decrypt by key option. As we indicated before, make sure you open and close symmetric key as shown earlier. Read more about the decrypt by key option.

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;
 
 -- Close the symmetric key
CLOSE SYMMETRIC KEY SymmetricKey1;
GO

Here are the results from the query:

Read SQL Server Encrypted Data

Step 10 - Adding Records to the Table

Below is the sample code to insert values into the newly created encrypted column.

USE encrypt_test;
GO
OPEN SYMMETRIC KEY SymmetricKey1
DECRYPTION BY CERTIFICATE Certificate1;
-- Performs the update of the record
INSERT INTO dbo.Customer_data (Customer_id, Customer_Name, Credit_card_number_encrypt)
VALUES (25665, 'mssqltips4', EncryptByKey( Key_GUID('SymmetricKey1'), CONVERT(varchar,'4545-58478-1245') ) );    
GO

Below are the results from the table after the insert statement.

Add an encrpyted record in a SQL Server database

Step 11 - Accessing the Encrypted Data

All the read access users will see the encrypted values while they do a select on table. A user need to have permission to symmetric key and certificate to decrypt data, if they still try to decrypt then they will receive null for encrypted values. However they do not receive any errors. In the below sample code I am running select in context of a user 'test' which has only read access on DB.

Execute as user='test'
GO
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;

Below you can see from the image below, the test user is not able to access the encrypted data.

Accessing SQL Server encrypted data with insufficient rights

Step 12 - Grant Permissions to the Encrypted Data

Permissions can be granted to a set of users to decrypt and read data using the commands below.

GRANT VIEW DEFINITION ON SYMMETRIC KEY::SymmetricKey1 TO test; 
GO
GRANT VIEW DEFINITION ON Certificate::Certificate1 TO test;
GO
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.


sql server categories

sql server webinars

subscribe to mssqltips

sql server tutorials

sql server white papers

next tip



About the author
MSSQLTips author Nitansh Agarwal Nitansh Agarwal is a lead with 4+ years of extensive experience in database administration where he handles large critical databases.

This author pledges the content of this article is based on professional experience and not AI generated.

View all my tips



Comments For This Article




Wednesday, November 1, 2023 - 4:05:03 PM - Ray Hastie Back To Top (91726)
One thing to note is that the cleartext argument to EncryptByKey only accepts nvarchar, char, varchar, binary, varbinary, or nchar.
To encrypt a money data type, requires casting the value (I used varchar):

EncryptByKey (Key_GUID('Key1'), Convert(VarChar, emp.pay_rate_pay1, 2))

and then to decryrpt:

Convert(Money, Convert(varchar, DecryptByKey([salary])))

Tuesday, January 25, 2022 - 2:40:21 PM - Saeed Back To Top (89698)
Hi.how to select with operator like on encrypted field?

Wednesday, September 23, 2020 - 2:38:37 PM - JUAN MIGUEL JIMENEZ SALVADOR Back To Top (86525)
Hi Nitansh.

I am on trouble decryting on Azure a columna encrypted on a SQL 2014 database.

I have a column in a table encrypted with a certificate in my SQL 2014 Enterprise instance (you know: KEY_SOURCE =... ALGORITHM = AES_256, IDENTITY_VALUE = ... ENCRYPTION BY CERTIFICATE ...); I've reproduced DMK, certificate, etc. on a Azure instance and transferred rows and column encrypted via a Web Service. When I try to decrypt on Azure (opening the key, etc.) allways I obtain NULL value. I've tried with other source SGBD instances (SQL 2019) and I can decrypt without problems using this same certificate, etc. created on the Azure instance. I've google a lot... but didn't find someone that has troubles with symmetrical keys generated on 2014 (I've found some articles talking about SQL 2017 CU3, but not with sql 2014).

Have you heard someone having similar troubles?

Best regards,

Juanmi

Wednesday, February 19, 2020 - 8:23:17 AM - NITANSH AGARWAL Back To Top (84636)

Dear Samit,

Please refer to this excellent article on exposing encrypted data via views https://www.mssqltips.com/sqlservertip/3081/using-views-to-expose-encrypted-data-in-sql-server/

Hope this helps.

NItansh


Wednesday, February 19, 2020 - 7:20:55 AM - NITANSH AGARWAL Back To Top (84634)

Dear GM,

Please refer to this excellent article here showing exactly how you can read encrypted Data via views.

https://www.mssqltips.com/sqlservertip/3081/using-views-to-expose-encrypted-data-in-sql-server/

Hope this helps.

Nitansh


Wednesday, February 19, 2020 - 5:16:53 AM - NITANSH AGARWAL Back To Top (84632)

Dear Rajkumar,

I believe you would need to write a custom code in C#, Unfortunately I am not very versed with C# hence won't be able to help you with the code.

Nitansh


Wednesday, February 19, 2020 - 4:59:42 AM - NITANSH AGARWAL Back To Top (84631)

Dear Hadi,

Please use below code to encrypt and decrypt Unicode values:

--Step 1 - Create a sample SQL Server table – Please note I’m using Nvarchar data type to support Unicode values.
USE [TDE]
GO
CREATE TABLE [dbo].[Customer_data2](
                [Customer_id] [int] NOT NULL,
                [Customer_Name] [varchar](100) NOT NULL,
                [Credit_card_number_encrypt] [nvarchar](max) NULL,
 CONSTRAINT [Pkey4] PRIMARY KEY CLUSTERED
(
                [Customer_id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
 
--Step 10 - Adding Records to the Table
OPEN SYMMETRIC KEY SymmetricKey2
DECRYPTION BY CERTIFICATE Certificate2;
-- Performs the update of the record
INSERT INTO dbo.Customer_data2 (Customer_id, Customer_Name, Credit_card_number_encrypt)
VALUES (74123, 'MSSQLTIPS13', EncryptByKey( Key_GUID('SymmetricKey2'), CONVERT(nvarchar,N'4545-!$*ካ-3333-8765') ) );    
GO
 
-- Checking Data is encrypted
select * from [Customer_data2]
 
--Step 11 - Accessing the Encrypted Data
SELECT Customer_id, Credit_card_number_encrypt AS 'Encrypted Credit Card Number',
CONVERT(nvarchar, DecryptByKey(Credit_card_number_encrypt)) AS 'Decrypted Credit Card Number'
FROM dbo.Customer_data2;

I have tested the code and it’s working for both normal and Unicode values. Let me know if you still experience any issues.

Nitansh


Thursday, February 6, 2020 - 2:35:04 PM - hadi Back To Top (84225)

In decrypting data with unicode characters it return '??????????????' as result!


Wednesday, April 24, 2019 - 7:50:42 AM - Rajkumar Back To Top (79680)

I have a task to encrypt and decrypt the data from Entity framework C#, How can I do the same encryption and decryption from C#.


Thursday, April 11, 2019 - 11:54:54 PM - GM Back To Top (79538)

Excellent Article. Thank you so much Nitansh.  I am trying to read the encrypted data using sql view but getting null values.. using open/close symmetric keys etc.. but not sure why it returns null value.. But when I check outside the view, it works fine.  Please let me know if there is anything that I have to do.


Tuesday, July 10, 2018 - 4:34:06 AM - vinu sk Back To Top (76595)

 Is it possible to decrypt this data from another database in the same server using stored procedure in the second server.

I have some columns in database A which are encrypted. I need to join this column with several other columns in a select query in database B.


Sunday, February 4, 2018 - 6:26:28 PM - Samit Back To Top (75098)

I wanted to loaded the file into sql server which has sensitive information. Is it possible to do column encryption with bcp command for SQL Server 2014? I have build up the function for encryption and used it in view. Instead of tablename , I am giving viewname to bcp command.  When I run bcp command, the column which needs to be encrypted are loaded as NULL with bcp. But when I try loading with simple insert statement, column values are encrypted.

 


Friday, October 27, 2017 - 5:30:53 AM - Nikhil Munj Back To Top (68863)

Hi Niftash,

 

The drwaback with this technoque(Column level encryption using Symmetric Key and a Certificate) is ,if a column has dependency on itself then you cannot delete that column.As a result, at the end the table will have an Unencrypted column(in which the all the data will be visible as we cannot delete the column).

 

 


Wednesday, August 16, 2017 - 5:59:11 AM - kear Back To Top (64907)

 Dear sir, 

when i copy database to other server, not work with cetificat, can you help ? 

 

thanks 

KEAR

 


Sunday, May 7, 2017 - 6:01:11 AM - Sathyanath Back To Top (55511)

Hi,

I am facing issue while decryption, Please help me if my column encryption/decryption process is wrong

I encrypted table in Source DB and back up certificate, then export my encrypted table result to CSV from source DB.

In the destination DB, I Created master Key, and using certificate backup (of my source DB) I created certificate in destination and then my symmetric key.

Now I imported the CSV result into my destination DB table and running my decryption script. But it gives me NULL value. (Decryption works fine in source DB, same is not working in destination)

Below is my sample script,

----AT MY SOURCE DB----

create table tbluser
(
id int ,
name varchar(200),
encryptname varbinary(200)
)

insert into tbluser (id,name)
values (1,'Raj'),(2,'Vimal')

CREATE MASTER KEY
ENCRYPTION BY PASSWORD = 'M@sterKey123'

CREATE CERTIFICATE TestCert1
WITH SUBJECT = 'Test my Certificate';

    
BACKUP CERTIFICATE TestCert1 TO FILE = 'D:\DESKTOP\Certificate\TestCert1.cer'  
WITH PRIVATE KEY ( FILE = 'D:\DESKTOP\Certificate\pkTestCert1.pvk' ,   
ENCRYPTION BY PASSWORD = 'Certific@te123' );  

CREATE SYMMETRIC KEY SymKeyTest1
WITH ALGORITHM = AES_256
ENCRYPTION BY CERTIFICATE TestCert1;

OPEN SYMMETRIC KEY SymKeyTest1
DECRYPTION BY CERTIFICATE TestCert1;
UPDATE tbluser SET Encryptname = ENCRYPTBYKEY(KEY_GUID('SymKeyTest1'), name);
CLOSE SYMMETRIC KEY SymKeyTest1;

OPEN SYMMETRIC KEY SymKeyTest1
DECRYPTION BY CERTIFICATE TestCert1;
SELECT TOP 5 name,  CONVERT(VARCHAR(50), DECRYPTBYKEY(Encryptname)) DecryptedName FROM tbluser;
CLOSE SYMMETRIC KEY SymKeyTest1

Declare @str nvarchar(2000), @path nvarchar(200)='D:\DESKTOP\Certificate' , @TableName nvarchar(100)='tbluser'
Set @str = 'BCP Test.dbo.'+@TableName+ ' OUT '+@path +'\'+@TableName+'.csv  -c -t^| -T -S MAILPTP45\SQL2012'
Exec xp_cmdshell @str


----AT MY DESTINATION DB----

CREATE MASTER KEY
ENCRYPTION BY PASSWORD = 'M@sterKey123'

create certificate TestCert1 from file = 'D:\DESKTOP\Certificate\TestCert1.cer'
with private key(file = 'D:\DESKTOP\Certificate\pkTestCert1.pvk',
decryption by password = 'Certific@te123')

CREATE SYMMETRIC KEY SymKeyTest1
WITH ALGORITHM = AES_256
ENCRYPTION BY CERTIFICATE TestCert1;

create table tbluser
(
id int ,
name varchar(200),
encryptname varbinary(200)
)

bulk insert [tbluser]
from 'D:\DESKTOP\Test\tbluser.csv'
with (fieldterminator = '|', rowterminator = '\n')

OPEN SYMMETRIC KEY SymKeyTest1
DECRYPTION BY CERTIFICATE TestCert1;
SELECT TOP 5 name,  CONVERT(VARCHAR(50), DECRYPTBYKEY(Encryptname)) DecryptedName FROM tbluser;
CLOSE SYMMETRIC KEY SymKeyTest1

Thanks



Thursday, April 27, 2017 - 2:53:12 PM - Bryant Back To Top (55251)

Excellent article. It has all the explanation that I need but was missing from the official TechNet/MSDN documentation.

Thank you!


Monday, April 10, 2017 - 4:34:23 AM - Justice Back To Top (54564)

Hi! I am using a stored procedure and would like to pass a parameter to the insert statement with the EncryptByKey. I am encrypting a Varchar field, the script below gives me error that there are more columns on the insert statement. Please assist:

USE encrypt_test;

GO
OPEN SYMMETRIC KEY SymmetricKey1
DECRYPTION BY CERTIFICATE Certificate1;
-- Performs the update of the record
INSERT INTO dbo.Customer_data (Customer_id, Customer_Name, Credit_card_number_encrypt)
VALUES (25665, 'mssqltips4', EncryptByKey( Key_GUID('SymmetricKey1'), @C_CardNo ) );    
GO

 


Wednesday, January 11, 2017 - 6:35:00 AM - jitendra kumar Back To Top (45208)

 Hi Nitansh 

 

I have go through whole process and executed all thing step by step successfully.

but after this process i want backup (.bak file with encrypted coloumn)  of encrypt_test databse and restore to another database server.

please help me out..

 

Thanks

Jitendra kumar yadav 

 


Tuesday, December 20, 2016 - 2:00:18 PM - Mehdi Back To Top (45011)

Well written and explained article.

Well done and thank you.

 

Mehdi


Thursday, August 11, 2016 - 1:03:18 AM - bhagya Back To Top (43098)

 

 can we do row level encryption????????


Wednesday, June 29, 2016 - 11:41:14 AM - Sandra Back To Top (41788)

 Hi,

Do you know if column level encryption like your article describes is available in SQL Server 2012 Standard Edition? I believe it is but I don't have a test area to try it out. I know TDE is only available in Enterprise Edition but I can't find much about column level encryption in 2012.

Thanks

 

 


Sunday, May 22, 2016 - 1:35:16 AM - Ali Back To Top (41530)

Nitansh Agarwal,thank you for your help. it is realy very amazing code with good explanation.

 


Monday, May 2, 2016 - 12:01:26 PM - NITANSH Back To Top (41387)

Thank you Steve!


Thursday, April 21, 2016 - 12:17:03 PM - Steve Back To Top (41296)

 I've searched videos and articles on column encryption. NOTHING I found was as comprehensive (yet still concise), and straightforward as this article. It's amazing how much information there isn't out there on this topic. Thank you!

 


Thursday, March 24, 2016 - 9:16:01 AM - Naresh Back To Top (41044)

 It is really helpfull**** Exellent

Thank you

 


Friday, June 5, 2015 - 4:53:47 PM - R. L. Dawson Back To Top (37761)

There is one other thing I didn't see mentioned in the article that is of some concern to security conscious and PCI compliant enterprises. Once set there is no mechanism for changing the password to the database master key. You can change the certificates assigned to symmetric keys. You can reencrypt the data. However once set you are stuck with your database master key password. Use a strong one. I set a standard of 100 + random number of additional characters for my systems.

Also, I didn't see it mentioned adding the dmk to the service master key so that you do not have to explicitly open it when you need to create new symmetric keys. We are a hosting system for merchants lending money. Each merchant has their own symmetric key and we add them regularly.

 

I hope this helps.

Richard L. Dawson


Thursday, February 19, 2015 - 12:14:53 PM - Jose Back To Top (36291)

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.


Monday, January 5, 2015 - 6:28:27 PM - Lauren Glenn Back To Top (35835)

Ogún 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 counter-productive.

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.


Tuesday, December 2, 2014 - 1:25:30 AM - Max Back To Top (35453)

select Password, UserName from aspnet_Membership, aspnet_Users where UserName='Max';

 

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 password in the password textbox, but when it comes to compare it will have : select Password, UserName from aspnet_Membership, aspnet_Users where UserName='Max'; then for the password it will be compared wiith the 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...


Tuesday, October 21, 2014 - 4:29:10 PM - Urvashi Saxena Back To Top (35032)

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?


Tuesday, October 14, 2014 - 4:12:40 AM - prakash Back To Top (34943)

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


Wednesday, October 1, 2014 - 1:23:30 PM - Ogún Niké Back To Top (34802)

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, Ogún Niké 


Wednesday, October 1, 2014 - 12:49:34 PM - Larry Back To Top (34799)

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


 


Wednesday, October 1, 2014 - 2:57:27 AM - Ogún Niké Back To Top (34789)

This article was hugely helpful. Thank you!!

I have implemented everything in ASP Classic with VBScript but I have not been able to use the "EncryptByKey" funciton in the WHERE portion of a SELECT statement.

For example, I have encrypted my username field but I cannot use EncryptByKey to match it with the user's entry. 

Here is my code. I would be very grateful if you could tell me where I am going wrong.

            AccountFinder.Open "OPEN SYMMETRIC KEY SymmetricKey1 DECRYPTION BY CERTIFICATE Certificate1; SELECT *, CONVERT(nvarchar(MAX), DecryptByKey(FName_encrypt)) AS 'FName_Denc', CONVERT(nvarchar(MAX), DecryptByKey(MName_encrypt)) AS 'MName_Denc', CONVERT(nvarchar(MAX), DecryptByKey(LName_encrypt)) AS 'LName_Denc' FROM Accounts WHERE Username_encrypt = EncryptByKey( Key_GUID('SymmetricKey1'), CONVERT(varbinary,'" & Request.Form("Username") &"')) AND Password = '"& strEncodedPassword &"'; CLOSE SYMMETRIC KEY SymmetricKey1;", OBJdbConnection

When I encrypt the user's submission of the Username, it does not match or cannot match the encrypted Username in the DB. I am very confident that these values should match. 
 
If I am correct, then there is something wrong with how I am using the EncryptByKey function.
 
Please advise. Many, many thanks in advance! All best, Ogún Niké

Monday, September 22, 2014 - 11:45:24 AM - Ameena Back To Top (34657)

I found the solution. Test user can see the encrypted data when used with open symmetric key and close symmetric key.

Thanks,

Ameena

 


Monday, September 22, 2014 - 11:28:40 AM - Ameena Back To Top (34656)

GRANT VIEW DEFINITION ON SYMMETRIC KEY::SymmetricKey1 TO test1; 
GO
GRANT control ON Certificate::Certificate1 TO test1;
GO

 Even after granting control permission, tes1 user sees NULL in the decrypted column. Any suggestion would be most welcome.

Thanks,

Ameena


Friday, February 14, 2014 - 11:21:30 AM - mario Back To Top (29457)

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 don’t want data inside that column to be exposed.
Thank you in advance for your help or suggestion


Wednesday, February 12, 2014 - 11:26:12 AM - Ravi A Back To Top (29420)

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

 


Saturday, September 28, 2013 - 9:09:39 AM - Srinivas Back To Top (26981)

Hi All,

 

I have 2 columns in one table, its datatype are numeric(18,0),datetime when i am going to encrypt these column i’m 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


Tuesday, July 23, 2013 - 2:13:39 PM - pratik Back To Top (25966)

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.

 


Friday, July 5, 2013 - 2:49:12 PM - Alex Back To Top (25731)

Thank you! Great job on this article. It helped me accoplish something I had not done before.


Wednesday, April 3, 2013 - 12:19:20 PM - Eesha Jayaweera Back To Top (23140)

Thanks a lot for this article


Tuesday, February 12, 2013 - 4:48:00 AM - Pavan Back To Top (22060)

Hi Nitansh

Am getting NULL values after restoring the DB in another server. Is there any work around to get rid of this issue


Saturday, December 1, 2012 - 4:44:36 AM - Surekha Back To Top (20685)
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;
 
 -- Close the symmetric key
CLOSE SYMMETRIC KEY SymmetricKey1;
GO
 
i get NULL in 'Decrypted Credit Card Number' when i execute the above but i get  'Encrypted Credit Card Number',
actually i need the data encrypted or decrypted to compare the datas
my database has a encrypted column , when the uses sends tht data i need to compare user data with the encrypted column data 
but not able to get it

Friday, December 16, 2011 - 2:20:28 PM - Nitansh Back To Top (15382)

Thanks for your comments Brian.


Friday, December 16, 2011 - 1:42:59 PM - Brian White Back To Top (15380)

"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.  

BACKUP CERTIFICATE MyCert

TO FILE = 'c:\MSSQL\DATA\MyCert'

WITH PRIVATE KEY

(

    FILE = 'c:\MSSQL\DATA\SQLPrivateKeyFile',

    ENCRYPTION BY PASSWORD = 's5usW2Daxap4-zuC'

);


 


Friday, December 16, 2011 - 1:37:52 PM - Brian White Back To Top (15379)

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.  


Wednesday, December 14, 2011 - 1:22:59 AM - Daniel Back To Top (15347)
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 ?
 
 

Wednesday, November 23, 2011 - 11:03:05 PM - Nitansh Back To Top (15194)

 

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.

 


Tuesday, November 22, 2011 - 3:53:32 PM - Mike Back To Top (15186)

Nice Article and it looks worth implementing. I am concerned about db performance issues. Can I index encrypted data to improve performance?


Tuesday, November 22, 2011 - 2:37:44 PM - Sim Back To Top (15184)

Great Article. Thanks for sharing.


Tuesday, November 22, 2011 - 11:45:28 AM - Nitansh Back To Top (15181)

Thanks Deep.


Tuesday, November 22, 2011 - 8:36:54 AM - Deep Pandey Back To Top (15175)

Great ! Thanks for sharing ..















get free sql tips
agree to terms