snø*_*ven 13 sql postgresql plpgsql
我的工作产生像在回答#2随机IDS系统上这里.
我的问题是,提到的pseudo_encrypt()函数适用于int而不是bigint.我试图重写它,但它返回总是相同的结果:
CREATE OR REPLACE FUNCTION pseudo_encrypt(VALUE bigint) returns bigint AS $$
DECLARE
l1 bigint;
l2 int;
r1 bigint;
r2 int;
i int:=0;
BEGIN
l1:= (VALUE >> 32) & 4294967296::bigint;
r1:= VALUE & 4294967296;
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 << 32) + r1);
END;
$$ LANGUAGE plpgsql strict immutable;
Run Code Online (Sandbox Code Playgroud)
有人可以查一下吗?
Dan*_*ité 17
4294967295必须用作位掩码来选择32位(而不是4294967296).这就是为什么你现在获得不同输入相同值的原因.
我也建议使用bigint的类型l2和r2,他们真的不应该从不同r1和l1
并且,为了更好的随机性,在PRNG函数中使用更高的乘数来获得真正占用32位的中间块,如32767*32767而不是32767.
完整的修改版本:
CREATE OR REPLACE FUNCTION pseudo_encrypt(VALUE bigint) returns bigint AS $$
DECLARE
l1 bigint;
l2 bigint;
r1 bigint;
r2 bigint;
i int:=0;
BEGIN
l1:= (VALUE >> 32) & 4294967295::bigint;
r1:= VALUE & 4294967295;
WHILE i < 3 LOOP
l2 := r1;
r2 := l1 # ((((1366.0 * r1 + 150889) % 714025) / 714025.0) * 32767*32767)::int;
l1 := l2;
r1 := r2;
i := i + 1;
END LOOP;
RETURN ((l1::bigint << 32) + r1);
END;
$$ LANGUAGE plpgsql strict immutable;
Run Code Online (Sandbox Code Playgroud)
第一个结果:
select x,pseudo_encrypt(x::bigint) from generate_series (1, 10) as x; x | pseudo_encrypt ----+--------------------- 1 | 3898573529235304961 2 | 2034171750778085465 3 | 169769968641019729 4 | 2925594765163772086 5 | 1061193016228543981 6 | 3808195743949274374 7 | 1943793931158625313 8 | 88214277952430814 9 | 2835217030863818694 10 | 970815170807835400 (10 rows)
小智 7
旧的,但仍然是一个有趣的问题.与Daniels的答案相比,我使用的是稍微修改过的版本,将return语句更改为此(交换r1和l1),如文章末尾Pseudo encrypt所述:
RETURN ((r1::bigint << 32) + l1);
Run Code Online (Sandbox Code Playgroud)
这种变化的原因是底层Feistel算法不应该在最后一轮结束时左右交换.通过此更改,函数重新获得充当其自身反函数的能力:
pseudo_encrypt(pseudo_encrypt(x) == x // always returns true
Run Code Online (Sandbox Code Playgroud)
这是pgsql中的完整代码:
CREATE OR REPLACE FUNCTION pseudo_encrypt(VALUE bigint) returns bigint AS $$
DECLARE
l1 bigint;
l2 bigint;
r1 bigint;
r2 bigint;
i int:=0;
BEGIN
l1:= (VALUE >> 32) & 4294967295::bigint;
r1:= VALUE & 4294967295;
WHILE i < 3 LOOP
l2 := r1;
r2 := l1 # ((((1366.0 * r1 + 150889) % 714025) / 714025.0) * 32767*32767)::int;
l1 := l2;
r1 := r2;
i := i + 1;
END LOOP;
RETURN ((r1::bigint << 32) + l1);
END;
$$ LANGUAGE plpgsql strict immutable;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3150 次 |
| 最近记录: |