我需要生成加密安全,随机和 唯一 字符串,每个字符串都将用作实际上访问令牌。为此,我计划使用Java的SecureRandom
类。但是,我不确定SecureRandom是否保证了它的独特性。换句话说,SecureRandom在每次生成时都会产生不同的值吗?
似乎创建具有seed
值的实例(即new SecureRandom(byte[] seed)
)可能有效。但是,我不确定。此外,这answer指出种子既不安全也不便携。种子价值服务器是我的目的吗?
如果您有SecureRandom以外的建议,我也想听听。
答案 0 :(得分:8)
不,SecureRandom
实例不保证唯一结果。如果它确实保证了,它就不会完全随机,因为你会知道你无法得到你已经收到的结果。
设置种子值不会改善这种情况。它也不会使情况变得更糟,因为你传递的种子被添加(补充)由SecureRandom
实现内部生成的种子。
如果您需要保证唯一的随机数,则需要保留所有先前生成的数字,然后检查生成新数字的时间(如果已经返回)。如果有,则需要生成一个新数字(并重复检查)。
然而,如果您生成的数字非常大,则生成非唯一数字的机会变得非常小。尝试生成256位或更多(32字节)的数字。这也是UUID用于生成“唯一”数字的机制。这些也不保证是独一无二的,但你必须等待很长时间(平均)才能获得副本。
答案 1 :(得分:1)
您可以利用Stream API支持从IntStream
生成SecureRandom
:
SecureRandom random = new SecureRandom();
OfInt iterator = random.ints().distinct().iterator();
int random = iterator.next();
ints
方法返回“有效无限的伪随机int
值流” ,您可以将其区分并获得元素上的迭代器。
鉴于存在2 ^ 32个可能的值,我想这对于实际使用应该足够了。