我有一个带有这种形式的输入字符串:
<single char><int starting at 1, going up>
并希望为每个人制作:
<the same single char><a unique 8 digit number>
即:
"s1" => "s78138782"
"t1" => "t18743682"
"t2" => "t49274876"
不允许 - 我们已经使用了这个8位数字:
"t1" => "t78138782"
这不需要是可逆的,即我不需要能够在算法上将“s78138782
”转换回s1
。我将它们保存在数据库中,以便我可以查找它。我只希望在我逐步浏览t1
,t2
,t3
等时,数字看起来是随机的,并且不会重复。
显然,8个字符的数字会限制我可以拥有的唯一起始字符串的数量:在这个阶段我很好。
任何人都可以给我一个算法吗?我在Ruby中这样做,所以Ruby是理想的,理想情况下使用标准的Ruby / Rails宝石。
答案 0 :(得分:1)
这个问题的常见解决方案是可逆的,它是为数据库选择随机加密密钥,然后加密每个输入字符串。为了使目标字符串的大小合适,首先用一些不能成为字符串一部分的字符填充输入字符串,例如空格。
请注意,此过程不安全,但它是伪随机的(或者至少看起来是随机的)并且它避免了任何碰撞的可能性。
不幸的是,我对Ruby一无所知,但我把这个例子放在Python中:
import Crypto.Cipher.Blowfish
import re
import struct
parse_id = re.compile("^(\D+)(\d+)$")
cipher = Crypto.Cipher.Blowfish.new("badsecret",
Crypto.Cipher.Blowfish.MODE_ECB)
def randomize(id):
pfx, integer = parse_id.match(id).groups()
return "%c%d" % (
pfx,
struct.unpack("!Q",
cipher.encrypt(pfx
+ struct.pack("!Q",
int(integer))[len(pfx):]))[0])
然后我测试了它:
>>> for i in range(8): print ("t" + str(i), randomize("t" + str(i)))
...
('t0', 't8812720357104479300')
('t1', 't14570648240240394176')
('t2', 't13775280166960833565')
('t3', 't6391672674195357485')
('t4', 't3595757360042384213')
('t5', 't10728238663553328366')
('t6', 't888684936954575988')
('t7', 't9447169127882289438')
>>> for i in range(8): print ("s" + str(i), randomize("s" + str(i)))
...
('s0', 's9209414168426526439')
('s1', 's5452467189798635654')
('s2', 's10995755223696930463')
('s3', 's1237785964853872245')
('s4', 's4976813073866522017')
('s5', 's17045636624557288261')
('s6', 's14217087933089289315')
('s7', 's3504968071130220057')
使数字更短需要找到具有更小块的块密码或使用流密码。我不知道Ruby在加密库方面提供了什么。 (事实上,在我编辑这个答案之前,我对Python的加密支持几乎一无所知。)
答案 1 :(得分:0)
如果您只是在寻找伪随机数字,我只需使用rand()函数生成一个随机数,并将索引添加到随机数中,这样您就不必担心碰撞。