[patch 3/3] new documentation

From: Marko Kreen <marko(at)l-t(dot)ee>
To: pgsql-patches(at)postgresql(dot)org
Subject: [patch 3/3] new documentation
Date: 2005-07-15 20:04:05
Message-ID: 20050715200442.404066000@grue
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-patches

- reformat in asciidoc syntax
- clarify various parts
- add high-level description of PGP structure
- add a comparison of crypt vs. regular hashes

Index: pgsql/contrib/pgcrypto/README.pgcrypto
===================================================================
*** pgsql.orig/contrib/pgcrypto/README.pgcrypto
--- pgsql/contrib/pgcrypto/README.pgcrypto
***************
*** 1,362 ****

! pgcrypto 0.4 - cryptographic functions for PostgreSQL.
! ======================================================
! by Marko Kreen <marko(at)l-t(dot)ee>


! INSTALLATION
! ============

! Edit makefile, if you want to use any external library.

! NB! Default randomness source is libc random() function. This
! is so only to get pgcrypto build everywhere. Randomness is
! needed for gen_salt() and pgp_encrypt() functions. So if you plan
! using those, you should definitely change that by editing Makefile.
! You can should use urandom device if your OS supports it, otherwise
! link pgcrypto against OpenSSL library and use its PRNG.

! After editing Makefile:

- make
- make install

! To run regression tests, install both PostgreSQL and pgcrypto
! and then run

! make installcheck

! SQL FUNCTIONS
! =============

! If any of arguments are NULL they return NULL.

! digest(data::bytea, type::text)::bytea

! Type is here the algorithm to use. E.g. 'md5', 'sha1', ...
! Returns binary hash.

! digest_exists(type::text)::bool

! Returns BOOL whether given hash exists.

! hmac(data::bytea, key::bytea, type::text)::bytea

- Calculates Hashed MAC over data. type is the same as
- in digest(). Returns binary hash. Similar to digest()
- but noone can alter data and re-calculate hash without
- knowing key. If the key is larger than hash blocksize
- it will first hashed and the hash will be used as key.
-
- [ HMAC is described in RFC2104. ]

! hmac_exists(type::text)::bool
! Returns BOOL. It is separate function because all hashes
! cannot be used in HMAC.

! crypt(password::text, salt::text)::text

- Calculates UN*X crypt(3) style hash. Useful for storing
- passwords. For generating salt you should use the
- gen_salt() function. Usage:

! New password:
!
! UPDATE .. SET pswhash = crypt(new_psw, gen_salt('md5'));
!
! Authentication:

! SELECT pswhash = crypt(given_psw, pswhash) WHERE .. ;
!
! returns BOOL whether the given_psw is correct. DES crypt
! has max key of 8 bytes, MD5 has max key at least 2^32-1
! bytes but may be larger on some platforms...

- Builtin crypt() supports DES, Extended DES, MD5 and Blowfish
- (variant 2a) algorithms.

! gen_salt(type::text)::text

! Generates a new random salt for usage in crypt(). Type
!
! 'des' - Old UNIX, not recommended
! 'md5' - md5-based crypt()
! 'xdes' - 'Extended DES'
! 'bf' - Blowfish-based, variant 2a

! When you use --enable-system-crypt then note that system
! libcrypt may not support them all.

! gen_salt(type::text, rounds::int4)::text

- same as above, but lets user specify iteration count
- for algorithm. Number is algorithm specific:

! type default min max
! ---------------------------------
! xdes 725 1 16777215
! bf 6 4 31

! In case of xdes there is a additional limitation that the
! count must be a odd number.

! The higher the count, the more time it takes to calculate
! crypt and therefore the more time to break it. But beware!
! With too high count it takes a _very_long_ time to
! calculate it.

! For maximum security, you should choose the 'bf' crypt
! and use maximum number of rounds you can still tolerate.

! armor(bytea)::text
! dearmor(text)::bytea

! Those wrap/unwrap data into PGP Ascii Armor which
! is basically Base64 with CRC and additional formatting.

! pgp_sym_encrypt(data::text, key::text)::bytea
! pgp_sym_encrypt(data::text, key::text, arg::text)::bytea
! pgp_sym_encrypt_bytea(data::bytea, key::text)::bytea
! pgp_sym_encrypt_bytea(data::bytea, key::text, arg::text)::bytea

- pgp_sym_decrypt(data::bytea, key::text)::text
- pgp_sym_decrypt(data::bytea, key::text, arg::text)::text
- pgp_sym_decrypt_bytea(data::text, key::text)::bytea
- pgp_sym_decrypt_bytea(data::text, key::text, arg::text)::bytea

! Encrypt data into OpenPGP Symmetrically Encrypted Data
! message. And decrypt it from it.

! Note that the pgp_sym_encrypt_bytea functions tag the data
! as binary, as the pgp_sym_encrypt will tag the data as text.
! You can not decrypt the binary data as text. But you can
! decrypt text data as binary. This rule avoids having
! broken textual data in PostgreSQL.

! Both encrypt and decrypt accept also third argument, which
! is parameters to the function in following format:
!
! parm=val[,parm=val]...
!
! Example:

! select pgp_sym_encrypt('data', 'psw',
! 'compress-algo=2, unicode-mode=1');

! Accepted parameters are:

- cipher-algo: bf, aes, aes128, aes192, aes256
- Cipher algorithm to use. OpenSSL gives additional algorithms:
- 3des, cast5
- Default: aes128
-
- compress-algo: 0, 1, 2
- Which compression algorithm to use.
- 0 - no compression
- 1 - ZIP compression
- 2 - ZLIB compression [=ZIP plus meta-data and block-CRC's]
- Default: 0

- compress-level: 0, 1-9
- How much to compress. Bigger level compresses smaller
- but also slower. 0 disables compression.
- Default: 6

! convert-crlf: 0, 1
! Whether to convert \n into \r\n when encrypting and
! \r\n to \n when decrypting. RFC2440 specifies that
! text packets should use "\r\n" line-feeds.
! Use this to get fully RFC-compliant behaviour.
! Default: 0

! disable-mdc: 0, 1
! Do not protect data with SHA-1. Note that SHA-1 protected
! packet is from upcoming update to RFC2440. (Currently at
! version RFC2440bis-13.) You need to disable it if you need
! compatibility with ancient PGP products. Recent gnupg.org
! and pgp.com software supports it fine.
! Default: 0
!
! enable-session-key: 0, 1
! Use separate session key.
! Default: 0
!
! s2k-mode: 0, 1, 3
! Which S2K algorithm to use. 0 is dangerous - without salt.
! Default: 3
!
! s2k-digest-algo: md5, sha1
! Which digest algorithm to use in S2K calculation.
! Default: SHA-1

! s2k-cipher-algo: bf, aes, aes128, aes192, aes256
! Which cipher to use for encrypting separate session key.
! Default: same as cipher-algo.

! unicode-mode: 0, 1
! Whether to convert textual data from database internal
! encoding to UTF-8 and back.
! Default: 0

! Only 'convert-crlf' applies to both encrypt and decrypt,
! all others apply only to encrypt - decrypt gets the
! settings from PGP data.
!
!
! pgp_pub_encrypt(data::text, key::bytea)::bytea
! pgp_pub_encrypt(data::text, key::bytea, arg::text)::bytea
! pgp_pub_encrypt_bytea(data::bytea, bytea::text)::bytea
! pgp_pub_encrypt_bytea(data::bytea, bytea::text, arg::text)::bytea

- pgp_pub_decrypt(data::bytea, key::bytea)::text
- pgp_pub_decrypt(data::bytea, key::bytea, psw::text)::text
- pgp_pub_decrypt(data::bytea, key::bytea, psw::text, arg::text)::text
- pgp_pub_decrypt_bytea(data::text, key::bytea)::bytea
- pgp_pub_decrypt_bytea(data::text, key::bytea, psw::text)::bytea
- pgp_pub_decrypt_bytea(data::text, key::bytea, psw::text, arg::bytea)::bytea

! Encrypt data into OpenPGP Public-Key Encrypted Data
! message. And decrypt it from it. The arg parameter is
! described in pgp_sym_* section.

! The key must be a public-key packet for pgp_pub_encrypt
! functions and a secret key packet for pgp_pub_decrypt
! functions. Trying to encrypt with secret key gives a error.
! While being technically possible, it is probably a sign of
! user error and leaking secret keys.

! Here is a example how to generate them:
!
! Generate a new key:
!
! gpg --gen-key
!
! You need to pick "DSA and Elgamal" key type, others
! are sign-only.

! List keys:
!
! gpg --list-secret-keys

! Export ascii-armored public key:

! gpg -a --export KEYID > public.key
!
! Export ascii-armored secret key:

! gpg -a --export-secret-keys KEYID > secret.key

! You need to use dearmor() on them before giving giving
! them to pgp_pub_* functions. Ofcourse, if you can handle
! binary data, you can drop "-a" from gpg.


! pgp_key_id(key / data)

! It shows you either key ID if given PGP public or secret
! key. Or it gives the key ID what was used for encrypting
! the data, if given encrypted data.

! It can return 2 special key ID's:

! SYMKEY - it got symmetrically encrypted data.
! ANYKEY - the data packet key ID is clear. That means
! you should try all you secret keys on it.

- encrypt(data::bytea, key::bytea, type::text)::bytea
- decrypt(data::bytea, key::bytea, type::text)::bytea
- encrypt_iv(data::bytea, key::bytea, iv::bytea, type::text)::bytea
- decrypt_iv(data::bytea, key::bytea, iv::bytea, type::text)::bytea

! Encrypt/decrypt data with cipher, padding data if needed.

! Pseudo-noteup:

! algo ['-' mode] ['/pad:' padding]

! Supported algorithms:
!
! bf - Blowfish
! aes, rijndael - Rijndael-128

! Others depend on library and are not tested enough, so
! play on your own risk.

! Modes: 'cbc' (default), 'ecb'. Again, library may support
! more.

! Padding is 'pkcs' (default), 'none'. 'none' is mostly for
! testing ciphers, you should not need it.

! So, example:

- encrypt(data, 'fooz', 'bf')
-
- is equal to

! encrypt(data, 'fooz', 'bf-cbc/pad:pkcs')

! IV is initial value for mode, defaults to all zeroes.
! It is ignored for ECB. It is clipped or padded with zeroes
! if not exactly block size.


! ALGORITHMS
! ==========

! The standard functionality at the moment consists of

! Hashes: md5, sha1
! Ciphers: bf, aes
! Modes: cbc, ecb

- TODO: write standard names for optional ciphers too.

! LIBRARIES
! =========

! * crypt()

- internal: des, xdes, md5, bf

! -lcrypt: ??? (whatever you have)

! * other:

! [ This only lists stuff that the libraries claim to support. So
! pgcrypto may work with all of them. But ATM tested are only the
! standard ciphers. On others pgcrypto and library may mess something
! up. You have been warned. ]

! internal (default):
! Hashes: MD5, SHA1
! Ciphers: Blowfish, Rijndael-128


! OpenSSL (0.9.7):
! Hashes: MD5, SHA1, RIPEMD160, MD2
! Ciphers: Blowfish, AES, CAST5, DES, 3DES
! License: BSD-like with strong advertisement
! Url: http://www.openssl.org/


! CREDITS
! =======

I have used code from following sources:

! DES crypt() by David Burren and others FreeBSD libcrypt
! MD5 crypt() by Poul-Henning Kamp FreeBSD libcrypt
! Blowfish crypt() by Solar Designer www.openwall.com
! Blowfish cipher by Niels Provos OpenBSD sys/crypto
! Rijndael cipher by Brian Gladman OpenBSD sys/crypto
! MD5 and SHA1 by WIDE Project KAME kame/sys/crypto

- LEGALESE
- ========

! * I owe a beer to Poul-Henning.

* This product includes software developed by Niels Provos.


--- 1,675 ----

! pgcrypto - cryptographic functions for PostgreSQL
! =================================================
! Marko Kreen <marko(at)l-t(dot)ee>


! 1. Installation
! -----------------

! Run following commands:

! make
! make install
! make installcheck

! The `make installcheck` command is important. It runs regression tests
! for the module. They make sure the functions here produce correct
! results.


! 2. Notes
! ----------

! 2.1. Configuration
! ~~~~~~~~~~~~~~~~~~~~

! pgcrypto configures itself according to the findings of main PostgreSQL
! `configure` script. The options that affect it are `--with-zlib` and
! `--with-openssl`.

! Without zlib, the PGP functions will not support compressed data inside
! PGP encrypted packets.

! Without OpenSSL public-key encryption does not work, as pgcrypto does
! not contain yet math functions for large integers.

! There are some other differences between with and without OpenSSL build:

! `----------------------------`---------`------------
! Functionality built-in OpenSSL
! ----------------------------------------------------
! MD5 yes yes
! SHA1 yes yes
! SHA256/384/512 yes since 0.9.8
! Any other digest algo no yes (1)
! Blowfish yes yes
! AES yes yes (2)
! DES/3DES/CAST5 no yes
! Raw encryption yes yes
! PGP Symmetric encryption yes yes
! PGP Public-Key encryption no yes
! ----------------------------------------------------

! 1. Any digest algorithm OpenSSL supports is automatically picked up.
! This is not possible with ciphers, which need to be supported
! explicitly.

! 2. 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.


! 2.2. NULL handling
! ~~~~~~~~~~~~~~~~~~~~

! As standard in SQL, all functions return NULL, if any of it's arguments
! are NULL. This may create security risks on careless usage.


! 2.3. Deprecated functions
! ~~~~~~~~~~~~~~~~~~~~~~~~~~~

! The `digest_exists()`, `hmac_exists()` and `cipher_exists()` functions
! are deprecated. The plan is to remove those in PostgreSQL 8.2.


! 2.4. Security
! ~~~~~~~~~~~~~~~

! All the functions here run inside database server. That means that all
! the data and passwords move between pgcrypto and client application in
! clear-text. Thus you must:

! 1. Connect locally or use SSL connections.
! 2. Trust both system and database administrator.

! If you cannot, then better do crypto inside client application.


! 3. General hashing
! --------------------

! 3.1. digest(data, type)
! ~~~~~~~~~~~~~~~~~~~~~~~~~

! digest(data text, type text) RETURNS bytea
! digest(data bytea, type text) RETURNS bytea

! Type is here the algorithm to use. Standard algorithms are `md5` and
! `sha1`, although there may be more supported, depending on build
! options.

! Returns binary hash.

! If you want hexadecimal string, use `encode()` on result. Example:

! CREATE OR REPLACE FUNCTION sha1(bytea) RETURNS text AS $$
! SELECT encode(digest($1, 'sha1'), 'hex')
! $$ LANGUAGE SQL STRICT IMMUTABLE;


! 3.2. hmac(data, key, type)
! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~

! hmac(data text, key text, type text) RETURNS bytea
! hmac(data bytea, key text, type text) RETURNS bytea

! Calculates Hashed MAC over data. `type` is the same as in `digest()`.
! If the key is larger than hash block size it will first hashed and the
! hash will be used as key.

! It is similar to digest() but the hash can be recalculated only knowing
! the key. This avoids the scenario of someone altering data and also
! changing the hash.

! Returns binary hash.



! 4. Password hashing
! ---------------------

! The functions `crypt()` and `gen_salt()` are specifically designed
! for hashing passwords. `crypt()` does the hashing and `gen_salt()`
! prepares algorithm parameters for it.

! The algorithms in `crypt()` differ from usual hashing algorithms like
! MD5 or SHA1 in following respects:

! 1. They are slow. As the amount of data is so small, this is only
! way to make brute-forcing passwords hard.
! 2. Include random 'salt' with result, so that users having same
! password would have different crypted passwords. This also
! additional defense against reversing the algorithm.
! 3. Include algorithm type in the result, so passwords hashed with
! different algorithms can co-exist.
! 4. Some of them are adaptive - that means after computers get
! faster, you can tune the algorithm to be slower, without
! introducing incompatibility with existing passwords.

! Supported algorithms:
! `------`-------------`---------`----------`---------------------------
! Type Max password Adaptive Salt bits Description
! ----------------------------------------------------------------------
! `bf` 72 yes 128 Blowfish-based, variant 2a
! `md5` unlimited no 48 md5-based crypt()
! `xdes` 8 yes 24 Extended DES
! `des` 8 no 12 Original UNIX crypt
! ----------------------------------------------------------------------


! 4.1. crypt(password, salt)
! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~

! crypt(password text, salt text) RETURNS text

! Calculates UN*X crypt(3) style hash of password. When storing new
! password, you need to use function `gen_salt()` to generate new salt.
! When checking password you should use existing hash as salt.

! Example - setting new password:

! UPDATE .. SET pswhash = crypt('new password', gen_salt('md5'));

! Example - authentication:

! SELECT pswhash = crypt('entered password', pswhash) WHERE .. ;

! returns true or false whether the entered password is correct.
! It also can return NULL if `pswhash` field is NULL.


! 4.2. gen_salt(type)
! ~~~~~~~~~~~~~~~~~~~~~

! gen_salt(type text) RETURNS text

! Generates a new random salt for usage in `crypt()`. For adaptible
! algorithms, it uses the default iteration count.

! Accepted types are: `des`, `xdes`, `md5` and `bf`.


! 4.3. gen_salt(type, rounds)
! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

! gen_salt(type text, rounds integer) RETURNS text

! Same as above, but lets user specify iteration count for some
! algorithms. The higher the count, the more time it takes to hash
! ti password and therefore the more time to break it. Although with
! too high count the time to calculate a hash may be several years
! - which is somewhat impractical.

! Number is algorithm specific:

! `-----'---------'-----'----------
! type default min max
! ---------------------------------
! `xdes` 725 1 16777215
! `bf` 6 4 31
! ---------------------------------

! In case of xdes there is a additional limitation that the count must be
! a odd number.

! Notes:

! - Original DES crypt was designed to have the speed of 4 hashes per
! second on the hardware that time.
! - Slower that 4 hashes per second would probably damper usability.
! - Faster that 100 hashes per second is probably too fast.
! - See next section about possible values for `crypt-bf`.


! 4.4. Comparison of crypt and regular hashes
! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

! Here is a table that should give overview of relative slowness
! of different hashing algorithms.

+ * The goal is to crack a 8-character password, which consists:
+ 1. Only from lowercase letters
+ 2. Numbers, lower- and uppercase letters.
+ * The table below shows how much time it would take to try all
+ combinations of characters.
+ * The `crypt-bf` is featured in several settings - the number
+ after slash is the `rounds` parameter of `gen_salt()`.

! `------------'----------'--------------'--------------------
! 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
! password 143781000 25 mins 18 days
! ------------------------------------------------------------

! * The machine used is 1.5GHz Pentium 4.
! * crypt-des and crypt-md5 algorithm numbers are taken from
! John the Ripper v1.6.38 `-test` output.
! * MD5 numbers are from mdcrack 1.2.
! * SHA1 numbers are from lcrack-20031130-beta.
! * MySQL password() numbers are from my own tests.
! (http://grue.l-t.ee/~marko/src/mypass/)
! * `crypt-bf` numbers are taken using simple program that loops
! over 1000 8-character passwords. That way I can show the speed with
! different number of rounds. For reference: `john -test` shows 213
! loops/sec for crypt-bf/5. (The small difference in results is in
! accordance to the fact that the `crypt-bf` implementation in pgcrypto
! is same one that is used in John the Ripper.)

! Note that the "try all combinations" is not a realistic exercise.
! Usually password cracking is done with the help of dictionaries, which
! contain both regular words and various mutations of them. So, even
! somewhat word-like passwords will be cracked much faster than the above
! numbers suggest, and a 6-character non-word like password may escape
! cracking. Or may not.


! 5. PGP encryption
! -------------------

! The functions here implement the encryption part of OpenPGP (RFC2440)
! standard.


! 5.1. Overview
! ~~~~~~~~~~~~~~~

! Encrypted PGP message consists of 2 packets:

! - Packet for session key - either symmetric- or public-key encrypted.
! - Packet for session-key encrypted data.

! When encrypting with password:

+ 1. Given password is hashed using String2Key (S2K) algorithm. This
+ is rather similar to `crypt()` algorithm - purposefully slow
+ and with random salt - but is produces a full-length binary key.
+ 2. If separate session key is requested, new random key will be
+ generated. Otherwise S2K key will be used directly as session key.
+ 3. 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.

! When encrypting with public key:

+ 1. New random session key is generated.
+ 2. It is encrypted using public key and put into session key packet.

! Now common part, the session-key encrypted data packet:
!
! 1. Optional data-manipulation: compression, conversion to UTF-8,
! conversion of line-endings.
! 2. Data is prefixed with block of random bytes. This is equal
! to using random IV.
! 3. A SHA1 hash of random prefix and data is appended.
! 4. All this is encrypted with session key.
!
!
! 5.2. pgp_sym_encrypt(data, psw)
! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!
! pgp_sym_encrypt(data text, psw text [, options text] ) RETURNS bytea
! pgp_sym_encrypt_bytea(data bytea, psw text [, options text] ) RETURNS bytea
!
! Return a symmetric-key encrypted PGP message.
!
! Options are described in section 5.7.
!
!
! 5.3. pgp_sym_decrypt(msg, psw)
! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!
! pgp_sym_decrypt(msg bytea, psw text [, options text] ) RETURNS text
! pgp_sym_decrypt_bytea(msg bytea, psw text [, options text] ) RETURNS bytea
!
! Decrypt a symmetric-key encrypted PGP message.
!
! Options are described in section 5.7.
!
!
! 5.4. pgp_pub_encrypt(data, pub_key)
! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!
! pgp_pub_encrypt(data text, key bytea [, options text] ) RETURNS bytea
! pgp_pub_encrypt_bytea(data bytea, key bytea [, options text] ) RETURNS bytea
!
! Encrypt data with a public key. Giving this function a secret key will
! produce a error.
!
! Options are described in section 5.7.
!
!
! 5.5. pgp_pub_decrypt(msg, sec_key [, psw])
! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!
! pgp_pub_decrypt(msg bytea, key bytea [, psw text [, options text]] ) \
! RETURNS text
! pgp_pub_decrypt_bytea(msg bytea, key bytea [,psw text [, options text]] ) \
! RETURNS bytea
!
! Decrypt a public-key encrypted message with secret key. If the secret
! key is password-protected, you must give the password in `psw`. If
! there is no password, but you want to specify option for function, you
! need to give empty password.
!
! Options are described in section 5.7.
!
!
! 5.6. pgp_key_id(key / msg)
! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!
! pgp_key_id(key or msg bytea) RETURNS text
!
! It shows you either key ID if given PGP public or secret key. Or it
! gives the key ID what was used for encrypting the data, if given
! encrypted message.
!
! It can return 2 special key ID's:
!
! SYMKEY::
! The data is encrypted with symmetric key.
!
! ANYKEY::
! The data is public-key encrypted, but the key ID is cleared.
! That means you need to try all your secret keys on it to see
! which one decrypts it. pgcrypto itself does not produce such
! messages.
!
! Note that different keys may have same ID. This is rare but normal
! event. Client application should then try to decrypt with each one,
! to see which fits - like handling ANYKEY.
!
!
! 5.7. armor / dearmor
! ~~~~~~~~~~~~~~~~~~~~~~
!
! armor(data bytea) RETURNS text
! dearmor(data text) RETURNS bytea
!
! Those wrap/unwrap data into PGP Ascii Armor which is basically Base64
! with CRC and additional formatting.
!
!
! 5.8. Options for PGP functions
! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!
! Option are named to be similar to GnuPG. Values should be given after
! equal sign, different options from each other with commas. Example:
!
! pgp_sym_encrypt(data, psw, 'compress-also=1, cipher-algo=aes256')
!
! All of the options except `convert-crlf` apply only to encrypt
! functions. Decrypt functions get the parameters from PGP data.
!
! Most interesting options are probably `compression-algo` and
! `unicode-mode`. The rest should have reasonable defaults.
!
!
! cipher-algo::
! What cipher algorithm to use.
!
! Values: bf, aes128, aes192, aes256 (OpenSSL-only: `3des`, `cast5`)
! Default: aes128
! Applies: pgp_sym_encrypt, pgp_pub_encrypt
!
!
! compress-algo::
! Which compression algorithm to use. Needs building with zlib.
!
! Values:
! 0 - no compression
! 1 - ZIP compression
! 2 - ZLIB compression [=ZIP plus meta-data and block-CRC's]
! Default: 0
! Applies: pgp_sym_encrypt, pgp_pub_encrypt
!
! compress-level::
! How much to compress. Bigger level compresses smaller but is slower.
! 0 disables compression.
!
! Values: 0, 1-9
! Default: 6
! Applies: pgp_sym_encrypt, pgp_pub_encrypt
!
! convert-crlf::
! Whether to convert `\n` into `\r\n` when encrypting and `\r\n` to `\n`
! when decrypting. RFC2440 specifies that text data should be stored
! using `\r\n` line-feeds. Use this to get fully RFC-compliant
! behavior.
!
! Values: 0, 1
! Default: 0
! Applies: pgp_sym_encrypt, pgp_pub_encrypt, pgp_sym_decrypt, pgp_pub_decrypt
!
! disable-mdc::
! Do not protect data with SHA-1. Only good reason to use is this
! option is to achieve compatibility with ancient PGP products, as the
! SHA-1 protected packet is from upcoming update to RFC2440. (Currently
! at version RFC2440bis-14.) Recent gnupg.org and pgp.com software
! supports it fine.
!
! Values: 0, 1
! Default: 0
! Applies: pgp_sym_encrypt, pgp_pub_encrypt
!
! enable-session-key::
! Use separate session key. Public-key encryption always uses separate
! session key, this is for symmetric-key encryption, which by default
! uses S2K directly.
!
! Values: 0, 1
! Default: 0
! Applies: pgp_sym_encrypt
!
! s2k-mode::
! Which S2K algorithm to use.
!
! Values:
! 0 - Dangerous! Without salt.
! 1 - With salt but with fixed iteration count.
! 3 - Variable iteration count.
! Default: 3
! Applies: pgp_sym_encrypt
!
! s2k-digest-algo::
! Which digest algorithm to use in S2K calculation.
!
! Values: md5, sha1
! Default: sha1
! Applies: pgp_sym_encrypt
!
! s2k-cipher-algo::
! Which cipher to use for encrypting separate session key.
!
! Values: bf, aes, aes128, aes192, aes256
! Default: same as cipher-algo.
! Applies: pgp_sym_encrypt
!
! unicode-mode::
! Whether to convert textual data from database internal encoding to
! 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
! it will not be.
!
! Values: 0, 1
! Default: 0
! Applies: pgp_sym_encrypt, pgp_pub_encrypt
!
!
! 5.9. Generating keys with GnuPG
! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!
! Generate a new key:
!
! gpg --gen-key
!
! You need to pick "DSA and Elgamal" key type, others are sign-only.
!
! List keys:
!
! gpg --list-secret-keys
!
! Export ascii-armored public key:
!
! gpg -a --export KEYID > public.key
!
! Export ascii-armored secret key:
!
! gpg -a --export-secret-keys KEYID > secret.key
!
! You need to use `dearmor()` on them before giving giving them to
! pgp_pub_* functions. Or if you can handle binary data, you can drop
! "-a" from gpg.
!
!
! 5.10. Limitations of PGP code
! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!
! - No support for signing. That also means that it is not checked
! whether the encryption subkey belongs to master key.
!
! - No support for RSA keys. Only Elgamal encryption keys are supported
!
! - No support for several encryption subkeys.
!
!
! 6. Raw encryption
! -------------------
!
! Those functions only run a cipher over data, they don't have any advanced
! features of PGP encryption. In addition, they have some major problems:
!
! 1. They use user key directly as cipher key.
! 2. They don't provide any integrity checking, to see
! if the encrypted data was modified.
! 3. They expect that users manage all encryption parameters
! themselves, even IV.
! 4. They don't handle text.
!
! So, with the introduction of PGP encryption, usage of raw
! encryption functions is discouraged.
!
!
! 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
! decrypt_iv(data bytea, key bytea, iv bytea, type text) RETURNS bytea
!
! Encrypt/decrypt data with cipher, padding data if needed.
!
! `type` parameter description in pseudo-noteup:
!
! algo ['-' mode] ['/pad:' padding]
!
! Supported algorithms:
!
! * `bf` - Blowfish
! * `aes` - AES (Rijndael-128)
!
! Modes:
!
! * `cbc` - next block depends on previous. (default)
! * `ecb` - each block in encrypted separately.
! (for testing only)
!
! Padding:
!
! * `pkcs` - data may be any length (default)
! * `none` - data must be multiple of cipher block size.
!
! IV is initial value for mode, defaults to all zeroes. It is ignored for
! ECB. It is clipped or padded with zeroes if not exactly block size.
!
! So, example:
!
! encrypt(data, 'fooz', 'bf')
!
! is equal to
!
! encrypt(data, 'fooz', 'bf-cbc/pad:pkcs')
!
!
! 7. Credits
! ------------

I have used code from following sources:

! `--------------------`-------------------------`----------------------
! Algorithm Author Source origin
! ----------------------------------------------------------------------
! DES crypt() David Burren and others FreeBSD libcrypt
! MD5 crypt() Poul-Henning Kamp FreeBSD libcrypt
! Blowfish crypt() Solar Designer www.openwall.com
! Blowfish cipher Niels Provos OpenBSD sys/crypto
! Rijndael cipher Brian Gladman OpenBSD sys/crypto
! MD5 and SHA1 WIDE Project KAME kame/sys/crypto
! SHA256/384/512 Aaron D. Gifford OpenBSD sys/crypto
! ----------------------------------------------------------------------


! 8. Legalese
! -------------

+ * I owe a beer to Poul-Henning.
* This product includes software developed by Niels Provos.


+ 9. References/Links
+ ---------------------
+
+ 9.1. Useful reading
+ ~~~~~~~~~~~~~~~~~~~~~
+
+ http://www.openwall.com/crypt/[]::
+ Describes the crypt-blowfish algorithm.
+
+ http://www.stack.nl/~galactus/remailers/passphrase-faq.html[]::
+ How to choose good password.
+
+ http://world.std.com/~reinhold/diceware.html[]::
+ Interesting idea for picking passwords.
+
+ http://www.interhack.net/people/cmcurtin/snake-oil-faq.html[]::
+ Describes good and bad cryptography.
+
+
+ 9.2. Technical references
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ http://www.ietf.org/rfc/rfc2440.txt[]::
+ OpenPGP message format
+
+ http://www.imc.org/draft-ietf-openpgp-rfc2440bis[]::
+ New version of RFC2440.
+
+ http://www.ietf.org/rfc/rfc1321.txt[]::
+ The MD5 Message-Digest Algorithm
+
+ http://www.ietf.org/rfc/rfc2104.txt[]::
+ HMAC: Keyed-Hashing for Message Authentication
+
+ http://www.usenix.org/events/usenix99/provos.html[]::
+ Comparison of crypt-des, crypt-md5 and bcrypt algorithms.
+
+ http://csrc.nist.gov/cryptval/des.htm[]::
+ Standards for DES, 3DES and AES.
+
+ http://en.wikipedia.org/wiki/Fortuna_(PRNG)[]::
+ Description of Fortuna CSPRNG.
+
+ http://jlcooke.ca/random/[]::
+ Jean-Luc Cooke Fortuna-based /dev/random driver for Linux.
+
+ http://www.cs.ut.ee/~helger/crypto/[]::
+ Collection of cryptology pointers.
+

--

In response to

Responses

Browse pgsql-patches by date

  From Date Subject
Next Message Kris Jurka 2005-07-16 01:06:15 Re: 4 pgcrypto regressions failures - 1 unsolved
Previous Message Marko Kreen 2005-07-15 20:04:04 [patch 2/3] Fortuna fixes