So I guess the ECDSA, or more precisely the Python implementation of ECDSA, gathers the key input from the entropy pool. Is this is how all bitcoin applications, Electrum included, do it?
I'd be happy to see a video or an article where someone explains it.
For the OldWallet implementation, as well as the NewWallet implementation of the seed generation, it uses the randrange function from ecdsa. (the file is util.py)
OldWallet is the seed generation used currently, and it routes through the random_seed function in bitcoin.py
From the ecdsa implementation packaged with the 1.9.7 tar.gz
def randrange(order, entropy=None):
"""Return a random integer k such that 1 <= k < order, uniformly
distributed across that range. For simplicity, this only behaves well if
'order' is fairly close (but below) a power of 256. The try-try-again
algorithm we use takes longer and longer time (on average) to complete as
'order' falls, rising to a maximum of avg=512 loops for the worst-case
(256**k)+1 . All of the standard curves behave well. There is a cutoff at
10k loops (which raises RuntimeError) to prevent an infinite loop when
something is really broken like the entropy function not working.
Note that this function is not declared to be forwards-compatible: we may
change the behavior in future releases. The entropy= argument (which
should get a callable that behaves like os.entropy) can be used to
achieve stability within a given release (for repeatable unit tests), but
should not be used as a long-term-compatible key generation algorithm.
"""
# we could handle arbitrary orders (even 256**k+1) better if we created
# candidates bit-wise instead of byte-wise, which would reduce the
# worst-case behavior to avg=2 loops, but that would be more complex. The
# change would be to round the order up to a power of 256, subtract one
# (to get 0xffff..), use that to get a byte-long mask for the top byte,
# generate the len-1 entropy bytes, generate one extra byte and mask off
# the top bits, then combine it with the rest. Requires jumping back and
# forth between strings and integers a lot.
if entropy is None:
entropy = os.urandom
assert order > 1
bytes = orderlen(order)
dont_try_forever = 10000 # gives about 2**-60 failures for worst case
while dont_try_forever > 0:
dont_try_forever -= 1
candidate = string_to_number(entropy(bytes)) + 1
if 1 <= candidate < order:
return candidate
continue
raise RuntimeError("randrange() tried hard but gave up, either something"
" is very wrong or you got realllly unlucky. Order was"
" %x" % order)
Electrum feeds in 128 bytes for the "order" variable in the function (160 for NewWallet, not yet actually used), and entropy is left default.
This triggers the first if, setting the entropy function as os.urandom.
It then checks to make sure the order value is greater than 1.
Then basically, it attempts at the most 10,000 times to return those 128 bytes of entropy created by os.urandom, converted to number plus 1.
If the candidate is greater than or equal to 1 and less than the order given (which is the highest value for the number of bytes, in this case 128) it returns the candidate.
So in the end it comes out to the question: Do you trust os.urandom? This is the entropy function of python, so if it wasn't cryptographically secure, a LOT of applications not even remotely related to bitcoin would be compromised.
But yeah, hey, if you want to write a pull request that takes mouse movements and includes them into the seed generation, I'd use it.