<!-- doc/src/sgml/database-encryption.sgml -->

<chapter id="database-file-encryption">
 <title>Cluster File Encryption</title>

 <indexterm zone="database-file-encryption">
  <primary>Cluster File Encryption</primary>
 </indexterm>

 <para>
  The purpose of cluster file encryption is to prevent users with read
  access to the directories used to store database files and write-ahead
  log from being able to access the data stored in those files.
  For example, when using cluster file encryption, users who have read
  access to the cluster directories for backup purposes will not be able
  to decrypt the data stored in these files.
 </para>

 <para>
  Cluster file encryption uses two levels of encryption.  The first level
  is data encryption keys, specifically keys zero and one.  Key zero is
  the key used to encrypt database heap and index files which are stored in
  the file system, plus temporary files created during database operation.
  Key one is used to encrypt write-ahead log (WAL) files.  Two different
  keys are used so that primary and standby servers can use different zero
  (heap/index/temp) keys, but the same one (WAL) key, so that these keys
  can eventually be rotated by switching the primary to the standby
  and then changing the WAL key.
 </para>

 <para>
  The second level of encryption is a key used to encrypt first-level
  keys.  This type of key is often referred to as a Key Encryption Key
  (<acronym>KEK</acronym>).  This key is <emphasis>not</emphasis> stored
  in the file system, but provided at <command>initdb</command> time and
  each time the server is started.  This key prevents anyone with access
  to the database directories from decrypting the data because they do
  not know the second-level key which encrypted the first-level keys
  which encrypted the database cluster files.
 </para>

 <sect1 id="encryption-file-encryption">
  <title>Initialization</title>

  <para>
   Cluster file encryption is enabled when
   <productname>PostgreSQL</productname> is built
   with <literal>--with-openssl</literal> and <xref
   linkend="app-initdb-cluster-key-command"/> is specified
   during <command>initdb</command>.  The cluster key
   provided by the <option>--cluster-key-command</option>
   option during <command>initdb</command> and the one generated
   by <xref linkend="guc-cluster-key-command"/> in the
   <filename>postgresql.conf</filename> must match for the database
   cluster to start. Note that the cluster key command
   passed to <command>initdb</command> must return a key of
   64 hexadecimal characters. For example.
<programlisting>
initdb -D dbname --cluster-key-command='ckey_passphrase.sh'
</programlisting>
  </para>
 </sect1>

 <sect1 id="key-encryption-key">
  <title>Internals</title>

  <para>
   During the <command>initdb</command> process, if
   <option>--cluster-key-command</option> is specified, two data-level
   encryption keys are created.   These two keys are then encrypted with
   the key encryption key (KEK) supplied by the cluster key command before
   being stored in the database directory.  The key or passphrase that
   derives the key must be supplied from the terminal or stored in a
   trusted key store, such as key vault software, hardware security module.
  </para>

  <para>
   If the <productname>PostgreSQL</productname> server has
   been initialized to require a cluster key, each time the
   server starts the <filename>postgresql.conf</filename>
   <varname>cluster_key_command</varname> command will be executed
   and the cluster key retrieved.  The data encryption keys in the
   <filename>pg_cryptokeys</filename> directory will then be decrypted
   using the supplied key and integrity-checked to ensure it
   matches the initdb-supplied key.  If this check fails, the
   server will refuse to start.
  </para>

  <para>
   The data encryption keys are randomly generated and are 128, 192,
   or 256-bits in length.  They are encrypted by the key encryption key
   (KEK) using Advanced Encryption Standard (<acronym>AES256</acronym>)
   encryption in Galois/Counter Mode (<acronym>GCM</acronym>), which also
   provides KEK authentication.
  </para>
 </sect1>
</chapter>
