Proposal: Signatures in SRI.

# Mike West (10 days ago)

TL;DR: I'd appreciate feedback on a proposal for a small, signature-based extension to SRI and CSP [https://github.com/w3c/webappsec-subresource-integrity/blob/master/signature-based-restrictions-explainer.markdown](https://github.com/w3c/webappsec-subresource-integrity/blob/master/signature-based-restrictions-explainer.markdown) .

In talking to some folks internally at Google, we've found some use cases for SRI in combination with CSP for some applications that the security team is particularly interested in locking down. Prototypes of this combined mechanism work the way they expect, but turning those prototypes into production will be quite difficult, given the dependencies on shared code written by several distinct teams and some additional requirements for out-of-band delivery that aren't directly relevant to this proposal.

Signatures seem like they would provide some of the same benefits, with real deployment advantages. It seems like these advantages might be applicable to other folks' projects as well, so I've written up a small explainer at w3c/webappsec-subresource-integrity/blob/master/signature-based-restrictions-explainer.markdown in the hopes of gauging interest. I'd appreciate y'all taking a look.

We've talked about extending SRI with signatures a few times over the years, and a few folks have put together different proposals for doing so (the thread at w3c/webappsec#449 contains a few examples). Mine is a fairly narrow approach in comparison with some other suggestions, which I hope is a feature. :)

In broad strokes, I'd suggest the following:

  1. We add support for Ed25519 in integrity attributes and CSP source expressions (e.g. <script src="whatever.js" integrity='ed25519-[public key]'>).

  2. We add support for a server-side mechanism of delivering an Ed25519 signature along with a resource (e.g. a new Signature: ed25519-[signature] header).

  3. We use the signature in the integrity attribute to verify the signature in the header after receiving the resource (much as we do for hashes today).

WDYT?

Contact us to advertise here
# Martin Thomson (10 days ago)

I think that signatures solve some of the concerns I've been seeing with SRI deployment, the biggest one being that you need to know what the content is before you can link to it. This would add a layer of indirection, allowing you to identify a signer.

I threw out a proposal a while back that would address a fairly significant shortcoming of SRI: an inability to progressively process content. It's a little more complicated than your proposal, but has the advantage of providing integrity over partial resources. It also degenerates neatly to what you propose here.

It's badly rotten, since I stopped maintaining it (time, wherefore art thou?), but I hope that you can at least get a taste: tools.ietf.org/html/draft-thomson-http-miser

That also suggests an enhancement for integrity more generally.

On your work: One major limitation of using ed25519 is that you can't incrementally calculate the signature; you should at a minimum consider the pre-hashed variant if you intend for this to be universally applicable. The draft above would be trivial to get to work with ed25519.

Should this identify multiple signers? This isn't quite pinning, but with long cache lifetimes, it could lead to similar sorts of lock-in.

# Mike West (10 days ago)

On Thu, Jun 1, 2017 at 11:42 AM, Martin Thomson martin.thomson@gmail.com

wrote:

I think that signatures solve some of the concerns I've been seeing with SRI deployment, the biggest one being that you need to know what the content is before you can link to it. This would add a layer of indirection, allowing you to identify a signer.

Right. I think it has real deployment advantages, especially for first-party resources (your own code), and quasi-first-party resources (colleagues with whom you have direct integration points).

sleevi@ and agl@ note that the usefulness for truly third-party resources is limited, because key management is hard. It would be nice to ensure that [https://apis.google.com/js/platform.js](https://apis.google.com/js/platform.js) is signed by Google, for instance, but hard-coding a public key into a million websites that embed that resource would make key rotation prohibitive, leading to some risk of key pinning suicide, similar to the risks that appear with HPKP.

I threw out a proposal a while back that would address a fairly

significant shortcoming of SRI: an inability to progressively process content. It's a little more complicated than your proposal, but has the advantage of providing integrity over partial resources. It also degenerates neatly to what you propose here.

It's badly rotten, since I stopped maintaining it (time, wherefore art thou?), but I hope that you can at least get a taste: tools.ietf.org/html/draft-thomson-http-miser

tools.ietf.org/html/draft-thomson-http-mice, is, I think, the link you were looking for.

That also suggests an enhancement for integrity more generally.

I think it's a reasonable one, pretty much in line with what agl@ was proposing a million years ago. We never ran with his proposal because folks were concentrating on scripts and style (which are processed atomicly), and the complexity of streaming was hard to justify.

On your work: One major limitation of using ed25519 is that you can't incrementally calculate the signature; you should at a minimum consider the pre-hashed variant if you intend for this to be universally applicable. The draft above would be trivial to get to work with ed25519.

I don't know enough in this space to have an informed opinion about the options. CCing agl@. :)

Should this identify multiple signers? This isn't quite pinning, but

with long cache lifetimes, it could lead to similar sorts of lock-in.

Yes. I imagine this would work just like hashes today: integrity="ed25519-A ed25519-B" would specify two public keys which would be accepted for the given resource.

# Ryan Sleevi (10 days ago)

On Thu, Jun 1, 2017 at 6:18 AM, Mike West mkwst@google.com wrote:

On Thu, Jun 1, 2017 at 11:42 AM, Martin Thomson martin.thomson@gmail.com wrote:

I think that signatures solve some of the concerns I've been seeing with SRI deployment, the biggest one being that you need to know what the content is before you can link to it. This would add a layer of indirection, allowing you to identify a signer.

Right. I think it has real deployment advantages, especially for first-party resources (your own code), and quasi-first-party resources (colleagues with whom you have direct integration points).

sleevi@ and agl@ note that the usefulness for truly third-party resources is limited, because key management is hard. It would be nice to ensure that [https://apis.google.com/js/platform.js](https://apis.google.com/js/platform.js) [https://apis.google.com/js/platform.js](https://apis.google.com/js/platform.js) is signed by Google, for instance, but hard-coding a public key into a million websites that embed that resource would make key rotation prohibitive, leading to some risk of key pinning suicide, similar to the risks that appear with HPKP.

Right. I think articulating the deployment scenarios - both with SRI-Hash and SRI-Sig - is extremely important in determining whether or not this provides value relative to the risk of the ecosystem.

Perhaps incomplete, but my proposed set of categories to consider are:

"Full" 1P - A single organization with a monolithic view of its code and dependencies. At any given time, a given page knows all of the expected versions/contents of its related dependencies. Publication is always centrally coordinated. "Quasi" 1P - An organization that might have multiple independent teams and versioning strategies, and not enforcing them via URLs. e.g. an organization that has Team X working on Component A, and Team Y working on Component B, and Team Z working on the overall Site, which ingests (unversioned) Components A and B. In this case, publication is not centrally coordinated (Components A, B, and the Site may all update at independent cadences), but they're all part of the same logical organization. "Versioned" 3P - A site is ingesting resources from one or more third-parties, at explicit versions "Rolling" 3P - A site is ingesting resources from one or more third-parties, each of which independently updates on their own cadence (providing backwards compatibility to the site, to some extent)

I propose these categories because it affects the deployment discussions:

  • Full 1P can use SRI-Hash, because there's a central publication mechanism in which all of the SRI hashes can be computed/known, and thus injected as appropriate.
  • Quasi 1P can't use SRI-Hash, because Components A and B are independently updating at a cadence distinct from Site. They believe they can use SRI-Sig, because as a singular organization, they can coordinate signing activities as part of the publication stream. In the event of a key rotation, all resources must be republished (with the new/rollover key), but continuity is otherwise maintained
  • Versioned 3P can use SRI-Hash, because the dependency graph of 3P resources is known at time of 1P publication.
  • Rolling 3P can't use SRI-Hash, because the constant update of 3P resources would otherwise mean an endless update of 1P hashes. Rolling 3P thinks it can use SRI-Sig, because then it could just express the keys of the 3P publisher. However, a 3P experiencing a key rollover event would require all consuming 1P to republish with the new key.

So the use cases that shake out are Quasi 1P (but with centralized publication for key rotation) and Rolling 3P. However, I think both of these cases are wrong and bad for security and the ecosystem :)

Quasi 1P still has to maintain a centralized republication mechanism (e.g. what Full 1P has) in order to handle key rollover events. A Quasi 1P entity that doesn't is just setting themselves up for breakage in the event of a key rollover event, the inability to publish (in the event of a key loss), or the loss of security (in the event of a key compromise). Two of these breakages directly affect users (the greatest constituent) for reasons beyond their or the UAs control - that is, it's a footgun. The third undermines the security guarantees, and thus isn't particularly compelling for the UA.

For Quasi 1P, I would assert that having the 1P have the capability to do centralized publication is a net-good for their deployment, and the experience of users. And while I realize that's telling site operators what to do, it's also recognizing that SRI-Sig is not going to solve their problem.

Rolling 3P is just building an ecosystem ripe for massive user disruption and the eventual disabling of SRI-Sig because of that. If you imagine a situation like some ad or analytics vendor publishing their key for consuming 1P, then any time they update that key (rotation, loss, compromise), all of those 1P become broken, which means the user experience is broken, which means the user agent is, while properly observing the site authors intent, breaking the Web for users. It too is a giant footgun.

Once you introduce SRI-Sig, however, it introduces a desire to get 'clever' with signatures, as is always the case. The argument for a design that avoids these issues is something like the 3P has a 'long-term' high security key (that all of 1P consume/encode in their page), and that signs a 3P resource that then 'chains' to the 'short-term' key used to sign the rolling updates. This is the classic offline/online PKI scheme - reflected in a variety of systems, most notably, the Web PKI. Once you introduce this chaining scheme though, you introduce worse user experience (since it's SRI, each of these signatures is effectively achieved by loading a subsequent resource - meaning you've got loading order pain), and you introduce a need for things like Key TTLs or Revocation (since without them, your online key isn't reducing the threat surface, since you can always do version rollbacks to a compromised key). And since it's something that 'anyone' could deploy, it makes it more likely that just like 10 year TLS server certificates (that people forget about / how to replace), these 'offline' keys are at an even greater likelihood of going missing.

To me, it seems like SRI-Sig's "use case" is to support SRI for the case of 'rolling updates', without requiring awareness of what those updated resources are. This does match the deployment reality of the Web - that 1P entities are often in the "Quasi 1P" scenario without centralized coordination/publishing (and I believe that is Mike's intended use case), and that most of the 3P resources - things like analytics and ads - are equally on 'rolling updates' without centralized coordination.

I can understand the desire and appeal to want to provide better assurance for these deployments. I just don't think this meaningfully does so, in a way that doesn't introduce giant footguns to the Web compatibility story. I think the level of support for SRI-Sig depends on how much you believe the Quasi-1P and Rolling-3P scenarios are 'valid' and 'good' to begin with, and how much you believe SRI "should" apply to them. I don't believe they're good (but they're real and the majority), but more importantly, I think that if you want to adopt those models, then the security tradeoff is unavoidable, because the usability tradeoff is too high.

# Adam Langley (9 days ago)

On Thu, Jun 1, 2017 at 3:18 AM, Mike West mkwst@google.com wrote:

tools.ietf.org/html/draft-thomson-http-mice, is, I think, the link you were looking for.

That also suggests an enhancement for integrity more generally.

I think it's a reasonable one, pretty much in line with what agl@ was proposing a million years ago. We never ran with his proposal because folks were concentrating on scripts and style (which are processed atomicly), and the complexity of streaming was hard to justify.

Yep. An unbalanced Merkle tree is the only reasonable solution that I'm aware of. An open question is whether the hashes should be distributed throughout the file (as I think I prefer, and Martin proposes) or served all at the beginning in an HTTP header. The latter allows the same resource on disk to be used for fetches both with, and without integrity, but is a bit shitty.

On your work:

One major limitation of using ed25519 is that you can't incrementally calculate the signature; you should at a minimum consider the pre-hashed variant if you intend for this to be universally applicable. The draft above would be trivial to get to work with ed25519.

I don't know enough in this space to have an informed opinion about the options. CCing agl@. :)

The current SRI assumes that resources are small and not incrementally parsed, so ed25519 fits nicely. Combining ed25519 with an unbalanced Merkle tree effectively does make it the pre-hashed version, so that's fine too. So, if SRI sticks to it's current goal of only covering small resources, ed25519 seems applicable. If it wants to cover large resources, support for Merkle trees is needed and then we effectively have ed25519ph already, or we can actually use ed25519ph on the basis that we're already there and why hash the first record twice?

# Mike West (9 days ago)

Thanks, Ryan! I appreciate the detailed response, and I agree with some of the critique. :)

I think we agree that scenarios exist in which it would be nice to make meaningful assertions about the content loaded into a page. I think we also agree that SRI's current digest-based mechanism deals with many use cases in a reasonable way. I think we even agree on the risks that signature-based mechanisms present if applied blindly to certain use cases. I think we disagree about the value that a signature-based system provides that balances against those risks; I'll try to outline the way I'm looking at this question in the discussion below.

On Thu, Jun 1, 2017 at 4:07 PM, Ryan Sleevi sleevi@google.com wrote:

Perhaps incomplete, but my proposed set of categories to consider are:

I think the categorization you've proposed is pretty reasonable, but I'd note that lots of sites will fall into more than one of these categories. They'll have some components they control completely, they'll have some components controlled by colleagues, and they'll load resources of various kinds from third-party servers. It's probably clear, but just to be explicit: the decision about when a given form of SRI is appropriate is totally possible to make on a case-by-case basis.

I'd also note that because of shared components, the notion of first- and third-party is relative. When example.com embeds a widget from api.com, that widget might well include more resources. example.com can't reasonably make assertions about them a priori, but the widget script from api.com probably could.

  • Full 1P can use SRI-Hash, because there's a central publication mechanism

    in which all of the SRI hashes can be computed/known, and thus injected as appropriate.

Full 1P can also use SRI-Sig, because there's a central publication mechanism in which all of the SRI public keys are known, and thus injected as appropriate. In fact, there are practical advantages to doing so, as in most cases the same public key can be used. As <script integrity='[key]'>

will remain stable for every embedding page, sweeping intermediate cache invalidation can usually be avoided, whereas <script integrity='[hash]'>

would require rebuilding the world every time any integrity-checked resource changed. This stability in the face of regular updates is pretty valuable, despite the challenges you note below.

I'd also note that the nature of the assertion made by a signature is different than that made by a hash: the latter requires foreknowledge of the content, while the former evaluates provenance. That latter assertion seems like a valuable primitive to add to the platform, and would enable some interesting things in the future. For instance, I think would be practically impossible for even "Full 1P" origins to deploy an Ormail.google.com/mail/u/0/#inboxigin Policy [https://wicg.github.io/origin-policy/](https://wicg.github.io/origin-policy/) that set a baseline CSP

listing hashes of each individual script the origin might wish to use on any page (if only for mundane performance reasons, as such a list would be constantly changing). Deploying a baseline CSP that restricted an origin to a small set of signing keys, on the other hand, might well be practical.

  • Versioned 3P can use SRI-Hash, because the dependency graph of 3P

    resources is known at time of 1P publication.

As above, SRI-Sig could be useful even in Versioned 3P scenarios because of the cascading side-effects of hash changes. Consider things like ES6 modules, which import scripts (which themselves import scripts (which themselves import scripts (and so on))). Changing a leaf node would alter its hash, which would require an update to its parent to encode the new hash, which would require an update to its parent, etc. Signatures seem like they would ease this churn.

Quasi 1P still has to maintain a centralized republication mechanism (e.g. what Full 1P has) in order to handle key rollover events. A Quasi 1P entity that doesn't is just setting themselves up for breakage in the event of a key rollover event, the inability to publish (in the event of a key loss), or the loss of security (in the event of a key compromise). Two of these breakages directly affect users (the greatest constituent) for reasons beyond their or the UAs control - that is, it's a footgun. The third undermines the security guarantees, and thus isn't particularly compelling for the UA.

For Quasi 1P, I would assert that having the 1P have the capability to do centralized publication is a net-good for their deployment, and the experience of users. And while I realize that's telling site operators what to do, it's also recognizing that SRI-Sig is not going to solve their problem.

I think I agree with you that anyone relying on signatures for validation needs to be able to deal with the inevitability of compromise or loss. Ideally, folks using signatures would set up systems which allowed for regular rotation to keep that joint well-oiled.

Rolling 3P is just building an ecosystem ripe for massive user disruption and the eventual disabling of SRI-Sig because of that. If you imagine a situation like some ad or analytics vendor publishing their key for consuming 1P, then any time they update that key (rotation, loss, compromise), all of those 1P become broken, which means the user experience is broken, which means the user agent is, while properly observing the site authors intent, breaking the Web for users. It too is a giant footgun.

I agree that this proposal isn't going to help massively shared libraries with rolling updates (e.g. [https://connect.facebook.net/en_US/sdk.js](https://connect.facebook.net/en_US/sdk.js) or [https://platform.twitter.com/widgets.js](https://platform.twitter.com/widgets.js)), unless we dive into the cleverness you rejected, which I'm not terribly interested in doing. As noted above, however, it might be a good fit for the resources that script expects to include. The embedder itself couldn't hard-code a key for those resources, but the script could. For example, if a developer decides to embed a Tweet, widgets.js will render it inline; it would be expensive to include hashes for every resource, but a key might be practical.

To me, it seems like SRI-Sig's "use case" is to support SRI for the case of

'rolling updates', without requiring awareness of what those updated resources are. This does match the deployment reality of the Web - that 1P entities are often in the "Quasi 1P" scenario without centralized coordination/publishing (and I believe that is Mike's intended use case), and that most of the 3P resources - things like analytics and ads - are equally on 'rolling updates' without centralized coordination.

I would hesitate to reject ads as a use case entirely. I can imagine signature-based restrictions being enforced on embedded contexts [https://w3c.github.io/webappsec-csp/embedded/](https://w3c.github.io/webappsec-csp/embedded/) as an additional defense

against malvertising. Since ads are unknown before page load, building up a set of a priori valid hashes would be difficult, but you could certainly imagine DoubleClick's frame selecting an ad, and then ensuring that only signed resources load. The footgun risk seems significantly lower in this scenario, as ads are short-lived by nature.

shrug I see some value in adding this primitive. It seems to increase developers' ability to practically distribute assertions about the content they intend to load, and do so in a way that's both straightforward and simple.

-mike

P.S. As an aside, I'll briefly touch on a much more narrow (possibly Google-only) use-case that the stability of signatures enables: Google's security team would like to lock down some particularly high-risk internal web pages by enforcing SRI through CSP. Moreover, they're interested in doing so out-of-band of the page itself. Until Origin Policy [https://wicg.github.io/origin-policy/](https://wicg.github.io/origin-policy/) ships, they're planning on doing so

by force-installing an extension that ensures a policy is applied to every page. They can do so today with hashes, but that would be quite brittle in deployment, as folks would need to have the right version of the extension installed at all times. Signatures significantly reduce that complexity, similar to the origin policy discussion above.

# Devdatta Akhawe (2 days ago)

+1 to all of Mike's points. I think this can be tremendously useful for a lot of scenarios and, for Dropbox, I can assert that we will likely deploy this for the full-1p case; SRI-hash is pretty painful to use for us (and I imagine Google too). While in theory it shouldn't be, in practice adding signatures is a lot easier. As I envision it, we should support a header that (at a high level) says "make sure all loaded scripts are signed by a key".

# Jeffrey Yasskin (a day ago)

On Thu, Jun 1, 2017 at 2:42 AM, Martin Thomson martin.thomson@gmail.com wrote:

I think that signatures solve some of the concerns I've been seeing with SRI deployment, the biggest one being that you need to know what the content is before you can link to it. This would add a layer of indirection, allowing you to identify a signer.

I threw out a proposal a while back that would address a fairly significant shortcoming of SRI: an inability to progressively process content. It's a little more complicated than your proposal, but has the advantage of providing integrity over partial resources. It also degenerates neatly to what you propose here.

It's badly rotten, since I stopped maintaining it (time, wherefore art thou?), but I hope that you can at least get a taste: tools.ietf.org/html/draft-thomson-http-miser

That also suggests an enhancement for integrity more generally.

On your work: One major limitation of using ed25519 is that you can't incrementally calculate the signature; you should at a minimum consider the pre-hashed variant if you intend for this to be universally applicable. The draft above would be trivial to get to work with ed25519.

I'm certainly not a cryptography expert, but I read in tools.ietf.org/html/rfc8032#section-4, "Note that single-pass verification is not possible with most uses of signatures, no matter which signature algorithm is chosen. This is because most of the time, one can't process the message until the signature is validated, which needs a pass on the entire message."

Does that not apply to uses of SRI?

Thanks, Jeffrey

# Martin Thomson (15 hours ago)

On 10 June 2017 at 06:04, Jeffrey Yasskin jyasskin@google.com wrote:

I'm certainly not a cryptography expert, but I read in tools.ietf.org/html/rfc8032#section-4, "Note that single-pass verification is not possible with most uses of signatures, no matter which signature algorithm is chosen. This is because most of the time, one can't process the message until the signature is validated, which needs a pass on the entire message."

The draft I cited includes a method for signing partial messages. The trade-off is that it's trivially vulnerable to truncation attacks, much in the same way that HTTP responses over TLS can be cut off.

So both things are true. Generally, you want a signature over a thing to be completely verified before you use it in any way, so what RFC 8032 says is entirely appropriate.

Want more features?

Request early access to our private beta of readable email premium.