我使用此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;
答案 0 :(得分:3)
您可以首先使用此自我可逆变体:
CREATE FUNCTION rev_pseudo_encrypt(VALUE bigint) 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 ((r1::bigint<<16) + l1);
END;
$$ LANGUAGE plpgsql strict immutable;
它与原始版本的不同之处在于将bigint
代替int
作为输入(但输入仍应小于2^32
),以及两个16位块的事实在32位最终结果中交换。
除了结果的唯一性之外,它还具有rev_pseudo_encrypt(rev_pseudo_encrypt(x)) = x
的属性
此外,还有一个优点是输入类型与输出类型相同。
另一方面,要反转原始版本生成的值,需要交换它们的16位块,然后再将其转换为算法,结果再次交换:
create function swap16(bigint) returns bigint as
'select (($1&65535)<<16)+(($1)>>16)'
language sql stable;
select pseudo_encrypt(1234);
pseudo_encrypt
----------------
223549288
select swap16(pseudo_encrypt(swap16(223549288)::int));
swap16
--------
1234