Pages:
Author

Topic: ANN: Python paper wallet generator with strong randomness - page 3. (Read 16939 times)

legendary
Activity: 1512
Merit: 1036
It's offline. And, he can of course publish the SHA256 of the executable as well as GPG sign it.
Okay, for your (dis)pleasure...

http://we.lovebitco.in/paperwal.exe (2.0MB, AMD64 exe)
SHA256: 7b9dc3b92ae7c853f0313c1498af7d9bf7d7578b3843be952e0f6e5e3c35ff5b

New Windows exe, see first post.
hero member
Activity: 658
Merit: 502
Doesn't use these forums that often.
Nice tool! I could mirror this on http://whiskers75.com if you like Wink

Got an .exe (for windows)? Or does that go against the philosophy? I liked your dice2key one.
The idea is that you don't use the most hackable OS in the world to make your keys ;P

speaking of being hacked..  Tongue
Yes? That was in October.
legendary
Activity: 3416
Merit: 1912
The Concierge of Crypto
It's offline. And, he can of course publish the SHA256 of the executable as well as GPG sign it.
hero member
Activity: 686
Merit: 504
always the student, never the master.
Nice tool! I could mirror this on http://whiskers75.com if you like Wink

Got an .exe (for windows)? Or does that go against the philosophy? I liked your dice2key one.
The idea is that you don't use the most hackable OS in the world to make your keys ;P

speaking of being hacked..  Tongue
hero member
Activity: 658
Merit: 502
Doesn't use these forums that often.
Nice tool! I could mirror this on http://whiskers75.com if you like Wink

Got an .exe (for windows)? Or does that go against the philosophy? I liked your dice2key one.
The idea is that you don't use the most hackable OS in the world to make your keys ;P
legendary
Activity: 3416
Merit: 1912
The Concierge of Crypto
Got an .exe (for windows)? Or does that go against the philosophy? I liked your dice2key one.
legendary
Activity: 1512
Merit: 1036
Updated to v1.1:
-removed all floating point math; floating point times are now retrieved as raw hex bits.
-simplified & robust time -> entropy functions
-interface cleanup
-partition library use into single methods needing them
-only OS random class is used, no python internal random
-no address calculation changes

(previous version at http://we.lovebitco.in/paperwal-v10.py)
full member
Activity: 219
Merit: 101
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.
legendary
Activity: 1512
Merit: 1036
Hi deepceleron,

I’m the guy behind Piper.  This is a cool alternative to standard entropy collection, however, Piper uses a hardware random number generator which collects entropy from thermal gradients...

Finally, I know you mentioned adding BIP0038 to this script.  Here's a python implementation of BIP0038 which should get you quite a bit closer to that goal.  I believe it could be added to your single file since it's only about 40 lines: https://github.com/zimage/python-bitcoinlib/blob/e9506aba6d53ad5bf760d67815d711a1c55b2557/bitcoin/bip38.py
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.

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 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.

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.

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?
full member
Activity: 219
Merit: 101
Hi deepceleron,

I’m the guy behind Piper.  This is a cool alternative to standard entropy collection, however, Piper uses a hardware random number generator which collects entropy from thermal gradients.  It does use a vanitygen binary, but that's because it supports setting your own address prefix and generating vanity keys.  But, the source for vanitygen is included and you can easily compile it yourself and compare the MD5 of the binary to the one used by the Piper software. 

RNGD runs on Piper and continuously feeds entropy into the /dev/random entropy pool from the hardware random number generator.  Vanitygen is called with parameters to tell it to use /dev/random instead of the default which is /dev/urandom.  Vanitygen is widely accepted in the bitcoin community as a good tool to generate safe keypairs and is used by hundreds of people everyday. 

So my point is, that the key generation method used by Piper is perfectly safe and the same solution widely used in the bitcoin community everyday.  I put a lot of thought into it and took community advice into account to make sure that the solution Piper uses is secure and safe.  I store my own coins with an unmodified Piper and I feel totally safe doing so.

That said, this is a really cool alternative to the standard entropy collection methods and if some community members can do a code audit on it and give it a thumbs up, I'm happy to include it on the base Piper SD card image or even eventually integrate it with the Piper GUI software.  I love giving people options, and this is a really cool one, especially for people who mistrust the OS random number generator.

Finally, I know you mentioned adding BIP0038 to this script.  Here's a python implementation of BIP0038 which should get you quite a bit closer to that goal.  I believe it could be added to your single file since it's only about 40 lines: https://github.com/zimage/python-bitcoinlib/blob/e9506aba6d53ad5bf760d67815d711a1c55b2557/bitcoin/bip38.py

That BIP0038 implementation has also been looked over by jgzarik in a pull request for the python-bitcoinlib and he doesn't seem to have any issues with it: https://github.com/jgarzik/python-bitcoinlib/pull/5

Thanks for making this really cool script.  I love creative ways of generating entropy!
legendary
Activity: 1512
Merit: 1036
Preface

Bitcoin requires cryptographically strong random numbers behind its ECC math when generating addresses and creating transactions. Bad math = stolen bitcoins. Important address keys used for savings must also be kept secure, ideally kept off Internet-connected computers that may be hacked.  Bad procedures = stolen bitcoins.

What's A Paper Wallet?

"Paper wallet" is a term often used for what is better called a "cold storage address". You create a hard-copy of a new address and its private key, unconnected to your normal daily-use wallet, and write it down, print it, or even stamp it into a block of metal. Money can be sent to this address as long-term savings, and copies can be secured in safe-deposit boxes, with relatives, etc. To redeem funds, you later spend the entire balance after importing the private key into wallet software, and disuse the address.

Bitcoin Paper Wallet Address Creator - paperwal.py

Where do you get the address for your paper wallet? Taking one from your everyday Bitcoin wallet software defeats the security you desire, as the private key to spend the coins is saved not only to the wallet on the hard drive, but also potentially to hard drive swap space or temporary files. Naive Bitcoin software also may call poorly-implemented, faulty, or even backdoored OS crypto libraries, creating less-than ideal pseudo-random numbers.

To address this need, I made a paper wallet generator, a single script written for Python 2.7 and requiring no additional packages, that will let you type keypresses to create the entropy necessary to generate a strong address and private key pair. It can be run on a disconnected-from-the-Internet computer to safely create a single address for paper wallet use. It employs several techniques and entropy sources besides simply the characters you enter, discussed later in thread. The actual code you run is readable to allow audit and review (although it's a bit complex).

Usage

The address generator uses Python, an interpreted script language. Linux and Mac OS usually have the required Python 2.7 language interpreter pre-installed (Ubuntu 16.04, April 2016, is the first distro to switch the default interpreter to Python 3). Windows would require installation of 2.7.x from python.org - but you already can guess that Windows is not recommended.

With the Python interpreter installed, a double-click on the downloaded script or typing "paperwal" is generally enough to launch the generator. If not, you can specify the Python interpreter in the path with the command "python paperwal.py".

Some command-line options are available for more specialized use:

>paperwal.py -h
Usage: paperwal [options]

Options:
  -h, --help            show this help message and exit
  -e, --encrypted       create BIP38-encrypted privkey (takes a LONG time)
  -v, --validate        enable extensive system tests for entropy
  -s, --silent          disable most console output except address
  -l, --loop            restart instead of exit
  -p, --nopause         disable the pause before exiting
  -d, --doublecalc      calculate twice and test results
  -z JUST A HELPFUL HINT
                        try ctrl-tab to abort the program

  Warning:
    If you use this option, you should supply REAL randomly generated
    entropy.It is probably a good idea not to reuse a seed.

    -r ENTROPY, --entropy=ENTROPY
                        random seed instead of keypresses, 64+ characters



Generate Address On A Secure Platform

You can make your address hacker-proof - by never storing it on a computer. This is commonly done by rebooting your computer to the "clean environment" of a standard Linux live CD. You can even be paranoid and disconnect your hard drive.

Here is an example procedure using Alpine Linux, a small security-focused distro and live CD that starts to a shell prompt. We will use the Internet to install Python and download the script, but then you can disconnect the network cable:

logon: root (no password)
>setup-alpine (and press enter for just about every option, including no hard drive)
>apk add python

Download script from my site:

>wget http://we.lovebitco.in/paperwal.py

Generate addresses:

Now disconnect internet to be secure, verify the file hash, run the script, pound on the keyboard when prompted, and see the output:

>sha256sum paperwal.py
9a88d46ad2ea6d19cb3940dc396be9f7cbe29186150d57440d26005c628597ad *paperwal.py
  (update 2014-01-03 v1.2a)

>python paperwal.py
Press keys to generate secure address....  OK

Bitcoin Address:
 1Cz7oXpaYycVeAoX1LXqniYGTzazjA7Zm9
Private Key:
 KwuZP7E2Zq5WmzcvZyLTHMerZKmWtzYbnDaEUCg9BWJ5uUU8qwRe


Note: the generator only generates compressed addresses (used by Bitcoin-Qt since v0.6.0). The private key is in "Wallet Import Format"  Be sure your wallet-of-choice can import some test private keys.


Password-Protected Paper Wallet

Someone finding your paper wallet printout would be able to to spend your bitcoins. Bitcoin Improvement Proposal BIP0038 adds a password feature to protect the private key, making it impossible to spend without knowing or cracking the password. The encryption is purposefully made very hard to brute-force - it takes about ten minutes for the address generator to encrypt a key using plain Python. When using the generator's --encrypted option, the private key is not displayed unencrypted.

BIP38 private key encryption is a recent feature developed separately from Bitcoin Core; most wallets don't have a built-in decrypting feature. One way to decrypt is by downloading the http://bitaddress.org HTML page and using the javascript-based utilities in it offline to reveal the true private key.

This address generator allows you to type passphrases that other utilities might not process correctly, such as typing only spaces. Be sure you can decrypt private keys generated with your passphrase before using this feature.


Example use with encryption:



>paperwal.exe -e
 Enter your wallet passphrase (will not appear).....*
 Re-enter to verify your wallet passphrase.....*

 Show your passphrase before continuing? (y/n)
   Passphrase: (456456)
    (counter):  123456

Press keys to generate secure address....  OK

Calculating encrypted private key...
stage 1 of 8...
stage 2 of 8...
stage 3 of 8...
stage 4 of 8...
stage 5 of 8...
stage 6 of 8...
stage 7 of 8...
stage 8 of 8...


Press "Enter" to close


Other stuff

I'll leave you the headache to figure out printing from your live CD.

Download Links

http://we.lovebitco.in/paperwal.py  (35kB) Python 2.7 script, no other libraries needed
sha256: 9a88d46ad2ea6d19cb3940dc396be9f7cbe29186150d57440d26005c628597ad *paperwal.py
md5: 4d26d19b041f1f8f2ba29d1de537579f *paperwal.py

http://we.lovebitco.in/paperwal.exe (4MB) Windows exe created with py2exe, Python 2.7.6 32 bit
sha256: 31af7bec9aa68c8a32ce09de42f16cf58868c6d6a69a71c701ae52efba842076 *paperwal.exe
md5: e2e5d1d648ccc1cabebd745a160e5277 *paperwal.exe

(Windows users - don't use the binary exe for more than just demonstration; install Python for yourself: http://www.python.org/download/ - the script is reviewable, EXEs are not; don't blindly trust EXEs from the Internet with your bitcoins.)
Pages:
Jump to: