一尘不染

混淆ID

algorithm

我正在寻找一种将整数ID加密/混淆为另一个整数的方法。更确切地说,我需要一个函数int F(int x),这样

  • x <-> F(x)是一一对应的(如果x!= y,F(x)!= F(y))
  • 给定F(x),很容易找出x-因此F不是哈希函数
  • 给定x和F(x),很难/不可能找出F(y),类似的东西是x ^ 0x1234行不通的

为了清楚起见,我并不是在寻找强大的加密解决方案,而只是在混淆。想象一下,像URL的Web应用程序example.com/profile/1example.com/profile/2等型材本身并不是秘密,但我想,以防止随意偷窥到视图/读取所有配置了一个又一个,所以我宁愿躲在他们身后像example.com/profile/23423example.com/profile/80980234等等。虽然数据库存储的令牌可以很轻松地完成这项工作,我很好奇是否有一些简单的数学方法可用于此。

我不清楚的一个重要要求是结果应该看起来是“随机的”,也就是说,给定一个序列x,x+1,...,x+nF(x),F(x+1)...F(x+n)不应形成任何形式的进展。


阅读 295

收藏
2020-07-28

共1个答案

一尘不染

使用2或3个简单方法的某种组合对其进行混淆:

  • 异或
  • 随机播放单个位
  • 转换为模块化表示(D.Knuth,第2卷,第4.3.2章)
  • 选择32个(或64个)重叠的位子集和每个子集中的XOR位(子集的奇偶校验位)
  • 用可变长度数字系统和随机数字表示
  • 选择一对奇数整数xy它们是彼此的乘法逆(模2 32),然后乘以x混淆并乘以y恢复,所有乘法都是模2 32(来源:Eric的“乘法逆的实际使用”)利珀特

变长数字系统方法本身并不能满足您的“进步”要求。它总是产生较短的算术级数。但是,当与其他方法结合使用时,它会产生良好的结果。

模块化表示方法也是如此。

这是其中3种方法的C
++代码示例。随机播放位示例可能会使用一些不同的掩码和距离,以使其更加不可预测。其他2个示例也适用于数量较少的人(仅出于说明目的)。应该扩展它们以正确混淆所有整数值。

// *** Numberic system base: (4, 3, 5) -> (5, 3, 4)
// In real life all the bases multiplied should be near 2^32
unsigned y = x/15 + ((x/5)%3)*4 + (x%5)*12; // obfuscate
unsigned z = y/12 + ((y/4)%3)*5 + (y%4)*15; // restore

// *** Shuffle bits (method used here is described in D.Knuth's vol.4a chapter 7.1.3)
const unsigned mask1 = 0x00550055; const unsigned d1 = 7;
const unsigned mask2 = 0x0000cccc; const unsigned d2 = 14;

// Obfuscate
unsigned t = (x ^ (x >> d1)) & mask1;
unsigned u = x ^ t ^ (t << d1);
t = (u ^ (u  >> d2)) & mask2;
y = u ^ t ^ (t << d2);

// Restore
t = (y ^ (y >> d2)) & mask2;
u = y ^ t ^ (t << d2);
t = (u ^ (u >> d1)) & mask1;
z = u ^ t ^ (t << d1);

// *** Subset parity
t = (x ^ (x >> 1)) & 0x44444444;
u = (x ^ (x << 2)) & 0xcccccccc;
y = ((x & 0x88888888) >> 3) | (t >> 1) | u; // obfuscate

t = ((y & 0x11111111) << 3) | (((y & 0x11111111) << 2) ^ ((y & 0x22222222) << 1));
z = t | ((t >> 2) ^ ((y >> 2) & 0x33333333)); // restore
2020-07-28