This is what I find untenable in the above code, not workable for a "run this script on your vanilla live CD":
import Crypto.Cipher.AES as AES
import scrypt
...
and the c behind them. A bounty got us a JavaScript native decoder, Python-drop-in-a-py libraries along the same lines would be awesome.
Oh good point, I overlooked that detail. I understand your thoughts on this and fully agree.
Thanks for your response. I called out the Piper because the source archive I found just has a vanitygen call; I don't have a device to dissect what you load them up with. When I examined deep into vanitygen previously, it was ultimately the OpenSSL build options that determined fips140 or OS entropy source, and such. The Pi has a HRNG, but it is low bit rate and it can't be examined for NSA bias insertion or such, but it is necessary with an unplugged environment-blind device. My script is really a response to the brainwallets and dice-rollers.
I totally understand and I agree with the need for your script. I just want to point out that I have indeed tested /dev/random being fed by the HRNG on Piper with all 26 of the "good" dieharder tests of randomness and it passed all of them. So at least we can be confident that the randomness is statistically sound and we're not just blindly trusting it.
I wrote the methods imagining it being run on a device with broken deterministic random, and check for a working precision clock before letting the user proceed. I spent probably more time than needed examining the output range, bias, and reasoning behind every line of math, that even if urandom returns 0's and you skip the user input, you still get an unrepeatable 256 bit entropy key. Also so users can see inside the black box.
This makes perfect sense and having the ability to still generate secure keys on a device with a broken rng is an insanely cool idea.
I get 512bit user entropy based on keypress times, with keypress values also used *8 (but not an integral component). I don't get the strict "time" between keypresses, there's a time->hash-driven variable length loop that runs after each keypress before time-poll to make CPU speed and system interrupts a factor, then I convolute the time. I seed the OS urandom with this user entropy and make a SHA256 hashed OS-based random key whitened with python's Mersenne Twister from oracle back to random bit depth. That's good enough, but then I re-seed the OS entropy pool every 1024 bits with time and user-based entropy plus hashes, then I XOR with a differently-obfuscated SHA2 of system random, and then I XOR with processor-time based and clock based time sources stretched to put 512bits of noise in the hash. Repeat 100 times. The code is easier to read than the explanation.
Wow, it sounds like you put a lot of effort into making sure this is a rock solid implementation. Thank you for taking the time to do this!
To bad the piper doesn't have a button other than print, maybe I'd hack mine so the user keys Morse code on it until they are satisfied it's using their input too?
The way the code on Piper is written (all python btw), you could easily hack it to support morse code on it until the user does something like holds the button down for 10 seconds to indicate that they are satisfied. Piper does also have a bunch of spare GPIO pins so you could also add your own button(s), or repurpose the remember/forget switch to be used for the morse code input. That would require a bit of soldering though.
Finally, don't forget that Piper is running a full linux distro and also has an HDMI port and a USB port so a user could hook up a keyboard and use your unmodified script if they like. I'm thinking about putting a button in the Piper GUI that essentially just launches your script, because combining all those forms of entropy with the whitening and everything is a really cool idea.
Edit: After looking over your code some more, it's clear that you put a ton of effort into this. I donated ~$10 in BTC to your forum address to say thank you.