Pseudo encrypt

From PostgreSQL wiki

Revision as of 11:15, 7 January 2012 by JakaJancar (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Library Snippets

pseudo_encrypt

Works with PostgreSQL

Any version

Written in

PL/pgSQL

Depends on

Nothing


This function was posted by Daniel Verite in http://archives.postgresql.org//pgsql-general/2009-05/msg00082.php

Given an input within int32 range, this function produces a different output within the same range. For any given input, the output is the same each time, and for any given output there is only one input that results in that output.

This function is a Feistel network; see http://en.wikipedia.org/wiki/Feistel_cipher

CREATE OR REPLACE FUNCTION pseudo_encrypt(VALUE int) returns bigint AS $$
DECLARE
l1 int;
l2 int;
r1 int;
r2 int;
i int:=0;
BEGIN
 l1:= (VALUE >> 16) & 65535;
 r1:= VALUE & 65535;
 WHILE i < 3 LOOP
   l2 := r1;
   r2 := l1 # ((((1366.0 * r1 + 150889) % 714025) / 714025.0) * 32767)::int;
   l1 := l2;
   r1 := r2;
   i := i + 1;
 END LOOP;
 RETURN ((l1::bigint << 16) + r1);
END;
$$ LANGUAGE plpgsql strict immutable;


Note that it returns a bigint because we don't have unsigned integers in PG. If you're OK with getting negative values, the return type can be changed to int.

Otherwise if you need a positive result that fits in 32 bits, it's possible to tweak the code to use 15 bits blocks instead of 16, but then the input will have to be less than 2^30.

Jaka Jancar, 7.1.2012: Since a normal Feistel Cipher does't swap left and right in last iteration, I believe the return line should have l1 and r1 reversed. This has the upside of pseudo_encrypt(pseudo_encrypt(X)) returning X. I'm also wondering why the LCG parameters are for 2^29 and whether 1366 really needs to be a float.

Personal tools