Add gen_random_uuid() to contrib/pgcrypto.

This function provides a way of generating version 4 (pseudorandom) UUIDs
based on pgcrypto's PRNG.  The main reason for doing this is that the
OSSP UUID library depended on by contrib/uuid-ossp is becoming more and
more of a porting headache, so we need an alternative for people who can't
install that.  A nice side benefit though is that this implementation is
noticeably faster than uuid-ossp's uuid_generate_v4() function.

Oskari Saarenmaa, reviewed by Emre Hasegeli
This commit is contained in:
Tom Lane 2014-01-17 16:52:06 -05:00
parent 708c529c7f
commit e6170126fc
9 changed files with 67 additions and 3 deletions

View File

@ -26,7 +26,7 @@ MODULE_big = pgcrypto
OBJS = $(SRCS:.c=.o) OBJS = $(SRCS:.c=.o)
EXTENSION = pgcrypto EXTENSION = pgcrypto
DATA = pgcrypto--1.0.sql pgcrypto--unpackaged--1.0.sql DATA = pgcrypto--1.1.sql pgcrypto--1.0--1.1.sql pgcrypto--unpackaged--1.0.sql
REGRESS = init md5 sha1 hmac-md5 hmac-sha1 blowfish rijndael \ REGRESS = init md5 sha1 hmac-md5 hmac-sha1 blowfish rijndael \
$(CF_TESTS) \ $(CF_TESTS) \

View File

@ -0,0 +1,9 @@
/* contrib/pgcrypto/pgcrypto--1.0--1.1.sql */
-- complain if script is sourced in psql, rather than via ALTER EXTENSION
\echo Use "ALTER EXTENSION pgcrypto UPDATE TO '1.1'" to load this file. \quit
CREATE FUNCTION gen_random_uuid()
RETURNS uuid
AS 'MODULE_PATHNAME', 'pg_random_uuid'
LANGUAGE C VOLATILE;

View File

@ -1,4 +1,4 @@
/* contrib/pgcrypto/pgcrypto--1.0.sql */ /* contrib/pgcrypto/pgcrypto--1.1.sql */
-- complain if script is sourced in psql, rather than via CREATE EXTENSION -- complain if script is sourced in psql, rather than via CREATE EXTENSION
\echo Use "CREATE EXTENSION pgcrypto" to load this file. \quit \echo Use "CREATE EXTENSION pgcrypto" to load this file. \quit
@ -63,6 +63,11 @@ RETURNS bytea
AS 'MODULE_PATHNAME', 'pg_random_bytes' AS 'MODULE_PATHNAME', 'pg_random_bytes'
LANGUAGE C VOLATILE STRICT; LANGUAGE C VOLATILE STRICT;
CREATE FUNCTION gen_random_uuid()
RETURNS uuid
AS 'MODULE_PATHNAME', 'pg_random_uuid'
LANGUAGE C VOLATILE;
-- --
-- pgp_sym_encrypt(data, key) -- pgp_sym_encrypt(data, key)
-- --

View File

@ -35,6 +35,7 @@
#include "parser/scansup.h" #include "parser/scansup.h"
#include "utils/builtins.h" #include "utils/builtins.h"
#include "utils/uuid.h"
#include "px.h" #include "px.h"
#include "px-crypt.h" #include "px-crypt.h"
@ -443,6 +444,32 @@ pg_random_bytes(PG_FUNCTION_ARGS)
PG_RETURN_BYTEA_P(res); PG_RETURN_BYTEA_P(res);
} }
/* SQL function: gen_random_uuid() returns uuid */
PG_FUNCTION_INFO_V1(pg_random_uuid);
Datum
pg_random_uuid(PG_FUNCTION_ARGS)
{
uint8 *buf = (uint8 *) palloc(UUID_LEN);
int err;
/* generate random bits */
err = px_get_pseudo_random_bytes(buf, UUID_LEN);
if (err < 0)
ereport(ERROR,
(errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
errmsg("Random generator error: %s", px_strerror(err))));
/*
* Set magic numbers for a "version 4" (pseudorandom) UUID, see
* http://tools.ietf.org/html/rfc4122#section-4.4
*/
buf[6] = (buf[6] & 0x0f) | 0x40; /* "version" field */
buf[8] = (buf[8] & 0x3f) | 0x80; /* "variant" field */
PG_RETURN_UUID_P((pg_uuid_t *) buf);
}
static void * static void *
find_provider(text *name, find_provider(text *name,
PFN provider_lookup, PFN provider_lookup,

View File

@ -1,5 +1,5 @@
# pgcrypto extension # pgcrypto extension
comment = 'cryptographic functions' comment = 'cryptographic functions'
default_version = '1.0' default_version = '1.1'
module_pathname = '$libdir/pgcrypto' module_pathname = '$libdir/pgcrypto'
relocatable = true relocatable = true

View File

@ -45,5 +45,6 @@ Datum pg_decrypt(PG_FUNCTION_ARGS);
Datum pg_encrypt_iv(PG_FUNCTION_ARGS); Datum pg_encrypt_iv(PG_FUNCTION_ARGS);
Datum pg_decrypt_iv(PG_FUNCTION_ARGS); Datum pg_decrypt_iv(PG_FUNCTION_ARGS);
Datum pg_random_bytes(PG_FUNCTION_ARGS); Datum pg_random_bytes(PG_FUNCTION_ARGS);
Datum pg_random_uuid(PG_FUNCTION_ARGS);
#endif #endif

View File

@ -4015,6 +4015,8 @@ a0ee-bc99-9c0b-4ef8-bb6d-6bb9-bd38-0a11
suited for every application. The <xref suited for every application. The <xref
linkend="uuid-ossp"> module linkend="uuid-ossp"> module
provides functions that implement several standard algorithms. provides functions that implement several standard algorithms.
The <xref linkend="pgcrypto"> module also provides a generation
function for random UUIDs.
Alternatively, UUIDs could be generated by client applications or Alternatively, UUIDs could be generated by client applications or
other libraries invoked through a server-side function. other libraries invoked through a server-side function.
</para> </para>

View File

@ -1084,6 +1084,17 @@ gen_random_bytes(count integer) returns bytea
At most 1024 bytes can be 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>
<indexterm>
<primary>gen_random_uuid</primary>
</indexterm>
<synopsis>
gen_random_uuid() returns uuid
</synopsis>
<para>
Returns a version 4 (random) UUID.
</para>
</sect2> </sect2>
<sect2> <sect2>

View File

@ -18,6 +18,15 @@
<ulink url="http://www.ossp.org/pkg/lib/uuid/"></ulink>. <ulink url="http://www.ossp.org/pkg/lib/uuid/"></ulink>.
</para> </para>
<note>
<para>
The OSSP UUID library is not well maintained, and is becoming increasingly
difficult to port to newer platforms. If you only need randomly-generated
(version 4) UUIDs, consider using the <function>gen_random_uuid()</>
function from the <xref linkend="pgcrypto"> module instead.
</para>
</note>
<sect2> <sect2>
<title><literal>uuid-ossp</literal> Functions</title> <title><literal>uuid-ossp</literal> Functions</title>