Overview
Windows Operating systems offer a lot of convenience not just to GUI users but to developers and system builders as well. A lot of times we need to hold data files at a particular location for further processing. Data in motion is usually protected quite well these days (using HTTPS) but a lot us aren't too careful about data-at-rest. This blog post discusses the NTFS encrypted file system functionality and a couple of related APIs for storing files securely on a Windows box.
How encrypted folders and files work on NTFS
All most all Windows OS installations are configured to use NTFS as the file system. NTFS has a feature by which the file system transparently encrypts data written to a particular file or files in a particular folder. Conversely, NTFS also tranparently decrypts the encrypted contents of a file when applications access such encrypted content.
Now, you may ask, if everything is transparent, where is the security? The way it works is - the user account which enables a file or folder for encryption only has access to the key which is used for encrypting and decrypting the content. No other user has access to the key. As long as the application is running in the context of the correct user, it will be able to encrypt and decrypt the content without any change to the application code. Now this is cool!
Generating the encryption key
The next question is - how does a user generate the key? Well, if the user does not have a key already, Windows generates one for you when you enable a file or folder for encryption for the first time. This key is stored in the Windows certificate Manager under 'Personal Certificates'. Here is a screenshot of it:
Backup the encryption key
If the encrypted file or folder contains important data, its a good idea to backup the encryption key. This can be done by:
- Start the Certificate Manager by typing certmgr.msc in the Run box
- Select the certificate
- Right-click and select 'All Tasks -> Export'
- Enter the password for protecting this file. You will need to enter this password when importing this file into the Certificate Manager
- Choose the option 'Yes, export the private key'in the following screen
Store the exported key somewhere safe, maybe you could email it to youself.
Using the APIs
If my case, I needed to enable a folder for encryption at the time of application configuration. Just like most things in Windows, there is an API to do it and a couple of related APIs.
The main idea is to:
- First check if the file system supports creating encrypted folders
- Create a directory
- Configure the directory for encryption.
The main APIs used are:
- GetVolumeInformation
- CreateDirectory
- EncryptFile
The code for this given below, its very simple and follows the same order of operations as mentioned above. The full sample is available on GitHub.
void CreateEncryptedFolder(const TCHAR* szPath) { if (nullptr == szPath) { throw ApplicationException("Path is null"); } if (CheckDirectoryExists(szPath)) { throw ApplicationException("Path already exists"); } if (lstrlen(szPath) < 4) { throw ApplicationException("Path is invalid"); } TCHAR strRootPath[4] = {}; DWORD dwFlags = 0; if (lstrcpyn(strRootPath, szPath, 4) == nullptr) { throw ApplicationException("Error copying path to rootpath"); } if (!GetVolumeInformation(strRootPath, nullptr, 0, nullptr, 0, &dwFlags, nullptr, 0)) { throw ApplicationException("Error getting volume information"); } if ((dwFlags & FILE_SUPPORTS_ENCRYPTION) == 0) { throw ApplicationException("File system does not support encryption"); } if (!CreateDirectory(szPath, nullptr)) { throw ApplicationException("Failed to create directory"); } if (EncryptFile(szPath) == 0) { throw ApplicationException("Failed to enable encryption"); } }