Pseudo encrypt

From PostgreSQL wiki

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

Jump to: navigation, search

Library Snippets


Works with PostgreSQL

Any version

Written in


Depends on


This function was posted by Daniel Verite in

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

CREATE OR REPLACE FUNCTION pseudo_encrypt(VALUE int) returns bigint AS $$
l1 int;
l2 int;
r1 int;
r2 int;
i int:=0;
 l1:= (VALUE >> 16) & 65535;
 r1:= VALUE & 65535;
   l2 := r1;
   r2 := l1 # ((((1366.0 * r1 + 150889) % 714025) / 714025.0) * 32767)::int;
   l1 := l2;
   r1 := r2;
   i := i + 1;
 RETURN ((l1::bigint << 16) + r1);
$$ 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