Encryption: Secret Key Management
One of the challenges in cryptosystems is "secret protection" - how to protect the encryption key. If the key is stored in plain text then any user that can access the key can access the encrypted data. If the key is to be encrypted, another key is needed, and so on.
In RavenDB this can be handled in one of two ways:
Providing a Master Key to RavenDB
If a master key is provided, RavenDB will use it to encrypt the secret keys of encrypted databases.
You can provide a master key by setting Security.MasterKey.Exec
and Security.MasterKey.Exec.Arguments
in
settings.json. RavenDB will invoke a process you specify, so
you can write your own scripts / mini programs and apply whatever logic you need. It creates a clean separation
between RavenDB and the secret store in use. This option is useful when you want to protect your master key
with other solutions such as "Azure Key Vault", "HashiCorp Vault" or even Hardware-Based Protection.
RavenDB expects to get a cryptographically secure 256-bit key through the standard output.
For example, the following C# Console Application (GiveMeKey.cs) will generate a random key and write it to the standard output. Obviously this is just an example and your executable should supply the same key every time it is invoked.
using System;
using System.Security.Cryptography;
namespace GiveMeKey
{
class Program
{
static void Main(string[] args)
{
var buffer = new byte[256 / 8];
using (var cryptoRandom = new RNGCryptoServiceProvider())
{
cryptoRandom.GetBytes(buffer);
}
var stream = Console.OpenStandardOutput();
stream.Write(buffer, 0, buffer.Length);
}
}
}
And settings.json can look like this:
{
"ServerUrl": "https://rvn-srv-1:8080",
"Setup.Mode": "None",
"DataDir": "RavenData",
"Security.Certificate.Path": "your-server-cert.pfx",
"Security.MasterKey.Exec": "C:\\secrets\\GiveMeKey.exe"
}
Another way to provide a master key is to use a file containing the raw key bytes. In that case, set
Security.MasterKey.Path
in settings.json with the file path.
RavenDB expects a cryptographically secure 256-bit key.
Relying on the OS Protection Methods
If a master key is not provided by the user RavenDB will use the following default behavior:
In Windows, secret keys are encrypted and stored using the Data Protection API (DPAPI), which means they can only be retrieved by the user who stored them.
In Unix, RavenDB will generate a random master key and store it in the user's home folder with read/write permissions (octal 1600) only for the user who stored it. Then, RavenDB will use this master key to encrypt the secret keys of encrypted databases.
Changing/Resetting a Windows User Password
This section is relevant only to Server Store encryption and only if you chose to rely on the Windows protection methods.
Windows uses the user password to encrypt secrets in DPAPI. When a Windows password is changed the following actions are taken:
- DPAPI receives notification from Winlogon during a password change operation.
- DPAPI decrypts all the secrets that were encrypted with the user's old passwords.
- DPAPI re-encrypts all the secrets with the user's new password.
Changing a password this way is supported and RavenDB is not affected.
On the other hand, if the password was reset (either by you or by the administrator), secrets cannot be decrypted anymore.
If you still need to reset the password for some reason, please follow these steps to ensure that secret keys which are protected with DPAPI aren't lost.
Navigate to the RavenDB application folder where you can find the rvn
tool.
Run the following get-key command for every encrypted database (including System
if it's encrypted):
./rvn offline-operation get-key <path-to-database-dir>
The output is the plaintext key which is not protected and not tied to a user.
Now reset the Windows password.
Then, run the following put-key command for every encrypted database. Supply the path of the database folder and the key you just got (using get-key):
./rvn offline-operation put-key <path-to-database-dir> <base64-plaintext-key>
This operation takes the key and protects it with the new Windows user password.
After doing this for all databases you can run the server and continue working.
Using the Admin JS Console
Do not use the console unless you're sure of what you're doing. Running a
script in the Admin Console could cause your server to crash, loss of
data, or other irreversible harm.
The server's Admin Console is found in the Studio. You can use it to access and change your master key. This method is useful for changing the key when you change your Windows user account.
On the console page, select a database or the server. If you select a database, the master key is read only, and can be accessed with this script:
return database.MasterKey
The master key for a given database can be modified with the script:
server.ServerStore.PutSecretKey(base64, name, overwrite)
Parameter | Type | Description |
---|---|---|
base64 | string |
The new master key for the database |
name | string |
The name of the database for which to change the key |
overwrite | bool |
Whether to overwrite an existing key. If this is false and the database has a master key, an exception will be thrown. Be sure that this is what you want to do. |
Changing the Windows User
To change your Windows user without losing access to your database, use the scripts described above to:
- Retrieve your current key
- Switch your windows user
- Inject the key back into your database
return database.MasterKey
// Save the returned key
// Change windows user
server.ServerStore.PutSecretKey(<master key>, <database name>, true)