可逆地改组一百万个数字

时间:2015-12-23 20:28:07

标签: algorithm encryption permutation

我需要发出一系列{1,2,3,4 ...}的门票(至少看似是)随机数{10,934,3,453,867,122,4,386,564 ......}。当呈现时,我必须能够计算其原始索引(例如122→3。)

换句话说,我需要在区间[1 ... N]上有一个看似随机的排列p,它具有逆置换p-1。 N约为10 7

原因是:

  • 这是一个密码:当收到一张票时,它应该不容易 猜猜之前发行的门票。
  • 门票应该是可以记下来的短字母数字字符串。
  • 我想避免记录所发出的每张票。

3 个答案:

答案 0 :(得分:2)

我会在计数器模式下使用一些众所周知的密码(例如DES)。

对于正常目的,DES通常被认为是相当破碎的,但它似乎很合适地满足您的需求,并且具有比大多数新算法更小的块大小。对你来说,这意味着它产生一个较小的结果(64位,如果内存服务)。一旦你将它转换为可读字符(例如,base 64),你最终会得到10个字符左右。

要检索原始号码,只需使用密钥解密即可。

结果看起来非常随机 - 基本上唯一已知的将它们排序回序的方法就是破坏DES,这可以完成(已经完成),但这样做的资源非常重要。

如果你确实需要比这更好的安全性,你可以使用AES而不是DES(代价是产生更长的“密钥”值)。

答案 1 :(得分:0)

您可以使用Linear congruential generator生成此类序列。 X0是种子(如果你愿意,可以是排列的索引)。 m 应等于N + 1。选择 c a 以确保完整的期间长度(如上面链接中的期间长度'部分所述)。这将为您提供大小为N的一对一映射。

要恢复索引,您可以使用系列中的少量连续伪随机数来破解LCG,即not too hard。当然你可以保留m,a和c并省去麻烦。

有关更安全的方法,请查看David Eisenstat的评论。您只需要密钥即可恢复索引。在缺点方面,如果您使用标准FPE,则N必须为2 ^ x-1(例如2 ^ 128-1)。

答案 2 :(得分:0)

1生成伪随机混乱,你可以使用Fisher-Yates算法:

https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle

What distribution do you get from this broken random shuffle?

for (int i = tickets.Length - 1; i > 0; i--)
{
int n = random(i + 1);
Swap(tickets[i], tickets[n]);
}

谨防不使用“错误”算法(他有偏见)。

你将获得排列,然后是逆排列。

2问题伴随着随机播放。

因为有10000000!排列,你应该有一个非常大的种子

然后问题在于随机生成器。标准的大概是32位,也许多一点,但远不是10000000!

你应该看到像fortuna这样的东西:

https://en.wikipedia.org/wiki/Fortuna_%28PRNG%29