Skip to main content

Access your teaching qualifications - Encryption

The application uses ActiveRecord Encryption to encrypt sensitive data.

Application-level encryption ensures that we reduce the risk of leaking PII information should the database ever be compromised.

Key derivation

Keys are derived with SHA-256, the Rails default since load_defaults 7.1.

Every encrypted column in this database was originally written under SHA-1, which was the default when they were first encrypted. They were rewritten under SHA-256 by a one-off pii:re_encrypt task, run with the service in maintenance mode, and the SHA-1 overrides in config/application.rb were removed once a companion pii:verify task confirmed no row depended on them. Both tasks were deleted afterwards. See https://github.com/DFE-Digital/teaching-record-team-project-board/issues/455

One thing worth knowing before changing a digest or key again: nothing in the ciphertext records which key derived it, because store_key_references is off. There is no way to tell a converted row from an unconverted one in SQL, and no way to count what is left. Any future change needs the same shape of migration, and the only completion check available is reading every row through a type with no previous schemes.

Note this is specific to Active Record encryption. active_support.key_generator_hash_digest_class, which signs session cookies, moved to SHA-256 back in Rails 7.0 and is not pinned.

Encryption keys

Rails encrypts data using a key that is stored outside of version control. In deployed environments we use the RAILS_MASTER_KEY environment variable to pass the key to the application.

For local development, the key is stored in config/master.key. This file is not encrypted, so it should be kept secret.

Accessing the key

To gain access to this key, you can call make dev print-keyvault-secret | grep RAILS_MASTER_KEY and then copy the value from the output to your local config/master.key file.

Rotating keys

There may be a reason to rotate the encryption key in the future. See this guide for the details.

ActiveRecord Encryption supports a list of keys. It uses the last key in the list for encrypting data and will try all the keys in the list for decrypting until one works.

To add a new key to the list, make sure you have the correct value set in config/master.key. Then...

EDITOR=vi rails credentials:edit

Add a new key to the list and then save the file. This will mutate the config/credentials.yml.enc file. Commit these changes to the repo and deploy.