-
Notifications
You must be signed in to change notification settings - Fork 8
Database Encryption
This document provides an overview of how MyUSA uses encryption to ensure the integrity of sensitive data entered by users as well as to comply with Government regulations and policies. The primary goal of the encryption is to protect sensitive data from being obtained through attacks on the database itself and to prevent the database administrator from having access to sensitive data.
Data is encrypted by the application on a field-by-field basis. Currently, we use a single encryption key for the database, but each field is encrypted separately.
A Ruby on Rails Gem called attr_encrypted provides the code to automatically encrypt and decrypt fields marked in the Ruby source as requiring encryption. Likewise, the database columns are named with a prefix of "encrypted_", such as "encrypted_first_name". As records are read from the database they are decrypted when accessed in memory. For example, when a Profile record is loaded, as it is being processed to respond to an API call, the individual fields are decrypted. This is triggered by the call in the model for the data. Likewise, when the record is being written to the database, the encryption is triggered for fields that were changed.
The encryption key is read by the application as the application is started so that it will be available by the runtime code.
attr_encrypted
leverages the Ruby library for OpenSSL as its underlying engine for encryption and decryption.
The key used for encryption is a single symmetric key. The key is used by the aes-256-cbc algorithm for both encryption and decryption. The key is managed through Chef and [Citadel](https://github.com/balanced-cookbooks/citadel].
The list of fields currently being encrypted are:
- Title
- First Name
- Middle Name
- Last Name
- Suffix
- Address
- Address2
- City
- State
- Zip
- Gender
- Marital Status
- Is Parent
- Is Student
- Is Veteran
- Is Retired
- Mobile
- Phone
A Ruby on Rails Gem called attr_encrypted provides the code to automatically encrypt and decrypt fields marked in the Ruby source as requiring encryption.
Internally, the Gem provides access to a number of different symmetric-key encryption algorithms. We are using aes-256-cbc
(AES 256-bit Cipher-Block-Chaining).
In most cases, the encryption and decryption is transparent to the developer. The Gem handles the encryption/decryption behind the scenes. The cases where a developer would be impacted are:
- When upgrading the version of Ruby or Rails, the
attr_encrypted
Gem should be updated to maintain compatibility - During initial deployment, the key must be set correctly where the application can find it
- When encrypted fields are changed/added/removed, they must be listed in the Model as being encrypted fields (add:
attr_encrypted: <name of attribute>, key: :key, marshal: true
) - When the encryption key is changed, a database migration must be performed to decrypt and re-encrypt each field of each row of data
- The attributes are actually virtual columns, prefixed with
encrypted_
. - All fields are of type
string
to store the encrypted values. - When writing scripts for the database, the fields are prefixed with
encrypted_
, e.g.encrypted_first_name
. - Loss of the encryption key would result in the loss of all of the data.
- When using the model to access fields, the encryption is transparent, since the attributes are virtual columns and the Gem takes care of encrypting and decrypting automatically.
Since all of the encryption/decryption is done within the application, there are no special ties to a particular database, and no special configuration or compatibility concerns for the database. However, if data is to be processed by an external application or analytics tool directly through the database, a similar decryption scheme (using the same key) would have to be used. This methodology of accessing data is discouraged, especially since the application provides its own API for securely accessing Profile data.
Normal database migrations are unaffected. There are a pair of migrations already written to handle adding and removing the encrypted fields. These migrations may be copied and customized for the following scenarios:
- Changing a field from encrypted to unencrypted
- Changing a field from unencrypted to encrypted
- Changing the encryption key
- Changing the Gem or methodology of encrypting fields