www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - std.random suggestions

reply Denis Feklushkin <feklushkin.denis gmail.com> writes:
I don't like the way the module std.random is designed

 From a software side we have three types of ~random numbers 
sources:

1. Hardware (or environmental) "true" noise.
The most reliable source, which may not be that fast, i.e. it may 
be emptied in some cases, so it can be blocking and non-blocking 
in block devices terms.
This is exacatly what provided by /dev/random in Linux. It should 
also be noted that this random source type does not exist on all 
platforms.

2. Based on hardware noise (described in 1) seeded pseudo-random 
sequence.
Less (but still) reliable because it extrapolates a true random 
number using a deterministic algorithm (like described in 3 
below). Suitable for generating large volumes of numbers.
This is exacatly what provided by /dev/urandom in Linux. Again, 
not all platforms providing it.

3. Pre-determined pseudorandom sequences based on some 
predictable algorithm.
Also good for getting large amounts of numbers and fast, but it 
strictly can't be used for cryptography etc. Its advantage is 
that it is always available in all systems since (at worst) it is 
just a mathematical function.

I think if we save users from deepening into details this will 
only go to the benefit of security. So, my suggestion:

1. Do not provide any access about entropy sources (I am about 
std.internal.entropy.EntropySource.tryAll and 
forceEntropySource). At the application programming level we 
usually have one source of true entropy. (If this is not so 
please correct me.) No need to make ambitious interfaces 
describing the theoretical diversity of RNGs. The "entropy" word 
can be excluded from the API description completely.

2. Completely exclude "seeding" concept: this is a source of 
potential issues 
(https://github.com/dlang/phobos/pull/10865/commits/3c2f87ef745ca6de6e3920
7421af81e661aecbe). Seeding can be encapsulated inside of of urandom generator
(see 2 above) if needed.

In fact, you know exactly what amount and quality of random bytes 
you want to get at some point of your code. And, for example, if 
system does not provides true RNG needed by you, then let the 
corresponding function be totally unavailable for compilation and 
leads to compile time error. Then you can't accidentally build 
your neat designed software with weak predictable RNG.

It follows from this that it is necessary to provide only four 
points for obtaining random numbers, all without the need for any 
combining of them by users. (My suggestion is place each of it in 
dedicated std.random.* module)

1. std.random.truerandom: implemented as OS/hardware call if 
system provides hardware (or environmental) random number 
generator. Suitable for encryption key generation, etc. Maybe 
three functions will be provided, something like:

ubyte[Size] trueRandom(size_t Size)(); // blocks and waits if no 
enough entropy
bool trueRandom(ref ubyte[] result); // returns false if no 
enough entropy
void trueRandomEx(ref ubyte[] result); // throws if no enough 
entropy

If there is no random number generator in the system, then these 
functions will not be available and the compilation may end with 
the error!

2. std.random.seededrandom: function(s) that is implemented 
either by OS call (for Linux/Windows/Mac) or by some another TRNG 
call + PseudoRandom (on baremetal platforms). Does not blocks and 
not throws. Does not exist if there is no TRNG avalable because 
internally uses seed value. So, again: if there is no random 
number generator in the system, then these functions will not be 
available and the compilation may fail.
These are pretty good random numbers for general purpose like 
UUID generation.

3. std.random.pseudorandom.pseudoRandom: not for cryptography at 
all. Name was specifically chosen so that the user would clearly 
see the "pseudo" prefix.
Suitable for drawing a starry sky in a retro games or so one. 
Internally calls std.random.seededrandom if exists or uses 
std.random.predetermined (4) with seed value if seededrandom 
doesn't exist. Guaranteed to exist on all platforms.

4. std.random.predetermined: functions implementing pseudorandom 
number generators (PRNG). Mostly for internal use, but sometimes 
users may want to get guaranteed repeatability of pseudorandom 
sequences.

That's all, and nothing superfluous! I.e., if you do not use 
something, it does not creates any global variables, etc. From 
the point of view of the user, seems, everything is also simple 
and clear. It will be difficult to make a issue with RNG in this 
case.

Perhaps this is suitable for Phobos 3?
Sep 16
next sibling parent reply "Richard (Rikki) Andrew Cattermole" <richard cattermole.co.nz> writes:
On 17/09/2025 12:04 AM, Denis Feklushkin wrote:
 Perhaps this is suitable for Phobos 3?
Not for V2. https://github.com/dlang/PhobosV3-Design
Sep 16
next sibling parent Denis Feklushkin <feklushkin.denis gmail.com> writes:
On Tuesday, 16 September 2025 at 12:08:38 UTC, Richard (Rikki) 
Andrew Cattermole wrote:

 Not for V2.

 https://github.com/dlang/PhobosV3-Design
https://github.com/dlang/PhobosV3-Design/discussions/42
Sep 16
prev sibling next sibling parent reply Denis Feklushkin <feklushkin.denis gmail.com> writes:
On Tuesday, 16 September 2025 at 12:08:38 UTC, Richard (Rikki) 
Andrew Cattermole wrote:
 On 17/09/2025 12:04 AM, Denis Feklushkin wrote:
 Perhaps this is suitable for Phobos 3?
Not for V2.
There is also a suggestion to urgently fix problem with "true" random numbers in Phobos v2 right now: it is just need to extend `std.random.unpredictableSeed` template with template argument ubyte[] Such patch will be accepted?
Sep 16
parent reply "H. S. Teoh" <hsteoh qfbox.info> writes:
On Tue, Sep 16, 2025 at 06:59:01PM +0000, Denis Feklushkin via Digitalmars-d
wrote:
 On Tuesday, 16 September 2025 at 12:08:38 UTC, Richard (Rikki) Andrew
 Cattermole wrote:
 On 17/09/2025 12:04 AM, Denis Feklushkin wrote:
 Perhaps this is suitable for Phobos 3?
Not for V2.
There is also a suggestion to urgently fix problem with "true" random numbers in Phobos v2 right now: it is just need to extend `std.random.unpredictableSeed` template with template argument ubyte[] Such patch will be accepted?
I'm not the one making decisions here, but from what I understand, std.random.unpredictableSeed is not meant to be a general interface for getting random bytes from the OS. It's meant to be an abstraction for obtaining a (small) system-dependent value suitable for seeding pseudo-random generators like the ones you'd use for games or Monte Carlo simulations. It just so happened that whoever implemented .unpredictableSeed decided to make use of OS random number APIs for obtaining this seed, but it was never meant for user code to call .unpredictableSeed as a source of random numbers. If you want an API for getting random numbers from the OS, you probably need to propose a new module, or at the very least a new function in std.random. T -- People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird. -- D. Knuth
Sep 16
parent Denis Feklushkin <feklushkin.denis gmail.com> writes:
On Tuesday, 16 September 2025 at 19:06:27 UTC, H. S. Teoh wrote:

 If you want an API for getting random numbers from the OS, you 
 probably need to propose a new module, or at the very least a 
 new function in std.random.
Technically, proposed new template will be a new function It just doesn't make sense to duplicate (for the third time, probably) code that calls getrandom
Sep 16
prev sibling parent reply Denis Feklushkin <feklushkin.denis gmail.com> writes:
On Tuesday, 16 September 2025 at 12:08:38 UTC, Richard (Rikki) 
Andrew Cattermole wrote:
 On 17/09/2025 12:04 AM, Denis Feklushkin wrote:
 Perhaps this is suitable for Phobos 3?
Not for V2.
...But why? My proposal does not involve changing to the current API. But it will be possible to declare it obsolete later, gradually
Sep 17
parent "Richard (Rikki) Andrew Cattermole" <richard cattermole.co.nz> writes:
On 17/09/2025 11:09 PM, Denis Feklushkin wrote:
 On Tuesday, 16 September 2025 at 12:08:38 UTC, Richard (Rikki) Andrew 
 Cattermole wrote:
 On 17/09/2025 12:04 AM, Denis Feklushkin wrote:
 Perhaps this is suitable for Phobos 3?
Not for V2.
...But why? My proposal does not involve changing to the current API. But it will be possible to declare it obsolete later, gradually
I've had a chat with Adam Wilson regarding your question, unfortunately he isn't able to reply right now. He is the one heading up V3. The official position is that V2 is on life support, work like this is currently considered out of scope. As for std.random replacement, first up is cryptography where calls out to systems libraries will be used in place of anything on our end. After which we can revisit non-cryptographic algorithms.
Sep 17
prev sibling next sibling parent reply Serg Gini <kornburn yandex.ru> writes:
On Tuesday, 16 September 2025 at 12:04:20 UTC, Denis Feklushkin 
wrote:
 I don't like the way the module std.random is designed
 Perhaps this is suitable for Phobos 3?
I think we also should take into account - http://mir-random.libmir.org/ - https://dlangscience.github.io/dstats/api/dstats/random.html
Sep 16
parent Denis Feklushkin <feklushkin.denis gmail.com> writes:
On Tuesday, 16 September 2025 at 12:36:41 UTC, Serg Gini wrote:
 On Tuesday, 16 September 2025 at 12:04:20 UTC, Denis Feklushkin 
 wrote:
 I don't like the way the module std.random is designed
 Perhaps this is suitable for Phobos 3?
I think we also should take into account - http://mir-random.libmir.org/ - https://dlangscience.github.io/dstats/api/dstats/random.html
This is more high-level functions mir-random have ~roughly same design as current std.random
Sep 16
prev sibling next sibling parent reply "H. S. Teoh" <hsteoh qfbox.info> writes:
On Tue, Sep 16, 2025 at 12:04:20PM +0000, Denis Feklushkin via Digitalmars-d
wrote:
 I don't like the way the module std.random is designed
[...]
 I think if we save users from deepening into details this will only go
 to the benefit of security. So, my suggestion:
 
 1. Do not provide any access about entropy sources (I am about
 std.internal.entropy.EntropySource.tryAll and forceEntropySource).
[...] Users are not supposed to use anything from std.internal. It's named "internal" for a reason.
 2. Completely exclude "seeding" concept: this is a source of potential
 issues
 (https://github.com/dlang/phobos/pull/10865/commits/3c2f87ef745ca6de6e392007421af81e661aecbe).
 Seeding can be encapsulated inside of of urandom generator (see 2
 above) if needed.
Seeding is useful for Monte Carlo simulations where you need pseudorandom numbers in large quantity, but completely reproducible from a seed value (e.g. for verification of certain results). Being unable to use seeding means users have to roll their own generators, which usually means it's done poorly because generating random numbers is not as simple as it looks. [...]
 It follows from this that it is necessary to provide only four points
 for obtaining random numbers, all without the need for any combining
 of them by users. (My suggestion is place each of it in dedicated
 std.random.* module)
std.random is not designed for cryptographically-safe random generation. We neither have the resources nor the expertise to do this. It should NOT be used for anything related to authentication, security, cryptography, or anything similar. If you need random numbers for any of these areas, please use a battle-tested library like openssl or one of the similar variants. It's unsafe to use anything that wasn't explicitly designed for security.
 1. std.random.truerandom: implemented as OS/hardware call if system
 provides hardware (or environmental) random number generator. Suitable
 for encryption key generation, etc. Maybe three functions will be
 provided, something like:
There's no need for this. You could just open /dev/random or /dev/urandom as a file yourself, and read whatever you need from it. It's OS-dependent anyway, so there's no need to add another layer of abstraction to pretend that you're portable. The problem with offering a crypto-level RNG in the standard library is that you need an active maintainer who's keeping on top of the latest security weaknesses and updates, and who has the expertise to actually understand the issues involved, because when it comes to crypto, rolling your own is extremely risky and almost certain to fall into unexpected pitfalls that will greatly weaken the security of your applications. We have no such person and no such expertise currently. Unless a crypto researcher shows up who has the time and energy to spend in such a project, I don't think we should go this route. Or if what you're really asking for is an API to /dev/random or /dev/urandom, then why not just open them as files yourself? That's why these devices are in /dev/ in the first place. [...]
 3. std.random.pseudorandom.pseudoRandom: not for cryptography at all.
 Name was specifically chosen so that the user would clearly see the
 "pseudo" prefix.
[...] What's currently in std.random falls in this category. Wouldn't be a bad idea to rename it this way. Good idea. T -- Real men don't take backups. They put their source on a public FTP-server and let the world mirror it. -- Linus Torvalds
Sep 16
next sibling parent Denis Feklushkin <feklushkin.denis gmail.com> writes:
On Tuesday, 16 September 2025 at 15:06:39 UTC, H. S. Teoh wrote:
 On Tue, Sep 16, 2025 at 12:04:20PM +0000, Denis Feklushkin via 
 Digitalmars-d wrote:
 I don't like the way the module std.random is designed
[...]
 I think if we save users from deepening into details this will 
 only go to the benefit of security. So, my suggestion:
 
 1. Do not provide any access about entropy sources (I am about 
 std.internal.entropy.EntropySource.tryAll and 
 forceEntropySource).
[...] Users are not supposed to use anything from std.internal. It's named "internal" for a reason.
Yes. But I saw that this function is public out and the fact that it even exists is strange.
 2. Completely exclude "seeding" concept: this is a source of 
 potential
 issues
 (https://github.com/dlang/phobos/pull/10865/commits/3c2f87ef745ca6de6e392007421af81e661aecbe).
 Seeding can be encapsulated inside of of urandom generator 
 (see 2
 above) if needed.
Seeding is useful for Monte Carlo simulations where you need pseudorandom numbers in large quantity, but completely reproducible from a seed value (e.g. for verification of certain results).
Sugggested `std.random.predetermined` exactly for this purpose At the moment I see that `unpredictableSeed` used for seeding returns 32 bits by default and called everywhere. 128 or 256 bits is more preferable. I am convinced that this occurs because we did not provide a simple function that returns just an array of random bytes. More precisely, we hid its name behind this "Seed" name
 std.random is not designed for cryptographically-safe random 
 generation.
It is in vain!
 We neither have the resources nor the expertise to do this.
We need just a copy bytes from TRNG to our arrays or ranges. This is not looks unsafe.
 1. std.random.truerandom: implemented as OS/hardware call if 
 system provides hardware (or environmental) random number 
 generator. Suitable for encryption key generation, etc. Maybe 
 three functions will be provided, something like:
There's no need for this. You could just open /dev/random or /dev/urandom as a file yourself, and read whatever you need from it. It's OS-dependent anyway, so there's no need to add another layer of abstraction to pretend that you're portable.
But in fact, this has already been implemented in `unpredictableSeed`
 The problem with offering a crypto-level RNG in the standard 
 library is that you need an active maintainer who's keeping on 
 top of the latest security weaknesses and updates,
All of this is already implemented in the operating systems we use - we just need to use the appropriate APIs.
 Or if what you're really asking for is an API to /dev/random or 
 /dev/urandom, then why not just open them as files yourself?
Because I do not want to research this for MacOS during developing on Linux. Usula all I want is 8-16 random bytes obtained in the way recommended by the target system.
 That's why these devices are in /dev/ in the first place.
Also /dev/* can be unavailable at load stages, getrandom is recommended way on Linux
 [...]
 3. std.random.pseudorandom.pseudoRandom: not for cryptography 
 at all. Name was specifically chosen so that the user would 
 clearly see the "pseudo" prefix.
[...] What's currently in std.random falls in this category. Wouldn't be a bad idea to rename it this way. Good idea.
Thanks
Sep 16
prev sibling parent Monkyyy <crazymonkyyy gmail.com> writes:
On Tuesday, 16 September 2025 at 15:06:39 UTC, H. S. Teoh wrote:
 to roll their own generators, which usually means it's done 
 poorly because generating random numbers is not as simple as it 
 looks.
 std.random is not designed for cryptographically-safe random
Insecure random numbers are trivial, very trivial. The cope of meta programming a whole theory o randomness that no one uses and writing it off as "not designed to be advanced randomness" is a worse of both worlds take. I don't know what goes into crypto level randomness but that airnt what I want or and what I want wasn't offered
Sep 16
prev sibling next sibling parent reply Monkyyy <crazymonkyyy gmail.com> writes:
On Tuesday, 16 September 2025 at 12:04:20 UTC, Denis Feklushkin 
wrote:
 2. Completely exclude "seeding" concept: this is a source of
You can make it implict called, and leave the data public for whoever wants it. Private whatever meme is a bad take in general, but especially in such a well understood and you unable to predict all usecases, magic value.
Sep 16
parent reply Denis Feklushkin <feklushkin.denis gmail.com> writes:
On Tuesday, 16 September 2025 at 18:04:20 UTC, Monkyyy wrote:
 On Tuesday, 16 September 2025 at 12:04:20 UTC, Denis Feklushkin 
 wrote:
 2. Completely exclude "seeding" concept: this is a source of
You can make it implict called, and leave the data public for whoever wants it.
It is difficult to achieve this because in most cases it will be just a libc getrandom() call (system-wide seeded PRNG)
Sep 16
parent reply monkyyy <crazymonkyyy gmail.com> writes:
On Tuesday, 16 September 2025 at 18:10:22 UTC, Denis Feklushkin 
wrote:
 On Tuesday, 16 September 2025 at 18:04:20 UTC, Monkyyy wrote:
 On Tuesday, 16 September 2025 at 12:04:20 UTC, Denis 
 Feklushkin wrote:
 2. Completely exclude "seeding" concept: this is a source of
You can make it implict called, and leave the data public for whoever wants it.
It is difficult to achieve this because in most cases it will be just a libc getrandom() call (system-wide seeded PRNG)
your suggested api does nothing for the majority of trivial randomness use cases Video games, fuzzing, and algorithms uses of randomness can be both fairly cheap and in each I would want deterministic playback for when I need it. Access to the seed is nessery for many video game randomness hacks, and unit testing some random values is great and all but if you looking at a 1 in 100000 bug youd want to be able to hack in a reported seed for *when* it breaks, then speed testing randomness-using algorithms could want to redo tests as well if something seemed slow. Fast randomness and secure randomness are different problems.
Sep 16
parent reply Denis Feklushkin <feklushkin.denis gmail.com> writes:
On Tuesday, 16 September 2025 at 18:59:48 UTC, monkyyy wrote:
 On Tuesday, 16 September 2025 at 18:10:22 UTC, Denis Feklushkin 
 wrote:
 On Tuesday, 16 September 2025 at 18:04:20 UTC, Monkyyy wrote:
 On Tuesday, 16 September 2025 at 12:04:20 UTC, Denis 
 Feklushkin wrote:
 2. Completely exclude "seeding" concept: this is a source of
You can make it implict called, and leave the data public for whoever wants it.
It is difficult to achieve this because in most cases it will be just a libc getrandom() call (system-wide seeded PRNG)
your suggested api does nothing for the majority of trivial randomness use cases
I disagree. I proposed major step forward for our ecosystem: you can just go and get 49 random bytes buffer. No seeding, no new calls to Random() (or genRnd?), etc. Just get a random sequence. All sorts of whistles and bells can be screwed on top of this, if need. For repeating sequences, I also proposed a solution. And I am categorically against "universal solution" with classes, seed-accepting constructors, and all the other overengineering as we have now - even experienced people can't use it correctly, as practice shows. (I myself even remember using a third-party library to generate a random number because I was just too lazy to figure out the standard one.)
Sep 16
parent reply monkyyy <crazymonkyyy gmail.com> writes:
On Tuesday, 16 September 2025 at 19:25:58 UTC, Denis Feklushkin 
wrote:
 On Tuesday, 16 September 2025 at 18:59:48 UTC, monkyyy wrote:
 On Tuesday, 16 September 2025 at 18:10:22 UTC, Denis 
 Feklushkin wrote:
 On Tuesday, 16 September 2025 at 18:04:20 UTC, Monkyyy wrote:
 On Tuesday, 16 September 2025 at 12:04:20 UTC, Denis 
 Feklushkin wrote:
 2. Completely exclude "seeding" concept: this is a source of
You can make it implict called, and leave the data public for whoever wants it.
It is difficult to achieve this because in most cases it will be just a libc getrandom() call (system-wide seeded PRNG)
your suggested api does nothing for the majority of trivial randomness use cases
I disagree. I proposed major step forward for our ecosystem: you can just go and get 49 random bytes buffer. No seeding, no new calls to Random() (or genRnd?), etc. Just get a random sequence.
Insecure randomness can just grab unixtime and poke it once. Your adding allot of complexity that I would manually untangle to find "better" 64 bits of data
 For repeating sequences, I also proposed a solution.
You proposed one new api (I get to learn, fun) that solves 1 kind of determistic replay, off the top of my head I can think of 3 You simply ignored my fuzzing example, to replay failed fuzzing unit tests you would need to be able to replay the sequence *from separate compiles and execution*. No Im not storing that manually, I need 5 lines of code ported from c ("unsafe" randomness is trivial everyone) and a someplace where a 64 bit int exists. The fuzzing lib then conditionally sets the seed or reports it before use.
Sep 16
parent Denis Feklushkin <feklushkin.denis gmail.com> writes:
On Tuesday, 16 September 2025 at 19:58:59 UTC, monkyyy wrote:

 your suggested api does nothing for the majority of trivial 
 randomness use cases
I disagree. I proposed major step forward for our ecosystem: you can just go and get 49 random bytes buffer. No seeding, no new calls to Random() (or genRnd?), etc. Just get a random sequence.
Insecure randomness can just grab unixtime and poke it once. Your adding allot of complexity
I think maybe you just didn't understand the idea. I propose to simplify everything by throwing out some seed abstractions and classes. Because that they are not needed by 99% of users, and those who will need them easily will make them themselves (I will show how below) And also I suggested simple functions (not classes with ctros and methods) for just. obtaining. randomized. buffer. (that are currently lacking because we are afraid to break the laws and get caught by the crypto-police) (I thought that maybe proposed functions will be compatible with betterC? Hmm)
 that I would manually untangle to find "better" 64 bits of data

 For repeating sequences, I also proposed a solution.
You proposed one new api (I get to learn, fun) that solves 1 kind of determistic replay, off the top of my head I can think of 3 You simply ignored my fuzzing example, to replay failed fuzzing unit tests you would need to be able to replay the sequence *from separate compiles and execution*. No Im not storing that manually, I need 5 lines of code ported from c ("unsafe" randomness is trivial everyone) and a someplace where a 64 bit int exists. The fuzzing lib then conditionally sets the seed or reports it before use.
I ignored it because I thought the answer was obvious. No one will take away your seeding and `Random()`: "seed" is just "true random" sequence, yes? It will be provided by `std.random.truerandom.getTrueRandom()` call `Random()` is just one of `std.random.predetermined` functions That's all. And you know what it is and how it works.
Sep 16
prev sibling next sibling parent reply Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On Tuesday, 16 September 2025 at 12:04:20 UTC, Denis Feklushkin 
wrote:
 I don't like the way the module std.random is designed

 From a software side we have three types of ~random numbers 
 sources:
 That's all, and nothing superfluous! I.e., if you do not use 
 something, it does not creates any global variables, etc. From 
 the point of view of the user, seems, everything is also simple 
 and clear. It will be difficult to make a issue with RNG in 
 this case.

 Perhaps this is suitable for Phobos 3?
To be honest this seems like a major overengineering. It’s a given in a whole lot of languages that random means PRNG with optional seed. The seed could be obtained via some function to be largely unpredictable, with the benefit that you could replay the program with a particular seed to ease debugging / fuzzing etc. Now of hardware sources most language would provide CryptoRandom which takes the bits from whatever deemed as secure source of random bits, most likely get_random or /dev/urandom (yes it is fine for generating keys, check the literature). Everything else is plain overengineering and deserves to be written in 3rd party library by these willing to pursue it.
Sep 17
next sibling parent Denis Feklushkin <feklushkin.denis gmail.com> writes:
On Wednesday, 17 September 2025 at 09:00:44 UTC, Dmitry Olshansky 
wrote:
 On Tuesday, 16 September 2025 at 12:04:20 UTC, Denis Feklushkin 
 wrote:
 I don't like the way the module std.random is designed

 From a software side we have three types of ~random numbers 
 sources:
 That's all, and nothing superfluous! I.e., if you do not use 
 something, it does not creates any global variables, etc. From 
 the point of view of the user, seems, everything is also 
 simple and clear. It will be difficult to make a issue with 
 RNG in this case.

 Perhaps this is suitable for Phobos 3?
To be honest this seems like a major overengineering.
Nope, this is a statement of the factual situation on 2025. All these things are already implemented inside of `std.random` and `std.internal.entropy` whether you want it or not. At the same time, with all the current overengineered(!) code you can't take 256 bit seed at all. (This size, as far as I know, is the recommended seed size for now.)
 It’s a given in a whole lot of languages that random means PRNG 
 with optional seed. The seed could be obtained via some 
 function to be largely unpredictable, with the benefit that you 
 could replay the program with a particular seed to ease 
 debugging / fuzzing etc.
Let me repeat a good example of an issue due to current `std.random` overcomplication: https://github.com/dlang/phobos/pull/10865 This wouldn't happen if we simply provided a function that would simply return a random buffer.
 Now of hardware sources most language would provide 
 CryptoRandom which takes the bits from whatever deemed as 
 secure source of random bits, most likely get_random or 
 /dev/urandom (yes it is fine for generating keys, check the 
 literature). Everything else is plain overengineering and 
 deserves to be written in 3rd party library by these willing to 
 pursue it.
Copied from https://github.com/dlang/PhobosV3-Design/discussions/42#discus ioncomment-14426280 : I think the opposite: OS can have any (proprietary) patch/module/driver about random and urandom sources. Architecture-independent standard library should not rely at all for a specific operating system internals. So we need an architecture-independent library that should take random/urandom difference into account And it is also need to understand that declaring of abandoning cryptographic quality of randoms in 2025 is nonsense! We have plenty of everyday applications of real true random numbers now. Distributed computend relies to them (see UUIDv7). TRNG generators have been built into all modern CPUs for 10 years now.
Sep 17
prev sibling parent reply IchorDev <zxinsworld gmail.com> writes:
On Wednesday, 17 September 2025 at 09:00:44 UTC, Dmitry Olshansky 
wrote:
 To be honest this seems like a major overengineering. It’s a 
 given in a whole lot of languages that random means PRNG with 
 optional seed. The seed could be obtained via some function to 
 be largely unpredictable, with the benefit that you could 
 replay the program with a particular seed to ease debugging / 
 fuzzing etc.

 Now of hardware sources most language would provide 
 CryptoRandom which takes the bits from whatever deemed as 
 secure source of random bits, most likely get_random or 
 /dev/urandom (yes it is fine for generating keys, check the 
 literature). Everything else is plain overengineering and 
 deserves to be written in 3rd party library by these willing to 
 pursue it.
Agreed. If anything, std.random is very well designed because it uses the range interface in a clever way.
Sep 18
parent reply Denis Feklushkin <feklushkin.denis gmail.com> writes:
On Thursday, 18 September 2025 at 12:53:25 UTC, IchorDev wrote:

 literature). Everything else is plain overengineering and 
 deserves to be written in 3rd party library by these willing 
 to pursue it.
Agreed. If anything, std.random is very well designed because it uses the range interface in a clever way.
Range interface is not unique to `std.random`. Same template patterns are possible in any other implementation. [I already made code](https://github.com/denizzzka/misc/tree/master/random) which I described in the main post. This is how I propose generate randoms using ranges: ```d int[] iarr = generate!(() => rndGen!int).take(5).array; ``` `rndGen` is helper template, it calls random generation for each range element. In my opinion, there's no difference in use such ranges with `std.random`. In addition, you also get access to basic functions for generating cryptographically secure random sequences without overhead and with lower possibility of screwing up with its calling: ```d ubyte[24] buf; getSeededRandomBlocking(buf); ``` It's very simple, yes. I think the last line covers 95% of all needings. (And I hope someone will ask why this function is called this way)
Sep 19
parent reply IchorDev <zxinsworld gmail.com> writes:
On Friday, 19 September 2025 at 16:38:59 UTC, Denis Feklushkin 
wrote:
 On Thursday, 18 September 2025 at 12:53:25 UTC, IchorDev wrote:
 If anything, std.random is very well designed because it uses 
 the range interface in a clever way.
Range interface is not unique to `std.random`.
That's what makes it well designed, obviously. You're the one who said
 I don't like the way the module std.random is designed
An integral part of why its design is good is that it uses the range interface rather than reinventing the wheel. Someone like you who can't understand the good parts of `std.random`'s design has no place in suggesting changes to it.
Sep 20
next sibling parent reply monkyyy <crazymonkyyy gmail.com> writes:
On Saturday, 20 September 2025 at 18:42:03 UTC, IchorDev wrote:
 On Friday, 19 September 2025 at 16:38:59 UTC, Denis Feklushkin 
 wrote:
 On Thursday, 18 September 2025 at 12:53:25 UTC, IchorDev wrote:
 If anything, std.random is very well designed because it uses 
 the range interface in a clever way.
Range interface is not unique to `std.random`.
That's what makes it well designed, obviously. You're the one who said
 I don't like the way the module std.random is designed
An integral part of why its design is good is that it uses the range interface rather than reinventing the wheel. Someone like you who can't understand the good parts of `std.random`'s design has no place in suggesting changes to it.
Using ranges where they dont belong is bad design; I think v3 will deprecate at least my complaint that nullable shouldnt be a range
Sep 20
parent IchorDev <zxinsworld gmail.com> writes:
On Saturday, 20 September 2025 at 19:31:48 UTC, monkyyy wrote:
 On Saturday, 20 September 2025 at 18:42:03 UTC, IchorDev wrote:
 An integral part of why its design is good is that it uses the 
 range interface rather than reinventing the wheel.
Using ranges where they dont belong is bad design
Every random number generator implementation that I've seen essentially functions like an infinite range: - `front` gets the current state. - `popFront` mutates the state, giving us our next random number. - `empty` is `false`.
Sep 21
prev sibling next sibling parent Denis Feklushkin <feklushkin.denis gmail.com> writes:
On Saturday, 20 September 2025 at 18:42:03 UTC, IchorDev wrote:
 On Friday, 19 September 2025 at 16:38:59 UTC, Denis Feklushkin 
 wrote:
 On Thursday, 18 September 2025 at 12:53:25 UTC, IchorDev wrote:
 If anything, std.random is very well designed because it uses 
 the range interface in a clever way.
Range interface is not unique to `std.random`.
That's what makes it well designed, obviously.
This is neither a necessary nor a sufficient condition. Also, wonderful D template ranges can be attached to any interface easily.
Sep 20
prev sibling parent reply Dennis <dkorpel gmail.com> writes:
On Saturday, 20 September 2025 at 18:42:03 UTC, IchorDev wrote:
 Someone like you who can't understand the good parts of 
 `std.random`'s design has no place in suggesting changes to it.
Personal attacks are not allowed on this forum, please have a respectful discussion.
Sep 20
parent reply IchorDev <zxinsworld gmail.com> writes:
On Saturday, 20 September 2025 at 22:11:37 UTC, Dennis wrote:
 On Saturday, 20 September 2025 at 18:42:03 UTC, IchorDev wrote:
 Someone like you who can't understand the good parts of 
 `std.random`'s design has no place in suggesting changes to it.
Personal attacks are not allowed on this forum
What personal attack? There is no personal attack.
Sep 21
parent reply Dennis <dkorpel gmail.com> writes:
On Sunday, 21 September 2025 at 07:27:42 UTC, IchorDev wrote:
 On Saturday, 20 September 2025 at 22:11:37 UTC, Dennis wrote:
 On Saturday, 20 September 2025 at 18:42:03 UTC, IchorDev wrote:
 Someone like you who can't understand the good parts of 
 `std.random`'s design has no place in suggesting changes to 
 it.
Personal attacks are not allowed on this forum
What personal attack? There is no personal attack.
If you want an explanation, give that sentence to any LLM and it can tell you why it's a personal attack. Maybe you don't agree with the term 'personal attack', but either way, just see this as a friendly warning that in the future, using more of this kind of language can get your post deleted. Denis Feklushkin has been very respectful so he's welcome to post suggestions for std.random.
Sep 21
parent reply IchorDev <zxinsworld gmail.com> writes:
On Sunday, 21 September 2025 at 11:54:22 UTC, Dennis wrote:
 On Sunday, 21 September 2025 at 07:27:42 UTC, IchorDev wrote:
 On Saturday, 20 September 2025 at 22:11:37 UTC, Dennis wrote:
 On Saturday, 20 September 2025 at 18:42:03 UTC, IchorDev 
 wrote:
 Someone like you who can't understand the good parts of 
 `std.random`'s design has no place in suggesting changes to 
 it.
Personal attacks are not allowed on this forum
What personal attack? There is no personal attack.
If you want an explanation, give that sentence to any LLM and it can tell you why it's a personal attack.
Do not insult my intelligence by implying that something with no comprehension of the context of our conversation understands what I said better than I do myself. An LLM is a clueless machine; we are people. You are fully capable of explaining your reasoning.
 using more of this kind of language can get your post deleted.
Perhaps my statement was poorly worded, but I don't think that telling someone that they have no business trying to 'fix' something that they don't understand raises to the level of '[that] kind of language'; implying that I said something heinous about their character.
 Denis Feklushkin has been very respectful so he's welcome to 
 post suggestions for std.random.
And I will disagree when I think people are wrong.
Sep 21
next sibling parent monkyyy <crazymonkyyy gmail.com> writes:
On Monday, 22 September 2025 at 00:29:11 UTC, IchorDev wrote:
 Someone like you who can't understand
implying that I said something heinous about their character.
Its a personal attack
Sep 21
prev sibling next sibling parent claptrap <clap trap.com> writes:
On Monday, 22 September 2025 at 00:29:11 UTC, IchorDev wrote:
 On Sunday, 21 September 2025 at 11:54:22 UTC, Dennis wrote:

 Perhaps my statement was poorly worded, but I don't think that 
 telling someone that they have no business trying to 'fix' 
 something that they don't understand raises to the level of 
 '[that] kind of language'; implying that I said something 
 heinous about their character.
If you say **anything** negative about someone's character then it is by definition a personal attack. You're attacking the person, not his argument. And what you're doing now is the equivalent of punching someone and then saying "but it's not like he died, really so what's the problem?" I mean if the upper threshold for "civil discourse" is saying something "heinous" well that leaves pretty much everything on the table.
Sep 21
prev sibling parent Mike Parker <aldacron gmail.com> writes:
On Monday, 22 September 2025 at 00:29:11 UTC, IchorDev wrote:

 Perhaps my statement was poorly worded, but I don't think that 
 telling someone that they have no business trying to 'fix' 
 something that they don't understand raises to the level of 
 '[that] kind of language'; implying that I said something 
 heinous about their character.
Whatever your intent, a moderator perceived it as a potential issue and, rather than deleting the post, asked you not to do it again. That was the right move and should have been the end of it. There's nothing to argue here. So let's please get back on topic. I'll delete any further off topic posts. Thanks!
Sep 21
prev sibling next sibling parent reply 0xEAB <desisma heidel.beer> writes:
On Tuesday, 16 September 2025 at 12:04:20 UTC, Denis Feklushkin 
wrote:
 No need to make ambitious interfaces
`std.internal.entropy` an internal module — not meant for user code. From a user’s perspective, there is nothing to interface with.
 1. Do not provide any access about entropy sources (I am about 
 std.internal.entropy.EntropySource.tryAll and 
 forceEntropySource). At the application programming level we 
 usually have one source of true entropy. (If this is not so
`tryAll` in particular exists so that the module can be used in a backwards compatible manner to replace the low entropy solutions previously used underneath by Phobos. We’ve tried replacing them with one solution per platform directly and people got upset.
 At the application programming level we usually have one source 
 of true entropy.
At Phobos v2 level, we have no source of true entropy. An application using only that library has therefore none. At system level, there might be multiple options available — depending on factors like the OS version (like Linux kernels older than the `getrandom` syscall, or Windows that has two crypto APIs where the supported parameters have also changed over time) or the runtime environment (think of chroots without `/dev/`).
Sep 21
parent reply Denis Feklushkin <feklushkin.denis gmail.com> writes:
On Sunday, 21 September 2025 at 21:44:54 UTC, 0xEAB wrote:
 On Tuesday, 16 September 2025 at 12:04:20 UTC, Denis Feklushkin 
 wrote:
 No need to make ambitious interfaces
`std.internal.entropy` an internal module — not meant for user code. From a user’s perspective, there is nothing to interface with.
Yes. But I wrote this because I realized that access to `getentropy` and `getrandom` (here I mean system-independed analogs) is absolutely necessary and actually it is already implemented in `std.internal.entropy` Otherwise, for example, if we want to generate 3 bytes of random numbers from freshly created `Ranadom()` we spent at least 4 bytes of expensive "true entropy" to establish our own PRNG, which we also declared as cryptographically insecure. It's much easier and not error prone to directly access the system RNG or create our own generator with implicit global seed value (if system not provides CSPRNG for us). This will immediately make it possible to obtain crypto-secure random numbers.
 1. Do not provide any access about entropy sources (I am about 
 std.internal.entropy.EntropySource.tryAll and 
 forceEntropySource). At the application programming level we 
 usually have one source of true entropy. (If this is not so
`tryAll` in particular exists so that the module can be used in a backwards compatible manner to replace the low entropy solutions previously used underneath by Phobos. We’ve tried replacing them with one solution per platform directly and people got upset.
At the coding stage we know exactly what quality of random numbers we are agreed at this particular code point: maybe, people got upset because they actually wanted crypto-secure randoms? And if `std.random` returning the same sequence every time it's launched (I'm not even talking about cryptographic security), then this is most likely not what they want. We could further add methods I suggested so that the user knows exactly what quality of random numbers they'll obtain. And then old interface can be deprecated over time.
 At the application programming level we usually have one 
 source of true entropy.
At Phobos v2 level, we have no source of true entropy. An application using only that library has therefore none.
(But, in fact, for most modern systems we are calling `getentropy` inside of Phobos `std.internal.entropy`)
 At system level, there might be multiple options available — 
 depending on factors like the OS version (like Linux kernels 
 older than the `getrandom` syscall, or Windows that has two 
 crypto APIs where the supported parameters have also changed 
 over time) or the runtime environment (think of chroots without 
 `/dev/`).
Yes, I mentioned this: if TRNG isn't available, proposed functions simply won't be available. So user will either be forced to agree insecure pseudo-random sequences or be forced to find another way to achieve randomness.
Sep 22
parent Denis Feklushkin <feklushkin.denis gmail.com> writes:
On Monday, 22 September 2025 at 09:37:28 UTC, Denis Feklushkin 
wrote:

 At system level, there might be multiple options available — 
 depending on factors like the OS version (like Linux kernels 
 older than the `getrandom` syscall, or Windows that has two 
 crypto APIs where the supported parameters have also changed 
 over time) or the runtime environment (think of chroots 
 without `/dev/`).
Forgot to add: these options should not be selected automatically based on some heuristics. Because we know exactly the minimum level of quality of random numbers that we are willing to agree to.
 Yes, I mentioned this: if TRNG isn't available, proposed 
 functions simply won't be available. So user will either be 
 forced to agree insecure pseudo-random sequences or be forced 
 to find another way to achieve randomness.
Sep 22
prev sibling parent GrimMaple <grimmaple95 gmail.com> writes:
On Tuesday, 16 September 2025 at 12:04:20 UTC, Denis Feklushkin 
wrote:
 I don't like the way the module std.random is designed
For one, I really hate how std.random is heavily templated, so it ends up being difficult to use in real-world scenarios where you might want to hot-swap the random engine for whatever reason. With current design choices, you are forced to template your stuff too, instead of just writing `IRandom r = new WhateverRandom()` and calling it a day. It was so painful that I ended up doing this https://github.com/GrimMaple/mud/blob/master/source/mud/random.d , which I use heavily in my games for random level generation. My current implementation is flawed - it should mark methods as `final` so the compiler can figure out to inline the calls when needed, but here's that.
Sep 22