Commit 0e88fc08 authored by Tom Lane's avatar Tom Lane

Make an editorial pass over the newly SGML-ified contrib documentation.

Fix lots of bad markup, bad English, bad explanations.

Last ones ... whew.  Man, that was tedious.
parent 665028f6
<!-- $PostgreSQL: pgsql/doc/src/sgml/pgcrypto.sgml,v 1.3 2007/12/16 23:00:42 tgl Exp $ -->
<sect1 id="pgcrypto"> <sect1 id="pgcrypto">
<title>pgcrypto</title> <title>pgcrypto</title>
<indexterm zone="pgcrypto"> <indexterm zone="pgcrypto">
<primary>pgcrypto</primary> <primary>pgcrypto</primary>
</indexterm> </indexterm>
<para> <para>
This module provides cryptographic functions for PostgreSQL. The <filename>pgcrypto</> module provides cryptographic functions for
<productname>PostgreSQL</>.
</para> </para>
<sect2> <sect2>
<title>Notes</title> <title>General hashing functions</title>
<sect3>
<title>Configuration</title>
<para>
pgcrypto configures itself according to the findings of main PostgreSQL
<literal>configure</literal> script. The options that affect it are
<literal>--with-zlib</literal> and <literal>--with-openssl</literal>.
</para>
<para>
When compiled with zlib, PGP encryption functions are able to
compress data before encrypting.
</para>
<para>
When compiled with OpenSSL there will be more algorithms available.
Also public-key encryption functions will be faster as OpenSSL
has more optimized BIGNUM functions.
</para>
<para>
Summary of functionality with and without OpenSSL:
</para>
<table>
<title>Summary of functionality with and without OpenSSL</title>
<tgroup cols="3">
<thead>
<row>
<entry>Functionality</entry>
<entry>built-in</entry>
<entry>OpenSSL</entry>
</row>
</thead>
<tbody>
<row>
<entry>MD5</entry>
<entry>yes</entry>
<entry>yes</entry>
</row>
<row>
<entry>SHA1</entry>
<entry>yes</entry>
<entry>yes</entry>
</row>
<row>
<entry>SHA224/256/384/512</entry>
<entry>yes</entry>
<entry>yes (3)</entry>
</row>
<row>
<entry>Any other digest algo</entry>
<entry>no</entry>
<entry>yes (1)</entry>
</row>
<row>
<entry>Blowfish</entry>
<entry>yes</entry>
<entry>yes</entry>
</row>
<row>
<entry>AES</entry>
<entry>yes</entry>
<entry>yes (2)</entry>
</row>
<row>
<entry>DES/3DES/CAST5</entry>
<entry>no</entry>
<entry>yes</entry>
</row>
<row>
<entry>Raw encryption</entry>
<entry>yes</entry>
<entry>yes</entry>
</row>
<row>
<entry>PGP Symetric encryption</entry>
<entry>yes</entry>
<entry>yes</entry>
</row>
<row>
<entry>PGP Public-Key encryption</entry>
<entry>yes</entry>
<entry>yes</entry>
</row>
</tbody>
</tgroup>
</table>
<orderedlist>
<listitem>
<para>
Any digest algorithm OpenSSL supports is automatically picked up.
This is not possible with ciphers, which need to be supported
explicitly.
</para>
</listitem>
<listitem>
<para>
AES is included in OpenSSL since version 0.9.7. If pgcrypto is
compiled against older version, it will use built-in AES code,
so it has AES always available.
</para>
</listitem>
<listitem>
<para>
SHA2 algorithms were added to OpenSSL in version 0.9.8. For
older versions, pgcrypto will use built-in code.
</para>
</listitem>
</orderedlist>
</sect3>
<sect3> <sect3>
<title>NULL handling</title> <title><function>digest()</function></title>
<para>
As standard in SQL, all functions return NULL, if any of the arguments
are NULL. This may create security risks on careless usage.
</para>
</sect3>
<sect3> <synopsis>
<title>Security</title> digest(data text, type text) returns bytea
<para> digest(data bytea, type text) returns bytea
All the functions here run inside database server. That means that all </synopsis>
the data and passwords move between pgcrypto and client application in
clear-text. Thus you must:
</para>
<orderedlist>
<listitem>
<para>Connect locally or use SSL connections.</para>
</listitem>
<listitem>
<para>Trust both system and database administrator.</para>
</listitem>
</orderedlist>
<para> <para>
If you cannot, then better do crypto inside client application. Computes a binary hash of the given <parameter>data</>.
<parameter>type</> is the algorithm to use.
Standard algorithms are <literal>md5</literal> and
<literal>sha1</literal>. If <filename>pgcrypto</> was built with
OpenSSL, more algorithms are available, as detailed in
<xref linkend="pgcrypto-with-without-openssl">.
</para> </para>
</sect3>
</sect2>
<sect2>
<title>General hashing</title>
<sect3>
<title><literal>digest(data, type)</literal></title>
<programlisting>
digest(data text, type text) RETURNS bytea
digest(data bytea, type text) RETURNS bytea
</programlisting>
<para>
Type is here the algorithm to use. Standard algorithms are `md5` and
`sha1`, although there may be more supported, depending on build
options.
</para>
<para>
Returns binary hash.
</para>
<para> <para>
If you want hexadecimal string, use `encode()` on result. Example: If you want the digest as a hexadecimal string, use
<function>encode()</> on the result. For example:
</para> </para>
<programlisting> <programlisting>
CREATE OR REPLACE FUNCTION sha1(bytea) RETURNS text AS $$ CREATE OR REPLACE FUNCTION sha1(bytea) returns text AS $$
SELECT encode(digest($1, 'sha1'), 'hex') SELECT encode(digest($1, 'sha1'), 'hex')
$$ LANGUAGE SQL STRICT IMMUTABLE; $$ LANGUAGE SQL STRICT IMMUTABLE;
</programlisting> </programlisting>
</sect3> </sect3>
<sect3> <sect3>
<title><literal>hmac(data, key, type)</literal></title> <title><function>hmac()</function></title>
<programlisting>
hmac(data text, key text, type text) RETURNS bytea <synopsis>
hmac(data bytea, key text, type text) RETURNS bytea hmac(data text, key text, type text) returns bytea
</programlisting> hmac(data bytea, key text, type text) returns bytea
</synopsis>
<para> <para>
Calculates Hashed MAC over data. `type` is the same as in `digest()`. Calculates hashed MAC for <parameter>data</> with key <parameter>key</>.
If the key is larger than hash block size it will first hashed and the <parameter>type</> is the same as in <function>digest()</>.
hash will be used as key.
</para> </para>
<para> <para>
It is similar to digest() but the hash can be recalculated only knowing This is similar to <function>digest()</> but the hash can only be
the key. This avoids the scenario of someone altering data and also recalculated knowing the key. This prevents the scenario of someone
changing the hash. altering data and also changing the hash to match.
</para> </para>
<para> <para>
Returns binary hash. If the key is larger than the hash block size it will first be hashed and
the result will be used as key.
</para> </para>
</sect3> </sect3>
</sect2> </sect2>
<sect2> <sect2>
<title>Password hashing</title> <title>Password hashing functions</title>
<para> <para>
The functions <literal>crypt()</literal> and <literal>gen_salt()</literal> are specifically designed The functions <function>crypt()</> and <function>gen_salt()</>
for hashing passwords. <literal>crypt()</literal> does the hashing and `gen_salt()` are specifically designed for hashing passwords.
<function>crypt()</> does the hashing and <function>gen_salt()</>
prepares algorithm parameters for it. prepares algorithm parameters for it.
</para> </para>
<para> <para>
The algorithms in `crypt()` differ from usual hashing algorithms like The algorithms in <function>crypt()</> differ from usual hashing algorithms
MD5 or SHA1 in following respects: like MD5 or SHA1 in the following respects:
</para> </para>
<orderedlist> <orderedlist>
<listitem> <listitem>
<para> <para>
They are slow. As the amount of data is so small, this is only They are slow. As the amount of data is so small, this is the only
way to make brute-forcing passwords hard. way to make brute-forcing passwords hard.
</para> </para>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
Include random 'salt' with result, so that users having same They use a random value, called the <firstterm>salt</>, so that users
password would have different crypted passwords. This is also having the same password will have different encrypted passwords.
additional defense against reversing the algorithm. This is also an additional defense against reversing the algorithm.
</para> </para>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
Include algorithm type in the result, so passwords hashed with They include the algorithm type in the result, so passwords hashed with
different algorithms can co-exist. different algorithms can co-exist.
</para> </para>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
Some of them are adaptive - that means after computers get Some of them are adaptive &mdash; that means when computers get
faster, you can tune the algorithm to be slower, without faster, you can tune the algorithm to be slower, without
introducing incompatibility with existing passwords. introducing incompatibility with existing passwords.
</para> </para>
</listitem> </listitem>
</orderedlist> </orderedlist>
<para> <table>
Supported algorithms: <title>Supported algorithms for <function>crypt()</></title>
</para> <tgroup cols="5">
<programlisting> <thead>
`------`-------------`---------`----------`--------------------------- <row>
Type Max password Adaptive Salt bits Description <entry>Algorithm</entry>
---------------------------------------------------------------------- <entry>Max password length</entry>
`bf` 72 yes 128 Blowfish-based, variant 2a <entry>Adaptive?</entry>
`md5` unlimited no 48 md5-based crypt() <entry>Salt bits</entry>
`xdes` 8 yes 24 Extended DES <entry>Description</entry>
`des` 8 no 12 Original UNIX crypt </row>
---------------------------------------------------------------------- </thead>
</programlisting> <tbody>
<row>
<entry><literal>bf</></entry>
<entry>72</entry>
<entry>yes</entry>
<entry>128</entry>
<entry>Blowfish-based, variant 2a</entry>
</row>
<row>
<entry><literal>md5</></entry>
<entry>unlimited</entry>
<entry>no</entry>
<entry>48</entry>
<entry>MD5-based crypt</entry>
</row>
<row>
<entry><literal>xdes</></entry>
<entry>8</entry>
<entry>yes</entry>
<entry>24</entry>
<entry>Extended DES</entry>
</row>
<row>
<entry><literal>des</></entry>
<entry>8</entry>
<entry>no</entry>
<entry>12</entry>
<entry>Original UNIX crypt</entry>
</row>
</tbody>
</tgroup>
</table>
<sect3> <sect3>
<title>crypt(password, salt)</title> <title><function>crypt()</></title>
<programlisting>
crypt(password text, salt text) RETURNS text <synopsis>
</programlisting> crypt(password text, salt text) returns text
</synopsis>
<para> <para>
Calculates UN*X crypt(3) style hash of password. When storing new Calculates a crypt(3)-style hash of <parameter>password</>.
password, you need to use function `gen_salt()` to generate new salt. When storing a new password, you need to use
When checking password you should use existing hash as salt. <function>gen_salt()</> to generate a new <parameter>salt</> value.
To check a password, pass the stored hash value as <parameter>salt</>,
and test whether the result matches the stored value.
</para> </para>
<para> <para>
Example - setting new password: Example of setting a new password:
</para> </para>
<programlisting> <programlisting>
UPDATE .. SET pswhash = crypt('new password', gen_salt('md5')); UPDATE ... SET pswhash = crypt('new password', gen_salt('md5'));
</programlisting> </programlisting>
<para> <para>
Example - authentication: Example of authentication:
</para> </para>
<programlisting> <programlisting>
SELECT pswhash = crypt('entered password', pswhash) WHERE .. ; SELECT pswhash = crypt('entered password', pswhash) FROM ... ;
</programlisting> </programlisting>
<para> <para>
returns true or false whether the entered password is correct. This returns <literal>true</> if the entered password is correct.
It also can return NULL if `pswhash` field is NULL.
</para> </para>
</sect3> </sect3>
<sect3> <sect3>
<title>gen_salt(type)</title> <title><function>gen_salt()</></title>
<programlisting>
gen_salt(type text) RETURNS text <synopsis>
</programlisting> gen_salt(type text [, iter_count integer ]) returns text
</synopsis>
<para> <para>
Generates a new random salt for usage in `crypt()`. For adaptible Generates a new random salt string for use in <function>crypt()</>.
algorithms, it uses the default iteration count. The salt string also tells <function>crypt()</> which algorithm to use.
</para> </para>
<para> <para>
Accepted types are: `des`, `xdes`, `md5` and `bf`. The <parameter>type</> parameter specifies the hashing algorithm.
The accepted types are: <literal>des</literal>, <literal>xdes</literal>,
<literal>md5</literal> and <literal>bf</literal>.
</para> </para>
</sect3>
<sect3>
<title>gen_salt(type, rounds)</title>
<programlisting>
gen_salt(type text, rounds integer) RETURNS text
</programlisting>
<para> <para>
algorithms. The higher the count, the more time it takes to hash The <parameter>iter_count</> parameter lets the user specify the iteration
count, for algorithms that have one.
The higher the count, the more time it takes to hash
the password and therefore the more time to break it. Although with the password and therefore the more time to break it. Although with
too high count the time to calculate a hash may be several years too high a count the time to calculate a hash may be several years
- which is somewhat impractical. &mdash; which is somewhat impractical. If the <parameter>iter_count</>
parameter is omitted, the default iteration count is used.
Allowed values for <parameter>iter_count</> depend on the algorithm:
</para> </para>
<table>
<title>Iteration counts for <function>crypt()</></title>
<tgroup cols="4">
<thead>
<row>
<entry>Algorithm</entry>
<entry>Default</entry>
<entry>Min</entry>
<entry>Max</entry>
</row>
</thead>
<tbody>
<row>
<entry><literal>xdes</></entry>
<entry>725</entry>
<entry>1</entry>
<entry>16777215</entry>
</row>
<row>
<entry><literal>bf</></entry>
<entry>6</entry>
<entry>4</entry>
<entry>31</entry>
</row>
</tbody>
</tgroup>
</table>
<para> <para>
Number is algorithm specific: For <literal>xdes</literal> there is an additional limitation that the
iteration count must be an odd number.
</para> </para>
<programlisting>
`-----'---------'-----'----------
type default min max
---------------------------------
`xdes` 725 1 16777215
`bf` 6 4 31
---------------------------------
</programlisting>
<para> <para>
In case of xdes there is a additional limitation that the count must be To pick an appropriate iteration count, consider that
a odd number. the original DES crypt was designed to have the speed of 4 hashes per
second on the hardware of that time.
Slower than 4 hashes per second would probably dampen usability.
Faster than 100 hashes per second is probably too fast.
</para> </para>
<para> <para>
Notes: Here is a table that gives an overview of the relative slowness
of different hashing algorithms.
The table shows how much time it would take to try all
combinations of characters in an 8-character password, assuming
that the password contains either only lowercase letters, or
upper- and lower-case letters and numbers.
In the <literal>crypt-bf</literal> entries, the number after a slash is
the <parameter>iter_count</parameter> parameter of
<function>gen_salt</function>.
</para> </para>
<itemizedlist>
<listitem>
<para>
Original DES crypt was designed to have the speed of 4 hashes per
second on the hardware of that time.
</para>
</listitem>
<listitem>
<para>
Slower than 4 hashes per second would probably dampen usability.
</para>
</listitem>
<listitem>
<para>
Faster than 100 hashes per second is probably too fast.
</para>
</listitem>
<listitem>
<para>
See next section about possible values for `crypt-bf`.
</para>
</listitem>
</itemizedlist>
</sect3>
<sect3> <table>
<title>Comparison of crypt and regular hashes</title> <title>Hash algorithm speeds</title>
<tgroup cols="4">
<thead>
<row>
<entry>Algorithm</entry>
<entry>Hashes/sec</entry>
<entry>For <literal>[a-z]</></entry>
<entry>For <literal>[A-Za-z0-9]</></entry>
</row>
</thead>
<tbody>
<row>
<entry><literal>crypt-bf/8</></entry>
<entry>28</entry>
<entry>246 years</entry>
<entry>251322 years</entry>
</row>
<row>
<entry><literal>crypt-bf/7</></entry>
<entry>57</entry>
<entry>121 years</entry>
<entry>123457 years</entry>
</row>
<row>
<entry><literal>crypt-bf/6</></entry>
<entry>112</entry>
<entry>62 years</entry>
<entry>62831 years</entry>
</row>
<row>
<entry><literal>crypt-bf/5</></entry>
<entry>211</entry>
<entry>33 years</entry>
<entry>33351 years</entry>
</row>
<row>
<entry><literal>crypt-md5</></entry>
<entry>2681</entry>
<entry>2.6 years</entry>
<entry>2625 years</entry>
</row>
<row>
<entry><literal>crypt-des</></entry>
<entry>362837</entry>
<entry>7 days</entry>
<entry>19 years</entry>
</row>
<row>
<entry><literal>sha1</></entry>
<entry>590223</entry>
<entry>4 days</entry>
<entry>12 years</entry>
</row>
<row>
<entry><literal>md5</></entry>
<entry>2345086</entry>
<entry>1 day</entry>
<entry>3 years</entry>
</row>
</tbody>
</tgroup>
</table>
<para> <para>
Here is a table that should give overview of relative slowness Notes:
of different hashing algorithms.
</para> </para>
<itemizedlist> <itemizedlist>
<listitem> <listitem>
<para> <para>
The goal is to crack a 8-character password, which consists: The machine used is a 1.5GHz Pentium 4.
</para>
<orderedlist>
<listitem><para>Only of lowercase letters</para></listitem>
<listitem><para>Numbers, lower- and uppercase letters.</para></listitem>
</orderedlist>
</listitem>
<listitem>
<para>
The table below shows how much time it would take to try all
combinations of characters.
</para>
</listitem>
<listitem>
<para>
The <literal>crypt-bf</literal> is featured in several settings - the number
after slash is the <literal>rounds</literal> parameter of
<literal>gen_salt()</literal>.
</para>
</listitem>
</itemizedlist>
<programlisting>
`------------'----------'--------------'--------------------
Algorithm Hashes/sec Chars: [a-z] Chars: [A-Za-z0-9]
------------------------------------------------------------
crypt-bf/8 28 246 years 251322 years
crypt-bf/7 57 121 years 123457 years
crypt-bf/6 112 62 years 62831 years
crypt-bf/5 211 33 years 33351 years
crypt-md5 2681 2.6 years 2625 years
crypt-des 362837 7 days 19 years
sha1 590223 4 days 12 years
md5 2345086 1 day 3 years
------------------------------------------------------------
</programlisting>
<itemizedlist>
<listitem>
<para>
The machine used is 1.5GHz Pentium 4.
</para> </para>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
crypt-des and crypt-md5 algorithm numbers are taken from <literal>crypt-des</> and <literal>crypt-md5</> algorithm numbers are
John the Ripper v1.6.38 `-test` output. taken from John the Ripper v1.6.38 <literal>-test</> output.
</para> </para>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
MD5 numbers are from mdcrack 1.2. <literal>md5</> numbers are from mdcrack 1.2.
</para> </para>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
SHA1 numbers are from lcrack-20031130-beta. <literal>sha1</> numbers are from lcrack-20031130-beta.
</para> </para>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
<literal>crypt-bf</literal> numbers are taken using simple program that loops <literal>crypt-bf</literal> numbers are taken using a simple program that
over 1000 8-character passwords. That way I can show the speed with loops over 1000 8-character passwords. That way I can show the speed
different number of rounds. For reference: <literal>john -test</literal> with different numbers of iterations. For reference: <literal>john
shows 213 loops/sec for crypt-bf/5. (The small difference in results is -test</literal> shows 213 loops/sec for <literal>crypt-bf/5</>.
in accordance to the fact that the <literal>crypt-bf</literal> implementation in pgcrypto (The very small
is same one that is used in John the Ripper.) difference in results is in accordance with the fact that the
<literal>crypt-bf</literal> implementation in <filename>pgcrypto</>
is the same one used in John the Ripper.)
</para> </para>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
<para> <para>
Note that "try all combinations" is not a realistic exercise. Note that <quote>try all combinations</quote> is not a realistic exercise.
Usually password cracking is done with the help of dictionaries, which Usually password cracking is done with the help of dictionaries, which
contain both regular words and various mutations of them. So, even contain both regular words and various mutations of them. So, even
somewhat word-like passwords could be cracked much faster than the above somewhat word-like passwords could be cracked much faster than the above
numbers suggest, and a 6-character non-word like password may escape numbers suggest, while a 6-character non-word-like password may escape
cracking. Or not. cracking. Or not.
</para> </para>
</sect3> </sect3>
</sect2> </sect2>
<sect2> <sect2>
<title>PGP encryption</title> <title>PGP encryption functions</title>
<para> <para>
The functions here implement the encryption part of OpenPGP (RFC2440) The functions here implement the encryption part of the OpenPGP (RFC2440)
standard. Supported are both symmetric-key and public-key encryption. standard. Supported are both symmetric-key and public-key encryption.
</para> </para>
<sect3> <para>
<title>Overview</title> An encrypted PGP message consists of 2 parts, or <firstterm>packets</>:
<para> </para>
Encrypted PGP message consists of 2 packets: <itemizedlist>
</para> <listitem>
<itemizedlist> <para>
<listitem><para>Packet for session key - either symmetric- or public-key encrypted.</para></listitem> Packet containing a session key &mdash; either symmetric-key or public-key
<listitem><para>Packet for session-key encrypted data.</para></listitem> encrypted.
</itemizedlist> </para>
<para> </listitem>
When encrypting with password: <listitem>
</para> <para>
<orderedlist> Packet containing data encrypted with the session key.
<listitem> </para>
<para> </listitem>
Given password is hashed using String2Key (S2K) algorithm. This </itemizedlist>
is rather similar to `crypt()` algorithm - purposefully slow
and with random salt - but it produces a full-length binary key.
</para>
</listitem>
<listitem>
<para>
If separate session key is requested, new random key will be
generated. Otherwise S2K key will be used directly as session key.
</para>
</listitem>
<listitem>
<para>
If S2K key is to be used directly, then only S2K settings will be put
into session key packet. Otherwise session key will be encrypted with
S2K key and put into session key packet.
</para>
</listitem>
</orderedlist>
<para>
When encrypting with public key:
</para>
<orderedlist>
<listitem><para>New random session key is generated.</para></listitem>
<listitem><para>It is encrypted using public key and put into session key packet.</para></listitem>
</orderedlist>
<para> <para>
Now common part, the session-key encrypted data packet: When encrypting with a symmetric key (i.e., a password):
</para> </para>
<orderedlist> <orderedlist>
<listitem> <listitem>
<para> <para>
Optional data-manipulation: compression, conversion to UTF-8, The given password is hashed using a String2Key (S2K) algorithm. This is
conversion of line-endings. rather similar to <function>crypt()</> algorithms &mdash; purposefully
</para> slow and with random salt &mdash; but it produces a full-length binary
</listitem> key.
<listitem> </para>
<para> </listitem>
Data is prefixed with block of random bytes. This is equal <listitem>
to using random IV. <para>
</para> If a separate session key is requested, a new random key will be
</listitem> generated. Otherwise the S2K key will be used directly as the session
<listitem> key.
<para> </para>
A SHA1 hash of random prefix and data is appended. </listitem>
</para> <listitem>
</listitem> <para>
<listitem> If the S2K key is to be used directly, then only S2K settings will be put
<para> into the session key packet. Otherwise the session key will be encrypted
All this is encrypted with session key. with the S2K key and put into the session key packet.
</para> </para>
</listitem> </listitem>
</orderedlist> </orderedlist>
</sect3>
<para>
When encrypting with a public key:
</para>
<orderedlist>
<listitem>
<para>
A new random session key is generated.
</para>
</listitem>
<listitem>
<para>
It is encrypted using the public key and put into the session key packet.
</para>
</listitem>
</orderedlist>
<para>
In either case the data to be encrypted is processed as follows:
</para>
<orderedlist>
<listitem>
<para>
Optional data-manipulation: compression, conversion to UTF-8,
and/or conversion of line-endings.
</para>
</listitem>
<listitem>
<para>
The data is prefixed with a block of random bytes. This is equivalent
to using a random IV.
</para>
</listitem>
<listitem>
<para>
An SHA1 hash of the random prefix and data is appended.
</para>
</listitem>
<listitem>
<para>
All this is encrypted with the session key and placed in the data packet.
</para>
</listitem>
</orderedlist>
<sect3> <sect3>
<title><literal>pgp_sym_encrypt(data, psw)</literal></title> <title><function>pgp_sym_encrypt()</function></title>
<programlisting>
pgp_sym_encrypt(data text, psw text [, options text] ) RETURNS bytea <synopsis>
pgp_sym_encrypt_bytea(data bytea, psw text [, options text] ) RETURNS bytea pgp_sym_encrypt(data text, psw text [, options text ]) returns bytea
</programlisting> pgp_sym_encrypt_bytea(data bytea, psw text [, options text ]) returns bytea
<para> </synopsis>
Return a symmetric-key encrypted PGP message.
</para>
<para> <para>
Options are described in section 5.8. Encrypt <parameter>data</> with a symmetric PGP key <parameter>psw</>.
The <parameter>options</> parameter can contain option settings,
as described below.
</para> </para>
</sect3> </sect3>
<sect3> <sect3>
<title><literal>pgp_sym_decrypt(msg, psw)</literal></title> <title><function>pgp_sym_decrypt()</function></title>
<programlisting>
pgp_sym_decrypt(msg bytea, psw text [, options text] ) RETURNS text <synopsis>
pgp_sym_decrypt_bytea(msg bytea, psw text [, options text] ) RETURNS bytea pgp_sym_decrypt(msg bytea, psw text [, options text ]) returns text
</programlisting> pgp_sym_decrypt_bytea(msg bytea, psw text [, options text ]) returns bytea
</synopsis>
<para> <para>
Decrypt a symmetric-key encrypted PGP message. Decrypt a symmetric-key-encrypted PGP message.
</para> </para>
<para> <para>
Decrypting bytea data with `pgp_sym_decrypt` is disallowed. Decrypting bytea data with <function>pgp_sym_decrypt</> is disallowed.
This is to avoid outputting invalid character data. Decrypting This is to avoid outputting invalid character data. Decrypting
originally textual data with `pgp_sym_decrypt_bytea` is fine. originally textual data with <function>pgp_sym_decrypt_bytea</> is fine.
</para> </para>
<para> <para>
Options are described in section 5.8. The <parameter>options</> parameter can contain option settings,
as described below.
</para> </para>
</sect3> </sect3>
<sect3> <sect3>
<title><literal>pgp_pub_encrypt(data, pub_key)</literal></title> <title><function>pgp_pub_encrypt()</function></title>
<programlisting>
pgp_pub_encrypt(data text, key bytea [, options text] ) RETURNS bytea <synopsis>
pgp_pub_encrypt_bytea(data bytea, key bytea [, options text] ) RETURNS bytea pgp_pub_encrypt(data text, key bytea [, options text ]) returns bytea
</programlisting> pgp_pub_encrypt_bytea(data bytea, key bytea [, options text ]) returns bytea
</synopsis>
<para> <para>
Encrypt data with a public key. Giving this function a secret key will Encrypt <parameter>data</> with a public PGP key <parameter>key</>.
produce a error. Giving this function a secret key will produce a error.
</para> </para>
<para> <para>
Options are described in section 5.8. The <parameter>options</> parameter can contain option settings,
as described below.
</para> </para>
</sect3> </sect3>
<sect3> <sect3>
<title><literal>pgp_pub_decrypt(msg, sec_key [, psw])</literal></title> <title><function>pgp_pub_decrypt()</function></title>
<programlisting>
pgp_pub_decrypt(msg bytea, key bytea [, psw text [, options text]] ) RETURNS text <synopsis>
pgp_pub_decrypt_bytea(msg bytea, key bytea [,psw text [, options text]] ) RETURNS bytea pgp_pub_decrypt(msg bytea, key bytea [, psw text [, options text ]]) returns text
</programlisting> pgp_pub_decrypt_bytea(msg bytea, key bytea [, psw text [, options text ]]) returns bytea
</synopsis>
<para> <para>
Decrypt a public-key encrypted message with secret key. If the secret Decrypt a public-key-encrypted message. <parameter>key</> must be the
key is password-protected, you must give the password in `psw`. If secret key corresponding to the public key that was used to encrypt.
there is no password, but you want to specify option for function, you If the secret key is password-protected, you must give the password in
need to give empty password. <parameter>psw</>. If there is no password, but you want to specify
options, you need to give an empty password.
</para> </para>
<para> <para>
Decrypting bytea data with `pgp_pub_decrypt` is disallowed. Decrypting bytea data with <function>pgp_pub_decrypt</> is disallowed.
This is to avoid outputting invalid character data. Decrypting This is to avoid outputting invalid character data. Decrypting
originally textual data with `pgp_pub_decrypt_bytea` is fine. originally textual data with <function>pgp_pub_decrypt_bytea</> is fine.
</para> </para>
<para> <para>
Options are described in section 5.8. The <parameter>options</> parameter can contain option settings,
as described below.
</para> </para>
</sect3> </sect3>
<sect3> <sect3>
<title><literal>pgp_key_id(key / msg)</literal></title> <title><function>pgp_key_id()</function></title>
<programlisting>
pgp_key_id(key or msg bytea) RETURNS text <synopsis>
</programlisting> pgp_key_id(bytea) returns text
</synopsis>
<para> <para>
It shows you either key ID if given PGP public or secret key. Or it <function>pgp_key_id</> extracts the key ID of a PGP public or secret key.
gives the key ID that was used for encrypting the data, if given Or it gives the key ID that was used for encrypting the data, if given
encrypted message. an encrypted message.
</para> </para>
<para> <para>
It can return 2 special key IDs: It can return 2 special key IDs:
...@@ -602,151 +577,163 @@ md5 2345086 1 day 3 years ...@@ -602,151 +577,163 @@ md5 2345086 1 day 3 years
<itemizedlist> <itemizedlist>
<listitem> <listitem>
<para> <para>
SYMKEY: <literal>SYMKEY</>
</para> </para>
<para> <para>
The data is encrypted with symmetric key. The message is encrypted with a symmetric key.
</para> </para>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
ANYKEY: <literal>ANYKEY</>
</para> </para>
<para> <para>
The data is public-key encrypted, but the key ID is cleared. The message is public-key encrypted, but the key ID has been removed.
That means you need to try all your secret keys on it to see That means you will need to try all your secret keys on it to see
which one decrypts it. pgcrypto itself does not produce such which one decrypts it. <filename>pgcrypto</> itself does not produce
messages. such messages.
</para> </para>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
<para> <para>
Note that different keys may have same ID. This is rare but normal Note that different keys may have the same ID. This is rare but a normal
event. Client application should then try to decrypt with each one, event. The client application should then try to decrypt with each one,
to see which fits - like handling ANYKEY. to see which fits &mdash; like handling <literal>ANYKEY</>.
</para> </para>
</sect3> </sect3>
<sect3> <sect3>
<title><literal>armor / dearmor</literal></title> <title><function>armor()</function>, <function>dearmor()</function></title>
<programlisting>
armor(data bytea) RETURNS text <synopsis>
dearmor(data text) RETURNS bytea armor(data bytea) returns text
</programlisting> dearmor(data text) returns bytea
</synopsis>
<para> <para>
Those wrap/unwrap data into PGP Ascii Armor which is basically Base64 These functions wrap/unwrap binary data into PGP Ascii Armor format,
with CRC and additional formatting. which is basically Base64 with CRC and additional formatting.
</para> </para>
</sect3> </sect3>
<sect3> <sect3>
<title>Options for PGP functions</title> <title>Options for PGP functions</title>
<para> <para>
Options are named to be similar to GnuPG. Values should be given after Options are named to be similar to GnuPG. An option's value should be
an equal sign; separate options from each other with commas. Example: given after an equal sign; separate options from each other with commas.
For example:
</para> </para>
<programlisting> <programlisting>
pgp_sym_encrypt(data, psw, 'compress-algo=1, cipher-algo=aes256') pgp_sym_encrypt(data, psw, 'compress-algo=1, cipher-algo=aes256')
</programlisting> </programlisting>
<para> <para>
All of the options except `convert-crlf` apply only to encrypt All of the options except <literal>convert-crlf</literal> apply only to
functions. Decrypt functions get the parameters from PGP data. encrypt functions. Decrypt functions get the parameters from the PGP
data.
</para> </para>
<para> <para>
Most interesting options are probably `compression-algo` and The most interesting options are probably
<literal>unicode-mode</literal>. The rest should have reasonable defaults. <literal>compress-algo</literal> and <literal>unicode-mode</literal>.
The rest should have reasonable defaults.
</para> </para>
</sect3>
<sect3> <sect4>
<title>cipher-algo</title> <title>cipher-algo</title>
<para> <para>
What cipher algorithm to use. Which cipher algorithm to use.
</para> </para>
<programlisting> <programlisting>
Values: bf, aes128, aes192, aes256 (OpenSSL-only: `3des`, `cast5`) Values: bf, aes128, aes192, aes256 (OpenSSL-only: <literal>3des</literal>, <literal>cast5</literal>)
Default: aes128 Default: aes128
Applies: pgp_sym_encrypt, pgp_pub_encrypt Applies to: pgp_sym_encrypt, pgp_pub_encrypt
</programlisting> </programlisting>
</sect3> </sect4>
<sect3> <sect4>
<title>compress-algo</title> <title>compress-algo</title>
<para> <para>
Which compression algorithm to use. Needs building with zlib. Which compression algorithm to use. Only available if
</para> <filename>pgcrypto</> was built with zlib.
<para>
Values:
</para> </para>
<programlisting> <programlisting>
0 - no compression Values:
1 - ZIP compression 0 - no compression
2 - ZLIB compression [=ZIP plus meta-data and block-CRC's] 1 - ZIP compression
2 - ZLIB compression (= ZIP plus meta-data and block CRCs)
Default: 0 Default: 0
Applies: pgp_sym_encrypt, pgp_pub_encrypt Applies to: pgp_sym_encrypt, pgp_pub_encrypt
</programlisting> </programlisting>
</sect3> </sect4>
<sect3> <sect4>
<title>compress-level</title> <title>compress-level</title>
<para> <para>
How much to compress. Bigger level compresses smaller but is slower. How much to compress. Higher levels compress smaller but are slower.
0 disables compression. 0 disables compression.
</para> </para>
<programlisting> <programlisting>
Values: 0, 1-9 Values: 0, 1-9
Default: 6 Default: 6
Applies: pgp_sym_encrypt, pgp_pub_encrypt Applies to: pgp_sym_encrypt, pgp_pub_encrypt
</programlisting> </programlisting>
</sect3> </sect4>
<sect3> <sect4>
<title>convert-crlf</title> <title>convert-crlf</title>
<para> <para>
Whether to convert `\n` into `\r\n` when encrypting and `\r\n` to `\n` Whether to convert <literal>\n</literal> into <literal>\r\n</literal> when
when decrypting. RFC2440 specifies that text data should be stored encrypting and <literal>\r\n</literal> to <literal>\n</literal> when
using `\r\n` line-feeds. Use this to get fully RFC-compliant decrypting. RFC2440 specifies that text data should be stored using
<literal>\r\n</literal> line-feeds. Use this to get fully RFC-compliant
behavior. behavior.
</para> </para>
<programlisting> <programlisting>
Values: 0, 1 Values: 0, 1
Default: 0 Default: 0
Applies: pgp_sym_encrypt, pgp_pub_encrypt, pgp_sym_decrypt, pgp_pub_decrypt Applies to: pgp_sym_encrypt, pgp_pub_encrypt, pgp_sym_decrypt, pgp_pub_decrypt
</programlisting> </programlisting>
</sect3> </sect4>
<sect3> <sect4>
<title>disable-mdc</title> <title>disable-mdc</title>
<para> <para>
Do not protect data with SHA-1. Only good reason to use this Do not protect data with SHA-1. The only good reason to use this
option is to achieve compatibility with ancient PGP products, as the option is to achieve compatibility with ancient PGP products, predating
SHA-1 protected packet is from upcoming update to RFC2440. (Currently the addition of SHA-1 protected packets to RFC2440.
at version RFC2440bis-14.) Recent gnupg.org and pgp.com software Recent gnupg.org and pgp.com software supports it fine.
supports it fine.
</para> </para>
<programlisting> <programlisting>
Values: 0, 1 Values: 0, 1
Default: 0 Default: 0
Applies: pgp_sym_encrypt, pgp_pub_encrypt Applies to: pgp_sym_encrypt, pgp_pub_encrypt
</programlisting> </programlisting>
</sect3> </sect4>
<sect3> <sect4>
<title>enable-session-key</title> <title>enable-session-key</title>
<para> <para>
Use separate session key. Public-key encryption always uses separate Use separate session key. Public-key encryption always uses a separate
session key, this is for symmetric-key encryption, which by default session key; this is for symmetric-key encryption, which by default
uses S2K directly. uses the S2K key directly.
</para> </para>
<programlisting> <programlisting>
Values: 0, 1 Values: 0, 1
Default: 0 Default: 0
Applies: pgp_sym_encrypt Applies to: pgp_sym_encrypt
</programlisting> </programlisting>
</sect3> </sect4>
<sect3> <sect4>
<title>s2k-mode</title> <title>s2k-mode</title>
<para> <para>
Which S2K algorithm to use. Which S2K algorithm to use.
</para> </para>
...@@ -756,126 +743,134 @@ md5 2345086 1 day 3 years ...@@ -756,126 +743,134 @@ md5 2345086 1 day 3 years
1 - With salt but with fixed iteration count. 1 - With salt but with fixed iteration count.
3 - Variable iteration count. 3 - Variable iteration count.
Default: 3 Default: 3
Applies: pgp_sym_encrypt Applies to: pgp_sym_encrypt
</programlisting> </programlisting>
</sect3> </sect4>
<sect3> <sect4>
<title>s2k-digest-algo</title> <title>s2k-digest-algo</title>
<para> <para>
Which digest algorithm to use in S2K calculation. Which digest algorithm to use in S2K calculation.
</para> </para>
<programlisting> <programlisting>
Values: md5, sha1 Values: md5, sha1
Default: sha1 Default: sha1
Applies: pgp_sym_encrypt Applies to: pgp_sym_encrypt
</programlisting> </programlisting>
</sect3> </sect4>
<sect3> <sect4>
<title>s2k-cipher-algo</title> <title>s2k-cipher-algo</title>
<para> <para>
Which cipher to use for encrypting separate session key. Which cipher to use for encrypting separate session key.
</para> </para>
<programlisting> <programlisting>
Values: bf, aes, aes128, aes192, aes256 Values: bf, aes, aes128, aes192, aes256
Default: use cipher-algo. Default: use cipher-algo
Applies: pgp_sym_encrypt Applies to: pgp_sym_encrypt
</programlisting> </programlisting>
</sect3> </sect4>
<sect3> <sect4>
<title>unicode-mode</title> <title>unicode-mode</title>
<para> <para>
Whether to convert textual data from database internal encoding to Whether to convert textual data from database internal encoding to
UTF-8 and back. If your database already is UTF-8, no conversion will UTF-8 and back. If your database already is UTF-8, no conversion will
be done, only the data will be tagged as UTF-8. Without this option be done, but the message will be tagged as UTF-8. Without this option
it will not be. it will not be.
</para> </para>
<programlisting> <programlisting>
Values: 0, 1 Values: 0, 1
Default: 0 Default: 0
Applies: pgp_sym_encrypt, pgp_pub_encrypt Applies to: pgp_sym_encrypt, pgp_pub_encrypt
</programlisting> </programlisting>
</sect4>
</sect3> </sect3>
</sect2>
<sect2> <sect3>
<title>Generating keys with GnuPG</title> <title>Generating PGP keys with GnuPG</title>
<para> <para>
Generate a new key: To generate a new key:
</para> </para>
<programlisting> <programlisting>
gpg --gen-key gpg --gen-key
</programlisting> </programlisting>
<para> <para>
The preferred key type is "DSA and Elgamal". The preferred key type is <quote>DSA and Elgamal</>.
</para> </para>
<para> <para>
For RSA encryption you must create either DSA or RSA sign-only key For RSA encryption you must create either DSA or RSA sign-only key
as master and then add RSA encryption subkey with `gpg --edit-key`. as master and then add an RSA encryption subkey with
<literal>gpg --edit-key</literal>.
</para> </para>
<para> <para>
List keys: To list keys:
</para> </para>
<programlisting> <programlisting>
gpg --list-secret-keys gpg --list-secret-keys
</programlisting> </programlisting>
<para> <para>
Export ascii-armored public key: To export a public key in ascii-armor format:
</para> </para>
<programlisting> <programlisting>
gpg -a --export KEYID > public.key gpg -a --export KEYID > public.key
</programlisting> </programlisting>
<para> <para>
Export ascii-armored secret key: To export a secret key in ascii-armor format:
</para> </para>
<programlisting> <programlisting>
gpg -a --export-secret-keys KEYID > secret.key gpg -a --export-secret-keys KEYID > secret.key
</programlisting> </programlisting>
<para> <para>
You need to use `dearmor()` on them before giving them to You need to use <function>dearmor()</> on these keys before giving them to
pgp_pub_* functions. Or if you can handle binary data, you can drop the PGP functions. Or if you can handle binary data, you can drop
"-a" from gpg. <literal>-a</literal> from the command.
</para> </para>
<para> <para>
For more details see `man gpg`, For more details see <literal>man gpg</literal>,
<ulink url="http://www.gnupg.org/gph/en/manual.html"></ulink>[The GNU <ulink url="http://www.gnupg.org/gph/en/manual.html">The GNU
Privacy Handbook] and other docs on Privacy Handbook</ulink> and other documentation on
<ulink url="http://www.gnupg.org"></ulink> site. <ulink url="http://www.gnupg.org"></ulink>.
</para> </para>
</sect2> </sect3>
<sect2> <sect3>
<title>Limitations of PGP code</title> <title>Limitations of PGP code</title>
<itemizedlist> <itemizedlist>
<listitem> <listitem>
<para> <para>
No support for signing. That also means that it is not checked No support for signing. That also means that it is not checked
whether the encryption subkey belongs to master key. whether the encryption subkey belongs to the master key.
</para> </para>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
No support for encryption key as master key. As such practice No support for encryption key as master key. As such practice
is generally discouraged, it should not be a problem. is generally discouraged, this should not be a problem.
</para> </para>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
No support for several subkeys. This may seem like a problem, as this No support for several subkeys. This may seem like a problem, as this
is common practice. On the other hand, you should not use your regular is common practice. On the other hand, you should not use your regular
GPG/PGP keys with pgcrypto, but create new ones, as the usage scenario GPG/PGP keys with <filename>pgcrypto</>, but create new ones,
is rather different. as the usage scenario is rather different.
</para> </para>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
</sect3>
</sect2> </sect2>
<sect2> <sect2>
<title>Raw encryption</title> <title>Raw encryption functions</title>
<para> <para>
Those functions only run a cipher over data, they don't have any advanced These functions only run a cipher over data; they don't have any advanced
features of PGP encryption. Therefore they have some major problems: features of PGP encryption. Therefore they have some major problems:
</para> </para>
<orderedlist> <orderedlist>
...@@ -906,117 +901,266 @@ md5 2345086 1 day 3 years ...@@ -906,117 +901,266 @@ md5 2345086 1 day 3 years
So, with the introduction of PGP encryption, usage of raw So, with the introduction of PGP encryption, usage of raw
encryption functions is discouraged. encryption functions is discouraged.
</para> </para>
<programlisting>
encrypt(data bytea, key bytea, type text) RETURNS bytea
decrypt(data bytea, key bytea, type text) RETURNS bytea
encrypt_iv(data bytea, key bytea, iv bytea, type text) RETURNS bytea <synopsis>
decrypt_iv(data bytea, key bytea, iv bytea, type text) RETURNS bytea encrypt(data bytea, key bytea, type text) returns bytea
</programlisting> decrypt(data bytea, key bytea, type text) returns bytea
<para>
Encrypt/decrypt data with cipher, padding data if needed. encrypt_iv(data bytea, key bytea, iv bytea, type text) returns bytea
</para> decrypt_iv(data bytea, key bytea, iv bytea, type text) returns bytea
</synopsis>
<para> <para>
<literal>type</literal> parameter description in pseudo-noteup: Encrypt/decrypt data using the cipher method specified by
<parameter>type</parameter>. The syntax of the
<parameter>type</parameter> string is:
</para> </para>
<programlisting>
algo ['-' mode] ['/pad:' padding] <synopsis>
</programlisting> <replaceable>algorithm</> <optional> <literal>-</> <replaceable>mode</> </optional> <optional> <literal>/pad:</> <replaceable>padding</> </optional>
</synopsis>
<para> <para>
Supported algorithms: where <replaceable>algorithm</> is one of:
</para> </para>
<itemizedlist> <itemizedlist>
<listitem><para><literal>bf</literal>- Blowfish</para></listitem> <listitem><para><literal>bf</literal> &mdash; Blowfish</para></listitem>
<listitem><para><literal>aes</literal>- AES (Rijndael-128)</para></listitem> <listitem><para><literal>aes</literal> &mdash; AES (Rijndael-128)</para></listitem>
</itemizedlist> </itemizedlist>
<para> <para>
Modes: and <replaceable>mode</> is one of:
</para> </para>
<itemizedlist> <itemizedlist>
<listitem> <listitem>
<para> <para>
<literal>cbc</literal>- next block depends on previous. (default) <literal>cbc</literal> &mdash; next block depends on previous (default)
</para> </para>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
<literal>ecb</literal>- each block is encrypted separately. (for testing <literal>ecb</literal> &mdash; each block is encrypted separately (for
only) testing only)
</para> </para>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
<para> <para>
Padding: and <replaceable>padding</> is one of:
</para> </para>
<itemizedlist> <itemizedlist>
<listitem> <listitem>
<para> <para>
<literal>pkcs</literal>-data may be any length (default) <literal>pkcs</literal> &mdash; data may be any length (default)
</para> </para>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
<literal>none</literal>- data must be multiple of cipher block size. <literal>none</literal> &mdash; data must be multiple of cipher block size
</para> </para>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
<para> <para>
IV is initial value for mode, defaults to all zeroes. It is ignored for So, for example, these are equivalent:
ECB. It is clipped or padded with zeroes if not exactly block size.
</para>
<para>
So, example:
</para> </para>
<programlisting> <programlisting>
encrypt(data, 'fooz', 'bf') encrypt(data, 'fooz', 'bf')
encrypt(data, 'fooz', 'bf-cbc/pad:pkcs')
</programlisting> </programlisting>
<para> <para>
is equal to In <function>encrypt_iv</> and <function>decrypt_iv</>, the
<parameter>iv</> parameter is the initial value for the CBC mode;
it is ignored for ECB.
It is clipped or padded with zeroes if not exactly block size.
It defaults to all zeroes in the functions without this parameter.
</para> </para>
<programlisting>
encrypt(data, 'fooz', 'bf-cbc/pad:pkcs')
</programlisting>
</sect2> </sect2>
<sect2> <sect2>
<title>Random bytes</title> <title>Random-data functions</title>
<programlisting>
gen_random_bytes(count integer) <synopsis>
</programlisting> gen_random_bytes(count integer) returns bytea
</synopsis>
<para> <para>
Returns `count` cryptographically strong random bytes as bytea value. Returns <parameter>count</> cryptographically strong random bytes.
There can be maximally 1024 bytes extracted at a time. This is to avoid At most 1024 bytes can be extracted at a time. This is to avoid
draining the randomness generator pool. draining the randomness generator pool.
</para> </para>
</sect2> </sect2>
<sect2> <sect2>
<title>References/Links</title> <title>Notes</title>
<sect3>
<title>Configuration</title>
<para>
<filename>pgcrypto</> configures itself according to the findings of the
main PostgreSQL <literal>configure</literal> script. The options that
affect it are <literal>--with-zlib</literal> and
<literal>--with-openssl</literal>.
</para>
<para>
When compiled with zlib, PGP encryption functions are able to
compress data before encrypting.
</para>
<para>
When compiled with OpenSSL, there will be more algorithms available.
Also public-key encryption functions will be faster as OpenSSL
has more optimized BIGNUM functions.
</para>
<table id="pgcrypto-with-without-openssl">
<title>Summary of functionality with and without OpenSSL</title>
<tgroup cols="3">
<thead>
<row>
<entry>Functionality</entry>
<entry>Built-in</entry>
<entry>With OpenSSL</entry>
</row>
</thead>
<tbody>
<row>
<entry>MD5</entry>
<entry>yes</entry>
<entry>yes</entry>
</row>
<row>
<entry>SHA1</entry>
<entry>yes</entry>
<entry>yes</entry>
</row>
<row>
<entry>SHA224/256/384/512</entry>
<entry>yes</entry>
<entry>yes (Note 1)</entry>
</row>
<row>
<entry>Other digest algorithms</entry>
<entry>no</entry>
<entry>yes (Note 2)</entry>
</row>
<row>
<entry>Blowfish</entry>
<entry>yes</entry>
<entry>yes</entry>
</row>
<row>
<entry>AES</entry>
<entry>yes</entry>
<entry>yes (Note 3)</entry>
</row>
<row>
<entry>DES/3DES/CAST5</entry>
<entry>no</entry>
<entry>yes</entry>
</row>
<row>
<entry>Raw encryption</entry>
<entry>yes</entry>
<entry>yes</entry>
</row>
<row>
<entry>PGP Symmetric encryption</entry>
<entry>yes</entry>
<entry>yes</entry>
</row>
<row>
<entry>PGP Public-Key encryption</entry>
<entry>yes</entry>
<entry>yes</entry>
</row>
</tbody>
</tgroup>
</table>
<para>
Notes:
</para>
<orderedlist>
<listitem>
<para>
SHA2 algorithms were added to OpenSSL in version 0.9.8. For
older versions, <filename>pgcrypto</> will use built-in code.
</para>
</listitem>
<listitem>
<para>
Any digest algorithm OpenSSL supports is automatically picked up.
This is not possible with ciphers, which need to be supported
explicitly.
</para>
</listitem>
<listitem>
<para>
AES is included in OpenSSL since version 0.9.7. For
older versions, <filename>pgcrypto</> will use built-in code.
</para>
</listitem>
</orderedlist>
</sect3>
<sect3>
<title>NULL handling</title>
<para>
As is standard in SQL, all functions return NULL, if any of the arguments
are NULL. This may create security risks on careless usage.
</para>
</sect3>
<sect3>
<title>Security limitations</title>
<para>
All <filename>pgcrypto</> functions run inside the database server.
That means that all
the data and passwords move between <filename>pgcrypto</> and client
applications in clear text. Thus you must:
</para>
<orderedlist>
<listitem>
<para>Connect locally or use SSL connections.</para>
</listitem>
<listitem>
<para>Trust both system and database administrator.</para>
</listitem>
</orderedlist>
<para>
If you cannot, then better do crypto inside client application.
</para>
</sect3>
<sect3> <sect3>
<title>Useful reading</title> <title>Useful reading</title>
<itemizedlist> <itemizedlist>
<listitem> <listitem>
<para><ulink url="http://www.gnupg.org/gph/en/manual.html"></ulink>:</para> <para><ulink url="http://www.gnupg.org/gph/en/manual.html"></ulink></para>
<para>The GNU Privacy Handbook</para> <para>The GNU Privacy Handbook.</para>
</listitem> </listitem>
<listitem> <listitem>
<para><ulink url="http://www.openwall.com/crypt/"></ulink>:</para> <para><ulink url="http://www.openwall.com/crypt/"></ulink></para>
<para>Describes the crypt-blowfish algorithm.</para> <para>Describes the crypt-blowfish algorithm.</para>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
<ulink url="http://www.stack.nl/~galactus/remailers/passphrase-faq.html"></ulink>: <ulink url="http://www.stack.nl/~galactus/remailers/passphrase-faq.html"></ulink>
</para> </para>
<para>How to choose good password.</para> <para>How to choose a good password.</para>
</listitem> </listitem>
<listitem> <listitem>
<para><ulink url="http://world.std.com/~reinhold/diceware.html"></ulink>:</para> <para><ulink url="http://world.std.com/~reinhold/diceware.html"></ulink></para>
<para>Interesting idea for picking passwords.</para> <para>Interesting idea for picking passwords.</para>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
<ulink url="http://www.interhack.net/people/cmcurtin/snake-oil-faq.html"></ulink>: <ulink url="http://www.interhack.net/people/cmcurtin/snake-oil-faq.html"></ulink>
</para> </para>
<para>Describes good and bad cryptography.</para> <para>Describes good and bad cryptography.</para>
</listitem> </listitem>
...@@ -1025,47 +1169,48 @@ md5 2345086 1 day 3 years ...@@ -1025,47 +1169,48 @@ md5 2345086 1 day 3 years
<sect3> <sect3>
<title>Technical references</title> <title>Technical references</title>
<itemizedlist> <itemizedlist>
<listitem> <listitem>
<para><ulink url="http://www.ietf.org/rfc/rfc2440.txt"></ulink>:</para> <para><ulink url="http://www.ietf.org/rfc/rfc2440.txt"></ulink></para>
<para>OpenPGP message format</para> <para>OpenPGP message format.</para>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
<ulink url="http://www.imc.org/draft-ietf-openpgp-rfc2440bis"></ulink>: <ulink url="http://www.imc.org/draft-ietf-openpgp-rfc2440bis"></ulink>
</para> </para>
<para>New version of RFC2440.</para> <para>New version of RFC2440.</para>
</listitem> </listitem>
<listitem> <listitem>
<para><ulink url="http://www.ietf.org/rfc/rfc1321.txt"></ulink>:</para> <para><ulink url="http://www.ietf.org/rfc/rfc1321.txt"></ulink></para>
<para>The MD5 Message-Digest Algorithm</para> <para>The MD5 Message-Digest Algorithm.</para>
</listitem> </listitem>
<listitem> <listitem>
<para><ulink url="http://www.ietf.org/rfc/rfc2104.txt"></ulink>:</para> <para><ulink url="http://www.ietf.org/rfc/rfc2104.txt"></ulink></para>
<para>HMAC: Keyed-Hashing for Message Authentication</para> <para>HMAC: Keyed-Hashing for Message Authentication.</para>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
<ulink url="http://www.usenix.org/events/usenix99/provos.html"></ulink>: <ulink url="http://www.usenix.org/events/usenix99/provos.html"></ulink>
</para> </para>
<para>Comparison of crypt-des, crypt-md5 and bcrypt algorithms.</para> <para>Comparison of crypt-des, crypt-md5 and bcrypt algorithms.</para>
</listitem> </listitem>
<listitem> <listitem>
<para><ulink url="http://csrc.nist.gov/cryptval/des.htm"></ulink>:</para> <para><ulink url="http://csrc.nist.gov/cryptval/des.htm"></ulink></para>
<para>Standards for DES, 3DES and AES.</para> <para>Standards for DES, 3DES and AES.</para>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
<ulink url="http://en.wikipedia.org/wiki/Fortuna_(PRNG)"></ulink>: <ulink url="http://en.wikipedia.org/wiki/Fortuna_(PRNG)"></ulink>
</para> </para>
<para>Description of Fortuna CSPRNG.</para> <para>Description of Fortuna CSPRNG.</para>
</listitem> </listitem>
<listitem> <listitem>
<para><ulink url="http://jlcooke.ca/random/"></ulink>:</para> <para><ulink url="http://jlcooke.ca/random/"></ulink></para>
<para>Jean-Luc Cooke Fortuna-based /dev/random driver for Linux.</para> <para>Jean-Luc Cooke Fortuna-based /dev/random driver for Linux.</para>
</listitem> </listitem>
<listitem> <listitem>
<para><ulink url="http://www.cs.ut.ee/~helger/crypto/"></ulink>:</para> <para><ulink url="http://www.cs.ut.ee/~helger/crypto/"></ulink></para>
<para>Collection of cryptology pointers.</para> <para>Collection of cryptology pointers.</para>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
...@@ -1073,72 +1218,70 @@ md5 2345086 1 day 3 years ...@@ -1073,72 +1218,70 @@ md5 2345086 1 day 3 years
</sect2> </sect2>
<sect2> <sect2>
<title>Credits</title> <title>Author</title>
<para>
Marko Kreen <email>markokr@gmail.com</email>
</para>
<para> <para>
<literal>pgcrypto</literal> uses code from the following sources: <filename>pgcrypto</filename> uses code from the following sources:
</para> </para>
<table> <table>
<title>Credits</title> <title>Credits</title>
<tgroup cols="3"> <tgroup cols="3">
<thead> <thead>
<row> <row>
<entry><para>Algorithm</para></entry> <entry>Algorithm</entry>
<entry><para>Author</para></entry> <entry>Author</entry>
<entry><para>Source origin</para></entry> <entry>Source origin</entry>
</row> </row>
</thead> </thead>
<tbody> <tbody>
<row> <row>
<entry><para>DES crypt()</para></entry> <entry>DES crypt</entry>
<entry><para>David Burren and others</para></entry> <entry>David Burren and others</entry>
<entry><para>FreeBSD libcrypt</para></entry> <entry>FreeBSD libcrypt</entry>
</row> </row>
<row> <row>
<entry><para>MD5 crypt()</para></entry> <entry>MD5 crypt</entry>
<entry><para>Poul-Henning Kamp</para></entry> <entry>Poul-Henning Kamp</entry>
<entry><para>FreeBSD libcrypt</para></entry> <entry>FreeBSD libcrypt</entry>
</row> </row>
<row> <row>
<entry><para>Blowfish crypt()</para></entry> <entry>Blowfish crypt</entry>
<entry><para>Solar Designer</para></entry> <entry>Solar Designer</entry>
<entry><para>www.openwall.com</para></entry> <entry>www.openwall.com</entry>
</row> </row>
<row> <row>
<entry><para>Blowfish cipher</para></entry> <entry>Blowfish cipher</entry>
<entry><para>Simon Tatham</para></entry> <entry>Simon Tatham</entry>
<entry><para>PuTTY</para></entry> <entry>PuTTY</entry>
</row> </row>
<row> <row>
<entry><para>Rijndael cipher</para></entry> <entry>Rijndael cipher</entry>
<entry><para>Brian Gladman</para></entry> <entry>Brian Gladman</entry>
<entry><para>OpenBSD sys/crypto</para></entry> <entry>OpenBSD sys/crypto</entry>
</row> </row>
<row> <row>
<entry><para>MD5 and SHA1</para></entry> <entry>MD5 and SHA1</entry>
<entry><para>WIDE Project</para></entry> <entry>WIDE Project</entry>
<entry><para>KAME kame/sys/crypto</para></entry> <entry>KAME kame/sys/crypto</entry>
</row> </row>
<row> <row>
<entry><para>SHA256/384/512 </para></entry> <entry>SHA256/384/512 </entry>
<entry><para>Aaron D. Gifford</para></entry> <entry>Aaron D. Gifford</entry>
<entry><para>OpenBSD sys/crypto</para></entry> <entry>OpenBSD sys/crypto</entry>
</row> </row>
<row> <row>
<entry><para>BIGNUM math</para></entry> <entry>BIGNUM math</entry>
<entry><para>Michael J. Fromberger</para></entry> <entry>Michael J. Fromberger</entry>
<entry><para>dartmouth.edu/~sting/sw/imath</para></entry> <entry>dartmouth.edu/~sting/sw/imath</entry>
</row> </row>
</tbody> </tbody>
</tgroup> </tgroup>
</table> </table>
</sect2> </sect2>
<sect2>
<title>Author</title>
<para>
Marko Kreen <email>markokr@gmail.com</email>
</para>
</sect2>
</sect1> </sect1>
<!-- $PostgreSQL: pgsql/doc/src/sgml/pgstandby.sgml,v 2.4 2007/12/16 23:00:42 tgl Exp $ -->
<sect1 id="pgstandby"> <sect1 id="pgstandby">
<title>pg_standby</title> <title>pg_standby</title>
<indexterm zone="pgstandby"> <indexterm zone="pgstandby">
<primary>pg_standby</primary> <primary>pg_standby</primary>
</indexterm> </indexterm>
<para> <para>
<literal>pg_standby</literal> allows the creation of a Warm Standby server. <application>pg_standby</> supports creation of a <quote>warm standby</>
Other configuration is required as well, all of which is described in the database server. It is designed to be a production-ready program, as well
main server manual. as a customizable template should you require specific modifications.
</para>
<para>
The program is designed to be a wait-for <literal>restore_command</literal>,
required to turn a normal archive recovery into a Warm Standby. Within the
<literal>restore_command</literal> of the <literal>recovery.conf</literal>
you could configure <literal>pg_standby</literal> in the following way:
</para> </para>
<programlisting>
restore_command = 'pg_standby archiveDir %f %p %r'
</programlisting>
<para> <para>
which would be sufficient to define that files will be restored from <application>pg_standby</> is designed to be a waiting
archiveDir. <literal>restore_command</literal>, which is needed to turn a standard
archive recovery into a warm standby operation. Other
configuration is required as well, all of which is described in the main
server manual (see <xref linkend="warm-standby">).
</para> </para>
<para> <para>
<literal>pg_standby</literal> features include: <application>pg_standby</application> features include:
</para> </para>
<itemizedlist> <itemizedlist>
<listitem> <listitem>
<para> <para>
It is written in C. So it is very portable Supports copy or link for restoring WAL files
and easy to install.
</para> </para>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
Supports copy or link from a directory (only) Written in C, so very portable and easy to install
</para> </para>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
Source easy to modify, with specifically designated Easy-to-modify source code, with specifically designated
sections to modify for your own needs, allowing sections to modify for your own needs
interfaces to be written for additional Backup Archive Restore
(BAR) systems
</para> </para>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
Already tested on Linux and Windows Already tested on Linux and Windows
</para> </para>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
<sect2> <sect2>
<title>Usage</title> <title>Usage</title>
<para> <para>
<literal>pg_standby</literal> should be used within the To configure a standby
<literal>restore_command</literal> of the <literal>recovery.conf</literal> server to use <application>pg_standby</>, put this into its
file. <filename>recovery.conf</filename> configuration file:
</para>
<para>
The basic usage should be like this:
</para> </para>
<programlisting> <programlisting>
restore_command = 'pg_standby archiveDir %f %p' restore_command = 'pg_standby <replaceable>archiveDir</> %f %p %r'
</programlisting> </programlisting>
<para> <para>
with the pg_standby command usage as where <replaceable>archiveDir</> is the directory from which WAL segment
files should be restored.
</para> </para>
<programlisting>
pg_standby [OPTION]... ARCHIVELOCATION NEXTWALFILE XLOGFILEPATH [RESTARTWALFILE]
</programlisting>
<para> <para>
When used within the <literal>restore_command</literal> the %f and %p macros The full syntax of <application>pg_standby</>'s command line is
will provide the actual file and path required for the restore/recovery. </para>
<synopsis>
pg_standby <optional> <replaceable>option</> ... </optional> <replaceable>archivelocation</> <replaceable>nextwalfile</> <replaceable>xlogfilepath</> <optional> <replaceable>restartwalfile</> </optional>
</synopsis>
<para>
When used within <literal>restore_command</literal>, the <literal>%f</> and
<literal>%p</> macros should be specified for <replaceable>nextwalfile</>
and <replaceable>xlogfilepath</> respectively, to provide the actual file
and path required for the restore.
</para> </para>
<para> <para>
<literal>pg_standby</literal> assumes that <literal>ARCHIVELOCATION</literal> If <replaceable>restartwalfile</> is specified, normally by using the
is a directory accessible by the server-owning user. <literal>%r</literal> macro, then all WAL files logically preceding this
file will be removed from <replaceable>archivelocation</>. This minimizes
the number of files that need to be retained, while preserving
crash-restart capability. Use of this parameter is appropriate if the
<replaceable>archivelocation</> is a transient staging area for this
particular standby server, but <emphasis>not</> when the
<replaceable>archivelocation</> is intended as a long-term WAL archive area.
</para> </para>
<para> <para>
If <literal>RESTARTWALFILE</literal> is specified, typically by using the <application>pg_standby</application> assumes that
<literal>%r</literal> option, then all files prior to this file will be <replaceable>archivelocation</> is a directory readable by the
removed from <literal>ARCHIVELOCATION</literal>. This then minimises the server-owning user. If <replaceable>restartwalfile</> (or <literal>-k</>)
number of files that need to be held, whilst at the same time maintaining is specified,
restart capability. This capability additionally assumes that the <replaceable>archivelocation</> directory must be writable too.
<literal>ARCHIVELOCATION</literal> directory is writable.
</para> </para>
<table> <table>
<title>Options</title> <title><application>pg_standby</> options</title>
<tgroup cols="2"> <tgroup cols="3">
<thead>
<row>
<entry>Option</entry>
<entry>Default</entry>
<entry>Description</entry>
</row>
</thead>
<tbody> <tbody>
<row> <row>
<entry>-c</entry> <entry><literal>-c</></entry>
<entry> use copy/cp command to restore WAL files from archive</entry> <entry>yes</entry>
<entry>
Use <literal>cp</> or <literal>copy</> command to restore WAL files
from archive.
</entry>
</row> </row>
<row> <row>
<entry>-d</entry> <entry><literal>-d</></entry>
<entry>debug/logging option.</entry> <entry>no</entry>
<entry>Print lots of debug logging output on <filename>stderr</>.</entry>
</row> </row>
<row> <row>
<entry>-k numfiles</entry> <entry><literal>-k</> <replaceable>numfiles</></entry>
<entry>0</entry>
<entry> <entry>
<para> Remove files from <replaceable>archivelocation</replaceable> so that
Cleanup files in the archive so that we maintain no more than this no more than this many WAL files before the current one are kept in the
many files in the archive. This parameter will be silently ignored if archive. Zero (the default) means not to remove any files from
<literal>RESTARTWALFILE</literal> is specified, since that <replaceable>archivelocation</replaceable>.
specification method is more accurate in determining the correct This parameter will be silently ignored if
cut-off point in archive. <replaceable>restartwalfile</replaceable> is specified, since that
</para> specification method is more accurate in determining the correct
<para> archive cut-off point.
You should be wary against setting this number too low, Use of this parameter is <emphasis>deprecated</> as of
since this may mean you cannot restart the standby. This <productname>PostgreSQL</> 8.3; it is safer and more efficient to
is because the last restartpoint marked in the WAL files specify a <replaceable>restartwalfile</replaceable> parameter. A too
may be many files in the past and can vary considerably. small setting could result in removal of files that are still needed
This should be set to a value exceeding the number of WAL for a restart of the standby server, while a too large setting wastes
files that can be recovered in 2*checkpoint_timeout seconds, archive space.
according to the value in the warm standby postgresql.conf.
It is wholly unrelated to the setting of checkpoint_segments
on either primary or standby.
</para>
<para>
Setting <literal>numfiles</literal> to be zero will disable deletion
of files from <literal>ARCHIVELOCATION</literal>.
</para>
<para>
If in doubt, use a large value or do not set a value at all.
</para>
<para>
If you specify neither <literal>RESTARTWALFILE</> nor <literal>-k</>,
then <literal>-k 0</> will be assumed, i.e. keep all files in archive.
</para>
</entry> </entry>
</row> </row>
<row> <row>
<entry>-l</entry> <entry><literal>-l</></entry>
<entry>no</entry>
<entry> <entry>
<para> Use <literal>ln</> command to restore WAL files from archive.
use ln command to restore WAL files from archive Link is more efficient than copy, but the default is copy since link
WAL files will remain in archive will not work in all scenarios.
</para> On Windows, this option uses the <literal>mklink</> command
<para> to provide a file-to-file symbolic link. <literal>-l</> will
Link is more efficient, but the default is copy to allow you to not work on versions of Windows prior to Vista.
maintain the WAL archive for recovery purposes as well as
high-availability. The default setting is not necessarily recommended,
consult the main database server manual for discussion.
</para>
<para>
This option uses the Windows Vista command mklink
to provide a file-to-file symbolic link. -l will
not work on versions of Windows prior to Vista.
Use the -c option instead.
see <ulink url="http://en.wikipedia.org/wiki/NTFS_symbolic_link"></ulink>
</para>
</entry> </entry>
</row> </row>
<row> <row>
<entry>-r maxretries</entry> <entry><literal>-r</> <replaceable>maxretries</></entry>
<entry>3</entry>
<entry> <entry>
<para> Set the maximum number of times to retry the copy or link command if it
the maximum number of times to retry the restore command if it fails. After each failure, we wait for <replaceable>sleeptime</> *
fails. After each failure, we wait for sleeptime * num_retries <replaceable>num_retries</>
so that the wait time increases progressively, so by default so that the wait time increases progressively. So by default,
we will wait 5 secs, 10 secs then 15 secs before reporting we will wait 5 secs, 10 secs, then 15 secs before reporting
the failure back to the database server. This will be the failure back to the standby server. This will be
interpreted as and end of recovery and the Standby will come interpreted as end of recovery and the standby will come
up fully as a result. <literal>Default=3 Min=0</literal> up fully as a result.
</para>
</entry> </entry>
</row> </row>
<row> <row>
<entry>-s sleeptime</entry> <entry><literal>-s</> <replaceable>sleeptime</></entry>
<entry>5</entry>
<entry> <entry>
the number of seconds to sleep between testing to see Set the number of seconds (up to 60) to sleep between tests to see
if the file to be restored is available in the archive yet. if the WAL file to be restored is available in the archive yet.
The default setting is not necessarily recommended, The default setting is not necessarily recommended;
consult the main database server manual for discussion. consult <xref linkend="warm-standby"> for discussion.
<literal>Default=5, Min=1, Max=60</literal>
</entry> </entry>
</row> </row>
<row> <row>
<entry>-t triggerfile</entry> <entry><literal>-t</> <replaceable>triggerfile</></entry>
<entry>none</entry>
<entry> <entry>
the presence of the triggerfile will cause recovery to end Specify a trigger file whose presence should cause recovery to end
whether or not the next file is available whether or not the next WAL file is available.
It is recommended that you use a structured filename to It is recommended that you use a structured filename to
avoid confusion as to which server is being triggered avoid confusion as to which server is being triggered
when multiple servers exist on same system. when multiple servers exist on the same system; for example
e.g. /tmp/pgsql.trigger.5432 <filename>/tmp/pgsql.trigger.5432</>.
</entry> </entry>
</row> </row>
<row> <row>
<entry>-w maxwaittime</entry> <entry><literal>-w</> <replaceable>maxwaittime</></entry>
<entry>0</entry>
<entry> <entry>
the maximum number of seconds to wait for the next file, Set the maximum number of seconds to wait for the next WAL file,
after which recovery will end and the Standby will come up. after which recovery will end and the standby will come up.
The default setting is not necessarily recommended, A setting of zero (the default) means wait forever.
consult the main database server manual for discussion. A setting of The default setting is not necessarily recommended;
zero means wait forever. consult <xref linkend="warm-standby"> for discussion.
<literal>Default=0, Min=0</literal>
</entry> </entry>
</row> </row>
</tbody> </tbody>
...@@ -209,89 +201,129 @@ restore_command = 'pg_standby archiveDir %f %p %r' ...@@ -209,89 +201,129 @@ restore_command = 'pg_standby archiveDir %f %p %r'
</table> </table>
<note> <note>
<para> <para>
<literal>--help</literal> is not supported since <literal>--help</literal> is not supported since
<literal>pg_standby</literal> is not intended for interactive use, except <application>pg_standby</application> is not intended for interactive use,
during development and testing. except during development and testing.
</para> </para>
</note> </note>
</sect2> </sect2>
<sect2> <sect2>
<title>Supported versions</title> <title>Examples</title>
<para>
<literal>pg_standby</literal> is designed to work with PostgreSQL 8.2 and
and later. It is currently compatible across minor changes between the way
8.3 and 8.2 operate.
</para>
<para>
PostgreSQL 8.3 provides the <literal>%r</literal> command line substitution,
designed to let <literal>pg_standby</literal> know the last file it needs to
keep. If the last parameter is omitted, no error is generated, allowing
<literal>pg_standby</literal> to function correctly with PostgreSQL 8.2
also. With PostgreSQL 8.2, the <literal>-k</literal> option must be used if
archive cleanup is required. This option remains available in 8.3.
</para>
</sect2>
<sect2> <para>On Linux or Unix systems, you might use:</para>
<title>Additional design notes</title>
<programlisting>
archive_command = 'cp %p .../archive/%f'
restore_command = 'pg_standby -l -d -s 2 -t /tmp/pgsql.trigger.5442 .../archive %f %p %r 2>>standby.log'
</programlisting>
<para> <para>
The use of a move command seems like it would be a good idea, but this would where the archive directory is physically located on the standby server,
prevent recovery from being restartable. Also, the last WAL file is always so that the <literal>archive_command</> is accessing it across NFS,
requested twice from the archive. but the files are local to the standby (enabling use of <literal>ln</>).
This will:
</para> </para>
</sect2> <itemizedlist>
<listitem>
<para>
use the <literal>ln</> command to restore WAL files from archive
</para>
</listitem>
<listitem>
<para>
produce debugging output in <filename>standby.log</>
</para>
</listitem>
<listitem>
<para>
sleep for 2 seconds between checks for next WAL file availability
</para>
</listitem>
<listitem>
<para>
stop waiting only when a trigger file called
<filename>/tmp/pgsql.trigger.5442</> appears
</para>
</listitem>
<listitem>
<para>
remove no-longer-needed files from the archive directory
</para>
</listitem>
</itemizedlist>
<sect2> <para>On Windows, you might use:</para>
<title>Examples</title>
<programlisting>
archive_command = 'copy %p ...\\archive\\%f'
restore_command = 'pg_standby -d -s 5 -t C:\pgsql.trigger.5442 ...\archive %f %p %r 2>>standby.log'
</programlisting>
<para>
Note that backslashes need to be doubled in the
<literal>archive_command</>, but <emphasis>not</emphasis> in the
<literal>restore_command</>. This will:
</para>
<itemizedlist> <itemizedlist>
<listitem> <listitem>
<para>Example on Linux</para>
<programlisting>
archive_command = 'cp %p ../archive/%f'
restore_command = 'pg_standby -l -d -k 255 -r 2 -s 2 -w 0 -t /tmp/pgsql.trigger.5442 $PWD/../archive %f %p 2>> standby.log'
</programlisting>
<para> <para>
which will use the <literal>copy</> command to restore WAL files from archive
</para> </para>
<itemizedlist>
<listitem><para>use a ln command to restore WAL files from archive</para></listitem>
<listitem><para>produce logfile output in standby.log</para></listitem>
<listitem><para>keep the last 255 full WAL files, plus the current one</para></listitem>
<listitem><para>sleep for 2 seconds between checks for next WAL file is full</para></listitem>
<listitem><para>never timeout if file not found</para></listitem>
<listitem><para>stop waiting when a trigger file called /tmp/pgsql.trigger.5442 appears</para></listitem>
</itemizedlist>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
Example on Windows produce debugging output in <filename>standby.log</>
</para> </para>
<programlisting> </listitem>
archive_command = 'copy %p ..\\archive\\%f' <listitem>
</programlisting>
<para> <para>
Note that backslashes need to be doubled in the archive_command, but sleep for 5 seconds between checks for next WAL file availability
*not* in the restore_command, in 8.2, 8.1, 8.0 on Windows.
</para> </para>
<programlisting> </listitem>
restore_command = 'pg_standby -c -d -s 5 -w 0 -t C:\pgsql.trigger.5442 ..\archive %f %p 2>> standby.log' <listitem>
</programlisting>
<para> <para>
which will stop waiting only when a trigger file called
<filename>C:\pgsql.trigger.5442</> appears
</para>
</listitem>
<listitem>
<para>
remove no-longer-needed files from the archive directory
</para> </para>
<itemizedlist>
<listitem><para>use a copy command to restore WAL files from archive</para></listitem>
<listitem><para>produce logfile output in standby.log</para></listitem>
<listitem><para>sleep for 5 seconds between checks for next WAL file is full</para></listitem>
<listitem><para>never timeout if file not found</para></listitem>
<listitem><para>stop waiting when a trigger file called C:\pgsql.trigger.5442 appears</para></listitem>
</itemizedlist>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
<para>
Since the Windows example uses <literal>copy</> at both ends, either
or both servers might be accessing the archive directory across the
network.
</para>
</sect2> </sect2>
<sect2>
<title>Supported server versions</title>
<para>
<application>pg_standby</application> is designed to work with
<productname>PostgreSQL</> 8.2 and later.
</para>
<para>
<productname>PostgreSQL</> 8.3 provides the <literal>%r</literal> macro,
which is designed to let <application>pg_standby</application> know the
last file it needs to keep. With <productname>PostgreSQL</> 8.2, the
<literal>-k</literal> option must be used if archive cleanup is
required. This option remains available in 8.3, but its use is deprecated.
</para>
</sect2>
<sect2>
<title>Author</title>
<para>
Simon Riggs
</para>
</sect2>
</sect1> </sect1>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment