Following patch provides function gen_random_bytes() to SQL-level,
that uses internal strong random number generator to generate
a bytea value.

I've looked at server-managed-encryption-keys that seems new trend
in commercial databases.  I don't think such functionality has a
place in pgcrypto, but I think it would be good to have low-level
tools to build such scheme on top of pgcrypto.  That was the only
missing piece that 

Index: pgsql/contrib/pgcrypto/pgcrypto.c
===================================================================
*** pgsql.orig/contrib/pgcrypto/pgcrypto.c
--- pgsql/contrib/pgcrypto/pgcrypto.c
*************** pg_decrypt_iv(PG_FUNCTION_ARGS)
*** 537,542 ****
--- 537,570 ----
        PG_RETURN_BYTEA_P(res);
  }
  
+ /* SQL function: pg_random_bytes(int4) returns bytea */
+ PG_FUNCTION_INFO_V1(pg_random_bytes);
+ 
+ Datum
+ pg_random_bytes(PG_FUNCTION_ARGS)
+ {
+       int err;
+       int len = PG_GETARG_INT32(0);
+       bytea *res;
+ 
+       if (len < 1 || len > 1024)
+               ereport(ERROR,
+                               
(errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
+                                errmsg("Length not in range")));
+ 
+       res = palloc(VARHDRSZ + len);
+       VARATT_SIZEP(res) = VARHDRSZ + len;
+ 
+       /* generate result */
+       err = px_get_random_bytes((uint8*)VARDATA(res), len);
+       if (err < 0)
+               ereport(ERROR,
+                               
(errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
+                                errmsg("Random generator error: %s", 
px_strerror(err))));
+ 
+       PG_RETURN_BYTEA_P(res);
+ }
+ 
  /* SQL function: pg_cipher_exists(text) returns bool */
  PG_FUNCTION_INFO_V1(pg_cipher_exists);
  
Index: pgsql/contrib/pgcrypto/pgcrypto.h
===================================================================
*** pgsql.orig/contrib/pgcrypto/pgcrypto.h
--- pgsql/contrib/pgcrypto/pgcrypto.h
*************** Datum           pg_decrypt(PG_FUNCTION_ARGS);
*** 47,51 ****
--- 47,52 ----
  Datum         pg_encrypt_iv(PG_FUNCTION_ARGS);
  Datum         pg_decrypt_iv(PG_FUNCTION_ARGS);
  Datum         pg_cipher_exists(PG_FUNCTION_ARGS);
+ Datum         pg_random_bytes(PG_FUNCTION_ARGS);
  
  #endif
Index: pgsql/contrib/pgcrypto/pgcrypto.sql.in
===================================================================
*** pgsql.orig/contrib/pgcrypto/pgcrypto.sql.in
--- pgsql/contrib/pgcrypto/pgcrypto.sql.in
*************** RETURNS bool
*** 71,76 ****
--- 71,81 ----
  AS 'MODULE_PATHNAME', 'pg_cipher_exists'
  LANGUAGE C IMMUTABLE STRICT;
  
+ CREATE OR REPLACE FUNCTION gen_random_bytes(int4)
+ RETURNS bytea
+ AS 'MODULE_PATHNAME', 'pg_random_bytes'
+ LANGUAGE 'C' VOLATILE STRICT;
+ 
  --
  -- pgp_sym_encrypt(data, key)
  --
Index: pgsql/contrib/pgcrypto/uninstall_pgcrypto.sql
===================================================================
*** pgsql.orig/contrib/pgcrypto/uninstall_pgcrypto.sql
--- pgsql/contrib/pgcrypto/uninstall_pgcrypto.sql
*************** DROP FUNCTION decrypt(bytea, bytea, text
*** 18,23 ****
--- 18,24 ----
  DROP FUNCTION encrypt_iv(bytea, bytea, bytea, text);
  DROP FUNCTION decrypt_iv(bytea, bytea, bytea, text);
  DROP FUNCTION cipher_exists(text);
+ DROP FUNCTION gen_random_bytes(int4);
  
  DROP FUNCTION pgp_sym_encrypt(text, text);
  DROP FUNCTION pgp_sym_encrypt_bytea(bytea, text);
Index: pgsql/contrib/pgcrypto/README.pgcrypto
===================================================================
*** pgsql.orig/contrib/pgcrypto/README.pgcrypto
--- pgsql/contrib/pgcrypto/README.pgcrypto
*************** is equal to
*** 621,627 ****
        encrypt(data, 'fooz', 'bf-cbc/pad:pkcs')
  
  
! 7.  Credits
  ------------
  
  I have used code from following sources:
--- 621,637 ----
        encrypt(data, 'fooz', 'bf-cbc/pad:pkcs')
  
  
! 7.  Random bytes
! -----------------
! 
!     gen_random_bytes(count integer)
! 
! Returns `count` cryptographically strong random bytes as bytea value.
! There can be maximally 1024 bytes extracted at a time.  This is to avoid
! draining the randomness generator pool.
! 
! 
! 8.  Credits
  ------------
  
  I have used code from following sources:
*************** I have used code from following sources:
*** 639,656 ****
  ----------------------------------------------------------------------
  
  
! 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.gnupg.org/gph/en/manual.html[]::
        The GNU Privacy Handbook
--- 649,666 ----
  ----------------------------------------------------------------------
  
  
! 9.  Legalese
  -------------
  
  * I owe a beer to Poul-Henning.
  * This product includes software developed by Niels Provos.
  
  
! 10.  References/Links
! ----------------------
  
! 10.1.  Useful reading
! ~~~~~~~~~~~~~~~~~~~~~~
  
  http://www.gnupg.org/gph/en/manual.html[]::
        The GNU Privacy Handbook
*************** http://www.interhack.net/people/cmcurtin
*** 668,675 ****
        Describes good and bad cryptography.
  
  
! 9.2.  Technical references
! ~~~~~~~~~~~~~~~~~~~~~~~~~~~
  
  http://www.ietf.org/rfc/rfc2440.txt[]::
        OpenPGP message format
--- 678,685 ----
        Describes good and bad cryptography.
  
  
! 10.2.  Technical references
! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  
  http://www.ietf.org/rfc/rfc2440.txt[]::
        OpenPGP message format

--

---------------------------(end of broadcast)---------------------------
TIP 9: In versions below 8.0, the planner will ignore your desire to
       choose an index scan if your joining column's datatypes do not
       match

Reply via email to