Encrypting Data In SQL Server 2005
I've been looking at the new encryption functionality in SQL Server 2005. Here's some sql that executes on IDW15 - June CTP (most of it should work on IDW14 - April CTP apart from DecryptByKeyAutoCert I think...
This sample code sets up a database and a table that will contain some data (national insurance numbers) we want to store encrypted. It shows how to set up a master key, certicate and encryption key and how to use these to insert and select data. It also demonstrates how to set up a view that takes away a lot of the pain.
It does expose that in IDW15 at least you need to give CONTROL level permission to a certificate to make this work - which I hope gets fixed in the next release... with CONTROL you can do anything to a certificate, including dropping and altering it and removing the private key!!! The last of these works even if the cert is used to decrypt keys in the database - which presents an untenable security problem. What we want is just to require REFERENCES level permission (I think).
Other than this little niggle, the functionality is awesome! I have been doing encryption/decryption in the middle tier: it's great to be able to move this to the database - particularly as this makes it much easier to create reports in report server that otherwise had to use a custom assembly to decrypt data.
Copy the below into management studio and walk through it.
create database SecurityDemo
go
use SecurityDemo
go
-- Create a master key - this is used as the root of the encryption
-- hierarchy: all keys and certs are encrypted with this
-- it is scoped to the database
create master key encryption by password = <'pass@word1'>
-- Now we will create a simple table with a column that will store
-- national security numbers in encrypted form
create table people (
id int identity constraint pk_people_id primary key clustered,
firstname nvarchar(50),
lastname nvarchar(50),
encrypted_ninumber varbinary(128) )
go
-- Now lets create a certicate - we will use this to encrypt a key
-- this will give a warning about an invalid start date, but
-- we can ignore this since sql doesn't care about cert dates
create certificate ni_cert with subject = 'NI Certificate'
go
-- Now create a symmetric key to encrypt/decrypt the data
create symmetric key ni_key with algorithm = aes_256
encryption by certificate ni_cert
go
-- Now we will create a procedure to insert and encrypt the data
create procedure dbo.insert_people (
@firstname nvarchar(50),
@lastname nvarchar(50),
@ninumber nchar(9)
) as
-- open the symmetric key
open symmetric key ni_key decryption by certificate ni_cert
-- insert and encrypt the data
insert people(firstname, lastname, encrypted_ninumber)
values(
@firstname,
@lastname,
EncryptByKey(Key_GUID('ni_key'), @ninumber)
)
-- close the key now
close symmetric key ni_key
go
-- now lets insert some data
insert_people 'James', 'World', 'JZ123488B'
go
-- looking at this data, you can see its nice and encrypted
select * from people
go
-- ok, so lets create a procedure to decrypt this
create procedure dbo.select_person (
@id int
) as
open symmetric key ni_key decryption by certificate ni_cert
select
id,
firstname,
lastname,
convert(nchar(9),DecryptByKey(encrypted_ninumber)) as ninumber
from
people
close symmetric key ni_key
go
-- and try it out
exec select_person 1
go
-- how about if we want another use to call this spoc?
create login bob with password = <'pass@word1'>
go
create user bob for login bob
go
-- this won't work as bob has no permissions
execute as user='bob' -- lets us run in the context of bob
exec select_person 1
revert -- puts us back to our dbo context
go
-- let's give him some and then the above should work
grant execute on dbo.select_person to bob
grant references on symmetric key::ni_key to bob
-- eek!!! currently need to grant *control* permission to bob
-- in IDW15... hope this improves!
grant control on certificate::ni_cert to bob
-- now it works
execute as user='bob' -- lets us run in the context of bob
exec select_person 1
revert -- puts us back to our dbo context
go
-- lets take away bob's permissions
revoke execute on dbo.select_person to bob
revoke references on symmetric key::ni_key to bob
revoke control on certificate::ni_cert to bob
go
-- a new feature lets us create a view that automatically decrypts
-- the data
create view view_people as
select
id,
firstname,
lastname,
convert(
nchar(9),
DecryptByKeyAutoCert(cert_id('ni_cert'),
null, encrypted_ninumber)
) AS ninumber
from
people
go
select * from view_people
go
-- can bob look at this view? clearly he needs permission on the view
grant select on view_people to bob
go
-- lets try...
execute as user='bob'
select * from view_people
revert
go
-- hmmm! we got null - this is what anyone gets that doesn't
-- have an open key when they try to read encrypted data
-- lets grant him permissions - control of the cert and references on the key
grant control on certificate::ni_cert to bob
grant references on symmetric key::ni_key to bob
go
-- lets try again
execute as user='bob'
select * from view_people
revert
go
-- this works! and best of all we didn't have to manage
-- opening the key
-- if they fix the level of permissions required on the cert
-- then this will be an awesome way to manage encrypted data
-- current weakness of needing CONTROL permission for bob on the cert:
-- we can do this and remove the ability to decrypt our data!
execute as user='bob'
alter certificate ni_cert remove private key
revert
go
-- certs can be backed up and restored, but this still sucks
-- other than that, this is an awesome feature set!
Comments
Anonymous
June 16, 2009
PingBack from http://workfromhomecareer.info/story.php?id=34588Anonymous
June 16, 2009
PingBack from http://fixmycrediteasily.info/story.php?id=16911Anonymous
June 19, 2009
PingBack from http://edebtsettlementprogram.info/story.php?id=24292