-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Deprecate Random()
default constructor, replace with Random.insecure()
#59715
Comments
+1 for just deprecating the unnamed constructor and making users choose one. |
I think it's an educational problem, but that it might not be a solvable problem. It requires users to know that secure and insecure random generators exist, that they need a secure random generator for a particular problem, and that they should never assume a random generator to be secure unless it explicitly says that it is. If they already know that, then they'll look for Having the plain That won't necessarily help the user realize whether they need security or not, but if there are only two explicitly named constructors, they'll at least be aware that they are making a choice. Only they can know what the right choice is. I don't use We hould be aware that, fx,
Really? Which? If it's not security, then you are at most risking bad distribution. That can be a performance problem, but that can scale to denial-of-service levels of performance problems. That probably won't be the only problem that code has. using secure random might just cause other performance issues. (If it is security, then it's never going to be secure if it is written by someone who used the first random generator they found. I'd rather they leave in this big red flag, so I can recognize it, than they just as blindly uses |
I think I prefer See also naming suggestions and arguments for and against making the default secure vs fast at https://news.ycombinator.com/item?id=42406773
I think it would make sense for us to use |
Of particular interest today is ef5295d |
Well, it was security. I'm reading the linked article on Hackernews. One refers to DTD with
The port is not security (you can scan 65536 ports fast enough that it doesn't matter whether it's predictable). That's just trying to avoid collisions. A predictable secret is a failure, because that should be secret and unpredictable. Would that code have been written differently if the author had had to write And relevantly, the SelfPrivacy example contains the code Let's do the rename. Let's consider uses of Having a slightly higher chance of avoiding mistakes like this is probably worth a little extra hassle for people who just want fast random numbers. (They can make their own |
I do think it should be explicitly named I do believe that would have avoided the specific issue at hand. It is much more obvious in review too. |
In a few simulation games the random seed and the inputs are shared to generate the same output in different machines. That way the output doesn't need to be shared across the network. Could "deterministic" be a good name or would it be too long and also weird to see import 'dart:math';
main() {
final (seed, inputs) = (42, [10, 10, 10]);
final random = Random(seed);
print(inputs.map(random.nextInt)); // Always prints 7, 8, 4.
} I thought calling |
Some patterns use a different generator if you give it a seed, than if you don't. Calling (The |
We can consider whether to change the That prompts the question of where to get 64 bits of entropy from. |
For me, the surprising fact was not that the default constructor is cryptographically insecure (this is well documented), but that there are "only" 2^32 different streams of pseudo random numbers, and that the seed could be brute-forced in less than 10 seconds with a modern CPU. IMHO, you should document that the (explicit or implicit) seed is restricted to 32 bits – or losen that restriction. |
We should probably document that this is a 32 bit RNG. It only emits 32 bits at a time (the doubles only have 32 significant bits, not 52). Even if the seed had more bits of entropy (and I wouldn't assume the current one even has 32 bits of real entropy), you should still assume that it can be broken in 10 seconds or less. Maybe not by brute force, but by any number of other techniques to reverse a hash. It's not secure, which means that you must assume that a dedicated opponent can create collisions, or reverse engineer at least some of the state, just by looking at the output. If you worry about having collisions in your own code, like starting a lot of independent processes and expecting a low risk of collision, then I can see why a larger set of starting states is relevant. Being breakable by a competent attacker isn't going to change. It's not secure against attacks. |
Sounds like this issue is discussing three separate changes that could be implemented independently:
|
Using an insecure seed for a random source is the wrong choice for many typical uses of random input. It would be easier to catch misuse if the constructor had a more obvious name. The default constructor, if anything, should be the safer version. If we think we can get away with changing behavior for current usage we could change the unnamed constructor to secure and add and insecure name constructor. If we think changing behavior is too risky (I lean this way) we can keep both named for the long term and deprecate the unnamed.
@lrhn what do you think?
The text was updated successfully, but these errors were encountered: