SQL Server 2005: How to regenerate the same symmetric key in two different databases

In a previous post on using symmetric keys, I mentioned that keys can be recreated using the KEY_SOURCE and IDENTITY_VALUE clauses of CREATE SYMMETRIC KEY. In this post, I'd like to expand a little on this topic and present a small demo as well.

Because keys cannot be individually backed up and restored, there is no direct way of moving a key from one database to another. However, by specifying the same values for the ALGORITHM, KEY_SOURCE, and IDENTITY_VALUE clauses of CREATE SYMMETRIC KEY, the same key can be generated on different databases. The KEY_SOURCE is the most important clause: the passphrase specified here is used to determine the key bits, so the phrase should be protected as carefully as the key itself or the data protected by it are protected. By specifying the same KEY_SOURCE, you are guaranteed to obtain the same key, assuming of course that you specified the same encryption algorithm. However, this is not sufficient to allow us to decrypt data encrypted by the key in another database - we also need for this key to be identified by the system as the same key - that is,  the key needs to have the same identifier, because this identifier is appended to the encrypted data and is used to determine the key that should be used for decryption. (The identifier of a key is shown in the key_guid column in the sys.symmetric_keys dialog and is also the value that needs to be passed to the encryptbykey functions). This is where the IDENTITY_VALUE clause comes into place - the phrase specified here will be used to generate a key identifier. The IDENTITY_VALUE clause doesn't have to be secret, but there's no reason it should be advertised either. The KEY_SOURCE is what you need to protect carefully.

And here is a small script that shows how to create a key using these clauses and how to decrypt data encrypted by it in a different database.

-- Set up the databases used for the demo
--
create database db_source;
create database db_destination;

use db_source;

-- Keep the key_source phrase carefully protected - it''s the key!!!
--
create symmetric key skey
with algorithm = triple_des,
identity_value = 'Data encryption key 07/06/2006',
key_source = 'Now he''s a clock-punching insurance claims adjuster fighting boredom and a bulging waistline.'
encryption by password = 'Avc#ptNO$cf@o!';

open symmetric key skey decryption by password = 'Avc#ptNO$cf@o!';

select * from sys.symmetric_keys;
select * from sys.openkeys;

-- Encrypt some data in a table
--
create table t (data varbinary(1024));
insert into t values (encryptbykey(key_guid('skey'), 'Top Secret!'));
select * from t;

close symmetric key skey;

-- Now copy the encrypted data to another table in another database
--
use db_destination;

create table t (data varbinary(1024));
insert into t (data) select t_src.data from db_source.dbo.t t_src;
select * from t;

-- Recreate the encryption key, so we can decrypt
-- The key can have a different name and can be protected with a different mechanism,
-- but it has to be obtained from the same algorithm, key_source, identity_value combo
-- In this database, we'll protect the key using a certificate
--
create master key encryption by password = 'Yahtf%pt@Hwht$f!O!';
create certificate cert_skey with subject = 'Certificate for accessing symmetric keys 07/06/2006';
create symmetric key skey2
with algorithm = triple_des,
identity_value = 'Data encryption key 07/06/2006',
key_source = 'Now he''s a clock-punching insurance claims adjuster fighting boredom and a bulging waistline.'
encryption by certificate cert_skey;

select * from sys.symmetric_keys;
select * from sys.openkeys;

-- Now use the key to decrypt the copied data
--
select convert(varchar(256), decryptbykeyautocert(cert_id('cert_skey'), NULL, data)) from t;

-- Cleanup
--
use master;

drop database db_source;
drop database db_destination;

You might want to experiment with the arguments used to create skey2. You will notice that if either the KEY_SOURCE or the IDENTITY_VALUE are not identical, the key will be created, but it will be different, and the decryption will not work.

Published 06 July 06 03:26 by lcris

Comments

# mikki said on July 12, 2006 9:19 AM:
Thanks, useful information
# Catherine Seto said on July 14, 2006 2:03 AM:
In Replication, do I create symmetric in this way, so the source database is the publisher, then I setup replication, with data pushed to the subscriber, then re-generate the symmetric key at the subscriber (i.e. destination database in your script)?
# lcris said on July 14, 2006 8:15 PM:
Yes, because replication cannot be set to replicate encryption keys, you would have to replicate them manually. You could also replicate the keys programatically, by storing the information used to generate them in a table and publishing that table, but such a solution would be less secure, because gaining access to the information in this table would compromise the keys.
# Cihat said on August 22, 2006 2:54 AM:
First of all, thank you for your blogs on sql server 2005 encryption. It is very useful for me (and lots of others).

What are the possibilities to restore a database on another sql 2005 database server? My main concern is that I encrypt table columns (with certificates) in server A and for a variaty of reasons I have to restore the database on server B. Is this possible, and if yes, can this be done without re-encrypting a whole table column which can contain millions of records?
# lcris said on August 22, 2006 2:06 PM:
Yes, you can restore a database without having to re-encrypt the data in it. See last paragraphs of http://blogs.msdn.com/lcris/archive/2005/09/30/475822.aspx and my answer to Regan Wick from http://blogs.msdn.com/lcris/archive/2005/10/14/481434.aspx.
# lcris said on March 12, 2007 5:03 PM:

This topic is now also covered in Books Online at: http://msdn2.microsoft.com/en-us/library/bb326115.aspx.

# Felipe Cembranelli said on November 27, 2008 1:05 PM:

Hi,

I have the following scenario:

1) SQL SERVER 2005 (central database server)

2) Several SQL SERVER 2005 Express (plant side databases)

I want to create a sql certificate in the "central" side and share it with my plants. This certificate will be used to encryp/decrypt data in the databases.

Is that possible? I have seem a lot of documentation about to share certificate in databases running in the same server.

Felipe Cembranelli

# Felipe Cembranelli said on December 3, 2008 10:29 AM:

Is that possible to do the same using just certificate, i mean, regenerate the same certificate in two differents databases? Is that make sense?

# lcris said on December 5, 2008 2:00 PM:

You can just backup the certificate to files and then restore it on the Express machines. Look at BACKUP/RESTORE CERTIFICATE in Books Online for additional information.

Anonymous comments are disabled
Page view tracker