Post
Topic
Board Development & Technical Discussion
Re: Bitaddress.org brain wallet & Electrum
by
kaii
on 20/08/2012, 04:47:51 UTC
I am reading through both of these code bases for the first time. What I have written here is just my take on what's going on.

Does bitaddress.org use the same method to create a brain wallet as electrum

They do not use the same method to generate private keys from a seed.

bitaddress.org -- https://github.com/pointbiz/bitaddress.org/blob/master/bitaddress.org.html#L3724
Electrum -- https://github.com/spesmilo/electrum/blob/master/lib/wallet.py#L272

With bitaddress.org, the seed that you enter is run through SHA256 to generate the private key.

Code:
var bytes = Crypto.SHA256(key, { asBytes: true });
var btcKey = new Bitcoin.ECKey(bytes);

In contrast, Electrum uses a random number generator to pick a seed for you.

Code:
seed = "%032x"%ecdsa.util.randrange( pow(2,128) )

The seed then goes through 100,000 rounds of SHA256 concatenated with itself to generate the private key.

Code:
oldseed = seed
for i in range(100000):
    seed = hashlib.sha256(seed + oldseed).digest()

Does anyone know how electrum does it?

Electrum generates multiple addresses from a single seed by concatenating the previous private key with a double SHA256 hash of the sequence number of the address being generated.

Code:
secexp = ( secexp + self.get_sequence(n,for_change) ) % order

Code:
def get_sequence(self,n,for_change):
    return string_to_number( Hash( "%d:%d:"%(n,for_change) + self.master_public_key ) )

Code:
def Hash(data):
    return hashlib.sha256(hashlib.sha256(data).digest()).digest()

  • secexp is the secret exponent, i.e., the private key
  • n is the sequence number of the address (1, 2, 3, etc.) being generated
  • for_change is a 1 or 0 value that indicates whether or not this is a change address
  • order is the number of discrete points on the elliptic curve, and modding keeps the private key in range
  • As far as I can tell from the code, self.master_public_key will always be an empty string

Does anyone see a problem with the above scheme?

I'm not a cryptography expert so I can't say anything definitively. Given that bitaddress.org only uses one SHA256 pass to encrypt the passphrase, I'd say there's a good chance that it's a bad idea just to append a number to the seed.

You may want to do something like what Electrum does -- concatenate the private key of the previous address with a hash based on the sequence number (e.g. SHA256 the string '2' for the second address) and mod the result by the maximum value for the private key.