Today, I was doing some tests in .NET Core, and I have come across some interesting thing.
Before (~ .NET Framework 4), Random
used Environment.TickCount
, but now I believe this has changed.
Consider the following code:
while (true)
{
Random random = new Random();
Console.WriteLine(random.Next(0, 10000));
}
In older .NET Framework versions, the new Random()
empty constructor would use Environment.TickCount, which would lead to repetition of pseudo-random values.
So you could expect results like:
542
4211
5244
5244
5244
9501
9501
so on and so fourth.
On the latest .NET Core version using the latest compiler, I have received the following result:
5332
220
3928
524
2973
2840
4965
5667
657
6434
3170
3046
7044
Which is definitely improved.
Other S.O questions demonstrating this behaviour in older versions:
How do I generate a random int number?
generate random numbers with no repeat in c#
Is C# Random Number Generator thread safe?
My setup: .NET Core 2.2 / latest C# compiler.
The actual question
So my question is, has the PRNG really improved or they just changed constructor to use another default seeds, and, if so, what they're using as a seed? Is it safer now for cryptography (if they actually changed the implementation)?
Answer
In the latest version of dotnet core, the Random
default constructor assigns its seed from a hidden private instance of Random
. The private instance uses Interop.GetRandomBytes for its seed. New instances use the private instances's Next()
result as its seed.
This basically makes it 'safe' to create several random instances in a loop.
Read more on the corefx GitHub:
Related code files: Private Random Instance, Default Constructor - Generate Seed and Private Random Instance - Generate Seed.
Seed change pull request Parameterless constructor seeding improvement #1919
No comments:
Post a Comment