简体   繁体   English

跨版本和平台的一致随机数

[英]Consistent random numbers across versions and platforms

I need/want to get random (well, not entirely) numbers to use for password generation. 我需要/想要获得随机的(不是全部)数字来生成密码。

What I do : Currently I am generating them with SecureRandom . 我的工作 :目前,我正在使用SecureRandom生成它们。
I am obtaining the object with 我正在用

SecureRandom sec = SecureRandom.getInstance("SHA1PRNG", "SUN");

and then seeding it like this 然后像这样播种

sec.setSeed(seed);

Target : A (preferably fast) way to create random numbers, which are cryptographically at least a safe as the SHA1PRNG SecureRandom implementation. 目标 :一种创建随机数的方法(最好是快速方法),该方法在密码上至少比SHA1PRNG SecureRandom实现安全。 These need to be the same on different versions of the JRE and Android. 在不同版本的JRE和Android上,这些设置必须相同。

EDIT: The seed is generated from user input. 编辑:种子是从用户输入生成的。

Problem : With SecureRandom.getInstance("SHA1PRNG", "SUN"); 问题 :使用SecureRandom.getInstance("SHA1PRNG", "SUN"); it fails like this: java.security.NoSuchProviderException: SUN . 它会像这样失败: java.security.NoSuchProviderException: SUN Omitting , "SUN" produces random numbers, but those are different than the default (JRE 7) numbers. 省略, "SUN"会产生随机数,但这些数字与默认 (JRE 7)数不同。

Question : How can I achieve my Target ? 问题 :如何实现目标

You don't want it to be predictable : I want, because I need the predictability so that the same preconditions result in the same output. 您不希望它是可预测的 :我想要,因为我需要可预测性,因此相同的前提条件会导致相同的输出。 If they are not the same, its impossible hard to do what the user expects from the application. 如果他们是不一样的,它不可能 很难做到用户从应用程序所期待的。

EDIT: By predictable I mean that, when knowing a single byte (or a hundred) you should not be able to predict the next, but when you know the seed, you should be able to predict the first (and all others). 编辑:通过可预测,我的意思是,当知道一个字节(或一百个字节)时,您不应该能够预测下一个字节,但是当您知道种子时,就应该可以预测第一个(以及所有其他字节)。 Maybe another word is reproducible . 也许另一个词是可复制的

If anyone knows of a more intuitive way, please tell me! 如果有人知道更直观的方法,请告诉我!

I ended up isolating the Sha1Prng from the sun sources which guarantees reproducibility on all versions of Java and android. 我最终将Sha1Prng与太阳光源隔离开,从而确保了所有版本的Java和android的可重复性。 I needed to drop some important methods to ensure compatibility with android, as android does not have access to nio classes... 我需要删除一些重要的方法来确保与android的兼容性,因为android无法访问nio类。

我建议使用UUID.randomUUID() ,然后使用getLeastSignificantBits()和getMostSignificantBits()将其拆分为long型

If you want predictable, they aren't random. 如果您希望可预测,则它们不是随机的。 That breaks your "Target" requirement of being "safe" and devolves into a simple shared secret between two servers. 这打破了您对“安全”的“目标”要求,并演变为两个服务器之间的简单共享机密。

You can get something that looks sort of random but is predicatable by using the characteristics of prime integers where you build a set of integers by starting with I (some specific integer) and add the first prime number and then modulo by the 2nd prime number. 通过使用素数整数的特性,您可以得到看似随机的东西,但它是可实现的,您可以通过以I(某个特定的整数)开头并先加第一个素数再乘以第2个素数为模来构建一组整数。 (In truth the first and second numbers only have to be relatively prime--meaning they have no common prime factors--not counting 1, in case you call that a factor. (实际上,第一个和第二个数字只必须是相对质数的-意味着它们没有共同的质因数-如果您将其称为一个因数,则不计1。

If you repeat the process of adding and doing the modulo, you will get a set of numbers that you can repeatably reproduce and they are ordered in the sense that taking any member of the set, adding the first prime and doing the modulo by the 2nd prime, you will always get the same result. 如果重复加法和求模的过程,则会得到一组可重复复制的数字,它们的排列方式是取集合中的任何成员,加第一个质数并乘第二个模。素数,您将始终获得相同的结果。

Finally, if the 1st prime number is large relative to the second one, the sequence is not easily predictable by humans and seems sort of random. 最后,如果第一个质数相对于第二个质数大,则该序列不容易被人类预测,并且看起来是随机的。

For example, 1st prime = 7, 2nd prime = 5 (Note that this shows how it works but is not useful in real life) 例如,第一个质数= 7,第二个质数= 5(请注意,这显示了它的工作原理,但在现实生活中没有用)

Start with 2. Add 7 to get 9. Modulo 5 to get 4. 4 plus 7 = 11. Modulo 5 = 1. 从2开始。加7得到9。取模5得到4。4加7 =11。取模5 = 1。

Sequence is 2, 4, 1, 3, 0 and then it repeats. 序列为2、4、1、3、0,然后重复。

Now for real life generation of numbers that seem random. 现在,对于现实生活中的数字,似乎是随机的。 The relatively prime numbers are 91193 and 65536. (I chose the 2nd one because it is a power of 2 so all modulo-ed values can fit in 16 bits.) 相对质数是91193和65536。(我选择第二个是因为它是2的幂,所以所有模数值都可以容纳16位。)

int first = 91193;
int modByLogicalAnd = 0xFFFF;

int nonRandomNumber = 2345; // Use something else
for (int i = 0; i < 1000 ; ++i) {
    nonRandomNumber += first;
    nonRandomNumber &= modByLogicalAnd;
    // print it here
}

Each iteration generates 2 bytes of sort of random numbers. 每次迭代都会生成2个字节的随机数。 You can pack several of them into a buffer if you need larger random "strings". 如果需要较大的随机“字符串”,则可以将其中几个打包到缓冲区中。

And they are repeatable . 而且它们是可重复的 Your user can pick the starting point and you can use any prime you want (or, in fact, any number without 2 as a factor). 您的用户可以选择起点,并且可以使用任何所需的质数(或者,实际上,任何不带2的数字)。

BTW - Using a power of 2 as the 2nd number makes it more predictable. 顺便说一句 -使用2的幂作为第二个数字可以使其更加可预测。

Ignoring RNGs that use some physical input (random clock bits, electrical noise, etc) all software RNGs are predicable, given the same starting conditions. 在给定相同的启动条件的情况下,忽略使用某些物理输入(随机时钟位,电噪声等)的RNG,所有软件RNG都是可预测的。 They are, after all, (hopefully) deterministic computer programs. 毕竟,它们是(希望)确定性的计算机程序。

There are some algorithms that intentionally include the physical input (by, eg, sampling the computer clock occasionally) in attempt to prevent predictability, but those are (to my knowledge) the exception. 有一些算法故意包括物理输入(例如,通过偶尔采样计算机时钟)以防止可预测性,但是(据我所知)是例外。

So any "conventional" RNG, given the same seed and implemented to the same specification, should produce the same sequence of "random" numbers. 因此,给定相同的种子并按相同的规范实现的任何“常规” RNG,都应产生相同的“随机”数序列。 (This is why a computer RNG is more properly called a " pseudo-random number generator".) (这就是为什么计算机RNG更恰当地称为“ 伪随机数生成器”的原因。)

The fact that an RNG can be seeded with a previously-used seed and reproduce a "known" sequence of numbers does not make the RNG any less secure than one where your are somehow prevented from seeding it (though it may be less secure than the fancy algorithms that reseed themselves at intervals). RNG可以用先前使用的种子进行播种并复制“已知”数字序列的事实,并不会使RNG的安全性比无法阻止您播种的RNG的安全性高(尽管它可能比RNG的安全性低)。花哨的算法会定期重新设置自身)。 And the ability to do this -- to reproduce the same sequence again and again is not only extraordinarily useful in testing, it has some "real life" applications in encryption and other security applications. 这样做的能力-一次又一次地重现相同的序列,不仅在测试中非常有用,而且在加密和其他安全性应用程序中具有“现实生活”的应用程序。 (In fact, an encryption algorithm is, in essence, simply a reproducible random number generator.) (实际上,加密算法本质上就是一个可重现的随机数生成器。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM