Hacker News new | ask | show | jobs
by mike_hearn 1140 days ago
I was writing about this exact problem of bad RNGs in web cryptocurrency wallets a ~decade ago. It is profoundly depressing that so little has changed:

https://medium.com/mike-hearn/type-safety-and-rngs-40e3ec71a...

Browsers have a number of problems that make it difficult to build wallets, but I’m not going to try and convince you to stop making them here. Suffice it to say there are alternatives for writing cross platform wallets you could consider.

Browsers just aren't intended for doing things that require the generation and safe storage of private keys. The developers don't care about these use cases. Like with so many others, if you want to do it properly you have to go outside the browser.

Back when I was involved with the cryptocurrency world (pre-2016) I kept hitting this general reluctance to just write normal desktop apps, and whenever I advised people to do it for security or stability reasons they'd insist on writing something browser/JS based instead. I did write desktop based wallets, but was considered old fashioned for doing so (at the ripe age of 35). Way too frequently people would end up losing all their money to dumb and entirely predictable hacks as a consequence of using a web-based wallet, or even just lose because of sites going offline. Browsers improved a bit since but as this episode shows, they still aren't intended for it.

Part of why people wanted to write js was that it is easy to distribute the results. They optimized for developer convenience over security. Chrome offers a portability layer and keeps extensions up to date for you. Years passed and I saw the same problem crop up in other contexts too: the right approach was to write a desktop app, people tried to hack Chrome into compliance instead so they could let it handle distribution, it didn't work, and that sometimes led to disaster for their users.

These days I have a company that tries to solve this problem. We make Conveyor [1], which has the goal of making desktop app distribution as easy as for a web app. And it mostly succeeds: it can cross-build/package apps for every platform, and on Win/macOS it can provide update-on-start so you can iterate as quickly as with a web app. You pick your preferred portability layer (flutter, jvm, electron, something rusty etc) and can choose between more battle tested frameworks or more experimental frameworks depending on your appetite for risk. Whatever you pick, the distribution experience is the same. You don't have to compromise on UX either. Frameworks like Compose for Desktop, Flutter, heck even JavaFX give you nice solid 60fps animations and can be made to look good easily. You can store private keys in the user's secure keystores. If your site goes down it's not an emergency, your app still works, only updates stop until you're back online. Even if your certificates expire your app will still work!

I hope that people will take this stuff more seriously in future. It's got a lot easier to distribute apps without relying on browsers or stores over time. Browser developers do a good job but are ultimately constrained by the web's origins. It's not just cryptocurrency wallets that can benefit from escaping the browser either! Quite a lot of security bugs can be eliminated when you leave the browser. For example you can write apps that are immune by design to XSS, XSRF, SQL injection, phishing and other common bug classes.

At some point I should probably write these thoughts down in a more modern blog post.

[1] https://hydraulic.software/

2 comments

> Browsers just aren't intended for doing things that require the generation and safe storage of private keys.

This sounds like webcrypto and it’s interface which is designed to make some data unexportable.

Last time I used WebCrypto the implementation in Safari was buggy in subtle ways. It was possible to work around it. I filed bugs against Apple so maybe it's fixed now.

These days you can argue that a browser is intended to do anything, as there seems to be no scope limit to what goes into HTML5. But it's not what they're really about. Why did this exploit occur, well, WebCrypto apparently isn't directly exposed to WASM as C/C++ APIs even though that seems like an obvious thing to do. Or an even more obvious possibility: expose it as a subset of some existing API like POSIX. But WASM is api-lite, so everything beyond pure computation requires invoking JS and that's not how any existing C++ is written.

Eventually people will blast through this stuff. But, it was worked out in other platforms in the 80s and early 90s.

> Last time I used WebCrypto the implementation in Safari was buggy in subtle ways.

Oh hell yes. I used maintain webcrypto code for a different job and yes Safari was broken forever. I don't have the codebase anymore (I sold the company in 2020) but we disabled keypair crypto features in Safari and told people to use a different browser. I believe it's since been fixed.

Congrats on selling the company!
This is very interesting and I agree about all the upsides of desktop apps. However, in web3, people’s blockchain credentials could be used to interact with many different websites. This seems hard to reproduce with desktop-based apps, right?
I imagine this should be possible with a very small connector addon that calls out to a secure wallet running on the desktop as a native application.

This requires some careful consideration to prevent phishing and other nastiness, but a native application could use native window prompts and techniques such as Windows Hello/TouchID as an authentication technique that's hard to spoof.

The complexity and risks are still there but you can hide away the important secrets much better with a native application than a browser extension ever could. It would also allow access to better sources of randomness and all kinds of sandboxing and exploit protection that aren't available with WASM.

Crypto wallets also have access to the secure enclave via webauthn. I develop a new wallet (Portal) which will have webauthn but I know Glow uses Windows Hello right now.
Yes, but WebAuthN can't be used for arbitrary signatures (which would be required to support various cryptocurrencies/blockchains), nor can it be used to decrypt data or derive keys, which would allow using it as an unlocking key for some hybrid solution.

I'm happy to be proven wrong if you've found a way around these fundamental constraints!

Interesting! Does the WebAuthn API provide enough of a cryptographic basis to fulfill the needs of cryptocurrency wallets?

I know it works through public/private key sharing but I wasn't aware that it provides such direct primitives.

It doesn't, at least not for generic/unmodified cryptographic applications.

WebAuthN signatures are of a very specific challenge/response format [1] that applications need to explicitly support. For example, SSH had to add new key and signature formats [2] to support it.

Theoretically, a blockchain/cryptocurrency application could adopt the WebAuthN signature format as its canonical or an alternative signature format, but I'm not aware of any popular one having done so.

[1] https://developers.yubico.com/WebAuthn/Concepts/Using_WebAut...

[2] https://github.com/openssh/openssh-portable/blob/master/PROT...

Thank you for explaining!
NEAR Protocol is interesting in this regard. Wallet users opt-in to create separate key pairs for each application. Key pairs are limited to specific contract addresses, function calls and gas limitations.

The traditional Web3 model is too open to abuse. It is as if they took the old "allow this Java applet outside of the sandbox? y/n " dialog and added banking.

Browser makers don't seem to really want people interacting with non-web stuff from the web, or extending web capabilities with desktop apps, as that reduces your dependence on them. Still, there are some ways to do it. Firstly, the much more common need is to log in to SSO services, not act as an auth provider. OAuth is kind of messy but can be done and Conveyor makes it easy to register URL handlers, there's a demo of how to package the GitHub Desktop electron app here [1] which uses "Sign in with GitHub". One feature we've considered adding is doing "Sign in with ..." for you, so you don't need to use OAuth libs, your app starts and there's a logged in token in an env var already.

To extend the web from a desktop app there are a few ways to do it. Chrome extensions offer native messaging [2]. By pairing a desktop app with an extension you can have the minimal logic needed in the extension to bridge between your app and the page. But you have to get the user to install the extension manually, as Chrome will try to block apps doing it for you.

Another way for credentials specifically is to use SSL client certificates. They were designed specifically to let you log in to services with cryptographic keys. There's a discussion of the extinct <keygen> tag running elsewhere on HN right now. The app can generate a client certificate, get it signed by some authority, and install it into the user's key store. Now browsers should use it automatically when challenged by a server (except maybe Firefox?). You have to pay attention to how it's used to avoid bad browser UX, e.g. you'd have to use an XMLHttpRequest to ensure you control error handling if the cert is missing. But this is one way to make phishing harder, for example (there is no password for the user to type in).

Another way is to use loopback connections, but that's not ideal.

Ultimately, yes, the web is controlled by the Chrome team and they want you to only write Chrome apps. If you name your project "web3" you have to accept that it's kind of meaningless because you're not Chrome so your views and ideas don't matter, in the end. That's why it never made sense to me and I didn't work on it. In the early days it made a bit more sense because the Ethereum guys tried to make a custom browser called Mist using Electron, but they gave up and did a talk/blog post on why they burned out on it [3].

In the end I concluded the web just isn't a good proving ground for experimental or new ideas.

[1] https://hydraulic.software/blog/8-packaging-electron-apps.ht...

[2] https://developer.chrome.com/docs/extensions/mv3/nativeMessa...

[3] https://avsa.medium.com/sunsetting-mist-da21c8e943d2

Thanks, very interesting.