Electron-cash: Load BIP38 private keys

Created on 18 Feb 2018  路  23Comments  路  Source: Electron-Cash/Electron-Cash

Enhancement: Can electron-cash support loading BIP38-encrypted private keys? Currently they aren't recognized and need to be decrypted somewhere else (say, cashaddress.org), which is both a hassle and a potential vulnerability.

Fixed WantWantWant backlog enhancement packaging

Most helpful comment

After over a year -- this issue has been ADDRESSED! Horray!

All 23 comments

Any thoughts on how/whether to do this @kyuupichan?

It's quite a bit of work. I won't be doing it.

Jonald's policy is that backlogged enhancements should be closed so only issues which will get any chance of attention should appear in open issues. If anyone is looking for ideas on things to do, they can trawl through closed backlogged enhancements.

@marceloneil : I have a whole thing written in Go to decode bip38 keys, which I can translate to Python easily enough. It isn't that bad although we would need a scrypt lib added to the project.

I'll keep this one in mind as a possible enhancement.

Hadn't noticed it until Roger closed it. :)

Helped a user sweep BSV off a BIP38 paper wallet today (it was left behind because of low-fee, https://github.com/Bitcoin-com/Wallet/issues/434). In the end they had to use https://www.bitaddress.org/ BIP38 decrypter to get the WIF.

For some reason another site (https://iancoleman.io/bitcoin-key-compression/) miscalculated the private key which was quite frustrating.

FWIW I use BIP38 encrypted keys on my paper wallets.. so if we ever get this implemented it would certainly scratch a personal itch. :/

When we go to Python 3.6, may be a good idea to add support:

https://docs.python.org/3/library/hashlib.html#hashlib.scrypt

Sweet! Actually.. why don't we go to Python 3.6? What's blocking that? Wind0ze?

Some long-term-support distros (looking at you, Debian Stretch) still has Python 3.5 and might not take 3.6 so well - but since Electron-cash is mostly used for desktop where Debian should be at Testing anyway, not sure if it's a big deal.

@imaginaryusername OK, that is a good point. Also Ubuntu 16.04 Xenial: https://packages.ubuntu.com/xenial/python3 .

Unfortunately for both Stretch and Xenial it looks like LTS stretches to 2021: https://wiki.debian.org/LTS/ https://wiki.ubuntu.com/Releases

I don't think we should stay stuck on python 3.5 until 2021 ... so we should probably wrap up a stable version of EC at some point that is the last 3.5-compatible version, and those old LTS users will be stuck with that.

@cculianu there exists a pure-python scrypt which is not completely awful in performance https://github.com/ricmoo/pyscrypt#performance

:thinking:

Oooh. This is pretty cool.

I commented on BCA discord that I'll shove 0.5 BCH into the pocket of whoever makes the PR implementing this, it still stands. :stuck_out_tongue:

HA! I can take a stab at it. It shouldn't be too hard. Hopefully the packaging (ie: including that lib) won't be too much of a nightmare.

No promises but maybe I'll give it a try...

Well I made a BIP38 implementation that is python-only using pyscrypt. It's slow as hell. It takes FOUR MINUTES to decrypt a single key on my 2016 MacbookPro.

Not sure what to do here.

Note: It's possible to use hashlib.scrypt (which is super-fast -- decrypts a key in under 1 second) but user needs to have Python 3.6 + OpenSSL 1.1 installed which isn't yet supported by our OSX or Windows builds. :/ Linux users could benefit from a fast hashlib.scrypt implementation though.

Anyway.. just leaving this note here for posterity. My implementation is in this file:

https://github.com/cculianu/electrum/blob/b9ff5f73b21a778697796f193b4798756743505a/lib/bitcoin.py#L888

Now that I think about it, since python 3.6's scrypt would require OpenSSL 1.1+ anyways, why not just make a quicky ctypes OpenSSL wrapper that would work in python 3.5 as well? I guess there are questions over whether the ctypes can access the same OpenSSL that might have come included in the Python distro.

https://www.openssl.org/docs/man1.1.1/man7/scrypt.html

Yes. It would be nearly trivial (very thin wrapper since it's only basically 1 function).

The only real concern I have is how to manage these situations:

  • Packaging to ensure OpenSSL 1.1 for MacOS. Right now there is a bug in pyenv which I use to build for macOS which forces the python interpreter to OpenSSL 1.0. I put in an issue to the pyenv maintainer but I would have to go in there and smack him around and/or issue a PR to get this actually fixed. He seems like a nice guy (a Japanese guy, very polite) so this may not take too long -- but I consider it a blocker.

    • A solution to this is just to package a custom-build libopenssl.dylib into the macos binary. This actually is probably the easiest thing to do (sort of the way we package pre-compiled libsecp256k1).
  • We have to get openssl 1.1 into the Windows build probably by packaging a .DLL.

  • What do we do if the system lacks openssl 1.1? (Mostly a concern for Linux although these days most distros come with it) The fall-back to python-only scrypt is terrible so -- that's a non-starter (it seriously takes minutes to decode 1 key!!!). I'm ok with not offering bip38 or scrypt based anything in the UI if the system lacks 1.1

So yeah.. the biggest blocker is the MacOS & Windows issues above -- not really that hard just have to put in time to get pyenv guy to accept a PR and/or just package OpenSSL ourselves.

May is suggest that in the cases where users don't have a recent enough version of Python or OpenSSL, simply gray out anything related to BIP38 and possibly provide an error message when hovering over? We can still pack in the functionality for 90% of the users without breaking the other 10% (I have no clue what the actual distribution would be).

Yeah that鈥檚 a good idea. Greyed out with perhaps a blurb about upgrading to OpenSSL 1..1

Linux users (who this would impact as they run from source) are generally smart enough to know what that means, we hope.

Yeah this is an edge case of an edge feature, I see no reason to delay it until Linux distros move to OpenSSL 1.1 or Python 3.6. Packaging for Windows/OSX might be more necessary though.

Yeah and that involves me sitting down for a few hours and ironing out the build scripts to do that. :)

UPDATE:

I just found out Cryptodome.Protocol.KDF.scrypt exists and is native and is fast. I updated bitcoin.py to use it, to fallback to hashlib.scrypt (if available), or pyscrypt (if available).

The first 2 are super fast (native code). The last is incredibly slow (not usable in production).

But given that we have Cryptodome as a requirement for this project -- we're golden! In the coming day or two I will add this to the wallet import wizard UI and other places as a possible thing a user can input.

After over a year -- this issue has been ADDRESSED! Horray!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

molecular picture molecular  路  5Comments

KarolTrzeszczkowski picture KarolTrzeszczkowski  路  6Comments

ProfessorVenkman picture ProfessorVenkman  路  4Comments

jcramer picture jcramer  路  4Comments

Drac42 picture Drac42  路  6Comments