gotosocial/docs/locales/zh/federation/http_signatures.md
2024-11-02 05:58:56 +08:00

4.9 KiB
Raw Blame History

HTTP 签名

GoToSocial 要求所有发送到 ActivityPub 服务器的 GETPOST 请求都必须附带有效的 HTTP 签名。

GoToSocial 也会为其向其他服务器发送的所有 GETPOST 请求签名。

这种行为与 Mastodon 的 AUTHORIZED_FETCH / "安全模式" 等效。

GoToSocial 使用 superseriousbusiness/httpsig 库(从 go-fed 派生)来为发出的请求签名,并解析和验证传入请求的签名。该库严格遵循 Cavage HTTP Signature RFC,这是其他实现(如 Mastodon、Pixelfed、Akkoma/Pleroma 等)使用的同一份 RFC。此 RFC 后来被 httpbis HTTP Signature RFC 取代,但尚未广泛实施。)

查询参数

关于是否应该在用于生成和验证签名的 URL 中包含查询参数HTTP 签名规范并无明确规定。

在历史上GoToSocial 在签名中包含了查询参数,而大多数其他实现则没有。这导致在对 Collection 端点进行签名 GET 请求或验证签名的 GET 请求时(通常使用查询参数进行分页),出现了兼容性问题。

从 0.14 开始GoToSocial 尝试同时签署和验证携带和不携带查询参数请求,以确保与其他实现更好的兼容性。

发送请求时GtS 将首先尝试包含查询参数的情况。当收到外站服务器的 401 响应时,它将尝试在不包含查询参数的情况下重新发送请求。

接收请求时GtS 将首先尝试验证包含查询参数的签名。如果签名验证失败,它将尝试在不包含查询参数的情况下重新验证签名。

详细信息请参见 #894

传入请求

GoToSocial 的请求签名验证在 internal/federation 中实现。

GoToSocial 将尝试按以下算法顺序解析签名,成功后将停止:

RSA_SHA256
RSA_SHA512
ED25519

发出请求

GoToSocial 的请求签名在 internal/transport 中实现。

一旦解决了 https://github.com/superseriousbusiness/gotosocial/issues/2991 GoToSocial 将使用 (created) 伪标头代替 date

然而,目前在组装签名时:

  • 发出的 GET 请求使用 (request-target) host date
  • 发出的 POST 请求使用 (request-target) host date digest

GoToSocial 在签名中将 algorithm 字段设置为 hs2019,这一般意味着“从与 keyId 关联的元数据中导出算法”。生成签名时使用的实际算法是 RSA_SHA256,这与其他 ActivityPub 实现一致。在验证 GoToSocial 的 HTTP 签名时,外站服务器可以安全地假设该签名是使用 sha256 生成的。

特点

GoToSocial 在 Signature 标头中使用的 keyId 格式如下所示:

https://example.org/users/example_user/main-key

这不同于大多数其他实现,它们通常在 keyId URI 中使用片段 (#)。例如,在 Mastodon 上,用户的密钥会这样表示:

https://example.org/users/example_user#main-key

对于 Mastodon用户的公钥作为该用户的 Actor 表示的一部分提供。GoToSocial 在提供用户的公钥时模仿了这种行为,但并不在 main-key 端点返回完整的 Actor这可能包含敏感字段而是仅返回 Actor 的部分存根。它如下所示:

{
  "@context": [
    "https://w3id.org/security/v1",
    "https://www.w3.org/ns/activitystreams"
  ],
  "id": "https://example.org/users/example_user",
  "preferredUsername": "example_user",
  "publicKey": {
    "id": "https://example.org/users/example_user/main-key",
    "owner": "https://example.org/users/example_user",
    "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzGB3yDvMl+8p+ViutVRG\nVDl9FO7ZURYXnwB3TedSfG13jyskoiMDNvsbLoUQM9ajZPB0zxJPZUlB/W3BWHRC\nNFQglE5DkB30GjTClNZoOrx64vLRT5wAEwIOjklKVNk9GJi1hFFxrgj931WtxyML\nBvo+TdEblBcoru6MKAov8IU4JjQj5KUmjnW12Rox8dj/rfGtdaH8uJ14vLgvlrAb\neQbN5Ghaxh9DGTo1337O9a9qOsir8YQqazl8ahzS2gvYleV+ou09RDhS75q9hdF2\nLI+1IvFEQ2ZO2tLk3umUP1ioa+5CWKsWD0GAXbQu9uunAV0VoExP4+/9WYOuP0ei\nKwIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  "type": "Person"
}

与 GoToSocial 联合的外站服务器应从 publicKey 字段提取公钥。然后,它们应该使用公钥的 owner 字段签名 GET 请求,进一步解引用 Actor 的完整版本。

这种行为是为了避免外站服务器对完整 Actor 端点进行未签名的 GET 请求引入的。然而,由于不合规且引发问题,此行为可能会在未来发生变化。在 此问题 中进行跟踪。