Sunday, October 5, 2014

A simple second Ruby bitcoin program

In order to get this to run you need install the ffi gem with:

     $ sudo gem install ffi

Now save the following code in a file (I called mine check.rb):

     require 'bitcoin'
   
     privwif = ARGV[0]
   
     mykey = Bitcoin::Key.from_base58(privwif)
     puts mykey.addr

If you run this with a valide base58 private key, it will output the corresponding public key. But there is one problem - if the private key is invalid, you get a complicated error. So let's add a section to check for this. Replace your file with the following:

     require 'bitcoin'
   
     privwif = ARGV[0]
   
     begin
       mykey = Bitcoin::Key.from_base58(privwif)
       puts mykey.addr
     rescue
         puts "Invalid private key."
     end

As soon as the wrong key error occurs the program jumps to the rescue section and prints out that there is an invalid key. However, if any other error occurs it will also print that message, so the program needs extending.

Sunday, September 21, 2014

Writing your first bitcoin-ruby program

Imagine you wrote down a WIF private bitcoin key, but because your handwriting was unclear or you wrote it in a hurry, it turns out one character was copied down wrong.

Here is the incorrect WIF: 5KL6HJfzZ4Uj4CJRFYT11z2W1t5kbULaDqHd7rn6ktLwT6sgyrY

You want to go through each character in the WIF string, replacing each single character in turn with one of the 58 valid characters for the WIF format, and check if it's a valid WIF key.

#!/usr/bin/env ruby
# First the required includes for bitcoin and openssl
require 'bitcoin'
require 'openssl'

# This function performs the correct checksum on a proposed WIF key
# to determine if it is a genuine WIF key
# See http://gobittest.appspot.com/PrivateKey (TP's Go Bitcoin Tests) for an explanation
def wif_valid?(hex)
hex = Bitcoin::base58_to_hex(hex)
hex1 = hex[0..-9]
hex1 = Bitcoin::checksum(hex1)
hex2 = hex.reverse[0..7].reverse
if hex1 == hex2
return true
end
return false
end

# This is our one character wrong WIF
badwif = "5KL6HJfzZ4Uj4CJRFYT11z2W1t5kbULaDqHd7rn6ktLwT6sgyrY"

# And this function takes a WIF, and loops through each character,
# changing it by one, and checking if it is now valid.
# It prints out any valid WIF it finds (there should only be one)
def one_alter(awif)
code_string = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
newwif = ""
for i in 1..awif.length-1
for j in 0..code_string.length-1
newwif = awif
   # Next line is a  hack to ensure that newwif is a new string 
   # and not a pointer to the same string as awif
newwif = newwif + ""
newwif[i] = code_string[j]
if wif_valid?(newwif) == true
    # print out the newwif if it is a correct key
puts newwif
end
end
end
end

one_alter badwif

So lets see what happens when we run it:

bitcoin-ruby$ ruby programs/address.rb 

5KL6HJfzZ4Uj4CJRFYT11z2W1t5kbULaDqHd7rn6ktLwT5sgyrY

There you go - the one valid WIF address within one character of the bad one is retrieved. And it's corresponding public address is 1MUDdayQ7Af39bT9mA6zRYd7ehEeuqFzLZ . Note: no balance, and unlike to have one for long from now on, given that I've committed the cardinal sin of bitcoin, and published the private key.

Setting up a Ruby Bitcoin Machine, part 2

Now we are going to install Ruby 1.9.3 and bitcoin-ruby plus required libraries.

1. First Ruby: go to the Ubuntu Software Center, and type 'ruby' in the search box. Select and install the standard 1.9.3 Ruby package. This installs the basic Ruby environment.

2. You're going to need a few extras to get bitcoin-ruby to run.

$ sudo apt-get install ruby1.9.1-dev
$ sudo apt-get install build-essential g++
$ sudo gem install eventmachine
$ sudo apt-get install openssl
$ sudo apt-get install sqlite libsqlite3-dev
$ sudo gem install sqlite3
$ sudo gem install sequel
$ sudo gem install em-dns
$ sudo apt-get install git 

3. And now bitcoin-ruby itself:

$ sudo git clone https://github.com/lian/bitcoin-ruby.git; cd bitcoin-ruby
$ ruby bin/bitcoin_node

The last command should execute without any errors, which shows that the system is working. Stop it with Ctrl+C.

The final step is to load all the blockchain data into an sqlite3 database, with the following command:

$ ruby bin/bitcoin_node --storage sequel::sqlite://bitcoin.db --import ~/.bitcoin/blocks --skip-validation

This reads the bitcoin blockchain from your bitcoin client directory, and parses it before loading relevant information into a bitcoin.db database in your bitcoin-ruby directory.

If you get an error about opening the database like SQLite3::CantOpenException: unable to open database file (Sequel::DatabaseConnectionError) try running the previous command with sudo in front.

Once this has been running for a bit you can check, for example, that the balance.rb program works:

$ ruby examples/balance.rb 12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX

This should return:

INFO  storage: opened sequel store sqlite://bitcoin.db
Balance: 50.00000000

It's the first address used in the first (genesis) block of the blockchain. As these coins can never be redeemed it will always have a non-zero balance.

Now that we've shown that it all works, it's time to install the Ruby gem for bitcoin-ruby so the various methods and objects can be called from anywhere:

$ sudo gem build bitcoin-ruby.gemspec && sudo gem install bitcoin-ruby-0.0.5.gem

Right, with that all working, you can start writing Ruby programs to do stuff with bitcoin.

Setting up a Ruby Bitcoin Machine, part 1

The next few posts are a record for myself, on how to install and set up a Linux machine to allow me to write programs that do bitcoin related things in Ruby, using the bitcoin-ruby system.

Step 1: Install Ubuntu 14.04 on a spare laptop. Make sure it's a 64 bit AMD machine, and that you install the right version. The required file can be obtained from http://www.ubuntu.com/download/desktop

It's free if you select the "No, take me to the download" link at the bottom right. An iso file called ubuntu-14.04.1-desktop-amd64.iso will appear in your download folder. Burn it to a DVD as an image.

Reboot the machine you want to install on, and boot from the DVD. Choose to install it, and don't select home folder encryption because it will slow down your programs.

Step 2: Boot up and get all the updates for Ubuntu (in the top left swirl icon, type updater and click on "Software Updater"). Then download the bootstrap.dat bitcoin blockchain by selecting the torrent bootstrap.dat.torrent from the page http://sourceforge.net/projects/bitcoin/files/Bitcoin/blockchain/

This is a multi-gigabyte file so the torrent downloaded will take a while.

In the meantime install the Bitcoin-qt client. Open a terminal (Ctrl+Alt+T) and type:

$ sudo apt-add-repository ppa:bitcoin/bitcoin
$ sudo apt-get update
$ sudo apt-get install bitcoin-qt

Click on the swirl icon and type bitcoin. The Bitcoin program with the orange logo should appear. Run it, but stop it after about 5 minutes.

When bootstrap.dat has downloaded copy it from the Downloads folder to the .bitcoin folder (you need to select Show Hidden Files from the View menu in the file explorer, or  user Ctrl+H).

Now you can run the Bitcoin client, and it will load the blocks off disk (this took about 4 hours for my laptop), and will then catch up with the remaining blocks from the network (another 16 hours or so). Now there is a complete copy of the blockchain in ~/.bitcoin/blocks/





Saturday, March 22, 2014

Bitcoin theft

A friend of mine had the misfortune of storing his bitcoins in Flexcoin, the Canadian Bitcoin Bank that was robbed of 800 bitcoins by a hacker earlier this week. Although of course, when I write "Canadian Bitcoin Bank", what it actually turns out to be is a company registered to a rented mailbox in the city of Edmonton Alberta, according to provincial records, with its sole director and voting shareholder one James Andrew Gray, who also gave the rented mailbox as his address. This according to Reuters.

The case is similar to Trade Fortress, another robbed Bitcoin Bank, that time in Australia, which lost 4100 bitcoins, allegedly to a hacker. Again, the "Bank" turned out to be a young Australian developer (I couldn't find out what his name was though).
It's tricky though to determine from a web page whether you're dealing with a teenager working from his parents' spare bedroom, or a large established company with proper offices in the bitcoin world.
However, even larger companies with proper offices don't offer any guarantees. Mt. Gox was supposedly one of those proper companies, but managed to somehow lose over 650,000 bitcoins. Again, information has since leaked out that the company didn't use bug tracking systems or source control for the code that it's developers produced, and the CEO was more interested in setting up a cafe that accepted bitcoins than running the exchange.
The only truly safe way of storing your bitcoins seems to be:

  1. Get yourself a computer that's never been on the internet
  2. Copy OpenSSL across to it using a USB stick
  3. Generate a private key by tossing a coin 256 times, carefully writing down the result
  4. Spend half a day checking you've typed the private key into your disconnected laptop properly, and generate a public key
  5. Send your bitcoins to the address associated with the public key

And even that's not guaranteed.

This is, in my opinion, the biggest problem bitcoin faces.

Friday, March 14, 2014

Interesting addresses on the blockchain

The technical bit

A quick recap:
  • Your bitcoin wallet consists of pairs of private/public keys.
  • Each private key is a 256 bit number between 1 and about (1.15 times 10 to the power of 77). Note that this is slightly lower than 2 to the power of 256.
  • The public key is generated from the private key using the "Eliptic Curve Digital Signature Algorithm", or ECDSA.
  • The Bitcoin address is generated by a series of hashes (called SHA256 and RIPEMD-160), a checksum and finally encoding into Base58.
  • The private key is used to sign any transaction transferring bitcoins from the bitcoin address associated with it to any other valid bitcoin address.
  • The public key can be used to check that the private key signature of the transfer is valid; this is done by the bitcoin miners before adding the transaction to the blockchain.
  • Once a transaction is added to a block in the blockchain it's finalized and can be spent (okay, in practice you need a few more blocks to add on afterwards to really finalize it - the block could be invalidated shortly afterwards. 6 further blocks is considered rock-solid confirmation).
So here is where the fun begins - lets take a test engineer approach to analyzing it.


What happens if you send bitcoins to a random address

If you simply invent a bitcoin address, like 1NyUkGNxZ1RoKmRUPYJBgouS1nJneDX6, the checksum shows that it's invalid, so the coins won't be sent.

If you accidentally pick a valid address, the coins are gone - no one will ever be able to spend them. The odds of someone having the private key to a random valid public bitcoin address are lower than you finding a specific grain of sand that was briefly stuck to your foot on the first day of your first beach holiday abroad.


The bitcoin address associated with a private key of 0

If you pick 0 as your private key (e.g. through programmer error) then the ECDSA algorithm returns a public key of 0400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000. The bitcoin address generating algorithm, when applied to this public key returns an address of 16QaFeudRUt8NYy2yzjm3BMvG4xBbAsBFM which at the time of writing this post has a balance of 0.01 bitcoins.

This sum can never be redeemed, as 0 isn't a valid private key and can't be used to sign the transfer transaction.

The blank bitcoin address

If you apply the bitcoin address generating algorithm to a public key that is null (i.e. the empty string), it returns a valid address. This could happen if there's an error in your software that doesn't pass the correct public key on to the bitcoin address generating algorithm in your code. The valid address returned is 1HT7xU2Ngenf7D4yocz2SAcnNLW7rK8d4E. This currently has nineteen transactions paid into it to a sum of almost 70 bitcoins - worth nearly 45,000 USD at the moment.

Unfortunately these coins can never be redeemed - there is no private key that returns a blank public key.

Obvious private keys

Here are some private keys with addresses that had a balance at some point, that I found.
Key 1, address 1EHNa6Q4Jz2uvNExL497mE43ikXhwF6kZm has had about 4.2 bitcoins over the years. There are several people monitoring it and transferring any balance within seconds if any is paid in.
Key 126, address 163bgHt747rfMKf7tM6XEoCzhKbvrYgZ6N had a small fraction of bitcoin paid into it once.
Key 2²⁵⁶-1, address 12M4QznuNZH2BRVbLK8SKvNqGTPJpCpST7 has had about 0.005 bitcoin. Technically speaking the key is invalid - it's too big, but in practice all code performs a modulo operation on it to reduce it's size.
Key (biggest valid ECDSA key), address 1JPbzbsAx1HyaDQoLMapWGoqf9pD5uha5m has also been used a few times.

Brain wallets

Some bright spark noticed that if you take a SHA256 hash of some text you get a 256 bit number, which can be used as a private key. So people started using phrases as passwords to "carry" their bitcoins around in their head. Unfortunately brute-forcing these kinds of passphrases is far too easy, so I wouldn't recommend it. Here are some passphrases that have addresses which had balances at some point:

Key SHA256("password")
Key SHA256 ("password1")
Key SHA256("correct horse battery staple")
Key SHA256("you don't win friends with salad!")
Key SHA256("bitcoin is awesome") - 500 bitcoins taken from this one, that's a third of a million dollars today
Key SHA256("satoshi nakamoto")

And that's it for today.

Saturday, March 8, 2014

Satoshi has been uncovered ... again.

Once again there's an article proclaiming that the mysterious founder of Bitcoin has been discovered. Amusingly, this candidate actually has the given name Satoshi Nakamoto, but now calls himself Dorian Nakamoto. However, the evidence is all circumstantial - the 64 year old man living in Temple City, California, could technically be the Bitcoin inventor; by all accounts he has the aptitude and the attitude, he was unemployed for five or so years leading up to the publishing of the original Bitcoin paper, and fell ill at about the time that Satoshi Nakamoto bowed out from developing the Bitcoin client further.

However, he denies that he is the founder, lives a relatively humble life, could do with the money that the million or so Bitcoins the real founder has presumably got access to, and his command of the English language appears to be much weaker than that of the writer of the original paper and bulletin board posts. Also, there's plenty of evidence that the real Bitcoin founder was paranoid about protecting his identity, so he's very unlikely to have used his own name in his dealings with the world.

My gut feeling is that he isn't the founder, although that may be wishful thinking on my part. But the coincidences add up to a fairly compelling story. I'd like to think that the real Bitcoin founder has thrown another red herring in our direction, and I'd be looking for a former associate of Dorian Nakamoto, who used the identity of his colleague as another layer of misdirection.

What do you think?

Update: even his own son describes Dorian S. Nakamoto as a bit of an "asshole". Perhaps the Bitcoin founder is indeed a previous co-worker who thought it would be an amusing to get a despised colleague to face a barrage of journalists.