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--
-- Keep the key_source phrase carefully protected - it''s the key!!!--
-- Encrypt some data in a table--
-- Now copy the encrypted data to another table in another database--
-- 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--
-- Now use the key to decrypt the copied data--
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.