• The Curious Case of BitFi and Secret Persistence

    For some slightly obscure reasons I've recently found myself looking at the Bitfi hardware wallet and some of the claims the company make, particularly in relation to whether or not it's actually possible to extract secrets from the device.

    The way the device is supposed to work is that, in order to (say) sign a transaction, you use an onscreen keyboard to enter a salt, and a >30 char passphrase.

    The device then derives a private key from those two inputs, uses it and then flushes the key, salt and passphrase out.

    Each time you want to use the device, you need to re-enter salt and passphrase - the idea being that if it never stores any of your secrets, then there's nothing to extract from a seized/stolen device. 

    From Bitfi's site we can see this wrapped up in marketing syntax:

    The Bitfi does not store your private keys. Ever. Your digital assets are stored on the Blockchains, when you want to make a transaction with your assets (move them, sell them, etc.) you simply enter your 6-character (minimum) SALT and your 30-character (minimum) PASSPHRASE into your Bitfi Legacy device which will then calculate your private key for any given token “on-demand” and then immediately expunge that private key.

    For various reasons (see Background) I was somewhat dubious about the veracity of this claim, and ultimately ended up looking over their source code in order to try and verify it.

    This post details the results of that examination, the following items should be noted

    • Although not explicitly vulnerabilities, the issues noted below have been submitted in advance to the Bitfi dev team (I did ask previously via email whether email or Bitfi.dev was preferable for raising issues).
    • Incomplete sources are published on Bitfi.dev - example here, so although I include code snippets in this post, it's updated versions of code that's already public - I'm not simply publishing their code on the net :)
    • I probably will make some mistakes: I've been ill, so focusing is hard, and I dislike C# so it's more than possible something's changed without me realising.
    • This is the result of a fairly short code review, and in no circumstances should be viewed or characterised as a full audit
    • In the sources, code version shows as v112

    The result is a long analysis, so some may prefer to jump to the Conclusion.