Is using sensor raw data a good way of generating true random numbers? I mean using an IPhone's gyro/accelerometer raw output as a base for generating an array of true random numbers.
- Anybody can ask a question
- Anybody can answer
- The best answers are voted up and rise to the top
Tl;dr: In theory, yes, if you do it carefully. But in practice, it is better to use SecRandomCopyBytes().
Breaking it down a bit first, we step into a definition. "True" random numbers of the kind you are discussing are those that are truly unpredictable, where the preceding data has absolutely no relationship to the next data. This measure of unpredictability is called "entropy" by the random number crowd.
You are asking "are physical sensors good sources of entropy?" The answer is "they can be", but it depends largely on what they're measuring and how often they're sampling it.
An accelerometer in an iPhone is a poor source of entropy if the phone is lying on your desk, because if I measure a string of values and they're all equal, the chances are pretty good the next one is equal as well. It's also not a good source if you're simply reading it while the owner is performing a rhythmic activity, such as walking. The motion of an accelerometer during walking is so predictable that smart pedometers (such as the fitbit) have an acceleration profile that can tell the difference between walking with it and just shaking it.
That is driven by the sampling rate. If you are reading samples 60 times per second, that walking profile curve is going to be very visible. But if you're sampling only once every ten minutes, even a marching band member is unlikely to yield predictable values over that duration. Of course, sampling infrequently produces less usable entropy over time than does rapid sampling.
If you can recognize events with the accelerometer, such as a "walking step" or a motion reversal, you can measure the time between events using a high precision timer or a CPU cycle counter. Repetitive human motion is precise only to a certain degree, such as a tenth of a millisecond. Any measurements taken with a much more finely grained clock, such as nanoseconds, will be influenced by random biological variances between them. If you take nanosecond timings (or CPU cycle counts) between two accelerometer events and keep only the bottom 8 bits, they'll all be unpredictable.
Most secure random number generators have an "entropy gathering service" continually running on a machine. It's job is to harvest entropy from multiple sources over time. Measuring user keypress timings and mouse movements using the high precision clock or the CPU cycle counter, the number of processes running at a given time, the total number of memory bytes allocated, network connection timings, hard drive seek times, all these things that the engineers "hope" are unpredictable are each measured just a few bits at a time, and those bits are mixed into and stored in an entropy pool. The values in the pool are generally "stretched" by feeding them into a cryptographic algorithm (such as a stream cipher or block cipher) to produce a larger sequence of unpredictable numbers from a smaller input. I believe Microsoft's CryptoAPI draws something like 512 bits from the pool and uses them as seeds to fill a buffer of random bytes. Whenever a random number is requested, data is immediately returned from this buffer. The buffer holds no more than 128 kb of random bytes, after which the random number generator returns to the pool for more seed bits and refills the buffer.
An accelerometer would be a good contributor to the pool if you were careful to recognize a stationary sensor and not harvest the bits generated when it's not moving, and use extraordinarily precise timings between events instead of directly sampling the raw values generated during the events.
No. I don't recommend you use this way of generating cryptographic-strength random numbers on an iPhone. It might sound cute and clever, but it's probably a bad idea.
Instead, on an iPhone, you should iOS's built-in method for this purpose: SecRandomCopyBytes(). That method has been designed carefully to be secure.
Other mobile platforms also provide good ways to generate cryptographic-strength random numbers. Use those platform-supported methods; don't try to roll your own. Rolling your own is generally best avoided: it's too easy to inadvertently introduce some security problem, if you try to do this yourself. Cryptographic random number generators are notorious for being tricky, and past systems have been broken because of poor random-number generation. Don't take a chance -- use existing, well-vetted methods provided by current platforms.