Closed chlordk closed 11 months ago
Seeding is very hard
For real entropy you need dedicated hardware, thats why I have the two modi analogRead and digitalRead to read from an external (noisy) source.
1) micros always has the last 2 bits zero on 16Mhz boards. So you can harvest 1 bit per ~8 micros max. But often not too bad
2) AnalogRead does not always float random if not connected. Sometimes it just stays stable. One can harvest 1 bit per call at most, and it needs a Neumann filter to remove bias. When it floats it is often good enough for games etc.
3) uniqueID - do you have a link. ?
4) EEPROM, could help however there are boards that do not have EE. So less usefull.
5) Hashing the content of all RAM including non initialized and time and date might give a reasonable seed, although predictable. To be tested.
6) key input from a user can be used to constantly harvest entropy. Especially in combination with micros.
On Hackaday there was recently an article of someone who had a geiger counter connected to an ESP32 (not sure ?) And used it as a random number server.
On the Arduino forum there was a great discussion about entropy by ??? in 2010-2023 or so. What he did was using the watchdog timer to generate entropy. If I understood well there are small differences in crystals / resonators and reboot time.
If I store the first value I can get with micros() it is 4. Minus two bits is one. So not very useful.
UniqueID is in the libraries https://github.com/ricaun/ArduinoUniqueID My ID is 55 33 33 34 38 39 12 1B 0C and I guess many of your bits are the same, so not so many bits to get there.
I meant: If the end user has EE he can use choose to use it. I didn't think of having it your library.
2) Now I recall seeing that ID Library, Need to find time to check it again.
The uniqueID is a nice library however not usable as seed It would provide different seeds per processor but give the same seed if a processor reboots, So in some scenarios still predictable. Usable as part of the seed.
How about this function? Definitely not random however useful for seeding.
An analogWrite() call (~12 us) is about 9x faster than analogRead() (112 us) on an UNO.
uint32_t randomizer()
{
uint32_t value = 0;
for (int i = 0; i < 32; i++)
{
uint32_t start = micros();
analogWrite(9, micros());
uint32_t stop = micros();
value <<= 1;
value |= (((stop - start) >> 2) & 1); // strip one bit per iteration
}
return value;
}
Seeding is very important however deriving good seeds is outside the scope of this library. It might be an idea to collect entropy generating algorithms in a repo. (Probably done already).
So I close this issue but feel free to add comments or remarks.
When using PRNG setting the seed to something random is very important, otherwise the result can be predicted.
Arduino does not have a disk or network to give entropy, so the possibilities is: