Hi, btchris!
I have made an interesting discovery: if you know the encoded seed of an Electrum wallet, then you can recover the unencrypted seed without the password stretching and fancy Elliptic Curve stuff. Simply try to decode the password, and if you get a valid hexadecimal number of 32 characters, then the password candidate is good, otherwise it is bad.
...
Its speed can be optimized to 10**7 (maybe 10**8 ) trials/sec/CPU_core.
Yup, that's exactly what I'm doing in
btcrecover here. I'm only managing around 10^5 tries/s per CPU core (it's written in Python but uses libraries for SHA and AES written in C) but I'd guess it could be improved if written entirely in C, or even better in OpenCL....
It turns out that you can play similar tricks with many wallet encryption schemes (but not with Armory as far as I could find - Armory really got wallet encryption right).
Very nice program!
I tried it yesterday, with an Electrum wallet.
I modified it to use only the first 44 characters of the encoded seed:
$ diff btcrecover.py btcrecover_mod.py
572c572
< if len(wallet) != 64: raise ValueError("Electrum encrypted seed plus iv is not 64 bytes long")
---
> ###if len(wallet) != 64: raise ValueError("Electrum encrypted seed plus iv is not 64 bytes long")
580c580
< encrypted_seed, iv = wallet[16:], wallet[:16]
---
> encrypted_seed, iv = wallet[16:32], wallet[:16]
584,585c584,587
< # If the 48 byte encrypted seed decrypts to exactly 32 bytes long (padded with 16 16s), we've found it
< if seed.endswith(b"\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10"):
---
> ### # If the 48 byte encrypted seed decrypts to exactly 32 bytes long (padded with 16 16s), we've found it
> ### if seed.endswith(b"\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10"):
> # if all the digits are hexadecimal
> if all(c in string.hexdigits for c in seed):
Maybe you can use it to extend your extract-scripts with Electrum as well.