Security and Encryption for SQL Server Compact

The nice thing about SQL Server Compact is the database can be treated as a document.  It's a single file, it's only "open" when being used and can use the standard set of security mechanisms that any other document can.  You can set ACLs on the files, and you can encrypt the file with the Windows Encrypted File System.

Any security expert worth their weight in "keys" will tell you security is a multi-layer process.  There's no "one master lock" you can use and be considered secure.  It's a layered approach. 

Here's a set of recommendations you can use for SQL Server Compact, but many of these will apply to any documents.

Use the Windows Encrypted File System
Encrypt the directory of all your "document", including the directory of your SQL Server Compact Data File

System.IO.DirectoryInfo dirInfo = new System.IO.DirectoryInfo(System.Windows.Forms.Application.LocalUserAppDataPath);

dirInfo.Attributes = System.IO.FileAttributes.Encrypted;

This will flip the EFS flag.

Alternatively, you could simply set the Encrypted flag for just the Compact data file

using (SqlCeConnection conn = new SqlCeConnection(Properties.Settings.Default.LocalConnectionString)) {

    System.IO.File.Encrypt(conn.Database);

}

This will encrypt the data file, and the directory of documents to the specific user.  This means evil people can't simply map a drive and copy the file.  It also means evil people can't just steal the hard drive and log on as an administrator and copy the file.  There's some caveats here, and a full study of EFS is recommended, but that's a different conversation. 

What EFS doesn't do is secure the file while "in flight".  If you email the database, copy it to a USB key, copy it to a network share you must remove the EFS flag.  So now how do you protect the database while in flight?

Use the SQL Server Compact File Encryption
Within the SQL Server Compact Connection String you can tell the engine to encrypt the datafile with a password.  By simply specifying a password, the database is automatically encrypted.  We used to support an encrypt = true name/value pair, but it was sort of silly to have a password without encryption, and encryption without a password is about as useful as putting a lock on a door but leaving the key in the lock (on the outside of the door).  So, we no longer use this name/value pair and will likely throw an error  in a future release if the engine sees it.  Today Compact just ignores it.

To turn on Encryption, simply set the Password like the following:

Data Source=|DataDirectory|\Localdatabase.sdf;Password=Foo

What level of encryption do you want?  
That turns out to almost be a silly question as well.  Does anyone want a somewhat secure encryption algorithm?  Of course not.  But, the evil people keep cracking the encryption algorithms, and the older operating systems don't actually support the newer algorithms.  Laxmi posted the different versions supported here.  For 4.0 we'll do the latest and greatest at the time we release. 

To set the extra bit, simply specify the Encryption Mode like the following:

Data Source=|DataDirectory|\Localdatabase.sdf;Password=Foo;Encryption Mode=Engine Default

This may be needed when creating a database on the server, and streaming it to a PPC 2003 device, or Win2k which uses the same algos as PPC 2003.

In an upcoming updated post on deploying database with scripts, and versioning databases, I'll show how you can incorporate this into your "Health Check" api to assure newly created databases are encrypted.

Steve