State of HTTP Signatures?

From what I’ve seen it looks like most implementations have hardcoded SHA256…

https://arewehs2019yet.vpzom.click/

Mastodon for sure hardcodes SHA256.

The go-fed implementation I think is slightly more flexible and is hs2019/expires compliant. It’s just not widely used. :wink:

I’m not sure there’s currently a standard to convey what kind of key metadata is associated with a key id. I think most Mastodon profiles, for example, just list id, owner, and publicKeyPem properties from the security vocabulary. There’s lots more that could be adopted.

Looks like the security vocab defines a signatureAlgorithm field. Would setting that on the key to http://www.w3.org/2001/04/xmldsig-more#rsa-sha256 (or another option as defined in RFC6931) be a reasonable method to indicate this?

I’m looking at the latest version of the HTTP sigs spec, since it has indeed changed a bit since we first implemented it, and tbh there are stuff i’m not sure about:

  • the rules for (created) and (expired) do not permit accounting for clock skew (which is an acknowledged shortcoming of the spec), and while that’s probably fine for (expired), that is probably not the case for (created)
  • I am very confused with https://www.ietf.org/id/draft-ietf-httpbis-message-signatures-00.html#section-3.2.2, which states that if the signature Algorithm starts with “rsa”, and “(created)” is in the covered content, then the implementation MUST produce an error. Yet the example covers “(created)” and uses rsa-sha256?
  • there’s also confusion between (expired) and (expires). Most places talk about (expires) but one refers to (expired)
  • in the signature parameters, sometimes the created parameter is written as such, sometimes as (created)
  • https://github.com/httpwg/http-extensions/issues/1187
  • It looks like the example uses “rsa-256”, which doesn’t seem to exist. Either way that’s an issue
  • I assume that’s a typo since it’s pretty consistent otherwise
  • created is the signature parameter, but it’s (created) when used as a pseudo-header in the signed content
  • regarding clock skew, I’m sorry, I don’t know what nbf stands for
  • alright, either way, if we consider the example to be wrong, then Mastodon probably does not need to support created and expires, as those MUST not be accepted for creation of signatures with the only algorithm it supports for now (arguably, it could/should support more algorithms, though)
  • (created) is also occasionally used in examples as a signature parameter, but I assume that is an error as it does not make for a proper token
  • I don’t know what nbf is either (might be from the JWT spec?), the open PR just adds some text allowing implementations to account for skew.
  • All algorithms other than hs2019 are deprecated, so it is important to support that
  • I didn’t catch that the first time, but yeah I see it now. Probably should report issues for the examples
1 Like

Other then the (speculative?) increase in hash digest size from 256 to 512, I don’t understand the differences between the sha-256 and hs2019 algorithms. Is there a reason to upgrade? The new algorithm looks very complicated, and I would prefer to limit the complexity of the HTTP Signature implementation in Mastodon as much as is feasibly possible while still maintaining interop. Specification complexity is a leading cause of security bugs in similar applications, and one of my favorite parts of HTTP Signatures up until now has been the straightforwardness of the algorithm.

1 Like

hs2019 isn’t really a signature algorithm, the entire algorithm field is basically deprecated since its existence is a security hole. Technically the spec requires that the algorithm is derived from the keyId, but the mechanics of that aren’t defined, so most implementations (including Mastodon) simply use rsa-sha256 anyway

1 Like

Yeah, I read the spec around hs2019 a bit fast and made the assumption it was RSASSA-PSS with SHA512, but even that way, I couldn’t get the examples to verify (and their description is pretty inconsistent, some of the examples claim to use SHA256, others SHA512, for the same key that is supposed to use SHA512).

While I made some progress with it (https://github.com/tootsuite/mastodon/pull/14556), it probably doesn’t make much sense to do anything with that until we have a standard mechanism to derive that info (but I could default to rsa-sha256 in the meantime).

The aforementioned PR has been merged into Mastodon, so the development branch should support the hs2019 “algorithm”, assuming the actual underlying algorithms to be the same as rsa-sha256 (as no mechanism for defining/using such key metadata is implemented), but accepting (created) and (expires) as well as parsing them correctly.

It still uses rsa-sha256 for outgoing requests.

Hey, I’m one of the Editors of the HTTP Signatures specification… how can I help?

There are talks in the IETF to do breaking changes to the specification to “make it better”. It would be good to hear from implementers here on what is working for you and what isn’t working for you. The comment about hs2019 not being defined is helpful… the goal with that was to define things as cryptosuites… and ideally, we wanted to close a security hole where you could say one thing in the algorithm field and then use a different key that some implementations were just blindly feeding into a cryptolibrary (that’s a bad idea, please don’t do that – it allows attackers to specially craft keys that can cause some badly implemented crypto libraries to do terrible things like… skip checking the validity of digital signatures!).

In any case, let me know how I can help.

If you’re wondering how you could help… post something about how you’re using HTTP Signatures to the IETF HTTP WG. Don’t be shy, if we don’t get enough feedback from implementers, the work will be shut down w/o a final RFC being created. To post, just send an email to ietf-http-wg@w3.org

Here’s an example of the sort of thing to write:

https://lists.w3.org/Archives/Public/ietf-http-wg/2020JanMar/0020.html

4 Likes

Given that the latest draft completely breaks real world uses of this spec, how can we fix that?

1 Like

I opened backward compatibility for current http-signatures implementations · Issue #1410 · httpwg/http-extensions · GitHub, but it’s super cool that we got burned on this.

Given that the latest draft completely breaks real world uses of this spec, how can we fix that?

There are two choices: stay with the old implementation of the specification – libraries are expected to support the old version for some time to come, while upgrading to the new version. The HTTP WG made a conscious decision to do breaking changes to align things with the direction that the new HTTP work is going in. Yes, it’s disruptive and none of us want to change our libraries/code, but the changes are for the better. If you want to provide input into the process, raising an issue (like you did) is the best course of action.

In the end, implementations have the real power, and if something has been changed and the implementation community (which is massive) doesn’t want to go along with it, you kick up a fuss until the thing that broke for you is changed back (or it becomes clear that things are better with the new way of doing things).

I’ll respond to your concern in the HTTP WG issue – there is a fairly straight forward answer that will keep old versions working while the official WG version is allowed to progress and eventually be adopted.

1 Like

I agree that there are a lot of design flaws in the old protocol, but the problem is, there is no logical path forward for ActivityPub implementations to support both versions at once.

And what happens if it changes again?

Why did the new draft not acknowledge that it broke current implementations and provide this advice?

Why should we not just fork HTTP Signatures and introduce our own X-ActivityPub-Signature header?

It is possible to make changes without breaking the consumers you asked 6 months ago to write into the IETF letting them know about our usage. Instead, as a thank you to anybody who did that, we get hit with a draft that completely breaks us.

I’m bumping this from last year as we’re starting to see a lot more hs2019 in the wild and I’ve only seen one implementation besides our own that supplies the algorithm in the actor record.

I agree this may be the best option, but the sec LD context turns signatureAlgorithm into sec:signingAlgorithm so we accept both; even though one or the other might have an issue with LD-signature normalisation. I haven’t had the time to check this; so in the meantime I’ve instituted a fallback to look for sigAlgorithm at the top of the actor record with any context. I’m hoping I won’t need to use this, but have allowed for it just in case LD signatures start failing.

And just because tracking through the relevant specifications is a hard slog, we will fall back to rsa-sha256 if we couldn’t find anything in the actor record.

They key here is to be liberal in what you accept and conservative in what you generate.

I’m not yet certain what to do about the conflicts in ietf-httpbis-message-signatures and the implementation seems quite heavy so I personally plan to wait for it to evolve a bit more before supporting it.

We will switch “soonish” to sending hs2019; as it appears to be close to a critical mass of support. But I’d like to see a few more projects providing sec:signatureAlgorithm instead of just assuming that hs2019 == rsa-sha256. It does not. I think the only way that developers are going to get the message is if/when somebody switches their preference intentionally to rsa-sha512 and starts filing bugs.

2 Likes

I’m looking at the latest draft and it is wildly different from whatever we have currently. @request-target ?

2 Likes

Yeah request-target surprised me too recently. I tried to federate an activity to Peertube, and it failed because the request-target header wasn’t included in the sig. I’d never heard of that header before, evidently it’s a synthetic thing that a recent HTTP Signatures draft invented?