Yes, if every single URL in your web application has a hash in it (including <a> hrefs) then you don’t have to worry about anyone maliciously serving a webpage anymore.
But how do you get new app versions? I argue, if you want any meaningful security guarantees, an answer to this question will require transparency and/or code signing (which itself requires transparency, per my comment below)
1. I didn't know about this [1] actually! It looks like it's been unsupported for a few years now. The format looks pretty barebones, and we'd still need hashes like you said, as well as "wildcard" entries. I reckon the JSON solution might still be the better choice, but this is good to have as a reference.
2. I agree, and this is something we have gone back and forth on. The nice thing about hashes as primary keys is you can easily represent a single path having many possible values, and you can represent "occurs anywhere" hashes by giving them the empty string. But the downside like you mention is that a hash cannot occur at multiple paths, which is far from ideal. I'll make an issue in the Github about this, because I don't think it's near settled.
3. I had read the spec [2] but never made this connection! You're right that it's not hard to imagine malleability sneaking in via headers and status codes. I'll make an issue for this.
4. I wanted to veer a bit from requiring sites to hold yet more cryptographic material than they already do. Yes you can keep signing keys "very very offline", but this requires a level of practice that I'm not sure most people would achieve. Also you run into key rotation annoyances as well. The current route to something like you describe is have every site have their own transparency log entry (though they can share manifests and even asset hosts), and use code signing to link their instance to the source of truth.
<3 FWIW, I know Hacker News discussions often go stale after a bit and later responses might never be seen, and I don't really have time until later tonight to work on this (I used up my minutes earlier frantically reading this article to leave that other comment), so I thought I'd leave a quick comment here saying that I will be doing some further explanation in a comment here later tonight into what I thought is so interesting with cache manifests and some further thoughts viz-a-viz shared origins. (And, if you also happen to think any of my commentary is somewhat useful, I'd love to have a call or something with you at some point to talk about some of your vision for this work: I have a number of use cases for this kind of verification, and I think I was one of the more serious users of cache manifests back a decade ago.)
So, the other standard that relates to this is Signed HTTP Exchanges (which, I only, just now, learned that Cloudflare I guess decided to, also just now, withdraw support of, lol), and I think when you fit all of these together, and look at the existing practice from both Android and Web3, a really amazing possible vision starts to form.
AFAIK, the goal there was the idea that you should be able to implement stuff like a caching peer-to-peer proxy network in a secure manner, as you'd be able to prove that a response came from the official server... and, since that could have a Date header and associated cache control information, that it was even "up to date"/valid content.
The way this works is that the signed exchange is considered part of the origin that signed the exchange, rather than the origin from which you received it; this totally changes the game for distributing censorship resistant applications... except that I believe it all ends up tied back to the TLS ecosystem, to establish the correct key.
Essentially, what I've seen a lot of people want to do -- primarily very much in the decentralized crypto / Web3 ecosystem -- is to be able to have an application where the "server" is a blockchain (accessed via a commodity server that just tracks access to blockchain state), identity is handled by keys, and all data is in local storage...
...but the problem is: where do you get this app from? It ends up having to be on a random web host, and, even with separate wallets managed by browser extensions or even full hardware, you end up in a terrifying place if the server can keep modifying the app you are using as you are using it. This is like, your core use case for this! ;P
Only, these people are trying to simultaneously solve this: they don't want the site to be tied to the existing website infrastructure at all. If I disappear, you should be able to continue to use the website forever, as long as someone has a backup copy of it and they are willing to host it, which is similar to the signed exchanges case.
The closest we have for this currently is to host the app on IPFS, but: 1) the browser doesn't have a supported way to verify anything that comes from IPFS, so we are reliant on the security of some random proxy server (which we could run local, but it is super expensive); and 2) the only way to get updates re-exposes the original issue.
To me then, "table stakes" for any attempt to solve this problem has to cover this use case, as this is where I see the vast majority of people, today, actively trying to pull this off. In fact, with the exception of WhatsApp, the only people I've ever even heard of with a need for this right now are these people who are going all the way.
One way to approach this would be to try to stare at IPFS and figure out how to make it better, but I totally appreciate that that might be a lost cause: IPFS is extremely inefficient and intricate... what I feel we need is for a standard to be put forward that allowed for stuff on top of IPFS--or all competing mechanisms--to be compliant.
Like, the thing I actually want to be able to do is to host a website "out there somewhere", maybe on a bunch of mirror sites, maybe on IPFS, maybe in .zip files that people distribute on USB keys... just, somewhere/somehow, and then when they use that website it is considered just as secure as any other way that they might get the app.
This is how it works with Android apps, for example: no matter how I found the app, or an upgrade to the app (even if that upgrade came from a different path than how I got to the app originally), the app gets access to its private/secure storage on a user's device because of its identity, not because of the path by which I'd found the app.
And this is where the whole problem just starts sounding like the same thing that we were doing with app cache manifests: the ostensible reason those existed is that one would like to be able to download a full copy of a web application so you aren't using it on a train and suddenly realize you are missing some key file for it to operate.
What that means, though, is that the app cache manifest essentially becomes a bill of materials for an entire web app: with a link to just the app cache manifest, what you are able to do is download and "install" the app. (iOS then used this heavily for their personal web app install to homescreen flow, so you really downloaded the app.)
The mechanism also had a kind of atomicity to it, wherein it would download the entire new application and only switch to the new app as a single unified unit: either it had an updated copy of all of the files in the new manifest, or it is going to keep using the old app; once ready, a script event fired and you could notify the user to reload.
So like, in my mind, there is this amazing intersection ready to be found, wherein the goals of the app cache manifest and Signed HTTP Exchanges -- but with a root of trust that is more like an Android app than the TLS authorities -- are combined together to let the ecosystem trying to build decentralized peer-to-peer e2ee web applications.
And like, viewed from that perspective, the "more cryptographic material" that people need for their app is just the same thing as the signing key they'd use for an Android app, a concept that people built workflows around and I don't think is such a big lift: somehow, Android was fine, despite this being how it worked for a dozen+ years.
That said, I think that this still has a lot of value even if it is tied back down to the centralized hostname ecosystem, but what I like about HTTP Message Signatures (not Signed HTTP Exchanges) is that I think they have a trust root that is more like DANE, using a DNS entry to anchor the public key rather than tying it to a TLS certificate.
Regardless, in my perfect world, what I want is for all of these copies of the app that might exist in the world -- whether signed by the same key or tied back through Signed HTTP Exchanges to an underlying host (which, maybe some day, can be on a fully decentralized registrar) and a key furnished by DNS -- to share the same web origin.
And like, the reason I keep coming back to this, is because most of the people I have seen in the wild trying to solve this problem barely have a server at all and want to be able to write an application that entirely uses local storage and distributed hash tables or blockchains or even manual message passing to connect up, peer-to-peer.
But so, yeah: I've now spent a bunch more time typing a giant manifesto for a thing that you are already working on and I get that that is an awkward thing if the vision doesn't align at all (or maybe you are actively trying not to solve the use case of the people I keep pointing at)... but, if you do, I'd love to chat about this (a lot).
I'll actually argue the opposite. Transparency is _the_ pivotal thing, and code signing needs to be built on top of it (it definitely should be built into the browser, but I'm just arguing the order of operations rn).
TL;DR you'll either re-invent transparency or end up with huge security holes.
Suppose you have code signing and no transparency. Your site has some way of signaling to the browser to check code signatures under a certain pubkey (or OIDC identity if you're using Sigstore). Suppose now that your site is compromised. What is to prevent an attacker from changing the pubkey and re-signing under the new pubkey. Or just removing the pubkey entirely and signaling no code signing at all?
There are a three answers off the top of my head. Lmk if there's one I missed:
1. Websites enroll into a code signing preload list that the browser periodically pulls. Sites in the list are expected to serve valid signatures with respect to the pubkeys in the preload list.
Problem: how do sites unenroll? They can ask to be removed from the preload list. But in the meantime, their site is unusable. So there needs to be a tombstone value recorded somewhere to show that it's been unenrolled. That place it's recorded needs to be publicly auditable, otherwise an attacker will just make a tombstone value and then remove it.
So we've reinvented transparency.
2. User browsers remember which sites have code signing after first access.
Problem: This TOFU method offers no guarantees to first-time users. Also, it has the same unenrollment problem as above, so you'd still have to reinvent transparency.
3. Users visually inspect the public key every time they visit the site to make sure it is the one they expect.
Problem: This is famously a usability issue in e2ee apps like Signal and WhatsApp. Users have a noticeable error rate when comparing just one line of a safety number [1; Table 5]. To make any security claim, you'd have to argue that users would be motivated to do this check and get it right for the safety numbers for every security-sensitive site they access, over a long period of time. This just doesn't seem plausible
I'll actually argue that you're arguing exactly what I'm arguing :)
My comment near the end is that we absolutely need transparency - just that what we need tracked more than all the code ever run under a URL is that one signing key. All your points are right: users aren't going to check it. It needs to be automatic and it needs to be distributed in a way that browsers and site owners can be confident that the code being run is the code the site owner intended to be run.
Gotcha, yeah I agree. Fwiw, with the imagined code signing setup, the pubkey will be committed to in the transparency log, without any extra work. The purpose of the plugin is to give the browser the ability to parse (really fetch, then parse) those extension values into a meaningful policy. Anyways I agree, it'd be best if this part were built into the browser too.
You're right that, when your own server is trustworthy, fully self-hosting removes the need for SRI and integrity manifests. But in the case that your server is compromised, you lose all guarantees.
Transparency adds a mechanism to detect when your server has been compromised. Basically you just run a monitor on your own device occasionally (or use a third party service if you like), and you get an email notif whenever the site's manifest changes.
I agree it's far more work than just not doing transparency. But the guarantees are real and not something you get from any existing technology afaict.
If they want to make a proposal, they should have httpc://sha-256;... URLS which are essentially constant ones, same as SRI but for top-level domains.
Then we can really have security on the Web!
Audit companies (even anonymous ones but with a good reputation) could vet certain hashes as being secure, and people and organizations could see a little padlock when M of N approved a new version.
As it is, we need an extension for that. Because SRI is only for subresource integrity. And it doesn't even work on HTML in iframes, which is a shame!
The linked proposal is basically a user-friendlier version of that, unless you have some other security property in mind that I've failed to properly understand.
If the server stores the transcript of a session, can it brute force the PIN later on?
Magic Wormhole (https://github.com/magic-wormhole/magic-wormhole) avoids this by using a password authenticated key exchange (PAKE) protocol. If you don’t use a PAKE, you get trivial brute force attacks from anyone with a transcript.
What do you mean by transcript? If you mean the messages that were shared - the answer is no, server sees no messages at all as message exchange is peer to peer via WebRTC. As soon as session is over(eg. When all clients disconnect) - message history is lost for good. Brute force attacks are theoretically possible for sessions in progress(though hard due to alphanumeric 6 character PIN and server throttling), so I'll introduce "safe session" as suggested by some of the commenter by introducing "waiting rooms" so the newly connected clients have to be approved. I'd definitely leave the current workflow as is as its frictionless and works for some of my usecases(quick link or log sharing, etc)
There are middle boxes between the two peers, yes? Routers and such. They observe the encrypted messages. They can brute force the password, even after the session is over.
Even if you assume the PIN is uniformly random (you should not assume this), it is only log2((10+26)^6) ~ 31 bits of entropy. This does not satisfy standard notions of secure channel establishment.
tl;dr: One peer generates a self-signed certificate and sends the fingerprint of that over the signalling channel; the other connects to it as a "client".
The resulting DTLS keying material is subsequently used for SRTP encryption (for media) and SCTP over DTLS (for the data channel, which is presumably what's being used here).
WebRTC is end-to-end encrypted by default and only requires a tamper-proof, but not confidential, signaling channel for that encryption to be secure, so retroactive, or even ongoing passive, signalling server compromises are not a concern.
Yes. In Germany there is Giropay, where you get redirected to your online banking (it remembers your bank), you have to log in, and submit the already pre-filled transaction. It's literally a normal bank transfer from the user perspective. Not something that happens on the server side.
I don't know about the others, but Giropay just does a redirect to your online banking account and prefills the bank transfer form. The actual payment is literally the instant bank transfer solution. (I think it's called TIPS, not SWIFT.)
It's a scheme layered on top of regular SEPA bank transfers. As such, it does not work across borders, for example, and not even with all German banks.
> TIPS is a harmonised and standardised pan-European service with common functionalities for the settlement of Instant Payments across different countries and jurisdictions. It is based on the Single Euro Payments Area (SEPA) Instant Credit Transfer scheme.
> In 2020, Lael Brainard announced the upcoming FedNow service would provide "a neutral platform on which the private sector can build to offer safe, efficient instant payment services to users across the country",[20] after 2018 the European Central Bank launched the TIPS instant payment settlement system.[21]
Unfortunately not every country in Europe. Zero banks in Ireland have implemented SEPA Instant and transfers still take at least a day. Thankfully though they have a deadline to implement this that's coming up soon and will be forced to comply.
Sometimes it can be worthwhile to see what other countries have been successfully doing for decades. It won't prevent anyone from reinventing the wheel if they still have their mind set on it :)
It’s not actually much different. The main reason to use this is because it’s the standardized version of that concept and has been analyzed by people. All the smaller cryptographic detailed like domain separation, proper key derivation, weak key rejection etc. have been worked out for you. So it’s a plug and play solution that previously didn’t exist.
Grim is the thought experiment of imagining 1.8 million chicken's being gassed to death. It's nearly psychopathic to think it's not just because human's kill exponentially more everyday. Not to disimiliar to brushing off someone's dying in a car accident because there's over 40,000 motor vehicle fatalities a year.
But that's what we do, don't we? You don't care about someone on the other side of the world dying on the road, or the next city over. It's not even newspaper-worthy. It's just another day.
But how do you get new app versions? I argue, if you want any meaningful security guarantees, an answer to this question will require transparency and/or code signing (which itself requires transparency, per my comment below)