I learned something pretty cool a while back that I thought I'd share here because it's applicable to cryptography and can be used during "offline" generation of bitcoin addresses.
It's called "randomness extraction" and it allows for high-quality randomness to be produced from an imperfect or weak entropy source.
The specific extractor that I want to outline below is due to John von Neumann and is known as the "Von Neumann extractor".
Although there are now more modern approaches to solving this problem, I think it's worth understanding this particular extractor both because of its elegance/cleverness and because it's easy to remember and possible to "execute" by hand (without a computer).
Okay, so imagine you have a coin that is "biased" (e.g. it produces heads more often than tails). To make the example more compelling, let's imagine that this coin is so badly biased that (on average) only one in every ten flips is heads and the rest are tails.
A coin that produces heads only 10% of the time seems pretty useless for generating a secure private key.
If you take heads to be 1 and tails to be 0, then here is a private key (in binary) that such a coin might produce:
0100000100001000000000010001000000010100000011010100001000000001000000110001001
0000000000000000001000001000001000000000000000000000000010010000100000000001100
0000101000000000000010101000000000000000000010000000010000000000000000000000000
0000000000000010000
Now, obviously, that is not a very secure private key. I don't want to derail with an aside defining "entropy" but, suffice it to say that this key doesn't have enough of it!
In physics, radioactive decay can produce sequences like the above where long stretches of inactivity (represented by 0's) are interrupted by infrequent "clicks" (represented by 1's). John von Neumann was studying sequences like these when he discovered a way to "unbias" them by considering the outcomes pair-wise instead of individually.
Going back to our coin, these are the statistics for individual outcomes:
------------------------
| T | 90% chance | 0.9 |
------------------------
| H | 10% chance | 0.1 |
------------------------And these are the statistics for pairs of consecutive outcomes:
-------------------------------
| TT | 81% chance | 0.9 * 0.9 |
-------------------------------
| TH | 9% chance | 0.9 * 0.1 |
-------------------------------
| HT | 9% chance | 0.1 * 0.9 |
-------------------------------
| HH | 1% chance | 0.1 * 0.1 |
-------------------------------The trick is to realize that the outcomes TH and HT always have equal probabilities of occurring (regardless of how biased the coin might be). That means that if you ignore the other two outcomes (TT and HH) you can treat TH and HT as each having a 50% chance of occurring, just like a fair coin!
So, if you have a (possibly biased) coin and a piece of paper you can produce an "unbiased" sequence of 1's and 0's by doing the following:
1. Flip the coin twice and mentally record the outcome
2. If you got TT, don't write anything and goto 1
3. If you got TH, write down "0" and goto 1
4. If you got HT, write down "1" and goto 1
5. If you got HH, don't write anything and goto 1
Pretty neat, huh? I really like simple techniques like this. I hope some of you found this interesting