Securing the data encryption key

Data encryption key

The key for transparent data encryption (the data key) is generated by initdb and stored in a file pg_encryption/key.bin under the data directory. This file contains several keys that are used for different purposes at runtime. The data key is a single sequence of random bytes in the file.

If you don't perform any further action, this file contains the key in plaintext, which isn't secure. Anyone with access to the encrypted data directory has access to the plaintext key, which defeats the purpose of encryption.

Choosing a mechanism to protect the data encryption key

To secure the data encryption key, you must specify a wrap and an unwrap command that provides TDE with a data encryption protection mechanism. You can set this parameter only at server start.

With the wrap and unwrap commands you can:

Configuring a wrapping and unwrapping command

After you choose a method to protect your key, you can create the wrapping/unwrapping commands. The configuration of these commands is left to the user, which allows you to tailor the setup to local requirements and integrate with existing key management software or similar.

Using a passphrase provides an example for wrapping and unwrapping commands using OpenSSL and a passphrase to secure the TDE data key. Using a key store provides an example for wrapping and unwrapping commands using an external key store key to protect the TDE data key.

When you initialize a server with TDE, the initdb command adds the data_encryption_key_unwrap_command parameter in the postgresql.conf configuration file. The string specified in data_encryption_key_unwrap_command can then unwrap (decrypt) the data encryption key.

The commands must contain a placeholder %p, which is replaced with the name of the file containing the key to unwrap. The command must print the unwrapped (decrypted) key to its standard output.

Providing the wrapping and unwrapping commands to TDE

You must make the commands available to the TDE database server so it can wrap and unwrap the data encryption key. You have the following options:

  • You can configure the wrapping and unwrapping commands as environment variables before creating the database, so TDE can fall back on those variables when initializing a server:

    Example
    PGDATAKEYWRAPCMD='openssl enc -e -aes-128-cbc -pbkdf2 -out "%p"'
    PGDATAKEYUNWRAPCMD='openssl enc -d -aes-128-cbc -pbkdf2 -in "%p"'
    export PGDATAKEYWRAPCMD PGDATAKEYUNWRAPCMD
    #After these variables are set, you can initialize the server:
    initdb --data-encryption -D /var/lib/edb/as16/data

  • You can provide the wrapping and unwrapping commands directly in the command line when initializing a server with the --key-wrap-command=<command> and --key-unwrap-command=<command> options:

    Example
    initdb --data-encryption -D /var/lib/edb/as16/data \
      --key-wrap-command='openssl enc -e -aes-128-cbc -pbkdf2 -out "%p"' \
      --key-unwrap-command='openssl enc -d -aes-128-cbc -pbkdf2 -in "%p"'

  • You can disable the protection of your data encryption key with --no-key-wrap. Doing so leaves your key unprotected and we recommend this practice only for testing purposes.

    Example
    initdb --data-encryption -D /var/lib/edb/as16/data --no-key-wrap