Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Wormhole-crypto: Streaming encryption based on Encrypted Content-Encoding (github.com/socketdev)
61 points by feross on April 20, 2021 | hide | past | favorite | 67 comments


There's already a very good, popular encrypted file sharing system called Magic Wormhole, with implementations in multiple languages.

https://github.com/magic-wormhole/magic-wormhole


Damn, someone made wormhole.app and it does the same thing but is unrelated to magic-wormhole? That's seriously uncool.


I know, right? It’d be like making a linter configuration for your personal JavaScript style and naming it “JavaScript Standard Style”.


More like making a linter configuration for your personal JavaScript style and then seeing the creator of JavaScript repeatedly endorse it [1][2][3][4][5][6][7].

Not to mention, the creator of the Web too [8].

EDIT: You might not like StandardJS – that's fine, feel free to use something else – but it's helped a lot of teams avoid pointless style debates and it's downloaded 1M+ times per month.

[1]: https://twitter.com/BrendanEich/status/1149082576847400960

[2]: https://twitter.com/BrendanEich/status/951558694570901504

[3]: https://twitter.com/BrendanEich/status/1157658128004997121

[4]: https://twitter.com/BrendanEich/status/1126229937197707265

[5]: https://twitter.com/BrendanEich/status/1014671417084792832

[6]: https://twitter.com/BrendanEich/status/1378443247576440835

[7]: https://twitter.com/BrendanEich/status/1170710893832753166

[8]: https://twitter.com/feross/status/740592720230518784


What is uncool is that it's using AES-GCM in all of its 128 bit glory, which is subpar compared to just using libsodium like magic-wormhole does.


Please don't spread FUD. AES-GCM 128 is perfectly fine and it's standard for a reason.


AES-GCM is imperfectly fine and its standard has nothing to do with any of it. It's inferior in more than one way to the Chapoly-style ciphers in Sodium.

Case in point: it looks like if callers to your ECE library pass in a repeated salt through Keychain for any reason, you'll generate a duplicate nonce, which blows up GCM. There are authenticated ciphers that mitigate this problem (most commonly: by having a nonce wide enough that you can simply always generate it randomly without requiring callers to manage it); GCM, on the other hand, is the poster child for that flaw.

Since this is browser crypto, and not native execution like Magic Wormhole, all of this is irrelevant; the important distinction between the two projects isn't that one uses a lesser cryptosystem, but rather that the other uses real end-to-end cryptography and the other uses client-server cryptography pretending to be end-to-end.


> Since this is browser crypto, and not native execution like Magic Wormhole, all of this is irrelevant; the important distinction between the two projects isn't that one uses a lesser cryptosystem, but rather that the other uses real end-to-end cryptography and the other uses client-server cryptography pretending to be end-to-end.

Is my reading of this as a vague and misleading way of saying that because the code responsible for the encryption is provided by the server it doesn’t count as end-to-end encryption accurate? Or is it an even vaguer hint towards something else?


I don't know what's "vague" or "misleading" about it. Almost every HTTP transaction you have with a server providing browser-based cryptography offers the server another opportunity to alter the code that handles cryptography secrets. It's not a matter of "software update", though that's where this discussion always seems to be pushed; it's every individual operation of the application.

People --- including the author of this application, if I'm reading it right --- talk about the need to "audit" these kinds of applications. But there's no such thing as "auditing" a browser Javascript application. The code it feeds you on startup is not necessarily the code that you are running at any given point during its execution. The entire web security model is based on the idea that the origin is the root of security; that's why we gave it a special name.

Compare with Magic Wormhole (a project I'm in no way affiliated with), which has the same basic functionality, and in which the server has no ability to subvert the cryptography used to transmit files; not on a run-by-run basis, or on a file-by-file basis, or even a protocol-message-by-protocol-message basis.

This is an old argument, one widely (though not absolutely) shared among software security engineers, so it's a little rich to see people express shock at reading it here. You can disagree with me; many have, over the years. But you can't claim it's an argument from left field.


You can't invent your own definition of end-to-end encryption. There is a material difference between a service which end-to-end encrypts your files – even if it sends you the code to do so – and one which does not.

When a user logs into 1Password.com, they're using end-to-end encryption. The master password and secret key never leave the browser. The server never receives the key and therefore does not have a way to access the contents of password vaults.

This is very different from an application which, by design, sends your plaintext data to remote servers.

The English phrase we use to describe this difference is "end-to-end encryption".


I have not in fact invented my own definition of end-to-end encryption, and yours is not the first application --- nor is browser crypto the only cryptography setting --- that has tried to claim "end-to-end security" for a design where both ends implicitly trust the server.


It’s vague because “client-server cryptography pretending to be end-to-end” could be referring to any of a number of different flaws when you could just be specific in the first place in as many words, and it’s misleading because actual client-server encryption in this case leaks private data to the server passively, which is a significant difference. Feel free to popularize a separate term for this if you don’t like “end-to-end”.


With E2E encryption you need to trust the developer of the software and the distribution channel (apt, App Store, web server). The GP comment is parroting the claim that browser based E2E encrypted systems are inherently less secure than native apps because web servers are untrustworthy systems for delivering software.

Does native software have fundamentally more trustworthy distribution channels than web servers? I see the argument in some cases - apt always delivers the same binary for the same request (I assume). And the App Store does binary signing, rather than just TLS. But plenty of native software is just installed via the developer’s website anyway. And if the developers host the website, they’re already a party you have to trust. Giving them more trust doesn’t change much - they could just slip something nasty in the binary if they wanted your data.

I still don’t totally buy it.


I think the argument against web-based software is that because you effectively re-download the application on every visit, there are more opportunities for a compromised provider to serve you a malicious version of the application.

I suppose it's the difference between TOFU (Trust On First Use) and BEEF (Beware Each & Every Fetch).

Okay, I made up that second acronym, but it seems like a reasonable name for that threat model. Anyway, as the sibling comment points out, the distinction is fairly moot if you have an auto-updating native application.

To improve the situation for native applications, it would make sense to use a tamper-evident log like Trillian[0] so that a package manager or auto-updater can be sure that it is receiving the same binary as every other user (and possibly after a sufficient delay to allow reviewers to raise the alarm about the corresponding reproducibly-buildable source code).

Applying this to web applications is more tricky, but can be done using the bookmarklet-dataURI trick[1] which effectively allows the user to freeze a copy of a web app "bootloader" that pulls in the remaining resources after checking their signatures against a hardcoded public key (as well as against a Trillian log).

[0] https://transparency.dev/application/add-tamper-checking-to-...

[1] https://news.ycombinator.com/item?id=17776456


Thanks for the pointer to bookmarklet data uri trick - that's clever.

I posted this elsewhere in the thread, but just wanted to mention it again in this context. Hyperboot [1] uses AppCache to give users the benefits of explicit, immutable versioning with control over upgrades using the html-version-spec while preserving the simplicity of passing around a URL.

It offered the usability benefits of web apps – you can give someone a URL and they can immediately load the app – with the security of installed apps – doesn't change without warning.

Unfortunately, AppCache is being removed from the web platform and there's no way to use ServiceWorker to accomplish the same thing.

[1]: https://github.com/substack/hyperboot


Yes, it's a pity that AppCache and ServiceWorkers won't be able to support this use case. Also, the data URI trick comes with its own limitations, such as the fact that the address bar won't present an actual domain name or padlock, so it has a slightly worse user experience than normal websites.

One simple way that the web platform could be improved, then, would be to adopt something like the Hashlink proposal[0], which would allow the hash of the initial "bootloader" to be stored in the query string. If this were possible then a simple bookmark would suffice, or a URL sent in an email, as your comment suggests.

[0] https://w3c-ccg.github.io/hashlink/


> I think the argument against web-based software is that because you effectively re-download the application on every visit, there are more opportunities for a compromised provider to serve you a malicious version of the application.

Maybe. Lets imagine Google Chrome's update servers were compromised for a day, and the servers hosting a somehow equally popular e2e web based chat app were compromised for a day.

For chrome, it will effect fewer users (most people only update chrome every month, so it only hits 1/30 users). Whereas every user who opened the chat app would be compromised.

The problem on google chrome would be easier to detect, because it wouldn't be able to pinpoint a specific user. Everyone gets the same bad code.

An infected version of chrome would do a lot more damage than a website (because native desktop apps aren't sandboxed at all).

And when the website clears the infection the next day, all infected users of the chat app would have the malicious code removed from their system[1]. But unfortunately, an infected copy of chrome would presumably have its update mechanism stripped out, so it would stay evil much longer. Though maybe this is a wash, because Microsoft and Apple have malicious software detection and removal built into their OSes.

I don't see this as a slam dunk for native software.

> To improve the situation for native applications, it would make sense to use a tamper-evident log like Trillian

This is a fantastic idea. I'd love to see this explored more, and I wonder if we could do something similar some day built into browsers for web apps.

Interestingly it also makes a strong case for apps (like chrome) not having their own binary responsible for updates. Apps on phones are more secure because a malicious binary can't stop itself being removed via Apple / Google's app stores.

And of course, we need better system level application sandboxing in order to reduce the impact of this sort of attack. Its crazy that a malicious binary on my computer can download and modify all data on my computer (owned by any app), and access network shares using my credentials.

[1] I think - there might be ways to prevent this with evil service workers. Does anyone know?


> (most people only update chrome every month, so it only hits 1/30 users).

What do you base that on? My understanding is that a system with Chrome installed will check for updates every 5 hours[0], and I assume most people accept the update on the day that they see it is available.

> The problem on google chrome would be easier to detect, because it wouldn't be able to pinpoint a specific user.

I'm also not clear what you mean here. An attacker could decide to target a victim by their IP address, or any detail about their computer which is available to Chrome.

I agree with you though about native applications being able to do more damage, and possibly persisting on a machine for longer.

> Apps on phones are more secure because a malicious binary can't stop itself being removed via Apple / Google's app stores.

On the other hand, the user isn't secure against threats from the app stores themselves, not least the threat to Availability when an app store uses a kill switch to delete an app without warning.[1]

[0] https://support.google.com/chrome/a/answer/6350036?hl=en

[1] https://www.macworld.com/article/191897/iphone_killswitch.ht...


> My understanding is that a system with Chrome installed will check for updates every 5 hours

Ah yes. I was thinking that chrome releases a new version every month, and imagining hackers infecting a new version of the browser. But you’re right - if hackers hit the update system and managed to deliver malicious code for more than 5 hours, they would get almost everyone to download their payload. Yikes.

As for targeting users, most update mechanisms use CDNs, and the attacks against update systems I’ve heard about just put nasty files in the CDN. To go after a single user you would also need to reconfigure the CDN to deliver different files to different IP addresses - which, well, it would depend on the attack vector.


A key aspect is that for native apps its harder (not necessarily impossible) to just at a selected point in time deliver malicious code to a selected user, with nothing persisting it. Compared to a native app that's installed in a way that it can't modify itself (and thus needs to deliver a vulnerable or malicious version during installation) that's very weak - arguably an app that can invisibly update itself is somewhere inbetween.

With a web app you always load the code from the server - while at the same time using E2E to protect yourself against said server...


I agree with this analysis. We'd love to offer more assurances that the code hasn't changed out from under you when using Wormhole.app. We really need a better way to "pin" a site to a current version and only update it with user consent.

Right now, we're limited by the capabilities of the web platform and will probably need to ship a native app to accomplish this.


What about using sub resource integrity to allow users to request a specific JS version using its integrity attribute in the URL, that way shares also use the same pinned version, and can check/verify the integrity themselves or via some centrally informative place as well.


The problem here is that there's no good way in the browser Javascript runtime to verify the current execution environment. All you can check are the script assets you load, not whether your current running code has been eval'd into something malicious.

This is a very old debate that we're recapitulating here; if you sense that I'm being less than forthcoming about it, it's because there's something like 11 years of history of it in the search box below the page.

I don't much care about the argument here. I'm have two things to say in this thread:

1. "Wormhole" is a bad name for a new secure file transfer system, since one of the better-known cryptographic file transfer systems is already named "Magic Wormhole" and has the command "Wormhole". It's confusing, and especially annoying since there's no dispute that Magic Wormhole is more secure than this application --- even if you think, incorrectly, that browser Javascript crypto is "end-to-end", there's no coherent way to suggest that it's as secure as the native Magic Wormhole program.

2. AES-GCM is not in fact a perfectly cromulent AEAD; it is an imperfectly cromulent AEAD, and one most designers would probably do well to avoid (use XSalsa-Poly1305, with random nonces).


X


I really don't understand this "if I disagree with an argument, it's fulmination" point you keep trying to make. Further: I haven't called you names at any point in this discussion --- that's a line you're starting to cross. I think perhaps we should just disengage. I'm not asking you to respond to me. If you feel we're not getting anywhere, we don't have to keep talking.


D


I don't think you're doing a very good job of advocating for this person; if you were arguing this way with someone else on my behalf, I'd ask you to stop.


Fair, adios. Would appreciate if you actually respond to subresource integrity question. Why isn’t that valid? One could couple this with a CSP that restricts eval and Function or what ever is necessary. This all seems to be just about browsers in general.


It is in fact about browsers in general. They're a very hostile environment for cryptography.


> Is my reading of this as a vague and misleading way of saying that because the code responsible for the encryption is provided by the server it doesn’t count as end-to-end encryption accurate?

This is how I read tptacek's comment as well. It's vague and misleading to say that any code provided to a client by a server cannot be end-to-end encryption.

By that logic, even something like the Signal Desktop client (which has an auto-updater) is not end-to-end encryption. This is a not a reasonable or honest definition of end-to-end encryption.


The point of end-to-end cryptography is not having to trust servers. Your argument is that a system that appears to need to trust its server on an HTTP-request-by-HTTP-request basis must be end-to-end, because browsers on either side also do some cryptography. But that's not how it works.


You can't invent your own definition of end-to-end encryption.

There is a material difference between a service which end-to-end encrypts your files – even if it sends you the code to do so – and one which does not.

Services like Dropbox or WeTransfer receive plaintext copies of your files. Firefox Send did not. And Wormhole, using the same design, does not either.



> the other uses client-server cryptography pretending to be end-to-end

This is misleading and false. Wormhole.app uses end-to-end encryption.

To address the larger point – auditing a web app is indeed challenging with current web technologies. In the past, I experimented with a technique using App Cache to permanently cache a web app on first use [1]. Later, that technique was expanded into hyperboot [2] to give users the benefits of explicit, immutable versioning with control over upgrades using the html-version-spec while preserving the simplicity of passing around a URL.

With the impending removal of AppCache from most browsers, the web is currently missing a way to "pin" a site to a specific version and only update it with user consent. Service Workers come close but they mandate a 24 hour maximum cache time before refetching from the server.

We'd love to offer the usability benefits of web apps – you can give someone a URL and they can immediately load the app – with the security of installed apps – doesn't change without warning – once web standards catch up. This is something that I care deeply about.

In the meantime, use magic-wormhole if you prefer a locally-installed command line tool and you're sending files to someone who understands the command line. Use Wormhole.app if you want usable end-to-end encryption, similar to what Firefox Send used to provide.

[1]: https://github.com/feross/infinite-app-cache

[2]: https://github.com/substack/hyperboot


> if you prefer a locally-installed command line tool and you're sending files to someone who understands the command line

There's at least one good desktop GUI for Magic Wormhole[0]. I've also recently released an Magic Wormhole Android app[1][2].

[0]: https://github.com/Jacalz/wormhole-gui

[1]: https://github.com/psanford/wormhole-william-mobile

[2]: https://play.google.com/store/apps/details?id=io.sanford.wor...


I stand by my analysis.


Do I have this right?

1. A duplicate salt, which in this case should be a 16 byte random value, causes an repeated use of an KEY+IV for AES, which allows for a dictionary attack on the KEY (which looks like a password in this case) and weaker encryption because there will be multiple files encrypted with the same KEY+IV. What are the authenticated ciphers that mitigate this?

2. The end-to-end property is useful because of man in the middle attacks, since the stream is sent to the server unencrypted and the server does the encryption work.


Is this comment in reference to Wormhole.app? If so, it contains multiple inaccuracies.

1. The salt is only ever used once. All shared files are concatenated into a single stream and encrypted one time.

2. Only end-to-end encrypted file data is sent to the server. By definition, the server cannot be involved in end-to-end encryption.


I'm referring only to the library Wormhole uses for this, and its security UX, and to the implications of using vanilla AES-GCM. I don't know of and haven't looked for vulnerabilities in your application.

I wouldn't have fully agreed with the grandparent comment either, but your refutation was also inaccurate, so here we are.


This thread is really annoying to me. I see two people I look up to basically talking past one another in a situation where one of them could be providing a lot more advice, as I've seen them do on many occasions, but seems not to want to because they are mad about a naming decision.

Every thread on hacker news that devolves into a fight over a name choice is pointless and distracts from the good work people are doing. Names are hard, and they're even harder to change, we should come up with a more productive way to have that conversation, or not have it at all.

In the mean time, I'm super disappointed.


I guess you'll have to stay disappointed, because "wormhole" is a very bad name for a new point-to-point file transfer system, browser-mediated cryptography is almost never really "end-to-end", and AES-GCM is not an ideal choice for an AEAD, though it is, as I said earlier, "imperfectly fine".

There's no larger issue I'm here to comment on!


Because of your presence as an often helpful contributor on this site, folks have brigaded around your low effort critique and tanked any chance that we'll have a productive conversation about the technology, or, heck, even the name at this point. You have an outweighed role in the direction conversations can go on this site, and playing ignorant to that while dragging feross and his work down every chance you get because of a naming choice is sad to watch.

Edit: it's also pretty clear feross received this feedback and decided to keep the name, so all you are doing is fanning flames: https://news.ycombinator.com/item?id=26666142

Edit2: I know you know the rules of the site, but really, read them, you seem to be breaking many of the top rules by riding on that high horse.

Be kind. Don't be snarky. Have curious conversation; don't cross-examine. Please don't fulminate. Please don't sneer, including at the rest of the community.

Comments should get more thoughtful and substantive, not less, as a topic gets more divisive.


Yeah, I stand by what I said, sorry.


Thanks for responding, you don't owe me or anyone an apology in my opinion and I appreciate that you took the time to read what I said, despite being disappointed with your response.


Just trying to expand on the points made by GP.

1. Salt is randomly generated, I see no reason why this would not be the case other than using the salt parameter incorrectly. I primarily want the GP to list the symmetric ciphers which mitigate incorrect salt usage, since that info is useful.

2. I see that RFC8188 spells out that the stream is encrypted before sent to the server. Again, I want to understand the issue here, why does the GP say that it is not an end-to-end system. The only thing I can think of is because this is a utility that is itself a server and not a client, so the man in the middle would be between the client and the wormhole server.


There's also a web-based relay for magic-wormhole: https://webwormhole.io/ https://github.com/saljam/webwormhole


My comment on this on ProductHunt, and the developer's response: https://www.producthunt.com/posts/wormhole-2#comment-1312733


Wormhole.app and magic-wormhole have different goals.

Wormhole.app works in the browser, which means that it provides usable security to normal people. No `pip install` or command line needed. Wormhole.app stores end-to-end encrypted files for 24 hours so the share link continues to work even after the sender closes the tab or powers off their device.


This is a confusing name choice, since the real Magic Wormhole --- whose command is literally "wormhole" --- is vetted and widely used, and this new "Wormhole.app" is not. I'd consider changing it, since you're going to get this response any time you talk about Feross Wormhole among clueful types, and the comparison (right now at least) isn't very favorable to you. At best, it suggests you're not familiar with Magic Wormhole, which would be a strange credential for someone trying to do a new secure file transfer system.


It creates confusion since both share the word wormhole and the goal the share files.

If you still can, changing the name of your product would help a lot, and also show respect to the older FOSS project.


Indeed it is different enough to justify using a different name.


There are at least one or two existing magic-wormhole browser implementations.


It sounds like you're suggesting that magic-wormhole only wishes to provide end-to-end encryption to "abnormal" people. I don't believe that's true and there already exist implementations of the open magic-wormhole protocol in several languages.

The original magic-wormhole project is at least 6 years old. How did you determine its goals?

FWIW, I agree with other comments that you've chosen a confusingly-similar name (and that's unfortunate).


I was very excited to check this out, as I imagined `Wormhole.app` was a MacOS package for `magic-wormhole`, but, alas, it's just a web app with a very similar name.


Then you'll also be disappointed if you run:

  $ brew info wormhole
  wormhole: 1.5.4
  https://er.run/
  Not installed
  From: https://github.com/Homebrew/homebrew-cask/blob/HEAD/Casks/wormhole.rb
  ==> Name
  Wormhole
  ==> Description
  Browse & Control phone on PC, Screen Fusion for iOS & Android
  ==> Artifacts
  Wormhole.app (App)


I'm sure you can see the distinction between two unrelated projects being called "wormhole" and two almost identical projects sharing the same name.


Trademark law uses the "likelihood of confusion" concept.


That sounds like FireFox's Send. They had problems because it was expensive to operate. How do you solve that issue?


We're planning to introduce a Pro plan for larger file limits and explore an enterprise version for organizations that have high security requirements (law firms, etc.) that can't use existing cloud storage providers.


This was also previously called out on HN.

https://news.ycombinator.com/item?id=26666142


I'm one of the creators of Wormhole.app.

Just want to highlight our $1000+ bug bounty program for responsible disclosure of security issues. Both the cryptography code and the website itself are in scope. More details here: https://wormhole.app/security/disclosure


Another note to the developers of this site: I'm not sure if you've tested with Safari, but if you attempt to upload a file over 1 GB you'll get a number of prompts asking if you'd like to allow the website to use an amount of disk space, which showed up in increments of 200-400 MB for me.

"Do you want to allow this site to use 1GB of space on your Mac?" "Do you want to allow this site to use 1.2GB of space on your Mac?" "Do you want to allow this site to use 1.4GB of space on your Mac?"

etc. It's rather an annoying bug.


This is an unfortunate Safari limitation that Apple has intentionally put in place. We'd like to be able to use temporary storage space on the user's device (which can be automatically cleared as soon as the user or another app needs it). But Safari gives web apps a 1GB limit after which the app must prompt the user for an additional allocation of 200MB.

So if the app needs e.g. 5GB of space the user will need to click "okay" on twenty prompts for 200MB more space to make the app work. Needless to say, this is totally ridiculous and definitely not an API that Apple would ever find acceptable to ship for native iOS apps.

It's hard to see Apple's decisions here as anything but outright hostile to the web and designed to push developers into making native apps.

It's especially ironic given that Apple recently suggested [1] to Australian authorities that they can't possibly have a monopoly on app distribution since they have no restrictions against developers distributing PWAs which "have the look, feel and functionality of a native app". But what they fail to mention is that they control exactly what functionality is actually available to web apps. And right now it's A LOT less than what is available to web apps.

Furthermore, most users are not aware that other iOS browsers like Chrome, Brave, and Firefox are actually just "light UI skins" on top of the Safari browser engine, Webkit, because Apple refuses to allow third party browser engines on iOS. So this means that it's not possible for users to just switch to another browser in order to use more powerful web apps. They're literally prevented from doing so by Apple's policy to ban browser competition on iOS.

[1]: https://www.accc.gov.au/system/files/Apple%20Pty%20Limited%2...


I love the serendipity of thinking about a problem earlier this week and wishing I had a trusted, encrypted, identity-aware pipe I could throw on top of a websocket or similar connection... and a few days later here it is on HN. Looks like a nifty project!


Wormhole.app mentions that the transfer is p2p AND that the encrypted files are stored on the server for 24 hours. Does the client send two streams (1 to server - 1 p2p)? What happens e.g. if the receiver client comes online during an ongoing upload to the server?


In that case we send two streams - one for the upload, and one for the receiver. We should probably optimize this further. I think pausing the server upload until the P2P transfer finishes would increase overall transfer speed.


Or have both clients upload different parts to the server over the course of the transfer, and optimize for the client with the highest upload speed to do most of the heavy lifting (this assumes you want the server to definitely have a full copy first).

Sounds like I'm saying make the server another peer as you may get even more transfer speed sending half the file to the server, then the other half from the server and sender to the receiver - depending on which you want to have the complete file first/faster/at all (more general).




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: