diff options
author | Thomas Voss <mail@thomasvoss.com> | 2024-11-27 20:54:24 +0100 |
---|---|---|
committer | Thomas Voss <mail@thomasvoss.com> | 2024-11-27 20:54:24 +0100 |
commit | 4bfd864f10b68b71482b35c818559068ef8d5797 (patch) | |
tree | e3989f47a7994642eb325063d46e8f08ffa681dc /doc/rfc/rfc9421.txt | |
parent | ea76e11061bda059ae9f9ad130a9895cc85607db (diff) |
doc: Add RFC documents
Diffstat (limited to 'doc/rfc/rfc9421.txt')
-rw-r--r-- | doc/rfc/rfc9421.txt | 5157 |
1 files changed, 5157 insertions, 0 deletions
diff --git a/doc/rfc/rfc9421.txt b/doc/rfc/rfc9421.txt new file mode 100644 index 0000000..a207d2a --- /dev/null +++ b/doc/rfc/rfc9421.txt @@ -0,0 +1,5157 @@ + + + + +Internet Engineering Task Force (IETF) A. Backman, Ed. +Request for Comments: 9421 Amazon +Category: Standards Track J. Richer, Ed. +ISSN: 2070-1721 Bespoke Engineering + M. Sporny + Digital Bazaar + February 2024 + + + HTTP Message Signatures + +Abstract + + This document describes a mechanism for creating, encoding, and + verifying digital signatures or message authentication codes over + components of an HTTP message. This mechanism supports use cases + where the full HTTP message may not be known to the signer and where + the message may be transformed (e.g., by intermediaries) before + reaching the verifier. This document also describes a means for + requesting that a signature be applied to a subsequent HTTP message + in an ongoing HTTP exchange. + +Status of This Memo + + This is an Internet Standards Track document. + + This document is a product of the Internet Engineering Task Force + (IETF). It represents the consensus of the IETF community. It has + received public review and has been approved for publication by the + Internet Engineering Steering Group (IESG). Further information on + Internet Standards is available in Section 2 of RFC 7841. + + Information about the current status of this document, any errata, + and how to provide feedback on it may be obtained at + https://www.rfc-editor.org/info/rfc9421. + +Copyright Notice + + Copyright (c) 2024 IETF Trust and the persons identified as the + document authors. All rights reserved. + + This document is subject to BCP 78 and the IETF Trust's Legal + Provisions Relating to IETF Documents + (https://trustee.ietf.org/license-info) in effect on the date of + publication of this document. Please review these documents + carefully, as they describe your rights and restrictions with respect + to this document. Code Components extracted from this document must + include Revised BSD License text as described in Section 4.e of the + Trust Legal Provisions and are provided without warranty as described + in the Revised BSD License. + +Table of Contents + + 1. Introduction + 1.1. Conventions and Terminology + 1.2. Requirements + 1.3. HTTP Message Transformations + 1.4. Application of HTTP Message Signatures + 2. HTTP Message Components + 2.1. HTTP Fields + 2.1.1. Strict Serialization of HTTP Structured Fields + 2.1.2. Dictionary Structured Field Members + 2.1.3. Binary-Wrapped HTTP Fields + 2.1.4. Trailer Fields + 2.2. Derived Components + 2.2.1. Method + 2.2.2. Target URI + 2.2.3. Authority + 2.2.4. Scheme + 2.2.5. Request Target + 2.2.6. Path + 2.2.7. Query + 2.2.8. Query Parameters + 2.2.9. Status Code + 2.3. Signature Parameters + 2.4. Signing Request Components in a Response Message + 2.5. Creating the Signature Base + 3. HTTP Message Signatures + 3.1. Creating a Signature + 3.2. Verifying a Signature + 3.2.1. Enforcing Application Requirements + 3.3. Signature Algorithms + 3.3.1. RSASSA-PSS Using SHA-512 + 3.3.2. RSASSA-PKCS1-v1_5 Using SHA-256 + 3.3.3. HMAC Using SHA-256 + 3.3.4. ECDSA Using Curve P-256 DSS and SHA-256 + 3.3.5. ECDSA Using Curve P-384 DSS and SHA-384 + 3.3.6. EdDSA Using Curve edwards25519 + 3.3.7. JSON Web Signature (JWS) Algorithms + 4. Including a Message Signature in a Message + 4.1. The Signature-Input HTTP Field + 4.2. The Signature HTTP Field + 4.3. Multiple Signatures + 5. Requesting Signatures + 5.1. The Accept-Signature Field + 5.2. Processing an Accept-Signature + 6. IANA Considerations + 6.1. HTTP Field Name Registration + 6.2. HTTP Signature Algorithms Registry + 6.2.1. Registration Template + 6.2.2. Initial Contents + 6.3. HTTP Signature Metadata Parameters Registry + 6.3.1. Registration Template + 6.3.2. Initial Contents + 6.4. HTTP Signature Derived Component Names Registry + 6.4.1. Registration Template + 6.4.2. Initial Contents + 6.5. HTTP Signature Component Parameters Registry + 6.5.1. Registration Template + 6.5.2. Initial Contents + 7. Security Considerations + 7.1. General Considerations + 7.1.1. Skipping Signature Verification + 7.1.2. Use of TLS + 7.2. Message Processing and Selection + 7.2.1. Insufficient Coverage + 7.2.2. Signature Replay + 7.2.3. Choosing Message Components + 7.2.4. Choosing Signature Parameters and Derived Components + over HTTP Fields + 7.2.5. Signature Labels + 7.2.6. Multiple Signature Confusion + 7.2.7. Collision of Application-Specific Signature Tag + 7.2.8. Message Content + 7.3. Cryptographic Considerations + 7.3.1. Cryptography and Signature Collision + 7.3.2. Key Theft + 7.3.3. Symmetric Cryptography + 7.3.4. Key Specification Mixup + 7.3.5. Non-deterministic Signature Primitives + 7.3.6. Key and Algorithm Specification Downgrades + 7.3.7. Signing Signature Values + 7.4. Matching Signature Parameters to the Target Message + 7.4.1. Modification of Required Message Parameters + 7.4.2. Matching Values of Covered Components to Values in the + Target Message + 7.4.3. Message Component Source and Context + 7.4.4. Multiple Message Component Contexts + 7.5. HTTP Processing + 7.5.1. Processing Invalid HTTP Field Names as Derived + Component Names + 7.5.2. Semantically Equivalent Field Values + 7.5.3. Parsing Structured Field Values + 7.5.4. HTTP Versions and Component Ambiguity + 7.5.5. Canonicalization Attacks + 7.5.6. Non-List Field Values + 7.5.7. Padding Attacks with Multiple Field Values + 7.5.8. Ambiguous Handling of Query Elements + 8. Privacy Considerations + 8.1. Identification through Keys + 8.2. Signatures do not provide confidentiality + 8.3. Oracles + 8.4. Required Content + 9. References + 9.1. Normative References + 9.2. Informative References + Appendix A. Detecting HTTP Message Signatures + Appendix B. Examples + B.1. Example Keys + B.1.1. Example RSA Key + B.1.2. Example RSA-PSS Key + B.1.3. Example ECC P-256 Test Key + B.1.4. Example Ed25519 Test Key + B.1.5. Example Shared Secret + B.2. Test Cases + B.2.1. Minimal Signature Using rsa-pss-sha512 + B.2.2. Selective Covered Components Using rsa-pss-sha512 + B.2.3. Full Coverage Using rsa-pss-sha512 + B.2.4. Signing a Response Using ecdsa-p256-sha256 + B.2.5. Signing a Request Using hmac-sha256 + B.2.6. Signing a Request Using ed25519 + B.3. TLS-Terminating Proxies + B.4. HTTP Message Transformations + Acknowledgements + Authors' Addresses + +1. Introduction + + Message integrity and authenticity are security properties that are + critical to the secure operation of many HTTP applications. + Application developers typically rely on the transport layer to + provide these properties, by operating their application over TLS + [TLS]. However, TLS only guarantees these properties over a single + TLS connection, and the path between the client and application may + be composed of multiple independent TLS connections (for example, if + the application is hosted behind a TLS-terminating gateway or if the + client is behind a TLS Inspection appliance). In such cases, TLS + cannot guarantee end-to-end message integrity or authenticity between + the client and application. Additionally, some operating + environments present obstacles that make it impractical to use TLS + (such as the presentation of client certificates from a browser) or + to use features necessary to provide message authenticity. + Furthermore, some applications require the binding of a higher-level + application-specific key to the HTTP message, separate from any TLS + certificates in use. Consequently, while TLS can meet message + integrity and authenticity needs for many HTTP-based applications, it + is not a universal solution. + + Additionally, many applications need to be able to generate and + verify signatures despite incomplete knowledge of the HTTP message as + seen on the wire, due to the use of libraries, proxies, or + application frameworks that alter or hide portions of the message + from the application at the time of signing or verification. These + applications need a means to protect the parts of the message that + are most relevant to the application without having to violate + layering and abstraction. + + Finally, object-based signature mechanisms such as JSON Web Signature + [JWS] require the intact conveyance of the exact information that was + signed. When applying such technologies to an HTTP message, elements + of the HTTP message need to be duplicated in the object payload + either directly or through the inclusion of a hash. This practice + introduces complexity, since the repeated information needs to be + carefully checked for consistency when the signature is verified. + + This document defines a mechanism for providing end-to-end integrity + and authenticity for components of an HTTP message by using a + detached signature on HTTP messages. The mechanism allows + applications to create digital signatures or message authentication + codes (MACs) over only the components of the message that are + meaningful and appropriate for the application. Strict + canonicalization rules ensure that the verifier can verify the + signature even if the message has been transformed in many of the + ways permitted by HTTP. + + The signing mechanism described in this document consists of three + parts: + + * A common nomenclature and canonicalization rule set for the + different protocol elements and other components of HTTP messages, + used to create the signature base (Section 2). + + * Algorithms for generating and verifying signatures over HTTP + message components using this signature base through the + application of cryptographic primitives (Section 3). + + * A mechanism for attaching a signature and related metadata to an + HTTP message and for parsing attached signatures and metadata from + HTTP messages. To facilitate this, this document defines the + "Signature-Input" and "Signature" fields (Section 4). + + This document also provides a mechanism for negotiating the use of + signatures in one or more subsequent messages via the "Accept- + Signature" field (Section 5). This optional negotiation mechanism + can be used along with opportunistic or application-driven message + signatures by either party. + + The mechanisms defined in this document are important tools that can + be used to build an overall security mechanism for an application. + This toolkit provides some powerful capabilities but is not + sufficient in creating an overall security story. In particular, the + requirements listed in Section 1.4 and the security considerations + discussed in Section 7 are of high importance to all implementors of + this specification. For example, this specification does not define + a means to directly cover HTTP message content (defined in + Section 6.4 of [HTTP]); rather, it relies on the Digest specification + [DIGEST] to provide a hash of the message content, as discussed in + Section 7.2.8. + +1.1. Conventions and Terminology + + The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", + "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and + "OPTIONAL" in this document are to be interpreted as described in + BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all + capitals, as shown here. + + The terms "HTTP message", "HTTP request", "HTTP response", "target + URI", "gateway", "header field", "intermediary", "request target", + "trailer field", "sender", "method", and "recipient" are used as + defined in [HTTP]. + + For brevity, the term "signature" on its own is used in this document + to refer to both digital signatures (which use asymmetric + cryptography) and keyed MACs (which use symmetric cryptography). + Similarly, the verb "sign" refers to the generation of either a + digital signature or keyed MAC over a given signature base. The + qualified term "digital signature" refers specifically to the output + of an asymmetric cryptographic signing operation. + + This document uses the following terminology from Section 3 of + [STRUCTURED-FIELDS] to specify data types: List, Inner List, + Dictionary, Item, String, Integer, Byte Sequence, and Boolean. + + This document defines several string constructions using ABNF [ABNF] + and uses the following ABNF rules: VCHAR, SP, DQUOTE, and LF. This + document uses the following ABNF rules from [STRUCTURED-FIELDS]: sf- + string, inner-list, and parameters. This document uses the following + ABNF rules from [HTTP] and [HTTP/1.1]: field-content, obs-fold, and + obs-text. + + In addition to those listed above, this document uses the following + terms: + + HTTP Message Signature: + A digital signature or keyed MAC that covers one or more portions + of an HTTP message. Note that a given HTTP message can contain + multiple HTTP message signatures. + + Signer: + The entity that is generating or has generated an HTTP message + signature. Note that multiple entities can act as signers and + apply separate HTTP message signatures to a given HTTP message. + + Verifier: + An entity that is verifying or has verified an HTTP message + signature against an HTTP message. Note that an HTTP message + signature may be verified multiple times, potentially by different + entities. + + HTTP Message Component: + A portion of an HTTP message that is capable of being covered by + an HTTP message signature. + + Derived Component: + An HTTP message component derived from the HTTP message through + the use of a specified algorithm or process. See Section 2.2. + + HTTP Message Component Name: + A String that identifies an HTTP message component's source, such + as a field name or derived component name. + + HTTP Message Component Identifier: + The combination of an HTTP message component name and any + parameters. This combination uniquely identifies a specific HTTP + message component with respect to a particular HTTP message + signature and the HTTP message it applies to. + + HTTP Message Component Value: + The value associated with a given component identifier within the + context of a particular HTTP message. Component values are + derived from the HTTP message and are usually subject to a + canonicalization process. + + Covered Components: + An ordered set of HTTP message component identifiers for fields + (Section 2.1) and derived components (Section 2.2) that indicates + the set of message components covered by the signature, never + including the @signature-params identifier itself. The order of + this set is preserved and communicated between the signer and + verifier to facilitate reconstruction of the signature base. + + Signature Base: + The sequence of bytes generated by the signer and verifier using + the covered components set and the HTTP message. The signature + base is processed by the cryptographic algorithm to produce or + verify the HTTP message signature. + + HTTP Message Signature Algorithm: + A cryptographic algorithm that describes the signing and + verification process for the signature, defined in terms of the + HTTP_SIGN and HTTP_VERIFY primitives described in Section 3.3. + + Key Material: + The key material required to create or verify the signature. The + key material is often identified with an explicit key identifier, + allowing the signer to indicate to the verifier which key was + used. + + Creation Time: + A timestamp representing the point in time that the signature was + generated, as asserted by the signer. + + Expiration Time: + A timestamp representing the point in time after which the + signature should no longer be accepted by the verifier, as + asserted by the signer. + + Target Message: + The HTTP message to which an HTTP message signature is applied. + + Signature Context: + The data source from which the HTTP message component values are + drawn. The context includes the target message and any additional + information the signer or verifier might have, such as the full + target URI of a request or the related request message for a + response. + + The term "UNIX timestamp" refers to what Section 4.16 of [POSIX.1] + calls "seconds since the Epoch". + + This document contains non-normative examples of partial and complete + HTTP messages. Some examples use a single trailing backslash (\) to + indicate line wrapping for long values, as per [RFC8792]. The \ + character and leading spaces on wrapped lines are not part of the + value. + +1.2. Requirements + + HTTP permits, and sometimes requires, intermediaries to transform + messages in a variety of ways. This can result in a recipient + receiving a message that is not bitwise-equivalent to the message + that was originally sent. In such a case, the recipient will be + unable to verify integrity protections over the raw bytes of the + sender's HTTP message, as verifying digital signatures or MACs + requires both signer and verifier to have the exact same signature + base. Since the exact raw bytes of the message cannot be relied upon + as a reliable source for a signature base, the signer and verifier + have to independently create the signature base from their respective + versions of the message, via a mechanism that is resilient to safe + changes that do not alter the meaning of the message. + + For a variety of reasons, it is impractical to strictly define what + constitutes a safe change versus an unsafe one. Applications use + HTTP in a wide variety of ways and may disagree on whether a + particular piece of information in a message (e.g., the message + content, the method, or a particular header field) is relevant. + Thus, a general-purpose solution needs to provide signers with some + degree of control over which message components are signed. + + HTTP applications may be running in environments that do not provide + complete access to or control over HTTP messages (such as a web + browser's JavaScript environment) or may be using libraries that + abstract away the details of the protocol (such as the Java HTTP + Client (HttpClient) library + (https://openjdk.java.net/groups/net/httpclient/intro.html)). These + applications need to be able to generate and verify signatures + despite incomplete knowledge of the HTTP message. + +1.3. HTTP Message Transformations + + As mentioned earlier, HTTP explicitly permits, and in some cases + requires, implementations to transform messages in a variety of ways. + Implementations are required to tolerate many of these + transformations. What follows is a non-normative and non-exhaustive + list of transformations that could occur under HTTP, provided as + context: + + * Reordering of fields with different field names (Section 5.3 of + [HTTP]). + + * Combination of fields with the same field name (Section 5.2 of + [HTTP]). + + * Removal of fields listed in the Connection header field + (Section 7.6.1 of [HTTP]). + + * Addition of fields that indicate control options (Section 7.6.1 of + [HTTP]). + + * Addition or removal of a transfer coding (Section 7.7 of [HTTP]). + + * Addition of fields such as Via (Section 7.6.3 of [HTTP]) and + Forwarded (Section 4 of [RFC7239]). + + * Conversion between different versions of HTTP (e.g., HTTP/1.x to + HTTP/2, or vice versa). + + * Changes in case (e.g., "Origin" to "origin") of any case- + insensitive components such as field names, request URI scheme, or + host. + + * Changes to the request target and authority that, when applied + together, do not result in a change to the message's target URI, + as defined in Section 7.1 of [HTTP]. + + Additionally, there are some transformations that are either + deprecated or otherwise not allowed but that could still occur in the + wild. These transformations can still be handled without breaking + the signature; they include such actions as: + + * Use, addition, or removal of leading or trailing whitespace in a + field value. + + * Use, addition, or removal of obs-fold in field values (Section 5.2 + of [HTTP/1.1]). + + We can identify these types of transformations as transformations + that should not prevent signature verification, even when performed + on message components covered by the signature. Additionally, all + changes to components not covered by the signature should not prevent + signature verification. + + Some examples of these kinds of transformations, and the effect they + have on the message signature, are found in Appendix B.4. + + Other transformations, such as parsing and reserializing the field + values of a covered component or changing the value of a derived + component, can cause a signature to no longer validate against a + target message. Applications of this specification need to take care + to ensure that the transformations expected by the application are + adequately handled by the choice of covered components. + +1.4. Application of HTTP Message Signatures + + HTTP message signatures are designed to be a general-purpose tool + applicable in a wide variety of circumstances and applications. In + order to properly and safely apply HTTP message signatures, an + application or profile of this specification MUST specify, at a + minimum, all of the following items: + + * The set of component identifiers (Section 2) and signature + parameters (Section 2.3) that are expected and required to be + included in the covered components list. For example, an + authorization protocol could mandate that the Authorization field + be covered to protect the authorization credentials and mandate + that the signature parameters contain a created parameter + (Section 2.3), while an API expecting semantically relevant HTTP + message content could require the Content-Digest field defined in + [DIGEST] to be present and covered as well as mandate a value for + the tag parameter (Section 2.3) that is specific to the API being + protected. + + * The expected Structured Field types [STRUCTURED-FIELDS] of any + required or expected covered component fields or parameters. + + * A means of retrieving the key material used to verify the + signature. An application will usually use the keyid parameter of + the signature parameters (Section 2.3) and define rules for + resolving a key from there, though the appropriate key could be + known from other means such as preregistration of a signer's key. + + * The set of allowable signature algorithms to be used by signers + and accepted by verifiers. + + * A means of determining that the signature algorithm used to verify + the signature is appropriate for the key material and context of + the message. For example, the process could use the alg parameter + of the signature parameters (Section 2.3) to state the algorithm + explicitly, derive the algorithm from the key material, or use + some preconfigured algorithm agreed upon by the signer and + verifier. + + * A means of determining that a given key and algorithm used for a + signature are appropriate for the context of the message. For + example, a server expecting only ECDSA signatures should know to + reject any RSA signatures, or a server expecting asymmetric + cryptography should know to reject any symmetric cryptography. + + * A means of determining the context for derivation of message + components from an HTTP message and its application context. + While this is normally the target HTTP message itself, the context + could include additional information known to the application + through configuration, such as an external hostname. + + * If binding between a request and response is needed using the + mechanism provided in Section 2.4, all elements of the request + message and the response message that would be required to provide + properties of such a binding. + + * The error messages and codes that are returned from the verifier + to the signer when the signature is invalid, the key material is + inappropriate, the validity time window is out of specification, a + component value cannot be calculated, or any other errors occur + during the signature verification process. For example, if a + signature is being used as an authentication mechanism, an HTTP + status code of 401 (Unauthorized) or 403 (Forbidden) could be + appropriate. If the response is from an HTTP API, a response with + an HTTP status code such as 400 (Bad Request) could include more + details [RFC7807] [RFC9457], such as an indicator that the wrong + key material was used. + + When choosing these parameters, an application of HTTP message + signatures has to ensure that the verifier will have access to all + required information needed to recreate the signature base. For + example, a server behind a reverse proxy would need to know the + original request URI to make use of the derived component @target- + uri, even though the apparent target URI would be changed by the + reverse proxy (see also Section 7.4.3). Additionally, an application + using signatures in responses would need to ensure that clients + receiving signed responses have access to all the signed portions of + the message, including any portions of the request that were signed + by the server using the req ("request-response") parameter + (Section 2.4). + + Details regarding this kind of profiling are within the purview of + the application and outside the scope of this specification; however, + some additional considerations are discussed in Section 7. In + particular, when choosing the required set of component identifiers, + care has to be taken to make sure that the coverage is sufficient for + the application, as discussed in Sections 7.2.1 and 7.2.8. This + specification defines only part of a full security system for an + application. When building a complete security system based on this + tool, it is important to perform a security analysis of the entire + system, of which HTTP message signatures is a part. Historical + systems, such as AWS Signature Version 4 [AWS-SIGv4], can provide + inspiration and examples of how to apply similar mechanisms to an + application, though review of such historical systems does not negate + the need for a security analysis of an application of HTTP message + signatures. + +2. HTTP Message Components + + In order to allow signers and verifiers to establish which components + are covered by a signature, this document defines component + identifiers for components covered by an HTTP message signature, a + set of rules for deriving and canonicalizing the values associated + with these component identifiers from the HTTP message, and the means + for combining these canonicalized values into a signature base. + + The signature context for deriving these values MUST be accessible to + both the signer and the verifier of the message. The context MUST be + the same across all components in a given signature. For example, it + would be an error to use the raw query string for the @query derived + component but combined query and form parameters for the @query-param + derived component. For more considerations regarding the message + component context, see Section 7.4.3. + + A component identifier is composed of a component name and any + parameters associated with that name. Each component name is either + an HTTP field name (Section 2.1) or a registered derived component + name (Section 2.2). The possible parameters for a component + identifier are dependent on the component identifier. The "HTTP + Signature Component Parameters" registry, which catalogs all possible + parameters, is defined in Section 6.5. + + Within a single list of covered components, each component identifier + MUST occur only once. One component identifier is distinct from + another if the component name differs or if any of the parameters + differ for the same component name. Multiple component identifiers + having the same component name MAY be included if they have + parameters that make them distinct, such as "foo";bar and "foo";baz. + The order of parameters MUST be preserved when processing a component + identifier (such as when parsing during verification), but the order + of parameters is not significant when comparing two component + identifiers for equality checks. That is to say, "foo";bar;baz + cannot be in the same message as "foo";baz;bar, since these two + component identifiers are equivalent, but a system processing one + form is not allowed to transform it into the other form. + + The component value associated with a component identifier is defined + by the identifier itself. Component values MUST NOT contain newline + (\n) characters. Some HTTP message components can undergo + transformations that change the bitwise value without altering the + meaning of the component's value (for example, when combining field + values). Message component values therefore need to be canonicalized + before they are signed, to ensure that a signature can be verified + despite such intermediary transformations. This document defines + rules for each component identifier that transform the identifier's + associated component value into such a canonical form. + + The following sections define component identifier names, their + parameters, their associated values, and the canonicalization rules + for their values. The method for combining message components into + the signature base is defined in Section 2.5. + +2.1. HTTP Fields + + The component name for an HTTP field is the lowercased form of its + field name as defined in Section 5.1 of [HTTP]. While HTTP field + names are case insensitive, implementations MUST use lowercased field + names (e.g., content-type, date, etag) when using them as component + names. + + The component value for an HTTP field is the field value for the + named field as defined in Section 5.5 of [HTTP]. The field value + MUST be taken from the named header field of the target message + unless this behavior is overridden by additional parameters and + rules, such as the req and tr flags, below. For most fields, the + field value is an ASCII string as recommended by [HTTP], and the + component value is exactly that string. Other encodings could exist + in some implementations, and all non-ASCII field values MUST be + encoded to ASCII before being added to the signature base. The bs + parameter, as described in Section 2.1.3, provides a method for + wrapping such problematic field values. + + Unless overridden by additional parameters and rules, HTTP field + values MUST be combined into a single value as defined in Section 5.2 + of [HTTP] to create the component value. Specifically, HTTP fields + sent as multiple fields MUST be combined by concatenating the values + using a single comma and a single space as a separator ("," + " "). + Note that intermediaries are allowed to combine values of HTTP fields + with any amount of whitespace between the commas, and if this + behavior is not accounted for by the verifier, the signature can + fail, since the signer and verifier will see a different component + value in their respective signature bases. For robustness, it is + RECOMMENDED that signed messages include only a single instance of + any field covered under the signature, particularly with the value + for any list-based fields serialized using the algorithm below. This + approach increases the chances of the field value remaining untouched + through intermediaries. Where that approach is not possible and + multiple instances of a field need to be sent separately, it is + RECOMMENDED that signers and verifiers process any list-based fields + taking all individual field values and combining them based on the + strict algorithm below, to counter possible intermediary behavior. + When the field in question is a Structured Field of type List or + Dictionary, this effect can be accomplished more directly by + requiring the strict Structured Field serialization of the field + value, as described in Section 2.1.1. + + Note that some HTTP fields, such as Set-Cookie [COOKIE], do not + follow a syntax that allows for the combination of field values in + this manner (such that the combined output is unambiguous from + multiple inputs). Even though the component value is never parsed by + the message signature process and is used only as part of the + signature base (Section 2.5), caution needs to be taken when + including such fields in signatures, since the combined value could + be ambiguous. The bs parameter, as described in Section 2.1.3, + provides a method for wrapping such problematic fields. See + Section 7.5.6 for more discussion regarding this issue. + + If the correctly combined value is not directly available for a given + field by an implementation, the following algorithm will produce + canonicalized results for list-based fields: + + 1. Create an ordered list of the field values of each instance of + the field in the message, in the order they occur (or will occur) + in the message. + + 2. Strip leading and trailing whitespace from each item in the list. + Note that since HTTP field values are not allowed to contain + leading and trailing whitespace, this would be a no-op in a + compliant implementation. + + 3. Remove any obsolete line folding within the line, and replace it + with a single space (" "), as discussed in Section 5.2 of + [HTTP/1.1]. Note that this behavior is specific to HTTP/1.1 and + does not apply to other versions of the HTTP specification, which + do not allow internal line folding. + + 4. Concatenate the list of values with a single comma (",") and a + single space (" ") between each item. + + The resulting string is the component value for the field. + + Note that some HTTP fields have values with multiple valid + serializations that have equivalent semantics, such as allowing case- + insensitive values that intermediaries could change. Applications + signing and processing such fields MUST consider how to handle the + values of such fields to ensure that the signer and verifier can + derive the same value, as discussed in Section 7.5.2. + + The following are non-normative examples of component values for + header fields, given the following example HTTP message fragment: + + Host: www.example.com + Date: Tue, 20 Apr 2021 02:07:56 GMT + X-OWS-Header: Leading and trailing whitespace. + X-Obs-Fold-Header: Obsolete + line folding. + Cache-Control: max-age=60 + Cache-Control: must-revalidate + Example-Dict: a=1, b=2;x=1;y=2, c=(a b c) + + The following example shows the component values for these example + header fields, presented using the signature base format defined in + Section 2.5: + + "host": www.example.com + "date": Tue, 20 Apr 2021 02:07:56 GMT + "x-ows-header": Leading and trailing whitespace. + "x-obs-fold-header": Obsolete line folding. + "cache-control": max-age=60, must-revalidate + "example-dict": a=1, b=2;x=1;y=2, c=(a b c) + + Empty HTTP fields can also be signed when present in a message. The + canonicalized value is the empty string. This means that the + following empty header field, with (SP) indicating a single trailing + space character before the empty field value: + + X-Empty-Header:(SP) + + is serialized by the signature base generation algorithm + (Section 2.5) with an empty string value following the colon and + space added after the component identifier. + + "x-empty-header":(SP) + + Any HTTP field component identifiers MAY have the following + parameters in specific circumstances, each described in detail in + their own sections: + + sf A Boolean flag indicating that the component value is serialized + using strict encoding of the Structured Field value + (Section 2.1.1). + + key A String parameter used to select a single member value from a + Dictionary Structured Field (Section 2.1.2). + + bs A Boolean flag indicating that individual field values are + encoded using Byte Sequence data structures before being combined + into the component value (Section 2.1.3). + + req A Boolean flag for signed responses indicating that the + component value is derived from the request that triggered this + response message and not from the response message directly. Note + that this parameter can also be applied to any derived component + identifiers that target the request (Section 2.4). + + tr A Boolean flag indicating that the field value is taken from the + trailers of the message as defined in Section 6.5 of [HTTP]. If + this flag is absent, the field value is taken from the header + fields of the message as defined in Section 6.3 of [HTTP] + (Section 2.1.4). + + Multiple parameters MAY be specified together, though some + combinations are redundant or incompatible. For example, the sf + parameter's functionality is already covered when the key parameter + is used on a Dictionary item, since key requires strict serialization + of the value. The bs parameter, which requires the raw bytes of the + field values from the message, is not compatible with the use of the + sf or key parameters, which require the parsed data structures of the + field values after combination. + + Additional parameters can be defined in the "HTTP Signature Component + Parameters" registry established in Section 6.5. + +2.1.1. Strict Serialization of HTTP Structured Fields + + If the value of an HTTP field is known by the application to be a + Structured Field type (as defined in [STRUCTURED-FIELDS] or its + extensions or updates) and the expected type of the Structured Field + is known, the signer MAY include the sf parameter in the component + identifier. If this parameter is included with a component + identifier, the HTTP field value MUST be serialized using the formal + serialization rules specified in Section 4 of [STRUCTURED-FIELDS] (or + the applicable formal serialization section of its extensions or + updates) applicable to the type of the HTTP field. Note that this + process will replace any optional internal whitespace with a single + space character, among other potential transformations of the value. + + If multiple field values occur within a message, these values MUST be + combined into a single List or Dictionary structure before + serialization. + + If the application does not know the type of the field or does not + know how to serialize the type of the field, the use of this flag + will produce an error. As a consequence, the signer can only + reliably sign fields using this flag when the verifier's system knows + the type as well. + + For example, the following Dictionary field is a valid serialization: + + Example-Dict: a=1, b=2;x=1;y=2, c=(a b c) + + If included in the signature base without parameters, its value would + be: + + "example-dict": a=1, b=2;x=1;y=2, c=(a b c) + + However, if the sf parameter is added, the value is reserialized as + follows: + + "example-dict";sf: a=1, b=2;x=1;y=2, c=(a b c) + + The resulting string is used as the component value; see Section 2.1. + +2.1.2. Dictionary Structured Field Members + + If a given field is known by the application to be a Dictionary + Structured Field, an individual member in the value of that + Dictionary is identified by using the parameter key and the + Dictionary member key as a String value. + + If multiple field values occur within a message, these values MUST be + combined into a single Dictionary structure before serialization. + + An individual member value of a Dictionary Structured Field is + canonicalized by applying the serialization algorithm described in + Section 4.1.2 of [STRUCTURED-FIELDS] on the member_value and its + parameters, not including the Dictionary key itself. Specifically, + the value is serialized as an Item or Inner List (the two possible + values of a Dictionary member), with all parameters and possible + subfields serialized using the strict serialization rules defined in + Section 4 of [STRUCTURED-FIELDS] (or the applicable section of its + extensions or updates). + + Each parameterized key for a given field MUST NOT appear more than + once in the signature base. Parameterized keys MAY appear in any + order in the signature base, regardless of the order they occur in + the source Dictionary. + + If a Dictionary key is named as a covered component but it does not + occur in the Dictionary, this MUST cause an error in the signature + base generation. + + The following are non-normative examples of canonicalized values for + Dictionary Structured Field members, given the following example + header field, whose value is known by the application to be a + Dictionary: + + Example-Dict: a=1, b=2;x=1;y=2, c=(a b c), d + + The following example shows canonicalized values for different + component identifiers of this field, presented using the signature + base format discussed in Section 2.5: + + "example-dict";key="a": 1 + "example-dict";key="d": ?1 + "example-dict";key="b": 2;x=1;y=2 + "example-dict";key="c": (a b c) + + Note that the value for key="c" has been reserialized according to + the strict member_value algorithm, and the value for key="d" has been + serialized as a Boolean value. + +2.1.3. Binary-Wrapped HTTP Fields + + If the value of the HTTP field in question is known by the + application to cause problems with serialization, particularly with + the combination of multiple values into a single line as discussed in + Section 7.5.6, the signer SHOULD include the bs parameter in a + component identifier to indicate that the values of the field need to + be wrapped as binary structures before being combined. + + If this parameter is included with a component identifier, the + component value MUST be calculated using the following algorithm: + + 1. Let the input be the ordered set of values for a field, in the + order they appear in the message. + + 2. Create an empty List for accumulating processed field values. + + 3. For each field value in the set: + + 3.1. Strip leading and trailing whitespace from the field value. + Note that since HTTP field values are not allowed to + contain leading and trailing whitespace, this would be a + no-op in a compliant implementation. + + 3.2. Remove any obsolete line folding within the line, and + replace it with a single space (" "), as discussed in + Section 5.2 of [HTTP/1.1]. Note that this behavior is + specific to [HTTP/1.1] and does not apply to other versions + of the HTTP specification. + + 3.3. Encode the bytes of the resulting field value as a Byte + Sequence. Note that most fields are restricted to ASCII + characters, but other octets could be included in the value + in some implementations. + + 3.4. Add the Byte Sequence to the List accumulator. + + 4. The intermediate result is a List of Byte Sequence values. + + 5. Follow the strict serialization of a List as described in + Section 4.1.1 of [STRUCTURED-FIELDS], and return this output. + + For example, the following field with internal commas prevents the + distinct field values from being safely combined: + + Example-Header: value, with, lots + Example-Header: of, commas + + In our example, the same field can be sent with a semantically + different single value: + + Example-Header: value, with, lots, of, commas + + Both of these versions are treated differently by the application. + However, if included in the signature base without parameters, the + component value would be the same in both cases: + + "example-header": value, with, lots, of, commas + + However, if the bs parameter is added, the two separate instances are + encoded and serialized as follows: + + "example-header";bs: :dmFsdWUsIHdpdGgsIGxvdHM=:, :b2YsIGNvbW1hcw==: + + For the single-instance field above, the encoding with the bs + parameter is: + + "example-header";bs: :dmFsdWUsIHdpdGgsIGxvdHMsIG9mLCBjb21tYXM=: + + This component value is distinct from the multiple-instance field + above, preventing a collision that could potentially be exploited. + +2.1.4. Trailer Fields + + If the signer wants to include a trailer field in the signature, the + signer MUST include the tr Boolean parameter to indicate that the + value MUST be taken from the trailer fields and not from the header + fields. + + For example, given the following message: + + HTTP/1.1 200 OK + Content-Type: text/plain + Transfer-Encoding: chunked + Trailer: Expires + + 4 + HTTP + 7 + Message + a + Signatures + 0 + Expires: Wed, 9 Nov 2022 07:28:00 GMT + + The signer decides to add both the Trailer header field and the + Expires trailer field to the signature base, along with the status + code derived component: + + "@status": 200 + "trailer": Expires + "expires";tr: Wed, 9 Nov 2022 07:28:00 GMT + + If a field is available as both a header and a trailer in a message, + both values MAY be signed, but the values MUST be signed separately. + The values of header fields and trailer fields of the same name MUST + NOT be combined for purposes of the signature. + + Since trailer fields could be merged into the header fields or + dropped entirely by intermediaries as per Section 6.5.1 of [HTTP], it + is NOT RECOMMENDED to include trailers in the signature unless the + signer knows that the verifier will have access to the values of the + trailers as sent. + +2.2. Derived Components + + In addition to HTTP fields, there are a number of different + components that can be derived from the control data, signature + context, or other aspects of the HTTP message being signed. Such + derived components can be included in the signature base by defining + a component name, possible parameters, message targets, and the + derivation method for its component value. + + Derived component names MUST start with the "at" (@) character. This + differentiates derived component names from HTTP field names, which + cannot contain the @ character as per Section 5.1 of [HTTP]. + Processors of HTTP message signatures MUST treat derived component + names separately from field names, as discussed in Section 7.5.1. + + This specification defines the following derived components: + + @method The method used for a request (Section 2.2.1). + + @target-uri The full target URI for a request (Section 2.2.2). + + @authority The authority of the target URI for a request + (Section 2.2.3). + + @scheme The scheme of the target URI for a request (Section 2.2.4). + + @request-target The request target (Section 2.2.5). + + @path The absolute path portion of the target URI for a request + (Section 2.2.6). + + @query The query portion of the target URI for a request + (Section 2.2.7). + + @query-param A parsed and encoded query parameter of the target URI + for a request (Section 2.2.8). + + @status The status code for a response (Section 2.2.9). + + Additional derived component names are defined in the "HTTP Signature + Derived Component Names" registry (Section 6.4). + + Derived component values are taken from the context of the target + message for the signature. This context includes information about + the message itself, such as its control data, as well as any + additional state and context held by the signer or verifier. In + particular, when signing a response, the signer can include any + derived components from the originating request by using the req + parameter (Section 2.4). + + request: Values derived from, and results applied to, an HTTP + request message as described in Section 3.4 of [HTTP]. If the + target message of the signature is a response, derived components + that target request messages can be included by using the req + parameter as defined in Section 2.4. + + response: Values derived from, and results applied to, an HTTP + response message as described in Section 3.4 of [HTTP]. + + request, response: Values derived from, and results applied to, + either a request message or a response message. + + A derived component definition MUST define all target message types + to which it can be applied. + + Derived component values MUST be limited to printable characters and + spaces and MUST NOT contain any newline characters. Derived + component values MUST NOT start or end with whitespace characters. + +2.2.1. Method + + The @method derived component refers to the HTTP method of a request + message. The component value is canonicalized by taking the value of + the method as a string. Note that the method name is case sensitive + as per [HTTP], Section 9.1. While conventionally standardized method + names are uppercase [ASCII], no transformation to the input method + value's case is performed. + + For example, the following request message: + + POST /path?param=value HTTP/1.1 + Host: www.example.com + + would result in the following @method component value: + + POST + + and the following signature base line: + + "@method": POST + +2.2.2. Target URI + + The @target-uri derived component refers to the target URI of a + request message. The component value is the target URI of the + request ([HTTP], Section 7.1), assembled from all available URI + components, including the authority. + + For example, the following message sent over HTTPS: + + POST /path?param=value HTTP/1.1 + Host: www.example.com + + would result in the following @target-uri component value: + + https://www.example.com/path?param=value + + and the following signature base line: + + "@target-uri": https://www.example.com/path?param=value + +2.2.3. Authority + + The @authority derived component refers to the authority component of + the target URI of the HTTP request message, as defined in [HTTP], + Section 7.2. In HTTP/1.1, this is usually conveyed using the Host + header field, while in HTTP/2 and HTTP/3 it is conveyed using the + :authority pseudo-header. The value is the fully qualified authority + component of the request, comprised of the host and, optionally, port + of the request target, as a string. The component value MUST be + normalized according to the rules provided in [HTTP], Section 4.2.3. + Namely, the hostname is normalized to lowercase, and the default port + is omitted. + + For example, the following request message: + + POST /path?param=value HTTP/1.1 + Host: www.example.com + + would result in the following @authority component value: + + www.example.com + + and the following signature base line: + + "@authority": www.example.com + + The @authority derived component SHOULD be used instead of signing + the Host header field directly. See Section 7.2.4. + +2.2.4. Scheme + + The @scheme derived component refers to the scheme of the target URL + of the HTTP request message. The component value is the scheme as a + lowercase string as defined in [HTTP], Section 4.2. While the scheme + itself is case insensitive, it MUST be normalized to lowercase for + inclusion in the signature base. + + For example, the following request message sent over plain HTTP: + + POST /path?param=value HTTP/1.1 + Host: www.example.com + + would result in the following @scheme component value: + + http + + and the following signature base line: + + "@scheme": http + +2.2.5. Request Target + + The @request-target derived component refers to the full request + target of the HTTP request message, as defined in [HTTP], + Section 7.1. The component value of the request target can take + different forms, depending on the type of request, as described + below. + + For HTTP/1.1, the component value is equivalent to the request target + portion of the request line. However, this value is more difficult + to reliably construct in other versions of HTTP. Therefore, it is + NOT RECOMMENDED that this component be used when versions of HTTP + other than 1.1 might be in use. + + The origin form value is a combination of the absolute path and query + components of the request URL. + + For example, the following request message: + + POST /path?param=value HTTP/1.1 + Host: www.example.com + + would result in the following @request-target component value: + + /path?param=value + + and the following signature base line: + + "@request-target": /path?param=value + + The following request to an HTTP proxy with the absolute-form value, + containing the fully qualified target URI: + + GET https://www.example.com/path?param=value HTTP/1.1 + + would result in the following @request-target component value: + + https://www.example.com/path?param=value + + and the following signature base line: + + "@request-target": https://www.example.com/path?param=value + + The following CONNECT request with an authority-form value, + containing the host and port of the target: + + CONNECT www.example.com:80 HTTP/1.1 + Host: www.example.com + + would result in the following @request-target component value: + + www.example.com:80 + + and the following signature base line: + + "@request-target": www.example.com:80 + + The following OPTIONS request message with the asterisk-form value, + containing a single asterisk (*) character: + + OPTIONS * HTTP/1.1 + Host: www.example.com + + would result in the following @request-target component value: + + * + + and the following signature base line: + + "@request-target": * + +2.2.6. Path + + The @path derived component refers to the target path of the HTTP + request message. The component value is the absolute path of the + request target defined by [URI], with no query component and no + trailing question mark (?) character. The value is normalized + according to the rules provided in [HTTP], Section 4.2.3. Namely, an + empty path string is normalized as a single slash (/) character. + Path components are represented by their values before decoding any + percent-encoded octets, as described in the simple string comparison + rules provided in Section 6.2.1 of [URI]. + + For example, the following request message: + + GET /path?param=value HTTP/1.1 + Host: www.example.com + + would result in the following @path component value: + + /path + + and the following signature base line: + + "@path": /path + +2.2.7. Query + + The @query derived component refers to the query component of the + HTTP request message. The component value is the entire normalized + query string defined by [URI], including the leading ? character. + The value is read using the simple string comparison rules provided + in Section 6.2.1 of [URI]. Namely, percent-encoded octets are not + decoded. + + For example, the following request message: + + GET /path?param=value&foo=bar&baz=bat%2Dman HTTP/1.1 + Host: www.example.com + + would result in the following @query component value: + + ?param=value&foo=bar&baz=bat%2Dman + + and the following signature base line: + + "@query": ?param=value&foo=bar&baz=bat%2Dman + + The following request message: + + POST /path?queryString HTTP/1.1 + Host: www.example.com + + would result in the following @query component value: + + ?queryString + + and the following signature base line: + + "@query": ?queryString + + Just like including an empty path component, the signer can include + an empty query component to indicate that this component is not used + in the message. If the query string is absent from the request + message, the component value is the leading ? character alone: + + ? + + resulting in the following signature base line: + + "@query": ? + +2.2.8. Query Parameters + + If the query portion of a request target URI uses HTML form + parameters in the format defined in Section 5 ("application/ + x-www-form-urlencoded") of [HTMLURL], the @query-param derived + component allows addressing of these individual query parameters. + The query parameters MUST be parsed according to Section 5.1 + ("application/x-www-form-urlencoded parsing") of [HTMLURL], resulting + in a list of (nameString, valueString) tuples. The REQUIRED name + parameter of each component identifier contains the encoded + nameString of a single query parameter as a String value. The + component value of a single named parameter is the encoded + valueString of that single query parameter. Several different named + query parameters MAY be included in the covered components. Single + named parameters MAY occur in any order in the covered components, + regardless of the order they occur in the query string. + + The value of the name parameter and the component value of a single + named parameter are calculated via the following process: + + 1. Parse the nameString or valueString of the named query parameter + defined by Section 5.1 ("application/x-www-form-urlencoded + parsing") of [HTMLURL]; this is the value after percent-encoded + octets are decoded. + + 2. Encode the nameString or valueString using the "percent-encode + after encoding" process defined by Section 5.2 ("application/ + x-www-form-urlencoded serializing") of [HTMLURL]; this results in + an ASCII string [ASCII]. + + 3. Output the ASCII string. + + Note that the component value does not include any leading question + mark (?) characters, equals sign (=) characters, or separating + ampersand (&) characters. Named query parameters with an empty + valueString have an empty string as the component value. Note that + due to inconsistencies in implementations, some query parameter + parsing libraries drop such empty values. + + If a query parameter is named as a covered component but it does not + occur in the query parameters, this MUST cause an error in the + signature base generation. + + For example, for the following request: + + GET /path?param=value&foo=bar&baz=batman&qux= HTTP/1.1 + Host: www.example.com + + Indicating the baz, qux, and param named query parameters would + result in the following @query-param component values: + + _baz_: batman + + _qux_: an empty string + + _param_: value + + and the following signature base lines, with (SP) indicating a single + trailing space character before the empty component value: + + "@query-param";name="baz": batman + "@query-param";name="qux":(SP) + "@query-param";name="param": value + + This derived component has some limitations. Specifically, the + algorithms provided in Section 5 ("application/ + x-www-form-urlencoded") of [HTMLURL] only support query parameters + using percent-escaped UTF-8 encoding. Other encodings are not + supported. Additionally, multiple instances of a named parameter are + not reliably supported in the wild. If a parameter name occurs + multiple times in a request, the named query parameter MUST NOT be + included. If multiple parameters are common within an application, + it is RECOMMENDED to sign the entire query string using the @query + component identifier defined in Section 2.2.7. + + The encoding process allows query parameters that include newlines or + other problematic characters in their values, or with alternative + encodings such as using the plus (+) character to represent spaces. + For the query parameters in this message: + + NOTE: '\' line wrapping per RFC 8792 + + GET /parameters?var=this%20is%20a%20big%0Amultiline%20value&\ + bar=with+plus+whitespace&fa%C3%A7ade%22%3A%20=something HTTP/1.1 + Host: www.example.com + Date: Tue, 20 Apr 2021 02:07:56 GMT + + The resulting values are encoded as follows: + + "@query-param";name="var": this%20is%20a%20big%0Amultiline%20value + "@query-param";name="bar": with%20plus%20whitespace + "@query-param";name="fa%C3%A7ade%22%3A%20": something + + If the encoding were not applied, the resultant values would be: + + "@query-param";name="var": this is a big + multiline value + "@query-param";name="bar": with plus whitespace + "@query-param";name="façade\": ": something + + This base string contains characters that violate the constraints on + component names and values and is therefore invalid. + +2.2.9. Status Code + + The @status derived component refers to the three-digit numeric HTTP + status code of a response message as defined in [HTTP], Section 15. + The component value is the serialized three-digit integer of the HTTP + status code, with no descriptive text. + + For example, the following response message: + + HTTP/1.1 200 OK + Date: Fri, 26 Mar 2010 00:05:00 GMT + + would result in the following @status component value: + + 200 + + and the following signature base line: + + "@status": 200 + + The @status component identifier MUST NOT be used in a request + message. + +2.3. Signature Parameters + + HTTP message signatures have metadata properties that provide + information regarding the signature's generation and verification, + consisting of the ordered set of covered components and the ordered + set of parameters, where the parameters include a timestamp of + signature creation, identifiers for verification key material, and + other utilities. This metadata is represented by a special message + component in the signature base for signature parameters; this + special message component is treated slightly differently from other + message components. Specifically, the signature parameters message + component is REQUIRED as the last line of the signature base + (Section 2.5), and the component identifier MUST NOT be enumerated + within the set of covered components for any signature, including + itself. + + The signature parameters component name is @signature-params. + + The signature parameters component value is the serialization of the + signature parameters for this signature, including the covered + components ordered set with all associated parameters. These + parameters include any of the following: + + created: Creation time as a UNIX timestamp value of type Integer. + Sub-second precision is not supported. The inclusion of this + parameter is RECOMMENDED. + + expires: Expiration time as a UNIX timestamp value of type Integer. + Sub-second precision is not supported. + + nonce: A random unique value generated for this signature as a + String value. + + alg: The HTTP message signature algorithm from the "HTTP Signature + Algorithms" registry, as a String value. + + keyid: The identifier for the key material as a String value. + + tag: An application-specific tag for the signature as a String + value. This value is used by applications to help identify + signatures relevant for specific applications or protocols. + + Additional parameters can be defined in the "HTTP Signature Metadata + Parameters" registry (Section 6.3). Note that the parameters are not + in any general order, but once an ordering is chosen for a given set + of parameters, it cannot be changed without altering the signature + parameters value. + + The signature parameters component value is serialized as a + parameterized Inner List using the rules provided in Section 4 of + [STRUCTURED-FIELDS] as follows: + + 1. Let the output be an empty string. + + 2. Determine an order for the component identifiers of the covered + components, not including the @signature-params component + identifier itself. Once this order is chosen, it cannot be + changed. This order MUST be the same order as that used in + creating the signature base (Section 2.5). + + 3. Serialize the component identifiers of the covered components, + including all parameters, as an ordered Inner List of String + values according to Section 4.1.1.1 of [STRUCTURED-FIELDS]; then, + append this to the output. Note that the component identifiers + can include their own parameters, and these parameters are + ordered sets. Once an order is chosen for a component's + parameters, the order cannot be changed. + + 4. Determine an order for any signature parameters. Once this order + is chosen, it cannot be changed. + + 5. Append the parameters to the Inner List in order according to + Section 4.1.1.2 of [STRUCTURED-FIELDS], skipping parameters that + are not available or not used for this message signature. + + 6. The output contains the signature parameters component value. + + Note that the Inner List serialization from Section 4.1.1.1 of + [STRUCTURED-FIELDS] is used for the covered component value instead + of the List serialization from Section 4.1.1 of [STRUCTURED-FIELDS] + in order to facilitate parallelism with this value's inclusion in the + Signature-Input field, as discussed in Section 4.1. + + This example shows the serialized component value for the parameters + of an example message signature: + + NOTE: '\' line wrapping per RFC 8792 + + ("@target-uri" "@authority" "date" "cache-control")\ + ;keyid="test-key-rsa-pss";alg="rsa-pss-sha512";\ + created=1618884475;expires=1618884775 + + Note that an HTTP message could contain multiple signatures + (Section 4.3), but only the signature parameters used for a single + signature are included in a given signature parameters entry. + +2.4. Signing Request Components in a Response Message + + When a request message results in a signed response message, the + signer can include portions of the request message in the signature + base by adding the req parameter to the component identifier. + + req A Boolean flag indicating that the component value is derived + from the request that triggered this response message and not from + the response message directly. + + This parameter can be applied to both HTTP fields and derived + components that target the request, with the same semantics. The + component value for a message component using this parameter is + calculated in the same manner as it is normally, but data is pulled + from the request message instead of the target response message to + which the signature is applied. + + Note that the same component name MAY be included with and without + the req parameter in a single signature base, indicating the same + named component from both the request message and the response + message. + + The req parameter MAY be combined with other parameters as + appropriate for the component identifier, such as the key parameter + for a Dictionary field. + + For example, when serving a response for this request: + + NOTE: '\' line wrapping per RFC 8792 + + POST /foo?param=Value&Pet=dog HTTP/1.1 + Host: example.com + Date: Tue, 20 Apr 2021 02:07:55 GMT + Content-Digest: sha-512=:WZDPaVn/7XgHaAy8pmojAkGWoRx2UFChF41A2svX+T\ + aPm+AbwAgBWnrIiYllu7BNNyealdVLvRwEmTHWXvJwew==: + Content-Type: application/json + Content-Length: 18 + + {"hello": "world"} + + This would result in the following unsigned response message: + + NOTE: '\' line wrapping per RFC 8792 + + HTTP/1.1 503 Service Unavailable + Date: Tue, 20 Apr 2021 02:07:56 GMT + Content-Type: application/json + Content-Length: 62 + Content-Digest: sha-512=:0Y6iCBzGg5rZtoXS95Ijz03mslf6KAMCloESHObfwn\ + HJDbkkWWQz6PhhU9kxsTbARtY2PTBOzq24uJFpHsMuAg==: + + {"busy": true, "message": "Your call is very important to us"} + + The server signs the response with its own key, including the @status + code and several header fields in the covered components. While this + covers a reasonable amount of the response for this application, the + server additionally includes several components derived from the + original request message that triggered this response. In this + example, the server includes the method, authority, path, and content + digest from the request in the covered components of the response. + The Content-Digest for both the request and the response is included + under the response signature. For the application in this example, + the query is deemed not to be relevant to the response and is + therefore not covered. Other applications would make different + decisions based on application needs, as discussed in Section 1.4. + + The signature base for this example is: + + NOTE: '\' line wrapping per RFC 8792 + + "@status": 503 + "content-digest": sha-512=:0Y6iCBzGg5rZtoXS95Ijz03mslf6KAMCloESHObf\ + wnHJDbkkWWQz6PhhU9kxsTbARtY2PTBOzq24uJFpHsMuAg==: + "content-type": application/json + "@authority";req: example.com + "@method";req: POST + "@path";req: /foo + "content-digest";req: sha-512=:WZDPaVn/7XgHaAy8pmojAkGWoRx2UFChF41A\ + 2svX+TaPm+AbwAgBWnrIiYllu7BNNyealdVLvRwEmTHWXvJwew==: + "@signature-params": ("@status" "content-digest" "content-type" \ + "@authority";req "@method";req "@path";req "content-digest";req)\ + ;created=1618884479;keyid="test-key-ecc-p256" + + The signed response message is: + + NOTE: '\' line wrapping per RFC 8792 + + HTTP/1.1 503 Service Unavailable + Date: Tue, 20 Apr 2021 02:07:56 GMT + Content-Type: application/json + Content-Length: 62 + Content-Digest: sha-512=:0Y6iCBzGg5rZtoXS95Ijz03mslf6KAMCloESHObfwn\ + HJDbkkWWQz6PhhU9kxsTbARtY2PTBOzq24uJFpHsMuAg==: + Signature-Input: reqres=("@status" "content-digest" "content-type" \ + "@authority";req "@method";req "@path";req "content-digest";req)\ + ;created=1618884479;keyid="test-key-ecc-p256" + Signature: reqres=:dMT/A/76ehrdBTD/2Xx8QuKV6FoyzEP/I9hdzKN8LQJLNgzU\ + 4W767HK05rx1i8meNQQgQPgQp8wq2ive3tV5Ag==: + + {"busy": true, "message": "Your call is very important to us"} + + Note that the ECDSA signature algorithm in use here is non- + deterministic, meaning that a different signature value will be + created every time the algorithm is run. The signature value + provided here can be validated against the given keys, but newly + generated signature values are not expected to match the example. + See Section 7.3.5. + + Since the component values from the request are not repeated in the + response message, the requester MUST keep the original message + component values around long enough to validate the signature of the + response that uses this component identifier parameter. In most + cases, this means the requester needs to keep the original request + message around, since the signer could choose to include any portions + of the request in its response, according to the needs of the + application. Since it is possible for an intermediary to alter a + request message before it is processed by the server, applications + need to take care not to sign such altered values, as the client + would not be able to validate the resulting signature. + + It is also possible for a server to create a signed response in + response to a signed request. For this example of a signed request: + + NOTE: '\' line wrapping per RFC 8792 + + POST /foo?param=Value&Pet=dog HTTP/1.1 + Host: example.com + Date: Tue, 20 Apr 2021 02:07:55 GMT + Content-Digest: sha-512=:WZDPaVn/7XgHaAy8pmojAkGWoRx2UFChF41A2svX+T\ + aPm+AbwAgBWnrIiYllu7BNNyealdVLvRwEmTHWXvJwew==: + Content-Type: application/json + Content-Length: 18 + Signature-Input: sig1=("@method" "@authority" "@path" "@query" \ + "content-digest" "content-type" "content-length")\ + ;created=1618884475;keyid="test-key-rsa-pss" + Signature: sig1=:e8UJ5wMiRaonlth5ERtE8GIiEH7Akcr493nQ07VPNo6y3qvjdK\ + t0fo8VHO8xXDjmtYoatGYBGJVlMfIp06eVMEyNW2I4vN7XDAz7m5v1108vGzaDljr\ + d0H8+SJ28g7bzn6h2xeL/8q+qUwahWA/JmC8aOC9iVnwbOKCc0WSrLgWQwTY6VLp4\ + 2Qt7jjhYT5W7/wCvfK9A1VmHH1lJXsV873Z6hpxesd50PSmO+xaNeYvDLvVdZlhtw\ + 5PCtUYzKjHqwmaQ6DEuM8udRjYsoNqp2xZKcuCO1nKc0V3RjpqMZLuuyVbHDAbCzr\ + 0pg2d2VM/OC33JAU7meEjjaNz+d7LWPg==: + + {"hello": "world"} + + The server could choose to sign portions of this response, including + several portions of the request, resulting in this signature base: + + NOTE: '\' line wrapping per RFC 8792 + + "@status": 503 + "content-digest": sha-512=:0Y6iCBzGg5rZtoXS95Ijz03mslf6KAMCloESHObf\ + wnHJDbkkWWQz6PhhU9kxsTbARtY2PTBOzq24uJFpHsMuAg==: + "content-type": application/json + "@authority";req: example.com + "@method";req: POST + "@path";req: /foo + "@query";req: ?param=Value&Pet=dog + "content-digest";req: sha-512=:WZDPaVn/7XgHaAy8pmojAkGWoRx2UFChF41A\ + 2svX+TaPm+AbwAgBWnrIiYllu7BNNyealdVLvRwEmTHWXvJwew==: + "content-type";req: application/json + "content-length";req: 18 + "@signature-params": ("@status" "content-digest" "content-type" \ + "@authority";req "@method";req "@path";req "@query";req \ + "content-digest";req "content-type";req "content-length";req)\ + ;created=1618884479;keyid="test-key-ecc-p256" + + and the following signed response: + + NOTE: '\' line wrapping per RFC 8792 + + HTTP/1.1 503 Service Unavailable + Date: Tue, 20 Apr 2021 02:07:56 GMT + Content-Type: application/json + Content-Length: 62 + Content-Digest: sha-512=:0Y6iCBzGg5rZtoXS95Ijz03mslf6KAMCloESHObfwn\ + HJDbkkWWQz6PhhU9kxsTbARtY2PTBOzq24uJFpHsMuAg==: + Signature-Input: reqres=("@status" "content-digest" "content-type" \ + "@authority";req "@method";req "@path";req "@query";req \ + "content-digest";req "content-type";req "content-length";req)\ + ;created=1618884479;keyid="test-key-ecc-p256" + Signature: reqres=:C73J41GVKc+TYXbSobvZf0CmNcptRiWN+NY1Or0A36ISg6ym\ + dRN6ZgR2QfrtopFNzqAyv+CeWrMsNbcV2Ojsgg==: + + {"busy": true, "message": "Your call is very important to us"} + + Note that the ECDSA signature algorithm in use here is non- + deterministic, meaning that a different signature value will be + created every time the algorithm is run. The signature value + provided here can be validated against the given keys, but newly + generated signature values are not expected to match the example. + See Section 7.3.5. + + Applications signing a response to a signed request SHOULD sign all + of the components of the request signature value to provide + sufficient coverage and protection against a class of collision + attacks, as discussed in Section 7.3.7. The server in this example + has included all components listed in the Signature-Input field of + the client's signature on the request in the response signature, in + addition to components of the response. + + While it is syntactically possible to include the Signature and + Signature-Input fields of the request message in the signature + components of a response to a message using this mechanism, this + practice is NOT RECOMMENDED. This is because signatures of + signatures do not provide transitive coverage of covered components + as one might expect, and the practice is susceptible to several + attacks as discussed in Section 7.3.7. An application that needs to + signal successful processing or receipt of a signature would need to + carefully specify alternative mechanisms for sending such a signal + securely. + + The response signature can only ever cover what is included in the + request message when using this flag. Consequently, if an + application needs to include the message content of the request under + the signature of its response, the client needs to include a means + for covering that content, such as a Content-Digest field. See the + discussion in Section 7.2.8 for more information. + + The req parameter MUST NOT be used for any component in a signature + that targets a request message. + +2.5. Creating the Signature Base + + The signature base is an ASCII string [ASCII] containing the + canonicalized HTTP message components covered by the signature. The + input to the signature base creation algorithm is the ordered set of + covered component identifiers and their associated values, along with + any additional signature parameters discussed in Section 2.3. + + Component identifiers are serialized using the strict serialization + rules defined by [STRUCTURED-FIELDS], Section 4. The component + identifier has a component name, which is a String Item value + serialized using the sf-string ABNF rule. The component identifier + MAY also include defined parameters that are serialized using the + parameters ABNF rule. The signature parameters line defined in + Section 2.3 follows this same pattern, but the component identifier + is a String Item with a fixed value and no parameters, and the + component value is always an Inner List with optional parameters. + + Note that this means the serialization of the component name itself + is encased in double quotes, with parameters following as a + semicolon-separated list, such as "cache-control", "@authority", + "@signature-params", or "example-dictionary";key="foo". + + The output is the ordered set of bytes that form the signature base, + which conforms to the following ABNF: + + signature-base = *( signature-base-line LF ) signature-params-line + signature-base-line = component-identifier ":" SP + ( derived-component-value / *field-content ) + ; no obs-fold nor obs-text + component-identifier = component-name parameters + component-name = sf-string + derived-component-value = *( VCHAR / SP ) + signature-params-line = DQUOTE "@signature-params" DQUOTE + ":" SP inner-list + + To create the signature base, the signer or verifier concatenates + entries for each component identifier in the signature's covered + components (including their parameters) using the following + algorithm. All errors produced as described MUST fail the algorithm + immediately, without outputting a signature base. + + 1. Let the output be an empty string. + + 2. For each message component item in the covered components set (in + order): + + 2.1. If the component identifier (including its parameters) has + already been added to the signature base, produce an error. + + 2.2. Append the component identifier for the covered component + serialized according to the component-identifier ABNF rule. + Note that this serialization places the component name in + double quotes and appends any parameters outside of the + quotes. + + 2.3. Append a single colon (:). + + 2.4. Append a single space (" "). + + 2.5. Determine the component value for the component identifier. + + * If the component identifier has a parameter that is not + understood, produce an error. + + * If the component identifier has parameters that are + mutually incompatible with one another, such as bs and + sf, produce an error. + + * If the component identifier contains the req parameter + and the target message is a request, produce an error. + + * If the component identifier contains the req parameter + and the target message is a response, the context for + the component value is the related request message of + the target response message. Otherwise, the context for + the component value is the target message. + + * If the component name starts with an "at" (@) character, + derive the component's value from the message according + to the specific rules defined for the derived component, + as provided in Section 2.2, including processing of any + known valid parameters. If the derived component name + is unknown or the value cannot be derived, produce an + error. + + * If the component name does not start with an "at" (@) + character, canonicalize the HTTP field value as + described in Section 2.1, including processing of any + known valid parameters. If the field cannot be found in + the message or the value cannot be obtained in the + context, produce an error. + + 2.6. Append the covered component's canonicalized component + value. + + 2.7. Append a single newline (\n). + + 3. Append the signature parameters component (Section 2.3) according + to the signature-params-line rule as follows: + + 3.1. Append the component identifier for the signature + parameters serialized according to the component-identifier + rule, i.e., the exact value "@signature-params" (including + double quotes). + + 3.2. Append a single colon (:). + + 3.3. Append a single space (" "). + + 3.4. Append the signature parameters' canonicalized component + values as defined in Section 2.3, i.e., Inner List + Structured Field values with parameters. + + 4. Produce an error if the output string contains any non-ASCII + characters [ASCII]. + + 5. Return the output string. + + If covered components reference a component identifier that cannot be + resolved to a component value in the message, the implementation MUST + produce an error and not create a signature base. Such situations + include, but are not limited to, the following: + + * The signer or verifier does not understand the derived component + name. + + * The component name identifies a field that is not present in the + message or whose value is malformed. + + * The component identifier includes a parameter that is unknown or + does not apply to the component identifier to which it is + attached. + + * The component identifier indicates that a Structured Field + serialization is used (via the sf parameter), but the field in + question is known to not be a Structured Field or the type of + Structured Field is not known to the implementation. + + * The component identifier is a Dictionary member identifier that + references a field that is not present in the message, that is not + a Dictionary Structured Field, or whose value is malformed. + + * The component identifier is a Dictionary member identifier or a + named query parameter identifier that references a member that is + not present in the component value or whose value is malformed. + For example, the identifier is "example-dict";key="c", and the + value of the Example-Dict header field is a=1, b=2, which does not + have the c value. + + In the following non-normative example, the HTTP message being signed + is the following request: + + NOTE: '\' line wrapping per RFC 8792 + + POST /foo?param=Value&Pet=dog HTTP/1.1 + Host: example.com + Date: Tue, 20 Apr 2021 02:07:55 GMT + Content-Type: application/json + Content-Digest: sha-512=:WZDPaVn/7XgHaAy8pmojAkGWoRx2UFChF41A2svX+T\ + aPm+AbwAgBWnrIiYllu7BNNyealdVLvRwEmTHWXvJwew==: + Content-Length: 18 + + {"hello": "world"} + + The covered components consist of the @method, @authority, and @path + derived components followed by the Content-Digest, Content-Length, + and Content-Type HTTP header fields, in order. The signature + parameters consist of a creation timestamp of 1618884473 and a key + identifier of test-key-rsa-pss. Note that no explicit alg parameter + is given here, since the verifier is known by the application to use + the RSA-PSS algorithm based on the identified key. The signature + base for this message with these parameters is: + + NOTE: '\' line wrapping per RFC 8792 + + "@method": POST + "@authority": example.com + "@path": /foo + "content-digest": sha-512=:WZDPaVn/7XgHaAy8pmojAkGWoRx2UFChF41A2svX\ + +TaPm+AbwAgBWnrIiYllu7BNNyealdVLvRwEmTHWXvJwew==: + "content-length": 18 + "content-type": application/json + "@signature-params": ("@method" "@authority" "@path" \ + "content-digest" "content-length" "content-type")\ + ;created=1618884473;keyid="test-key-rsa-pss" + + Figure 1: Non-normative Example Signature Base + + Note that the example signature base above does not include the final + newline that ends the displayed example, nor do other example + signature bases displayed elsewhere in this specification. + +3. HTTP Message Signatures + + An HTTP message signature is a signature over a string generated from + a subset of the components of an HTTP message in addition to metadata + about the signature itself. When successfully verified against an + HTTP message, an HTTP message signature provides cryptographic proof + that the message is semantically equivalent to the message for which + the signature was generated, with respect to the subset of message + components that was signed. + +3.1. Creating a Signature + + Creation of an HTTP message signature is a process that takes as its + input the signature context (including the target message) and the + requirements for the application. The output is a signature value + and set of signature parameters that can be communicated to the + verifier by adding them to the message. + + In order to create a signature, a signer MUST apply the following + algorithm: + + 1. The signer chooses an HTTP signature algorithm and key material + for signing from the set of potential signing algorithms. The + set of potential algorithms is determined by the application and + is out of scope for this document. The signer MUST choose key + material that is appropriate for the signature's algorithm and + that conforms to any requirements defined by the algorithm, such + as key size or format. The mechanism by which the signer chooses + the algorithm and key material is out of scope for this document. + + 2. The signer sets the signature's creation time to the current + time. + + 3. If applicable, the signer sets the signature's expiration time + property to the time at which the signature is to expire. The + expiration is a hint to the verifier, expressing the time at + which the signer is no longer willing to vouch for the signature. + An appropriate expiration length, and the processing requirements + of this parameter, are application specific. + + 4. The signer creates an ordered set of component identifiers + representing the message components to be covered by the + signature and attaches signature metadata parameters to this set. + The serialized value of this set is later used as the value of + the Signature-Input field as described in Section 4.1. + + * Once an order of covered components is chosen, the order MUST + NOT change for the life of the signature. + + * Each covered component identifier MUST be either (1) an HTTP + field (Section 2.1) in the signature context or (2) a derived + component listed in Section 2.2 or in the "HTTP Signature + Derived Component Names" registry. + + * Signers of a request SHOULD include some or all of the message + control data in the covered components, such as the @method, + @authority, @target-uri, or some combination thereof. + + * Signers SHOULD include the created signature metadata + parameter to indicate when the signature was created. + + * The @signature-params derived component identifier MUST NOT be + present in the list of covered component identifiers. The + derived component is required to always be the last line in + the signature base, ensuring that a signature always covers + its own metadata and the metadata cannot be substituted. + + * Further guidance on what to include in this set and in what + order is out of scope for this document. + + 5. The signer creates the signature base using these parameters and + the signature base creation algorithm (Section 2.5). + + 6. The signer uses the HTTP_SIGN primitive function to sign the + signature base with the chosen signing algorithm using the key + material chosen by the signer. The HTTP_SIGN primitive and + several concrete applications of signing algorithms are defined + in Section 3.3. + + 7. The byte array output of the signature function is the HTTP + message signature output value to be included in the Signature + field as defined in Section 4.2. + + For example, given the HTTP message and signature parameters in the + example in Section 2.5, the example signature base is signed with the + test-key-rsa-pss key (see Appendix B.1.2) and the RSASSA-PSS + algorithm described in Section 3.3.1, giving the following message + signature output value, encoded in Base64: + + NOTE: '\' line wrapping per RFC 8792 + + HIbjHC5rS0BYaa9v4QfD4193TORw7u9edguPh0AW3dMq9WImrlFrCGUDih47vAxi4L2\ + YRZ3XMJc1uOKk/J0ZmZ+wcta4nKIgBkKq0rM9hs3CQyxXGxHLMCy8uqK488o+9jrptQ\ + +xFPHK7a9sRL1IXNaagCNN3ZxJsYapFj+JXbmaI5rtAdSfSvzPuBCh+ARHBmWuNo1Uz\ + VVdHXrl8ePL4cccqlazIJdC4QEjrF+Sn4IxBQzTZsL9y9TP5FsZYzHvDqbInkTNigBc\ + E9cKOYNFCn4D/WM7F6TNuZO9EgtzepLWcjTymlHzK7aXq6Am6sfOrpIC49yXjj3ae6H\ + RalVc/g== + + Figure 2: Non-normative Example Signature Value + + Note that the RSA-PSS algorithm in use here is non-deterministic, + meaning that a different signature value will be created every time + the algorithm is run. The signature value provided here can be + validated against the given keys, but newly generated signature + values are not expected to match the example. See Section 7.3.5. + +3.2. Verifying a Signature + + Verification of an HTTP message signature is a process that takes as + its input the signature context (including the target message, + particularly its Signature and Signature-Input fields) and the + requirements for the application. The output of the verification is + either a positive verification or an error. + + In order to verify a signature, a verifier MUST apply the following + algorithm: + + 1. Parse the Signature and Signature-Input fields as described in + Sections 4.1 and 4.2, and extract the signatures to be verified + and their labels. + + 1.1. If there is more than one signature value present, + determine which signature should be processed for this + message based on the policy and configuration of the + verifier. If an applicable signature is not found, produce + an error. + + 1.2. If the chosen Signature field value does not have a + corresponding Signature-Input field value (i.e., one with + the same label), produce an error. + + 2. Parse the values of the chosen Signature-Input field as a + parameterized Inner List to get the ordered list of covered + components and the signature parameters for the signature to be + verified. + + 3. Parse the value of the corresponding Signature field to get the + byte array value of the signature to be verified. + + 4. Examine the signature parameters to confirm that the signature + meets the requirements described in this document, as well as any + additional requirements defined by the application such as which + message components are required to be covered by the signature + (Section 3.2.1). + + 5. Determine the verification key material for this signature. If + the key material is known through external means such as static + configuration or external protocol negotiation, the verifier will + use the applicable technique to obtain the key material from this + external knowledge. If the key is identified in the signature + parameters, the verifier will dereference the key identifier to + appropriate key material to use with the signature. The verifier + has to determine the trustworthiness of the key material for the + context in which the signature is presented. If a key is + identified that the verifier does not know or trust for this + request or that does not match something preconfigured, the + verification MUST fail. + + 6. Determine the algorithm to apply for verification: + + 6.1. Start with the set of allowable algorithms known to the + application. If any of the following steps select an + algorithm that is not in this set, the signature validation + fails. + + 6.2. If the algorithm is known through external means such as + static configuration or external protocol negotiation, the + verifier will use that algorithm. + + 6.3. If the algorithm can be determined from the keying + material, such as through an algorithm field on the key + value itself, the verifier will use that algorithm. + + 6.4. If the algorithm is explicitly stated in the signature + parameters using a value from the "HTTP Signature + Algorithms" registry, the verifier will use the referenced + algorithm. + + 6.5. If the algorithm is specified in more than one location + (e.g., a combination of static configuration, the algorithm + signature parameter, and the key material itself), the + resolved algorithms MUST be the same. If the algorithms + are not the same, the verifier MUST fail the verification. + + 7. Use the received HTTP message and the parsed signature parameters + to recreate the signature base, using the algorithm defined in + Section 2.5. The value of the @signature-params input is the + value of the Signature-Input field for this signature serialized + according to the rules described in Section 2.3. Note that this + does not include the signature's label from the Signature-Input + field. + + 8. If the key material is appropriate for the algorithm, apply the + appropriate HTTP_VERIFY cryptographic verification algorithm to + the signature, recalculated signature base, key material, and + signature value. The HTTP_VERIFY primitive and several concrete + algorithms are defined in Section 3.3. + + 9. The results of the verification algorithm function are the final + results of the cryptographic verification function. + + If any of the above steps fail or produce an error, the signature + validation fails. + + For example, verifying the signature with the label sig1 of the + following message with the test-key-rsa-pss key (see Appendix B.1.2) + and the RSASSA-PSS algorithm described in Section 3.3.1: + + NOTE: '\' line wrapping per RFC 8792 + + POST /foo?param=Value&Pet=dog HTTP/1.1 + Host: example.com + Date: Tue, 20 Apr 2021 02:07:55 GMT + Content-Type: application/json + Content-Digest: sha-512=:WZDPaVn/7XgHaAy8pmojAkGWoRx2UFChF41A2svX+T\ + aPm+AbwAgBWnrIiYllu7BNNyealdVLvRwEmTHWXvJwew==: + Content-Length: 18 + Signature-Input: sig1=("@method" "@authority" "@path" \ + "content-digest" "content-length" "content-type")\ + ;created=1618884473;keyid="test-key-rsa-pss" + Signature: sig1=:HIbjHC5rS0BYaa9v4QfD4193TORw7u9edguPh0AW3dMq9WImrl\ + FrCGUDih47vAxi4L2YRZ3XMJc1uOKk/J0ZmZ+wcta4nKIgBkKq0rM9hs3CQyxXGxH\ + LMCy8uqK488o+9jrptQ+xFPHK7a9sRL1IXNaagCNN3ZxJsYapFj+JXbmaI5rtAdSf\ + SvzPuBCh+ARHBmWuNo1UzVVdHXrl8ePL4cccqlazIJdC4QEjrF+Sn4IxBQzTZsL9y\ + 9TP5FsZYzHvDqbInkTNigBcE9cKOYNFCn4D/WM7F6TNuZO9EgtzepLWcjTymlHzK7\ + aXq6Am6sfOrpIC49yXjj3ae6HRalVc/g==: + + {"hello": "world"} + + With the additional requirements that at least the method, authority, + path, content-digest, content-length, and content-type entries be + signed, and that the signature creation timestamp be recent enough at + the time of verification, the verification passes. + +3.2.1. Enforcing Application Requirements + + The verification requirements specified in this document are intended + as a baseline set of restrictions that are generally applicable to + all use cases. Applications using HTTP message signatures MAY impose + requirements above and beyond those specified by this document, as + appropriate for their use case. + + Some non-normative examples of additional requirements an application + might define are: + + * Requiring a specific set of header fields to be signed (e.g., + Authorization, Content-Digest). + + * Enforcing a maximum signature age from the time of the created + timestamp. + + * Rejecting signatures past the expiration time in the expires + timestamp. Note that the expiration time is a hint from the + signer and that a verifier can always reject a signature ahead of + its expiration time. + + * Prohibiting certain signature metadata parameters, such as runtime + algorithm signaling with the alg parameter when the algorithm is + determined from the key information. + + * Ensuring successful dereferencing of the keyid parameter to valid + and appropriate key material. + + * Prohibiting the use of certain algorithms or mandating the use of + a specific algorithm. + + * Requiring keys to be of a certain size (e.g., 2048 bits vs. 1024 + bits). + + * Enforcing uniqueness of the nonce parameter. + + * Requiring an application-specific value for the tag parameter. + + Application-specific requirements are expected and encouraged. When + an application defines additional requirements, it MUST enforce them + during the signature verification process, and signature verification + MUST fail if the signature does not conform to the application's + requirements. + + Applications MUST enforce the requirements defined in this document. + Regardless of use case, applications MUST NOT accept signatures that + do not conform to these requirements. + +3.3. Signature Algorithms + + An HTTP message signature MUST use a cryptographic digital signature + or MAC method that is appropriate for the key material, environment, + and needs of the signer and verifier. This specification does not + strictly limit the available signature algorithms, and any signature + algorithm that meets these basic requirements MAY be used by an + application of HTTP message signatures. + + For each signing method, HTTP_SIGN takes as its input the signature + base defined in Section 2.5 as a byte array (M) and the signing key + material (Ks), and outputs the resultant signature as a byte array + (S): + + HTTP_SIGN (M, Ks) -> S + + For each verification method, HTTP_VERIFY takes as its input the + regenerated signature base defined in Section 2.5 as a byte array + (M), the verification key material (Kv), and the presented signature + to be verified as a byte array (S), and outputs the verification + result (V) as a Boolean: + + HTTP_VERIFY (M, Kv, S) -> V + + The following sections contain several common signature algorithms + and demonstrate how these cryptographic primitives map to the + HTTP_SIGN and HTTP_VERIFY definitions above. Which method to use can + be communicated through the explicit algorithm (alg) signature + parameter (Section 2.3), by reference to the key material, or through + mutual agreement between the signer and verifier. Signature + algorithms selected using the alg parameter MUST use values from the + "HTTP Signature Algorithms" registry (Section 6.2). + +3.3.1. RSASSA-PSS Using SHA-512 + + To sign using this algorithm, the signer applies the RSASSA-PSS-SIGN + (K, M) function defined in [RFC8017] with the signer's private + signing key (K) and the signature base (M) (Section 2.5). The mask + generation function is MGF1 as specified in [RFC8017] with a hash + function of SHA-512 [RFC6234]. The salt length (sLen) is 64 bytes. + The hash function (Hash) SHA-512 [RFC6234] is applied to the + signature base to create the digest content to which the digital + signature is applied. The resulting signed content byte array (S) is + the HTTP message signature output used in Section 3.1. + + To verify using this algorithm, the verifier applies the RSASSA-PSS- + VERIFY ((n, e), M, S) function [RFC8017] using the public key portion + of the verification key material (n, e) and the signature base (M) + recreated as described in Section 3.2. The mask generation function + is MGF1 as specified in [RFC8017] with a hash function of SHA-512 + [RFC6234]. The salt length (sLen) is 64 bytes. The hash function + (Hash) SHA-512 [RFC6234] is applied to the signature base to create + the digest content to which the verification function is applied. + The verifier extracts the HTTP message signature to be verified (S) + as described in Section 3.2. The results of the verification + function indicate whether the signature presented is valid. + + Note that the output of the RSASSA-PSS algorithm is non- + deterministic; therefore, it is not correct to recalculate a new + signature on the signature base and compare the results to an + existing signature. Instead, the verification algorithm defined here + needs to be used. See Section 7.3.5. + + The use of this algorithm can be indicated at runtime using the rsa- + pss-sha512 value for the alg signature parameter. + +3.3.2. RSASSA-PKCS1-v1_5 Using SHA-256 + + To sign using this algorithm, the signer applies the RSASSA- + PKCS1-V1_5-SIGN (K, M) function defined in [RFC8017] with the + signer's private signing key (K) and the signature base (M) + (Section 2.5). The hash SHA-256 [RFC6234] is applied to the + signature base to create the digest content to which the digital + signature is applied. The resulting signed content byte array (S) is + the HTTP message signature output used in Section 3.1. + + To verify using this algorithm, the verifier applies the RSASSA- + PKCS1-V1_5-VERIFY ((n, e), M, S) function [RFC8017] using the public + key portion of the verification key material (n, e) and the signature + base (M) recreated as described in Section 3.2. The hash function + SHA-256 [RFC6234] is applied to the signature base to create the + digest content to which the verification function is applied. The + verifier extracts the HTTP message signature to be verified (S) as + described in Section 3.2. The results of the verification function + indicate whether the signature presented is valid. + + The use of this algorithm can be indicated at runtime using the rsa- + v1_5-sha256 value for the alg signature parameter. + +3.3.3. HMAC Using SHA-256 + + To sign and verify using this algorithm, the signer applies the HMAC + function [RFC2104] with the shared signing key (K) and the signature + base (text) (Section 2.5). The hash function SHA-256 [RFC6234] is + applied to the signature base to create the digest content to which + the HMAC is applied, giving the signature result. + + For signing, the resulting value is the HTTP message signature output + used in Section 3.1. + + For verification, the verifier extracts the HTTP message signature to + be verified (S) as described in Section 3.2. The output of the HMAC + function is compared bytewise to the value of the HTTP message + signature, and the results of the comparison determine the validity + of the signature presented. + + The use of this algorithm can be indicated at runtime using the hmac- + sha256 value for the alg signature parameter. + +3.3.4. ECDSA Using Curve P-256 DSS and SHA-256 + + To sign using this algorithm, the signer applies the ECDSA signature + algorithm defined in [FIPS186-5] using curve P-256 with the signer's + private signing key and the signature base (Section 2.5). The hash + SHA-256 [RFC6234] is applied to the signature base to create the + digest content to which the digital signature is applied (M). The + signature algorithm returns two integer values: r and s. These are + both encoded as big-endian unsigned integers, zero-padded to 32 + octets each. These encoded values are concatenated into a single + 64-octet array consisting of the encoded value of r followed by the + encoded value of s. The resulting concatenation of (r, s) is a byte + array of the HTTP message signature output used in Section 3.1. + + To verify using this algorithm, the verifier applies the ECDSA + signature algorithm defined in [FIPS186-5] using the public key + portion of the verification key material and the signature base + recreated as described in Section 3.2. The hash function SHA-256 + [RFC6234] is applied to the signature base to create the digest + content to which the signature verification function is applied (M). + The verifier extracts the HTTP message signature to be verified (S) + as described in Section 3.2. This value is a 64-octet array + consisting of the encoded values of r and s concatenated in order. + These are both encoded as big-endian unsigned integers, zero-padded + to 32 octets each. The resulting signature value (r, s) is used as + input to the signature verification function. The results of the + verification function indicate whether the signature presented is + valid. + + Note that the output of ECDSA signature algorithms is non- + deterministic; therefore, it is not correct to recalculate a new + signature on the signature base and compare the results to an + existing signature. Instead, the verification algorithm defined here + needs to be used. See Section 7.3.5. + + The use of this algorithm can be indicated at runtime using the + ecdsa-p256-sha256 value for the alg signature parameter. + +3.3.5. ECDSA Using Curve P-384 DSS and SHA-384 + + To sign using this algorithm, the signer applies the ECDSA signature + algorithm defined in [FIPS186-5] using curve P-384 with the signer's + private signing key and the signature base (Section 2.5). The hash + SHA-384 [RFC6234] is applied to the signature base to create the + digest content to which the digital signature is applied (M). The + signature algorithm returns two integer values: r and s. These are + both encoded as big-endian unsigned integers, zero-padded to 48 + octets each. These encoded values are concatenated into a single + 96-octet array consisting of the encoded value of r followed by the + encoded value of s. The resulting concatenation of (r, s) is a byte + array of the HTTP message signature output used in Section 3.1. + + To verify using this algorithm, the verifier applies the ECDSA + signature algorithm defined in [FIPS186-5] using the public key + portion of the verification key material and the signature base + recreated as described in Section 3.2. The hash function SHA-384 + [RFC6234] is applied to the signature base to create the digest + content to which the signature verification function is applied (M). + The verifier extracts the HTTP message signature to be verified (S) + as described in Section 3.2. This value is a 96-octet array + consisting of the encoded values of r and s concatenated in order. + These are both encoded as big-endian unsigned integers, zero-padded + to 48 octets each. The resulting signature value (r, s) is used as + input to the signature verification function. The results of the + verification function indicate whether the signature presented is + valid. + + Note that the output of ECDSA signature algorithms is non- + deterministic; therefore, it is not correct to recalculate a new + signature on the signature base and compare the results to an + existing signature. Instead, the verification algorithm defined here + needs to be used. See Section 7.3.5. + + The use of this algorithm can be indicated at runtime using the + ecdsa-p384-sha384 value for the alg signature parameter. + +3.3.6. EdDSA Using Curve edwards25519 + + To sign using this algorithm, the signer applies the Ed25519 + algorithm defined in Section 5.1.6 of [RFC8032] with the signer's + private signing key and the signature base (Section 2.5). The + signature base is taken as the input message (M) with no prehash + function. The signature is a 64-octet concatenation of R and S as + specified in Section 5.1.6 of [RFC8032], and this is taken as a byte + array for the HTTP message signature output used in Section 3.1. + + To verify using this algorithm, the signer applies the Ed25519 + algorithm defined in Section 5.1.7 of [RFC8032] using the public key + portion of the verification key material (A) and the signature base + recreated as described in Section 3.2. The signature base is taken + as the input message (M) with no prehash function. The signature to + be verified is processed as the 64-octet concatenation of R and S as + specified in Section 5.1.7 of [RFC8032]. The results of the + verification function indicate whether the signature presented is + valid. + + The use of this algorithm can be indicated at runtime using the + ed25519 value for the alg signature parameter. + +3.3.7. JSON Web Signature (JWS) Algorithms + + If the signing algorithm is a JSON Object Signing and Encryption + (JOSE) signing algorithm from the "JSON Web Signature and Encryption + Algorithms" registry established by [RFC7518], the JWS algorithm + definition determines the signature and hashing algorithms to apply + for both signing and verification. + + For both signing and verification, the HTTP message's signature base + (Section 2.5) is used as the entire "JWS Signing Input". The JOSE + Header [JWS] [RFC7517] is not used, and the signature base is not + first encoded in Base64 before applying the algorithm. The output of + the JWS Signature is taken as a byte array prior to the Base64url + encoding used in JOSE. + + The JWS algorithm MUST NOT be "none" and MUST NOT be any algorithm + with a JOSE Implementation Requirement of "Prohibited". + + JSON Web Algorithm (JWA) values from the "JSON Web Signature and + Encryption Algorithms" registry are not included as signature + parameters. Typically, the JWS algorithm can be signaled using JSON + Web Keys (JWKs) or other mechanisms common to JOSE implementations. + In fact, JWA values are not registered in the "HTTP Signature + Algorithms" registry (Section 6.2), and so the explicit alg signature + parameter is not used at all when using JOSE signing algorithms. + +4. Including a Message Signature in a Message + + HTTP message signatures can be included within an HTTP message via + the Signature-Input and Signature fields, both defined within this + specification. + + The Signature-Input field identifies the covered components and + parameters that describe how the signature was generated, while the + Signature field contains the signature value. Each field MAY contain + multiple labeled values. + + An HTTP message signature is identified by a label within an HTTP + message. This label MUST be unique within a given HTTP message and + MUST be used in both the Signature-Input field and the Signature + field. The label is chosen by the signer, except where a specific + label is dictated by protocol negotiations such as those described in + Section 5. + + An HTTP message signature MUST use both the Signature-Input field and + the Signature field, and each field MUST contain the same labels. + The presence of a label in one field but not the other is an error. + +4.1. The Signature-Input HTTP Field + + The Signature-Input field is a Dictionary Structured Field (defined + in Section 3.2 of [STRUCTURED-FIELDS]) containing the metadata for + one or more message signatures generated from components within the + HTTP message. Each member describes a single message signature. The + member's key is the label that uniquely identifies the message + signature within the HTTP message. The member's value is the covered + components ordered set serialized as an Inner List, including all + signature metadata parameters identified by the label: + + NOTE: '\' line wrapping per RFC 8792 + + Signature-Input: sig1=("@method" "@target-uri" "@authority" \ + "content-digest" "cache-control");\ + created=1618884475;keyid="test-key-rsa-pss" + + To facilitate signature validation, the Signature-Input field value + MUST contain the same serialized value used in generating the + signature base's @signature-params value defined in Section 2.3. + Note that in a Structured Field value, list order and parameter order + have to be preserved. + + The signer MAY include the Signature-Input field as a trailer to + facilitate signing a message after its content has been processed by + the signer. However, since intermediaries are allowed to drop + trailers as per [HTTP], it is RECOMMENDED that the Signature-Input + field be included only as a header field to avoid signatures being + inadvertently stripped from a message. + + Multiple Signature-Input fields MAY be included in a single HTTP + message. The signature labels MUST be unique across all field + values. + +4.2. The Signature HTTP Field + + The Signature field is a Dictionary Structured Field (defined in + Section 3.2 of [STRUCTURED-FIELDS]) containing one or more message + signatures generated from the signature context of the target + message. The member's key is the label that uniquely identifies the + message signature within the HTTP message. The member's value is a + Byte Sequence containing the signature value for the message + signature identified by the label: + + NOTE: '\' line wrapping per RFC 8792 + + Signature: sig1=:P0wLUszWQjoi54udOtydf9IWTfNhy+r53jGFj9XZuP4uKwxyJo\ + 1RSHi+oEF1FuX6O29d+lbxwwBao1BAgadijW+7O/PyezlTnqAOVPWx9GlyntiCiHz\ + C87qmSQjvu1CFyFuWSjdGa3qLYYlNm7pVaJFalQiKWnUaqfT4LyttaXyoyZW84jS8\ + gyarxAiWI97mPXU+OVM64+HVBHmnEsS+lTeIsEQo36T3NFf2CujWARPQg53r58Rmp\ + Z+J9eKR2CD6IJQvacn5A4Ix5BUAVGqlyp8JYm+S/CWJi31PNUjRRCusCVRj05NrxA\ + BNFv3r5S9IXf2fYJK+eyW4AiGVMvMcOg==: + + The signer MAY include the Signature field as a trailer to facilitate + signing a message after its content has been processed by the signer. + However, since intermediaries are allowed to drop trailers as per + [HTTP], it is RECOMMENDED that the Signature field be included only + as a header field to avoid signatures being inadvertently stripped + from a message. + + Multiple Signature fields MAY be included in a single HTTP message. + The signature labels MUST be unique across all field values. + +4.3. Multiple Signatures + + Multiple distinct signatures MAY be included in a single message. + Each distinct signature MUST have a unique label. These multiple + signatures could all be added by the same signer, or they could come + from several different signers. For example, a signer may include + multiple signatures signing the same message components with + different keys or algorithms to support verifiers with different + capabilities, or a reverse proxy may include information about the + client in fields when forwarding the request to a service host, + including a signature over the client's original signature values. + + The following non-normative example starts with a signed request from + the client. A reverse proxy takes this request and validates the + client's signature: + + NOTE: '\' line wrapping per RFC 8792 + + POST /foo?param=Value&Pet=dog HTTP/1.1 + Host: example.com + Date: Tue, 20 Apr 2021 02:07:55 GMT + Content-Type: application/json + Content-Length: 18 + Content-Digest: sha-512=:WZDPaVn/7XgHaAy8pmojAkGWoRx2UFChF41A2svX+T\ + aPm+AbwAgBWnrIiYllu7BNNyealdVLvRwEmTHWXvJwew==: + Signature-Input: sig1=("@method" "@authority" "@path" \ + "content-digest" "content-type" "content-length")\ + ;created=1618884475;keyid="test-key-ecc-p256" + Signature: sig1=:X5spyd6CFnAG5QnDyHfqoSNICd+BUP4LYMz2Q0JXlb//4Ijpzp\ + +kve2w4NIyqeAuM7jTDX+sNalzA8ESSaHD3A==: + + {"hello": "world"} + + The proxy then alters the message before forwarding it on to the + origin server, changing the target host and adding the Forwarded + header field defined in [RFC7239]: + + NOTE: '\' line wrapping per RFC 8792 + + POST /foo?param=Value&Pet=dog HTTP/1.1 + Host: origin.host.internal.example + Date: Tue, 20 Apr 2021 02:07:56 GMT + Content-Type: application/json + Content-Length: 18 + Forwarded: for=192.0.2.123;host=example.com;proto=https + Content-Digest: sha-512=:WZDPaVn/7XgHaAy8pmojAkGWoRx2UFChF41A2svX+T\ + aPm+AbwAgBWnrIiYllu7BNNyealdVLvRwEmTHWXvJwew==: + Signature-Input: sig1=("@method" "@authority" "@path" \ + "content-digest" "content-type" "content-length")\ + ;created=1618884475;keyid="test-key-ecc-p256" + Signature: sig1=:X5spyd6CFnAG5QnDyHfqoSNICd+BUP4LYMz2Q0JXlb//4Ijpzp\ + +kve2w4NIyqeAuM7jTDX+sNalzA8ESSaHD3A==: + + {"hello": "world"} + + The proxy is in a position to validate the incoming client's + signature and make its own statement to the origin server about the + nature of the request that it is forwarding by adding its own + signature over the new message before passing it along to the origin + server. The proxy also includes all the elements from the original + message that are relevant to the origin server's processing. In many + cases, the proxy will want to cover all the same components that were + covered by the client's signature, which is the case in the following + example. Note that in this example, the proxy is signing over the + new authority value, which it has changed. The proxy also adds the + Forwarded header field to its own signature value. The proxy + identifies its own key and algorithm and, in this example, includes + an expiration for the signature to indicate to downstream systems + that the proxy will not vouch for this signed message past this short + time window. This results in a signature base of: + + NOTE: '\' line wrapping per RFC 8792 + + "@method": POST + "@authority": origin.host.internal.example + "@path": /foo + "content-digest": sha-512=:WZDPaVn/7XgHaAy8pmojAkGWoRx2UFChF41A2svX\ + +TaPm+AbwAgBWnrIiYllu7BNNyealdVLvRwEmTHWXvJwew==: + "content-type": application/json + "content-length": 18 + "forwarded": for=192.0.2.123;host=example.com;proto=https + "@signature-params": ("@method" "@authority" "@path" \ + "content-digest" "content-type" "content-length" "forwarded")\ + ;created=1618884480;keyid="test-key-rsa";alg="rsa-v1_5-sha256"\ + ;expires=1618884540 + + and a signature output value of: + + NOTE: '\' line wrapping per RFC 8792 + + S6ZzPXSdAMOPjN/6KXfXWNO/f7V6cHm7BXYUh3YD/fRad4BCaRZxP+JH+8XY1I6+8Cy\ + +CM5g92iHgxtRPz+MjniOaYmdkDcnL9cCpXJleXsOckpURl49GwiyUpZ10KHgOEe11s\ + x3G2gxI8S0jnxQB+Pu68U9vVcasqOWAEObtNKKZd8tSFu7LB5YAv0RAGhB8tmpv7sFn\ + Im9y+7X5kXQfi8NMaZaA8i2ZHwpBdg7a6CMfwnnrtflzvZdXAsD3LH2TwevU+/PBPv0\ + B6NMNk93wUs/vfJvye+YuI87HU38lZHowtznbLVdp770I6VHR6WfgS9ddzirrswsE1w\ + 5o0LV/g== + + These values are added to the HTTP request message by the proxy. The + original signature is included under the label sig1, and the reverse + proxy's signature is included under the label proxy_sig. The proxy + uses the key test-key-rsa to create its signature using the rsa- + v1_5-sha256 signature algorithm, while the client's original + signature was made using the key test-key-rsa-pss and an RSA-PSS + signature algorithm: + + NOTE: '\' line wrapping per RFC 8792 + + POST /foo?param=Value&Pet=dog HTTP/1.1 + Host: origin.host.internal.example + Date: Tue, 20 Apr 2021 02:07:56 GMT + Content-Type: application/json + Content-Length: 18 + Forwarded: for=192.0.2.123;host=example.com;proto=https + Content-Digest: sha-512=:WZDPaVn/7XgHaAy8pmojAkGWoRx2UFChF41A2svX+T\ + aPm+AbwAgBWnrIiYllu7BNNyealdVLvRwEmTHWXvJwew==: + Signature-Input: sig1=("@method" "@authority" "@path" \ + "content-digest" "content-type" "content-length")\ + ;created=1618884475;keyid="test-key-ecc-p256", \ + proxy_sig=("@method" "@authority" "@path" "content-digest" \ + "content-type" "content-length" "forwarded")\ + ;created=1618884480;keyid="test-key-rsa";alg="rsa-v1_5-sha256"\ + ;expires=1618884540 + Signature: sig1=:X5spyd6CFnAG5QnDyHfqoSNICd+BUP4LYMz2Q0JXlb//4Ijpzp\ + +kve2w4NIyqeAuM7jTDX+sNalzA8ESSaHD3A==:, \ + proxy_sig=:S6ZzPXSdAMOPjN/6KXfXWNO/f7V6cHm7BXYUh3YD/fRad4BCaRZxP+\ + JH+8XY1I6+8Cy+CM5g92iHgxtRPz+MjniOaYmdkDcnL9cCpXJleXsOckpURl49G\ + wiyUpZ10KHgOEe11sx3G2gxI8S0jnxQB+Pu68U9vVcasqOWAEObtNKKZd8tSFu7\ + LB5YAv0RAGhB8tmpv7sFnIm9y+7X5kXQfi8NMaZaA8i2ZHwpBdg7a6CMfwnnrtf\ + lzvZdXAsD3LH2TwevU+/PBPv0B6NMNk93wUs/vfJvye+YuI87HU38lZHowtznbL\ + Vdp770I6VHR6WfgS9ddzirrswsE1w5o0LV/g==: + + {"hello": "world"} + + While the proxy could additionally include the client's Signature + field value and Signature-Input fields from the original message in + the new signature's covered components, this practice is NOT + RECOMMENDED due to known weaknesses in signing signature values as + discussed in Section 7.3.7. The proxy is in a position to validate + the client's signature; the changes the proxy makes to the message + will invalidate the existing signature when the message is seen by + the origin server. In this example, it is possible for the origin + server to have additional information in its signature context to + account for the change in authority, though this practice requires + additional configuration and extra care as discussed in + Section 7.4.4. In other applications, the origin server will not be + able to verify the original signature itself but will still want to + verify that the proxy has done the appropriate validation of the + client's signature. An application that needs to signal successful + processing or receipt of a signature would need to carefully specify + alternative mechanisms for sending such a signal securely. + +5. Requesting Signatures + + While a signer is free to attach a signature to a request or response + without prompting, it is often desirable for a potential verifier to + signal that it expects a signature from a potential signer using the + Accept-Signature field. + + When the Accept-Signature field is sent in an HTTP request message, + the field indicates that the client desires the server to sign the + response using the identified parameters, and the target message is + the response to this request. All responses from resources that + support such signature negotiation SHOULD either be uncacheable or + contain a Vary header field that lists Accept-Signature, in order to + prevent a cache from returning a response with a signature intended + for a different request. + + When the Accept-Signature field is used in an HTTP response message, + the field indicates that the server desires the client to sign its + next request to the server with the identified parameters, and the + target message is the client's next request. The client can choose + to also continue signing future requests to the same server in the + same way. + + The target message of an Accept-Signature field MUST include all + labeled signatures indicated in the Accept-Signature field, each + covering the same identified components of the Accept-Signature + field. + + The sender of an Accept-Signature field MUST include only identifiers + that are appropriate for the type of the target message. For + example, if the target message is a request, the covered components + cannot include the @status component identifier. + +5.1. The Accept-Signature Field + + The Accept-Signature field is a Dictionary Structured Field (defined + in Section 3.2 of [STRUCTURED-FIELDS]) containing the metadata for + one or more requested message signatures to be generated from message + components of the target HTTP message. Each member describes a + single message signature. The member's key is the label that + uniquely identifies the requested message signature within the + context of the target HTTP message. + + The member's value is the serialization of the desired covered + components of the target message, including any allowed component + metadata parameters, using the serialization process defined in + Section 2.3: + + NOTE: '\' line wrapping per RFC 8792 + + Accept-Signature: sig1=("@method" "@target-uri" "@authority" \ + "content-digest" "cache-control");\ + keyid="test-key-rsa-pss";created;tag="app-123" + + The list of component identifiers indicates the exact set of + component identifiers to be included in the requested signature, + including all applicable component parameters. + + The signature request MAY include signature metadata parameters that + indicate desired behavior for the signer. The following behavior is + defined by this specification: + + created: The signer is requested to generate and include a creation + time. This parameter has no associated value when sent as a + signature request. + + expires: The signer is requested to generate and include an + expiration time. This parameter has no associated value when sent + as a signature request. + + nonce: The signer is requested to include the value of this + parameter as the signature nonce in the target signature. + + alg: The signer is requested to use the indicated signature + algorithm from the "HTTP Signature Algorithms" registry to create + the target signature. + + keyid: The signer is requested to use the indicated key material to + create the target signature. + + tag: The signer is requested to include the value of this parameter + as the signature tag in the target signature. + +5.2. Processing an Accept-Signature + + The receiver of an Accept-Signature field fulfills that header as + follows: + + 1. Parse the field value as a Dictionary. + + 2. For each member of the Dictionary: + + 2.1. The key is taken as the label of the output signature as + specified in Section 4.1. + + 2.2. Parse the value of the member to obtain the set of covered + component identifiers. + + 2.3. Determine that the covered components are applicable to the + target message. If not, the process fails and returns an + error. + + 2.4. Process the requested parameters, such as the signing + algorithm and key material. If any requested parameters + cannot be fulfilled or if the requested parameters conflict + with those deemed appropriate to the target message, the + process fails and returns an error. + + 2.5. Select and generate any additional parameters necessary for + completing the signature. + + 2.6. Create the HTTP message signature over the target message. + + 2.7. Create the Signature-Input and Signature field values, and + associate them with the label. + + 3. Optionally create any additional Signature-Input and Signature + field values, with unique labels not found in the Accept- + Signature field. + + 4. Combine all labeled Signature-Input and Signature field values, + and attach both fields to the target message. + + By this process, a signature applied to a target message MUST have + the same label, MUST include the same set of covered components, MUST + process all requested parameters, and MAY have additional parameters. + + The receiver of an Accept-Signature field MAY ignore any signature + request that does not fit application parameters. + + The target message MAY include additional signatures not specified by + the Accept-Signature field. For example, to cover additional message + components, the signer can create a second signature that includes + the additional components as well as the signature output of the + requested signature. + +6. IANA Considerations + + IANA has updated one registry and created four new registries, + according to the following sections. + +6.1. HTTP Field Name Registration + + IANA has updated the entries in the "Hypertext Transfer Protocol + (HTTP) Field Name Registry" as follows: + + +==================+===========+=========================+ + | Field Name | Status | Reference | + +==================+===========+=========================+ + | Signature-Input | permanent | Section 4.1 of RFC 9421 | + +------------------+-----------+-------------------------+ + | Signature | permanent | Section 4.2 of RFC 9421 | + +------------------+-----------+-------------------------+ + | Accept-Signature | permanent | Section 5.1 of RFC 9421 | + +------------------+-----------+-------------------------+ + + Table 1: Updates to the Hypertext Transfer Protocol + (HTTP) Field Name Registry + +6.2. HTTP Signature Algorithms Registry + + This document defines HTTP signature algorithms, for which IANA has + created and now maintains a new registry titled "HTTP Signature + Algorithms". Initial values for this registry are given in + Section 6.2.2. Future assignments and modifications to existing + assignments are to be made through the Specification Required + registration policy [RFC8126]. + + The algorithms listed in this registry identify some possible + cryptographic algorithms for applications to use with this + specification, but the entries neither represent an exhaustive list + of possible algorithms nor indicate fitness for purpose with any + particular application of this specification. An application is free + to implement any algorithm that suits its needs, provided the signer + and verifier can agree to the parameters of that algorithm in a + secure and deterministic fashion. When an application needs to + signal the use of a particular algorithm at runtime using the alg + signature parameter, this registry provides a mapping between the + value of that parameter and a particular algorithm. However, the use + of the alg parameter needs to be treated with caution to avoid + various forms of algorithm confusion and substitution attacks, as + discussed in Section 7. + + The Status value should reflect standardization status and the broad + opinion of relevant interest groups such as the IETF or security- + related Standards Development Organizations (SDOs). When an + algorithm is first registered, the designated expert (DE) should set + the Status field to "Active" if there is consensus for the algorithm + to be generally recommended as secure or "Provisional" if the + algorithm has not reached that consensus, e.g., for an experimental + algorithm. A status of "Provisional" does not mean that the + algorithm is known to be insecure but instead indicates that the + algorithm has not reached consensus regarding its properties. If at + a future time the algorithm as registered is found to have flaws, the + registry entry can be updated and the algorithm can be marked as + "Deprecated" to indicate that the algorithm has been found to have + problems. This status does not preclude an application from using a + particular algorithm; rather, it serves to provide a warning + regarding possible known issues with an algorithm that need to be + considered by the application. The DE can further ensure that the + registration includes an explanation and reference for the Status + value; this is particularly important for deprecated algorithms. + + The DE is expected to do the following: + + * Ensure that the algorithms referenced by a registered algorithm + identifier are fully defined with all parameters (e.g., salt, + hash, required key length) fixed by the defining text. + + * Ensure that the algorithm definition fully specifies the HTTP_SIGN + and HTTP_VERIFY primitive functions, including how all defined + inputs and outputs map to the underlying cryptographic algorithm. + + * Reject any registrations that are aliases of existing + registrations. + + * Ensure that all registrations follow the template presented in + Section 6.2.1; this includes ensuring that the length of the name + is not excessive while still being unique and recognizable. + + This specification creates algorithm identifiers by including major + parameters in the identifier String in order to make the algorithm + name unique and recognizable by developers. However, algorithm + identifiers in this registry are to be interpreted as whole String + values and not as a combination of parts. That is to say, it is + expected that implementors understand rsa-pss-sha512 as referring to + one specific algorithm with its hash, mask, and salt values set as + defined in the defining text that establishes the identifier in + question. Implementors do not parse out the rsa, pss, and sha512 + portions of the identifier to determine parameters of the signing + algorithm from the String, and the registration of one combination of + parameters does not imply the registration of other combinations. + +6.2.1. Registration Template + + Algorithm Name: + An identifier for the HTTP signature algorithm. The name MUST be + an ASCII string that conforms to the sf-string ABNF rule in + Section 3.3.3 of [STRUCTURED-FIELDS] and SHOULD NOT exceed 20 + characters in length. The identifier MUST be unique within the + context of the registry. + + Description: + A brief description of the algorithm used to sign the signature + base. + + Status: + The status of the algorithm. MUST start with one of the following + values and MAY contain additional explanatory text. The options + are: + + "Active": For algorithms without known problems. The signature + algorithm is fully specified, and its security properties are + understood. + + "Provisional": For unproven algorithms. The signature algorithm + is fully specified, but its security properties are not known + or proven. + + "Deprecated": For algorithms with known security issues. The + signature algorithm is no longer recommended for general use + and might be insecure or unsafe in some known circumstances. + + Reference: + Reference to the document or documents that specify the algorithm, + preferably including a URI that can be used to retrieve a copy of + the document(s). An indication of the relevant sections may also + be included but is not required. + +6.2.2. Initial Contents + + The table below contains the initial contents of the "HTTP Signature + Algorithms" registry. + + +===================+===================+========+===============+ + | Algorithm Name | Description | Status | Reference | + +===================+===================+========+===============+ + | rsa-pss-sha512 | RSASSA-PSS using | Active | Section 3.3.1 | + | | SHA-512 | | of RFC 9421 | + +-------------------+-------------------+--------+---------------+ + | rsa-v1_5-sha256 | RSASSA-PKCS1-v1_5 | Active | Section 3.3.2 | + | | using SHA-256 | | of RFC 9421 | + +-------------------+-------------------+--------+---------------+ + | hmac-sha256 | HMAC using | Active | Section 3.3.3 | + | | SHA-256 | | of RFC 9421 | + +-------------------+-------------------+--------+---------------+ + | ecdsa-p256-sha256 | ECDSA using curve | Active | Section 3.3.4 | + | | P-256 DSS and | | of RFC 9421 | + | | SHA-256 | | | + +-------------------+-------------------+--------+---------------+ + | ecdsa-p384-sha384 | ECDSA using curve | Active | Section 3.3.5 | + | | P-384 DSS and | | of RFC 9421 | + | | SHA-384 | | | + +-------------------+-------------------+--------+---------------+ + | ed25519 | EdDSA using curve | Active | Section 3.3.6 | + | | edwards25519 | | of RFC 9421 | + +-------------------+-------------------+--------+---------------+ + + Table 2: Initial Contents of the HTTP Signature Algorithms + Registry + +6.3. HTTP Signature Metadata Parameters Registry + + This document defines the signature parameters structure + (Section 2.3), which may have parameters containing metadata about a + message signature. IANA has created and now maintains a new registry + titled "HTTP Signature Metadata Parameters" to record and maintain + the set of parameters defined for use with member values in the + signature parameters structure. Initial values for this registry are + given in Section 6.3.2. Future assignments and modifications to + existing assignments are to be made through the Expert Review + registration policy [RFC8126]. + + The DE is expected to do the following: + + * Ensure that the name follows the template presented in + Section 6.3.1; this includes ensuring that the length of the name + is not excessive while still being unique and recognizable for its + defined function. + + * Ensure that the defined functionality is clear and does not + conflict with other registered parameters. + + * Ensure that the definition of the metadata parameter includes its + behavior when used as part of the normal signature process as well + as when used in an Accept-Signature field. + +6.3.1. Registration Template + + Name: + An identifier for the HTTP signature metadata parameter. The name + MUST be an ASCII string that conforms to the key ABNF rule defined + in Section 3.1.2 of [STRUCTURED-FIELDS] and SHOULD NOT exceed 20 + characters in length. The identifier MUST be unique within the + context of the registry. + + Description: + A brief description of the metadata parameter and what it + represents. + + Reference: + Reference to the document or documents that specify the parameter, + preferably including a URI that can be used to retrieve a copy of + the document(s). An indication of the relevant sections may also + be included but is not required. + +6.3.2. Initial Contents + + The table below contains the initial contents of the "HTTP Signature + Metadata Parameters" registry. Each row in the table represents a + distinct entry in the registry. + + +=========+===============================+=============+ + | Name | Description | Reference | + +=========+===============================+=============+ + | alg | Explicitly declared signature | Section 2.3 | + | | algorithm | of RFC 9421 | + +---------+-------------------------------+-------------+ + | created | Timestamp of signature | Section 2.3 | + | | creation | of RFC 9421 | + +---------+-------------------------------+-------------+ + | expires | Timestamp of proposed | Section 2.3 | + | | signature expiration | of RFC 9421 | + +---------+-------------------------------+-------------+ + | keyid | Key identifier for the | Section 2.3 | + | | signing and verification keys | of RFC 9421 | + | | used to create this signature | | + +---------+-------------------------------+-------------+ + | nonce | A single-use nonce value | Section 2.3 | + | | | of RFC 9421 | + +---------+-------------------------------+-------------+ + | tag | An application-specific tag | Section 2.3 | + | | for a signature | of RFC 9421 | + +---------+-------------------------------+-------------+ + + Table 3: Initial Contents of the HTTP Signature + Metadata Parameters Registry + +6.4. HTTP Signature Derived Component Names Registry + + This document defines a method for canonicalizing HTTP message + components, including components that can be derived from the context + of the target message outside of the HTTP fields. These derived + components are identified by a unique String, known as the component + name. Component names for derived components always start with the + "at" (@) symbol to distinguish them from HTTP field names. IANA has + created and now maintains a new registry titled "HTTP Signature + Derived Component Names" to record and maintain the set of non-field + component names and the methods used to produce their associated + component values. Initial values for this registry are given in + Section 6.4.2. Future assignments and modifications to existing + assignments are to be made through the Expert Review registration + policy [RFC8126]. + + The DE is expected to do the following: + + * Ensure that the name follows the template presented in + Section 6.4.1; this includes ensuring that the length of the name + is not excessive while still being unique and recognizable for its + defined function. + + * Ensure that the component value represented by the registration + request can be deterministically derived from the target HTTP + message. + + * Ensure that any parameters defined for the registration request + are clearly documented, along with their effects on the component + value. + + The DE should ensure that a registration is sufficiently distinct + from existing derived component definitions to warrant its + registration. + + When setting a registered item's status to "Deprecated", the DE + should ensure that a reason for the deprecation is documented, along + with instructions for moving away from the deprecated functionality. + +6.4.1. Registration Template + + Name: + A name for the HTTP derived component. The name MUST begin with + the "at" (@) character followed by an ASCII string consisting only + of lowercase characters ("a"-"z"), digits ("0"-"9"), and hyphens + ("-"), and SHOULD NOT exceed 20 characters in length. The name + MUST be unique within the context of the registry. + + Description: + A description of the derived component. + + Status: + A brief text description of the status of the algorithm. The + description MUST begin with one of "Active" or "Deprecated" and + MAY provide further context or explanation as to the reason for + the status. A value of "Deprecated" indicates that the derived + component name is no longer recommended for use. + + Target: + The valid message targets for the derived parameter. MUST be one + of the values "Request", "Response", or "Request, Response". The + semantics of these entries are defined in Section 2.2. + + Reference: + Reference to the document or documents that specify the derived + component, preferably including a URI that can be used to retrieve + a copy of the document(s). An indication of the relevant sections + may also be included but is not required. + +6.4.2. Initial Contents + + The table below contains the initial contents of the "HTTP Signature + Derived Component Names" registry. + + +===================+==============+========+==========+===========+ + | Name | Description | Status | Target | Reference | + +===================+==============+========+==========+===========+ + | @signature-params | Reserved for | Active | Request, | Section | + | | signature | | Response | 2.3 of | + | | parameters | | | RFC 9421 | + | | line in | | | | + | | signature | | | | + | | base | | | | + +-------------------+--------------+--------+----------+-----------+ + | @method | The HTTP | Active | Request | Section | + | | request | | | 2.2.1 of | + | | method | | | RFC 9421 | + +-------------------+--------------+--------+----------+-----------+ + | @authority | The HTTP | Active | Request | Section | + | | authority, | | | 2.2.3 of | + | | or target | | | RFC 9421 | + | | host | | | | + +-------------------+--------------+--------+----------+-----------+ + | @scheme | The URI | Active | Request | Section | + | | scheme of | | | 2.2.4 of | + | | the request | | | RFC 9421 | + | | URI | | | | + +-------------------+--------------+--------+----------+-----------+ + | @target-uri | The full | Active | Request | Section | + | | target URI | | | 2.2.2 of | + | | of the | | | RFC 9421 | + | | request | | | | + +-------------------+--------------+--------+----------+-----------+ + | @request-target | The request | Active | Request | Section | + | | target of | | | 2.2.5 of | + | | the request | | | RFC 9421 | + +-------------------+--------------+--------+----------+-----------+ + | @path | The full | Active | Request | Section | + | | path of the | | | 2.2.6 of | + | | request URI | | | RFC 9421 | + +-------------------+--------------+--------+----------+-----------+ + | @query | The full | Active | Request | Section | + | | query of the | | | 2.2.7 of | + | | request URI | | | RFC 9421 | + +-------------------+--------------+--------+----------+-----------+ + | @query-param | A single | Active | Request | Section | + | | named query | | | 2.2.8 of | + | | parameter | | | RFC 9421 | + +-------------------+--------------+--------+----------+-----------+ + | @status | The status | Active | Response | Section | + | | code of the | | | 2.2.9 of | + | | response | | | RFC 9421 | + +-------------------+--------------+--------+----------+-----------+ + + Table 4: Initial Contents of the HTTP Signature Derived + Component Names Registry + +6.5. HTTP Signature Component Parameters Registry + + This document defines several kinds of component identifiers, some of + which can be parameterized in specific circumstances to provide + unique modified behavior. IANA has created and now maintains a new + registry titled "HTTP Signature Component Parameters" to record and + maintain the set of parameter names, the component identifiers they + are associated with, and the modifications these parameters make to + the component value. Definitions of parameters MUST define the + targets to which they apply (such as specific field types, derived + components, or contexts). Initial values for this registry are given + in Section 6.5.2. Future assignments and modifications to existing + assignments are to be made through the Expert Review registration + policy [RFC8126]. + + The DE is expected to do the following: + + * Ensure that the name follows the template presented in + Section 6.5.1; this includes ensuring that the length of the name + is not excessive while still being unique and recognizable for its + defined function. + + * Ensure that the definition of the field sufficiently defines any + interactions or incompatibilities with other existing parameters + known at the time of the registration request. + + * Ensure that the component value defined by the component + identifier with the parameter applied can be deterministically + derived from the target HTTP message in cases where the parameter + changes the component value. + +6.5.1. Registration Template + + Name: + A name for the parameter. The name MUST be an ASCII string that + conforms to the key ABNF rule defined in Section 3.1.2 of + [STRUCTURED-FIELDS] and SHOULD NOT exceed 20 characters in length. + The name MUST be unique within the context of the registry. + + Description: + A description of the parameter's function. + + Reference: + Reference to the document or documents that specify the derived + component, preferably including a URI that can be used to retrieve + a copy of the document(s). An indication of the relevant sections + may also be included but is not required. + +6.5.2. Initial Contents + + The table below contains the initial contents of the "HTTP Signature + Component Parameters" registry. + + +======+=======================================+===============+ + | Name | Description | Reference | + +======+=======================================+===============+ + | sf | Strict Structured Field serialization | Section 2.1.1 | + | | | of RFC 9421 | + +------+---------------------------------------+---------------+ + | key | Single key value of Dictionary | Section 2.1.2 | + | | Structured Fields | of RFC 9421 | + +------+---------------------------------------+---------------+ + | bs | Byte Sequence wrapping indicator | Section 2.1.3 | + | | | of RFC 9421 | + +------+---------------------------------------+---------------+ + | tr | Trailer | Section 2.1.4 | + | | | of RFC 9421 | + +------+---------------------------------------+---------------+ + | req | Related request indicator | Section 2.4 | + | | | of RFC 9421 | + +------+---------------------------------------+---------------+ + | name | Single named query parameter | Section 2.2.8 | + | | | of RFC 9421 | + +------+---------------------------------------+---------------+ + + Table 5: Initial Contents of the HTTP Signature Component + Parameters Registry + +7. Security Considerations + + In order for an HTTP message to be considered _covered_ by a + signature, all of the following conditions have to be true: + + * A signature is expected or allowed on the message by the verifier. + + * The signature exists on the message. + + * The signature is verified against the identified key material and + algorithm. + + * The key material and algorithm are appropriate for the context of + the message. + + * The signature is within expected time boundaries. + + * The signature covers the expected content, including any critical + components. + + * The list of covered components is applicable to the context of the + message. + + In addition to the application requirement definitions listed in + Section 1.4, the following security considerations provide discussion + and context regarding the requirements of creating and verifying + signatures on HTTP messages. + +7.1. General Considerations + +7.1.1. Skipping Signature Verification + + HTTP message signatures only provide security if the signature is + verified by the verifier. Since the message to which the signature + is attached remains a valid HTTP message without the Signature or + Signature-Input fields, it is possible for a verifier to ignore the + output of the verification function and still process the message. + Common reasons for this could be relaxed requirements in a + development environment or a temporary suspension of enforcing + verification while debugging an overall system. Such temporary + suspensions are difficult to detect under positive-example testing, + since a good signature will always trigger a valid response whether + or not it has been checked. + + To detect this, verifiers should be tested using both valid and + invalid signatures, ensuring that an invalid signature fails as + expected. + +7.1.2. Use of TLS + + The use of HTTP message signatures does not negate the need for TLS + or its equivalent to protect information in transit. Message + signatures provide message integrity over the covered message + components but do not provide any confidentiality for communication + between parties. + + TLS provides such confidentiality between the TLS endpoints. As part + of this, TLS also protects the signature data itself from being + captured by an attacker. This is an important step in preventing + signature replay (Section 7.2.2). + + When TLS is used, it needs to be deployed according to the + recommendations provided in [BCP195]. + +7.2. Message Processing and Selection + +7.2.1. Insufficient Coverage + + Any portions of the message not covered by the signature are + susceptible to modification by an attacker without affecting the + signature. An attacker can take advantage of this by introducing or + modifying a header field or other message component that will change + the processing of the message but will not be covered by the + signature. Such an altered message would still pass signature + verification, but when the verifier processes the message as a whole, + the unsigned content injected by the attacker would subvert the trust + conveyed by the valid signature and change the outcome of processing + the message. + + To combat this, an application of this specification should require + as much of the message as possible to be signed, within the limits of + the application and deployment. The verifier should only trust + message components that have been signed. Verifiers could also strip + out any sensitive unsigned portions of the message before processing + of the message continues. + +7.2.2. Signature Replay + + Since HTTP message signatures allow sub-portions of the HTTP message + to be signed, it is possible for two different HTTP messages to + validate against the same signature. The most extreme form of this + would be a signature over no message components. If such a signature + were intercepted, it could be replayed at will by an attacker, + attached to any HTTP message. Even with sufficient component + coverage, a given signature could be applied to two similar HTTP + messages, allowing a message to be replayed by an attacker with the + signature intact. + + To counteract these kinds of attacks, it's first important for the + signer to cover sufficient portions of the message to differentiate + it from other messages. In addition, the signature can use the nonce + signature parameter to provide a per-message unique value to allow + the verifier to detect replay of the signature itself if a nonce + value is repeated. Furthermore, the signer can provide a timestamp + for when the signature was created and a time at which the signer + considers the signature to be expired, limiting the utility of a + captured signature value. + + If a verifier wants to trigger a new signature from a signer, it can + send the Accept-Signature header field with a new nonce parameter. + An attacker that is simply replaying a signature would not be able to + generate a new signature with the chosen nonce value. + +7.2.3. Choosing Message Components + + Applications of HTTP message signatures need to decide which message + components will be covered by the signature. Depending on the + application, some components could be expected to be changed by + intermediaries prior to the signature's verification. If these + components are covered, such changes would, by design, break the + signature. + + However, this document allows for flexibility in determining which + components are signed precisely so that a given application can + choose the appropriate portions of the message that need to be + signed, avoiding problematic components. For example, a web + application framework that relies on rewriting query parameters might + avoid using the @query derived component in favor of sub-indexing the + query value using @query-param derived components instead. + + Some components are expected to be changed by intermediaries and + ought not to be signed under most circumstances. The Via and + Forwarded header fields, for example, are expected to be manipulated + by proxies and other middleboxes, including replacing or entirely + dropping existing values. These fields should not be covered by the + signature, except in very limited and tightly coupled scenarios. + + Additional considerations for choosing signature aspects are + discussed in Section 1.4. + +7.2.4. Choosing Signature Parameters and Derived Components over HTTP + Fields + + Some HTTP fields have values and interpretations that are similar to + HTTP signature parameters or derived components. In most cases, it + is more desirable to sign the non-field alternative. In particular, + the following fields should usually not be included in the signature + unless the application specifically requires it: + + "date" The Date header field value represents the timestamp of the + HTTP message. However, the creation time of the signature itself + is encoded in the created signature parameter. These two values + can be different, depending on how the signature and the HTTP + message are created and serialized. Applications processing + signatures for valid time windows should use the created signature + parameter for such calculations. An application could also put + limits on how much skew there is between the Date field and the + created signature parameter, in order to limit the application of + a generated signature to different HTTP messages. See also + Sections 7.2.2 and 7.2.1. + + "host" The Host header field is specific to HTTP/1.1, and its + functionality is subsumed by the @authority derived component, + defined in Section 2.2.3. In order to preserve the value across + different HTTP versions, applications should always use the + @authority derived component. See also Section 7.5.4. + +7.2.5. Signature Labels + + HTTP message signature values are identified in the Signature and + Signature-Input field values by unique labels. These labels are + chosen only when attaching the signature values to the message and + are not accounted for during the signing process. An intermediary is + allowed to relabel an existing signature when processing the message. + + Therefore, applications should not rely on specific labels being + present, and applications should not put semantic meaning on the + labels themselves. Instead, additional signature parameters can be + used to convey whatever additional meaning is required to be attached + to, and covered by, the signature. In particular, the tag parameter + can be used to define an application-specific value as described in + Section 7.2.7. + +7.2.6. Multiple Signature Confusion + + Since multiple signatures can be applied to one message + (Section 4.3), it is possible for an attacker to attach their own + signature to a captured message without modifying existing + signatures. This new signature could be completely valid based on + the attacker's key, or it could be an invalid signature for any + number of reasons. Each of these situations needs to be accounted + for. + + A verifier processing a set of valid signatures needs to account for + all of the signers, identified by the signing keys. Only signatures + from expected signers should be accepted, regardless of the + cryptographic validity of the signature itself. + + A verifier processing a set of signatures on a message also needs to + determine what to do when one or more of the signatures are not + valid. If a message is accepted when at least one signature is + valid, then a verifier could drop all invalid signatures from the + request before processing the message further. Alternatively, if the + verifier rejects a message for a single invalid signature, an + attacker could use this to deny service to otherwise valid messages + by injecting invalid signatures alongside the valid signatures. + +7.2.7. Collision of Application-Specific Signature Tag + + Multiple applications and protocols could apply HTTP signatures on + the same message simultaneously. In fact, this is a desired feature + in many circumstances; see Section 4.3. A naive verifier could + become confused while processing multiple signatures, either + accepting or rejecting a message based on an unrelated or irrelevant + signature. In order to help an application select which signatures + apply to its own processing, the application can declare a specific + value for the tag signature parameter as defined in Section 2.3. For + example, a signature targeting an application gateway could require + tag="app-gateway" as part of the signature parameters for that + application. + + The use of the tag parameter does not prevent an attacker from also + using the same value as a target application, since the parameter's + value is public and otherwise unrestricted. As a consequence, a + verifier should only use a value of the tag parameter to limit which + signatures to check. Each signature still needs to be examined by + the verifier to ensure that sufficient coverage is provided, as + discussed in Section 7.2.1. + +7.2.8. Message Content + + On its own, this specification does not provide coverage for the + content of an HTTP message under the signature, in either a request + or a response. However, [DIGEST] defines a set of fields that allow + a cryptographic digest of the content to be represented in a field. + Once this field is created, it can be included just like any other + field as defined in Section 2.1. + + For example, in the following response message: + + HTTP/1.1 200 OK + Content-Type: application/json + + {"hello": "world"} + + The digest of the content can be added to the Content-Digest field as + follows: + + NOTE: '\' line wrapping per RFC 8792 + + HTTP/1.1 200 OK + Content-Type: application/json + Content-Digest: \ + sha-256=:X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=: + + {"hello": "world"} + + This field can be included in a signature base just like any other + field along with the basic signature parameters: + + "@status": 200 + "content-digest": \ + sha-256=:X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=: + "@signature-input": ("@status" "content-digest") + + From here, the signing process proceeds as usual. + + Upon verification, it is important that the verifier validate not + only the signature but also the value of the Content-Digest field + itself against the actual received content. Unless the verifier + performs this step, it would be possible for an attacker to + substitute the message content but leave the Content-Digest field + value untouched to pass the signature. Since only the field value is + covered by the signature directly, checking only the signature is not + sufficient protection against such a substitution attack. + + As discussed in [DIGEST], the value of the Content-Digest field is + dependent on the content encoding of the message. If an intermediary + changes the content encoding, the resulting Content-Digest value + would change. This would in turn invalidate the signature. Any + intermediary performing such an action would need to apply a new + signature with the updated Content-Digest field value, similar to the + reverse proxy use case discussed in Section 4.3. + + Applications that make use of the req parameter (Section 2.4) also + need to be aware of the limitations of this functionality. + Specifically, if a client does not include something like a Content- + Digest header field in the request, the server is unable to include a + signature that covers the request's content. + +7.3. Cryptographic Considerations + +7.3.1. Cryptography and Signature Collision + + This document does not define any of its own cryptographic primitives + and instead relies on other specifications to define such elements. + If the signature algorithm or key used to process the signature base + is vulnerable to any attacks, the resulting signature will also be + susceptible to these same attacks. + + A common attack against signature systems is to force a signature + collision, where the same signature value successfully verifies + against multiple different inputs. Since this specification relies + on reconstruction of the signature base from an HTTP message and the + list of components signed is fixed in the signature, it is difficult + but not impossible for an attacker to effect such a collision. An + attacker would need to manipulate the HTTP message and its covered + message components in order to make the collision effective. + + To counter this, only vetted keys and signature algorithms should be + used to sign HTTP messages. The "HTTP Signature Algorithms" registry + is one source of trusted signature algorithms for applications to + apply to their messages. + + While it is possible for an attacker to substitute the signature + parameters value or the signature value separately, the signature + base generation algorithm (Section 2.5) always covers the signature + parameters as the final value in the signature base using a + deterministic serialization method. This step strongly binds the + signature base with the signature value in a way that makes it much + more difficult for an attacker to perform a partial substitution on + the signature base. + +7.3.2. Key Theft + + A foundational assumption of signature-based cryptographic systems is + that the signing key is not compromised by an attacker. If the keys + used to sign the message are exfiltrated or stolen, the attacker will + be able to generate their own signatures using those keys. As a + consequence, signers have to protect any signing key material from + exfiltration, capture, and use by an attacker. + + To combat this, signers can rotate keys over time to limit the amount + of time that stolen keys are useful. Signers can also use key escrow + and storage systems to limit the attack surface against keys. + Furthermore, the use of asymmetric signing algorithms exposes key + material less than the use of symmetric signing algorithms + (Section 7.3.3). + +7.3.3. Symmetric Cryptography + + This document allows both asymmetric and symmetric cryptography to be + applied to HTTP messages. By their nature, symmetric cryptographic + methods require the same key material to be known by both the signer + and verifier. This effectively means that a verifier is capable of + generating a valid signature, since they have access to the same key + material. An attacker that is able to compromise a verifier would be + able to then impersonate a signer. + + Where possible, asymmetric methods or secure key agreement mechanisms + should be used in order to avoid this type of attack. When symmetric + methods are used, distribution of the key material needs to be + protected by the overall system. One technique for this is the use + of separate cryptographic modules that separate the verification + process (and therefore the key material) from other code, minimizing + the vulnerable attack surface. Another technique is the use of key + derivation functions that allow the signer and verifier to agree on + unique keys for each message without having to share the key values + directly. + + Additionally, if symmetric algorithms are allowed within a system, + special care must be taken to avoid key downgrade attacks + (Section 7.3.6). + +7.3.4. Key Specification Mixup + + The existence of a valid signature on an HTTP message is not + sufficient to prove that the message has been signed by the + appropriate party. It is up to the verifier to ensure that a given + key and algorithm are appropriate for the message in question. If + the verifier does not perform such a step, an attacker could + substitute their own signature using their own key on a message and + force a verifier to accept and process it. To combat this, the + verifier needs to ensure not only that the signature can be validated + for a message but that the key and algorithm used are appropriate. + +7.3.5. Non-deterministic Signature Primitives + + Some cryptographic primitives, such as RSA-PSS and ECDSA, have non- + deterministic outputs, which include some amount of entropy within + the algorithm. For such algorithms, multiple signatures generated in + succession will not match. A lazy implementation of a verifier could + ignore this distinction and simply check for the same value being + created by re-signing the signature base. Such an implementation + would work for deterministic algorithms such as HMAC and EdDSA but + fail to verify valid signatures made using non-deterministic + algorithms. It is therefore important that a verifier always use the + correctly defined verification function for the algorithm in question + and not do a simple comparison. + +7.3.6. Key and Algorithm Specification Downgrades + + Applications of this specification need to protect against key + specification downgrade attacks. For example, the same RSA key can + be used for both RSA-PSS and RSA v1.5 signatures. If an application + expects a key to only be used with RSA-PSS, it needs to reject + signatures for any key that uses the weaker RSA 1.5 specification. + + Another example of a downgrade attack would be when an asymmetric + algorithm is expected, such as RSA-PSS, but an attacker substitutes a + signature using a symmetric algorithm, such as HMAC. A naive + verifier implementation could use the value of the public RSA key as + the input to the HMAC verification function. Since the public key is + known to the attacker, this would allow the attacker to create a + valid HMAC signature against this known key. To prevent this, the + verifier needs to ensure that both the key material and the algorithm + are appropriate for the usage in question. Additionally, while this + specification does allow runtime specification of the algorithm using + the alg signature parameter, applications are encouraged to use other + mechanisms such as static configuration or a higher-protocol-level + algorithm specification instead, preventing an attacker from + substituting the algorithm specified. + +7.3.7. Signing Signature Values + + When applying the req parameter (Section 2.4) or multiple signatures + (Section 4.3) to a message, it is possible to sign the value of an + existing Signature field, thereby covering the bytes of the existing + signature output in the new signature's value. While it would seem + that this practice would transitively cover the components under the + original signature in a verifiable fashion, the attacks described in + [JACKSON2019] can be used to impersonate a signature output value on + an unrelated message. + + In this example, Alice intends to send a signed request to Bob, and + Bob wants to provide a signed response to Alice that includes a + cryptographic proof that Bob is responding to Alice's incoming + message. Mallory wants to intercept this traffic and replace Alice's + message with her own, without Alice being aware that the interception + has taken place. + + 1. Alice creates a message Req_A and applies a signature Sig_A + using her private key Key_A_Sign. + + 2. Alice believes she is sending Req_A to Bob. + + 3. Mallory intercepts Req_A and reads the value Sig_A from this + message. + + 4. Mallory generates a different message Req_M to send to Bob + instead. + + 5. Mallory crafts a signing key Key_M_Sign such that she can create + a valid signature Sig_M over her request Req_M using this key, + but the byte value of Sig_M exactly equals that of Sig_A. + + 6. Mallory sends Req_M with Sig_M to Bob. + + 7. Bob validates Sig_M against Mallory's verification key + Key_M_Verify. At no time does Bob think that he's responding to + Alice. + + 8. Bob responds with response message Res_B to Req_M and creates + signature Sig_B over this message using his key Key_B_Sign. Bob + includes the value of Sig_M under Sig_B's covered components but + does not include anything else from the request message. + + 9. Mallory receives the response Res_B from Bob, including the + signature Sig_B value. Mallory replays this response to Alice. + + 10. Alice reads Res_B from Mallory and verifies Sig_B using Bob's + verification key Key_B_Verify. Alice includes the bytes of her + original signature Sig_A in the signature base, and the + signature verifies. + + 11. Alice is led to believe that Bob has responded to her message + and believes she has cryptographic proof of this happening, but + in fact Bob responded to Mallory's malicious request and Alice + is none the wiser. + + To mitigate this, Bob can sign more portions of the request message + than just the Signature field, in order to more fully differentiate + Alice's message from Mallory's. Applications using this feature, + particularly for non-repudiation purposes, can stipulate that any + components required in the original signature also be covered + separately in the second signature. For signed messages, requiring + coverage of the corresponding Signature-Input field of the first + signature ensures that unique items such as nonces and timestamps are + also covered sufficiently by the second signature. + +7.4. Matching Signature Parameters to the Target Message + +7.4.1. Modification of Required Message Parameters + + An attacker could effectively deny a service by modifying an + otherwise benign signature parameter or signed message component. + While rejecting a modified message is the desired behavior, + consistently failing signatures could lead to (1) the verifier + turning off signature checking in order to make systems work again + (see Section 7.1.1) or (2) the application minimizing the + requirements related to the signed component. + + If such failures are common within an application, the signer and + verifier should compare their generated signature bases with each + other to determine which part of the message is being modified. If + an expected modification is found, the signer and verifier can agree + on an alternative set of requirements that will pass. However, the + signer and verifier should not remove the requirement to sign the + modified component when it is suspected that an attacker is modifying + the component. + +7.4.2. Matching Values of Covered Components to Values in the Target + Message + + The verifier needs to make sure that the signed message components + match those in the message itself. For example, the @method derived + component requires that the value within the signature base be the + same as the HTTP method used when presenting this message. This + specification encourages this by requiring the verifier to derive the + signature base from the message, but lazy caching or conveyance of a + raw signature base to a processing subsystem could lead to downstream + verifiers accepting a message that does not match the presented + signature. + + To counter this, the component that generates the signature base + needs to be trusted by both the signer and verifier within a system. + +7.4.3. Message Component Source and Context + + The signature context for deriving message component values includes + the target HTTP message itself, any associated messages (such as the + request that triggered a response), and additional information that + the signer or verifier has access to. Both signers and verifiers + need to carefully consider the source of all information when + creating component values for the signature base and take care not to + take information from untrusted sources. Otherwise, an attacker + could leverage such a loosely defined message context to inject their + own values into the signature base string, overriding or corrupting + the intended values. + + For example, in most situations, the target URI of the message is as + defined in [HTTP], Section 7.1. However, let's say that there is an + application that requires signing of the @authority of the incoming + request, but the application doing the processing is behind a reverse + proxy. Such an application would expect a change in the @authority + value, and it could be configured to know the external target URI as + seen by the client on the other side of the proxy. This application + would use this configured value as its target URI for the purposes of + deriving message component values such as @authority instead of using + the target URI of the incoming message. + + This approach is not without problems, as a misconfigured system + could accept signed requests intended for different components in the + system. For this scenario, an intermediary could instead add its own + signature to be verified by the application directly, as demonstrated + in Section 4.3. This alternative approach requires a more active + intermediary but relies less on the target application knowing + external configuration values. + + As another example, Section 2.4 defines a method for signing response + messages and also including portions of the request message that + triggered the response. In this case, the context for component + value calculation is the combination of the response and request + messages, not just the single message to which the signature is + applied. For this feature, the req flag allows both signers to + explicitly signal which part of the context is being sourced for a + component identifier's value. Implementations need to ensure that + only the intended message is being referred to for each component; + otherwise, an attacker could attempt to subvert a signature by + manipulating one side or the other. + +7.4.4. Multiple Message Component Contexts + + It is possible that the context for deriving message component values + could be distinct for each signature present within a single message. + This is particularly the case when proxies mutate messages and + include signatures over the mutated values, in addition to any + existing signatures. For example, a reverse proxy can replace a + public hostname in a request to a service with the hostname for the + individual service host to which it is forwarding the request. If + both the client and the reverse proxy add signatures covering + @authority, the service host will see two signatures on the request, + each signing different values for the @authority message component, + reflecting the change to that component as the message made its way + from the client to the service host. + + In such a case, it's common for the internal service to verify only + one of the signatures or to use externally configured information, as + discussed in Section 7.4.3. However, a verifier processing both + signatures has to use a different message component context for each + signature, since the component value for the @authority component + will be different for each signature. Verifiers like this need to be + aware of both the reverse proxy's context for incoming messages and + the target service's context for the message coming from the reverse + proxy. The verifier needs to take particular care to apply the + correct context to the correct signature; otherwise, an attacker + could use knowledge of this complex setup to confuse the inputs to + the verifier. + + Such verifiers also need to ensure that any differences in message + component contexts between signatures are expected and permitted. + For example, in the above scenario, the reverse proxy could include + the original hostname in a Forwarded header field and could sign + @authority, forwarded, and the client's entry in the Signature field. + The verifier can use the hostname from the Forwarded header field to + confirm that the hostname was transformed as expected. + +7.5. HTTP Processing + +7.5.1. Processing Invalid HTTP Field Names as Derived Component Names + + The definition of HTTP field names does not allow for the use of the + @ character anywhere in the name. As such, since all derived + component names start with the @ character, these namespaces should + be completely separate. However, some HTTP implementations are not + sufficiently strict about the characters accepted in HTTP field + names. In such implementations, a sender (or attacker) could inject + a header field starting with an @ character and have it passed + through to the application code. These invalid header fields could + be used to override a portion of the derived message content and + substitute an arbitrary value, providing a potential place for an + attacker to mount a signature collision (Section 7.3.1) attack or + other functional substitution attack (such as using the signature + from a GET request on a crafted POST request). + + To combat this, when selecting values for a message component, if the + component name starts with the @ character, it needs to be processed + as a derived component and never processed as an HTTP field. Only if + the component name does not start with the @ character can it be + taken from the fields of the message. The algorithm discussed in + Section 2.5 provides a safe order of operations. + +7.5.2. Semantically Equivalent Field Values + + The signature base generation algorithm (Section 2.5) uses the value + of an HTTP field as its component value. In the common case, this + amounts to taking the actual bytes of the field value as the + component value for both the signer and verifier. However, some + field values allow for transformation of the values in semantically + equivalent ways that alter the bytes used in the value itself. For + example, a field definition can declare some or all of its values to + be case insensitive or to have special handling of internal + whitespace characters. Other fields have expected transformations + from intermediaries, such as the removal of comments in the Via + header field. In such cases, a verifier could be tripped up by using + the equivalent transformed field value, which would differ from the + byte value used by the signer. The verifier would have a difficult + time finding this class of errors, since the value of the field is + still acceptable for the application but the actual bytes required by + the signature base would not match. + + When processing such fields, the signer and verifier have to agree on + how to handle such transformations, if at all. One option is to not + sign problematic fields, but care must be taken to ensure that there + is still sufficient signature coverage (Section 7.2.1) for the + application. Another option is to define an application-specific + canonicalization value for the field before it is added to the HTTP + message, such as to always remove internal comments before signing or + to always transform values to lowercase. Since these transformations + are applied prior to the field being used as input to the signature + base generation algorithm, the signature base will still simply + contain the byte value of the field as it appears within the message. + If the transformations were to be applied after the value is + extracted from the message but before it is added to the signature + base, different attack surfaces such as value substitution attacks + could be launched against the application. All application-specific + additional rules are outside the scope of this specification, and by + their very nature these transformations would harm interoperability + of the implementation outside of this specific application. It is + recommended that applications avoid the use of such additional rules + wherever possible. + +7.5.3. Parsing Structured Field Values + + Several parts of this specification rely on the parsing of Structured + Field values [STRUCTURED-FIELDS] -- in particular, strict + serialization of HTTP Structured Field values (Section 2.1.1), + referencing members of a Dictionary Structured Field (Section 2.1.2), + and processing the @signature-input value when verifying a signature + (Section 3.2). While Structured Field values are designed to be + relatively simple to parse, a naive or broken implementation of such + a parser could lead to subtle attack surfaces being exposed in the + implementation. + + For example, if a buggy parser of the @signature-input value does not + enforce proper closing of quotes around string values within the list + of component identifiers, an attacker could take advantage of this + and inject additional content into the signature base through + manipulating the Signature-Input field value on a message. + + To counteract this, implementations should use fully compliant and + trusted parsers for all Structured Field processing, on both the + signer side and the verifier side. + +7.5.4. HTTP Versions and Component Ambiguity + + Some message components are expressed in different ways across HTTP + versions. For example, the authority of the request target is sent + using the Host header field in HTTP/1.1 but with the :authority + pseudo-header in HTTP/2. If a signer sends an HTTP/1.1 message and + signs the Host header field but the message is translated to HTTP/2 + before it reaches the verifier, the signature will not validate, as + the Host header field could be dropped. + + It is for this reason that HTTP message signatures define a set of + derived components that define a single way to get the value in + question, such as the @authority derived component (Section 2.2.3) in + lieu of the Host header field. Applications should therefore prefer + derived components for such options where possible. + +7.5.5. Canonicalization Attacks + + Any ambiguity in the generation of the signature base could provide + an attacker with leverage to substitute or break a signature on a + message. Some message component values, particularly HTTP field + values, are potentially susceptible to broken implementations that + could lead to unexpected and insecure behavior. Naive + implementations of this specification might implement HTTP field + processing by taking the single value of a field and using it as the + direct component value without processing it appropriately. + + For example, if the handling of obs-fold field values does not remove + the internal line folding and whitespace, additional newlines could + be introduced into the signature base by the signer, providing a + potential place for an attacker to mount a signature collision + (Section 7.3.1) attack. Alternatively, if header fields that appear + multiple times are not joined into a single string value, as required + by this specification, similar attacks can be mounted, as a signed + component value would show up in the signature base more than once + and could be substituted or otherwise attacked in this way. + + To counter this, the entire field value processing algorithm needs to + be implemented by all implementations of signers and verifiers. + +7.5.6. Non-List Field Values + + When an HTTP field occurs multiple times in a single message, these + values need to be combined into a single one-line string value to be + included in the HTTP signature base, as described in Section 2.5. + Not all HTTP fields can be combined into a single value in this way + and still be a valid value for the field. For the purposes of + generating the signature base, the message component value is never + meant to be read back out of the signature base string or used in the + application. Therefore, it is considered best practice to treat the + signature base generation algorithm separately from processing the + field values by the application, particularly for fields that are + known to have this property. If the field values that are being + signed do not validate, the signed message should also be rejected. + + If an HTTP field allows for unquoted commas within its values, + combining multiple field values can lead to a situation where two + semantically different messages produce the same line in a signature + base. For example, take the following hypothetical header field with + an internal comma in its syntax, here used to define two separate + lists of values: + + Example-Header: value, with, lots + Example-Header: of, commas + + For this header field, sending all of these values as a single field + value results in a single list of values: + + Example-Header: value, with, lots, of, commas + + Both of these messages would create the following line in the + signature base: + + "example-header": value, with, lots, of, commas + + Since two semantically distinct inputs can create the same output in + the signature base, special care has to be taken when handling such + values. + + Specifically, the Set-Cookie field [COOKIE] defines an internal + syntax that does not conform to the List syntax provided in + [STRUCTURED-FIELDS]. In particular, some portions allow unquoted + commas, and the field is typically sent as multiple separate field + lines with distinct values when sending multiple cookies. When + multiple Set-Cookie fields are sent in the same message, it is not + generally possible to combine these into a single line and be able to + parse and use the results, as discussed in [HTTP], Section 5.3. + Therefore, all the cookies need to be processed from their separate + field values, without being combined, while the signature base needs + to be processed from the special combined value generated solely for + this purpose. If the cookie value is invalid, the signed message + ought to be rejected, as this is a possible padding attack as + described in Section 7.5.7. + + To deal with this, an application can choose to limit signing of + problematic fields like Set-Cookie, such as including the field in a + signature only when a single field value is present and the results + would be unambiguous. Similar caution needs to be taken with all + fields that could have non-deterministic mappings into the signature + base. Signers can also make use of the bs parameter to armor such + fields, as described in Section 2.1.3. + +7.5.7. Padding Attacks with Multiple Field Values + + Since HTTP field values need to be combined into a single string + value to be included in the HTTP signature base (see Section 2.5), it + is possible for an attacker to inject an additional value for a given + field and add this to the signature base of the verifier. + + In most circumstances, this causes the signature validation to fail + as expected, since the new signature base value will not match the + one used by the signer to create the signature. However, it is + theoretically possible for the attacker to inject both a garbage + value into a field and a desired value into another field in order to + force a particular input. This is a variation of the collision + attack described in Section 7.3.1, where the attacker accomplishes + their change in the message by adding to existing field values. + + To counter this, an application needs to validate the content of the + fields covered in the signature in addition to ensuring that the + signature itself validates. With such protections, the attacker's + padding attack would be rejected by the field value processor, even + in the case where the attacker could force a signature collision. + +7.5.8. Ambiguous Handling of Query Elements + + The HTML form parameters format defined in Section 5 ("application/ + x-www-form-urlencoded") of [HTMLURL] is widely deployed and supported + by many application frameworks. For convenience, some of these + frameworks in particular combine query parameters that are found in + the HTTP query and those found in the message content, particularly + for POST messages with a Content-Type value of "application/x-www- + form-urlencoded". The @query-param derived component identifier + defined in Section 2.2.8 draws its values only from the query section + of the target URI of the request. As such, it would be possible for + an attacker to shadow or replace query parameters in a request by + overriding a signed query parameter with an unsigned form parameter, + or vice versa. + + To counter this, an application needs to make sure that values used + for the signature base and the application are drawn from a + consistent context, in this case the query component of the target + URI. Additionally, when the HTTP request has content, an application + should sign the message content as well, as discussed in + Section 7.2.8. + +8. Privacy Considerations + +8.1. Identification through Keys + + If a signer uses the same key with multiple verifiers or uses the + same key over time with a single verifier, the ongoing use of that + key can be used to track the signer throughout the set of verifiers + that messages are sent to. Since cryptographic keys are meant to be + functionally unique, the use of the same key over time is a strong + indicator that it is the same party signing multiple messages. + + In many applications, this is a desirable trait, and it allows HTTP + message signatures to be used as part of authenticating the signer to + the verifier. However, it could also result in unintentional + tracking that a signer might not be aware of. To counter this kind + of tracking, a signer can use a different key for each verifier that + it is in communication with. Sometimes, a signer could also rotate + their key when sending messages to a given verifier. These + approaches do not negate the need for other anti-tracking techniques + to be applied as necessary. + +8.2. Signatures do not provide confidentiality + + HTTP message signatures do not provide confidentiality for any of the + information protected by the signature. The content of the HTTP + message, including the value of all fields and the value of the + signature itself, is presented in plaintext to any party with access + to the message. + + To provide confidentiality at the transport level, TLS or its + equivalent can be used, as discussed in Section 7.1.2. + +8.3. Oracles + + It is important to balance the need for providing useful feedback to + developers regarding error conditions without providing additional + information to an attacker. For example, a naive but helpful server + implementation might try to indicate the required key identifier + needed for requesting a resource. If someone knows who controls that + key, a correlation can be made between the resource's existence and + the party identified by the key. Access to such information could be + used by an attacker as a means to target the legitimate owner of the + resource for further attacks. + +8.4. Required Content + + A core design tenet of this specification is that all message + components covered by the signature need to be available to the + verifier in order to recreate the signature base and verify the + signature. As a consequence, if an application of this specification + requires that a particular field be signed, the verifier will need + access to the value of that field. + + For example, in some complex systems with intermediary processors, + this could cause surprising behavior where, for fear of breaking the + signature, an intermediary cannot remove privacy-sensitive + information from a message before forwarding it on for processing. + One way to mitigate this specific situation would be for the + intermediary to verify the signature itself and then modify the + message to remove the privacy-sensitive information. The + intermediary can add its own signature at this point to signal to the + next destination that the incoming signature was validated, as shown + in the example in Section 4.3. + +9. References + +9.1. Normative References + + [ABNF] Crocker, D., Ed. and P. Overell, "Augmented BNF for Syntax + Specifications: ABNF", STD 68, RFC 5234, + DOI 10.17487/RFC5234, January 2008, + <https://www.rfc-editor.org/info/rfc5234>. + + [ASCII] Cerf, V., "ASCII format for network interchange", STD 80, + RFC 20, DOI 10.17487/RFC0020, October 1969, + <https://www.rfc-editor.org/info/rfc20>. + + [FIPS186-5] + NIST, "Digital Signature Standard (DSS)", + DOI 10.6028/NIST.FIPS.186-5, February 2023, + <https://doi.org/10.6028/NIST.FIPS.186-5>. + + [HTMLURL] WHATWG, "URL (Living Standard)", January 2024, + <https://url.spec.whatwg.org/>. + + [HTTP] Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke, + Ed., "HTTP Semantics", STD 97, RFC 9110, + DOI 10.17487/RFC9110, June 2022, + <https://www.rfc-editor.org/info/rfc9110>. + + [HTTP/1.1] Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke, + Ed., "HTTP/1.1", STD 99, RFC 9112, DOI 10.17487/RFC9112, + June 2022, <https://www.rfc-editor.org/info/rfc9112>. + + [POSIX.1] IEEE, "The Open Group Base Specifications Issue 7, 2018 + edition", 2018, + <https://pubs.opengroup.org/onlinepubs/9699919799/>. + + [RFC2104] Krawczyk, H., Bellare, M., and R. Canetti, "HMAC: Keyed- + Hashing for Message Authentication", RFC 2104, + DOI 10.17487/RFC2104, February 1997, + <https://www.rfc-editor.org/info/rfc2104>. + + [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate + Requirement Levels", BCP 14, RFC 2119, + DOI 10.17487/RFC2119, March 1997, + <https://www.rfc-editor.org/info/rfc2119>. + + [RFC6234] Eastlake 3rd, D. and T. Hansen, "US Secure Hash Algorithms + (SHA and SHA-based HMAC and HKDF)", RFC 6234, + DOI 10.17487/RFC6234, May 2011, + <https://www.rfc-editor.org/info/rfc6234>. + + [RFC7517] Jones, M., "JSON Web Key (JWK)", RFC 7517, + DOI 10.17487/RFC7517, May 2015, + <https://www.rfc-editor.org/info/rfc7517>. + + [RFC7518] Jones, M., "JSON Web Algorithms (JWA)", RFC 7518, + DOI 10.17487/RFC7518, May 2015, + <https://www.rfc-editor.org/info/rfc7518>. + + [RFC8017] Moriarty, K., Ed., Kaliski, B., Jonsson, J., and A. Rusch, + "PKCS #1: RSA Cryptography Specifications Version 2.2", + RFC 8017, DOI 10.17487/RFC8017, November 2016, + <https://www.rfc-editor.org/info/rfc8017>. + + [RFC8032] Josefsson, S. and I. Liusvaara, "Edwards-Curve Digital + Signature Algorithm (EdDSA)", RFC 8032, + DOI 10.17487/RFC8032, January 2017, + <https://www.rfc-editor.org/info/rfc8032>. + + [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC + 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, + May 2017, <https://www.rfc-editor.org/info/rfc8174>. + + [STRUCTURED-FIELDS] + Nottingham, M. and P. Kamp, "Structured Field Values for + HTTP", RFC 8941, DOI 10.17487/RFC8941, February 2021, + <https://www.rfc-editor.org/info/rfc8941>. + + [URI] Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform + Resource Identifier (URI): Generic Syntax", STD 66, + RFC 3986, DOI 10.17487/RFC3986, January 2005, + <https://www.rfc-editor.org/info/rfc3986>. + +9.2. Informative References + + [AWS-SIGv4] + Amazon Simple Storage Service, "Authenticating Requests + (AWS Signature Version 4)", March 2006, + <https://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4- + authenticating-requests.html>. + + [BCP195] Moriarty, K. and S. Farrell, "Deprecating TLS 1.0 and TLS + 1.1", BCP 195, RFC 8996, March 2021. + + Sheffer, Y., Saint-Andre, P., and T. Fossati, + "Recommendations for Secure Use of Transport Layer + Security (TLS) and Datagram Transport Layer Security + (DTLS)", BCP 195, RFC 9325, November 2022. + + <https://www.rfc-editor.org/info/bcp195> + + [CLIENT-CERT] + Campbell, B. and M. Bishop, "Client-Cert HTTP Header + Field", RFC 9440, DOI 10.17487/RFC9440, July 2023, + <https://www.rfc-editor.org/info/rfc9440>. + + [COOKIE] Barth, A., "HTTP State Management Mechanism", RFC 6265, + DOI 10.17487/RFC6265, April 2011, + <https://www.rfc-editor.org/info/rfc6265>. + + [DIGEST] Polli, R. and L. Pardue, "Digest Fields", RFC 9530, + DOI 10.17487/RFC9530, February 2024, + <https://www.rfc-editor.org/info/rfc9530>. + + [JACKSON2019] + Jackson, D., Cremers, C., Cohn-Gordon, K., and R. Sasse, + "Seems Legit: Automated Analysis of Subtle Attacks on + Protocols that Use Signatures", CCS '19: Proceedings of + the 2019 ACM SIGSAC Conference on Computer and + Communications Security, pp. 2165-2180, + DOI 10.1145/3319535.3339813, November 2019, + <https://dl.acm.org/doi/10.1145/3319535.3339813>. + + [JWS] Jones, M., Bradley, J., and N. Sakimura, "JSON Web + Signature (JWS)", RFC 7515, DOI 10.17487/RFC7515, May + 2015, <https://www.rfc-editor.org/info/rfc7515>. + + [RFC7239] Petersson, A. and M. Nilsson, "Forwarded HTTP Extension", + RFC 7239, DOI 10.17487/RFC7239, June 2014, + <https://www.rfc-editor.org/info/rfc7239>. + + [RFC7468] Josefsson, S. and S. Leonard, "Textual Encodings of PKIX, + PKCS, and CMS Structures", RFC 7468, DOI 10.17487/RFC7468, + April 2015, <https://www.rfc-editor.org/info/rfc7468>. + + [RFC7807] Nottingham, M. and E. Wilde, "Problem Details for HTTP + APIs", RFC 7807, DOI 10.17487/RFC7807, March 2016, + <https://www.rfc-editor.org/info/rfc7807>. + + [RFC8126] Cotton, M., Leiba, B., and T. Narten, "Guidelines for + Writing an IANA Considerations Section in RFCs", BCP 26, + RFC 8126, DOI 10.17487/RFC8126, June 2017, + <https://www.rfc-editor.org/info/rfc8126>. + + [RFC8792] Watsen, K., Auerswald, E., Farrel, A., and Q. Wu, + "Handling Long Lines in Content of Internet-Drafts and + RFCs", RFC 8792, DOI 10.17487/RFC8792, June 2020, + <https://www.rfc-editor.org/info/rfc8792>. + + [RFC9457] Nottingham, M., Wilde, E., and S. Dalal, "Problem Details + for HTTP APIs", RFC 9457, DOI 10.17487/RFC9457, July 2023, + <https://www.rfc-editor.org/info/rfc9457>. + + [SIGNING-HTTP-MESSAGES] + Cavage, M. and M. Sporny, "Signing HTTP Messages", Work in + Progress, Internet-Draft, draft-cavage-http-signatures-12, + 21 October 2019, <https://datatracker.ietf.org/doc/html/ + draft-cavage-http-signatures-12>. + + [SIGNING-HTTP-REQS-OAUTH] + Richer, J., Ed., Bradley, J., and H. Tschofenig, "A Method + for Signing HTTP Requests for OAuth", Work in Progress, + Internet-Draft, draft-ietf-oauth-signed-http-request-03, 8 + August 2016, <https://datatracker.ietf.org/doc/html/draft- + ietf-oauth-signed-http-request-03>. + + [TLS] Rescorla, E., "The Transport Layer Security (TLS) Protocol + Version 1.3", RFC 8446, DOI 10.17487/RFC8446, August 2018, + <https://www.rfc-editor.org/info/rfc8446>. + +Appendix A. Detecting HTTP Message Signatures + + There have been many attempts to create signed HTTP messages in the + past, including other non-standardized definitions of the Signature + field that is used within this specification. It is recommended that + developers wishing to support this specification, other published + documents, or other historical drafts do so carefully and + deliberately, as incompatibilities between this specification and + other documents or various versions of other drafts could lead to + unexpected problems. + + It is recommended that implementors first detect and validate the + Signature-Input field defined in this specification to detect that + the mechanism described in this document is in use and not an + alternative. If the Signature-Input field is present, all Signature + fields can be parsed and interpreted in the context of this + specification. + +Appendix B. Examples + + The following non-normative examples are provided as a means of + testing implementations of HTTP message signatures. The signed + messages given can be used to create the signature base with the + stated parameters, creating signatures using the stated algorithms + and keys. + + The private keys given can be used to generate signatures, though + since several of the demonstrated algorithms are non-deterministic, + the results of a signature are expected to be different from the + exact bytes of the examples. The public keys given can be used to + validate all signed examples. + +B.1. Example Keys + + This section provides cryptographic keys that are referenced in + example signatures throughout this document. These keys MUST NOT be + used for any purpose other than testing. + + The key identifiers for each key are used throughout the examples in + this specification. It is assumed for these examples that the signer + and verifier can unambiguously dereference all key identifiers used + here and that the keys and algorithms used are appropriate for the + context in which the signature is presented. + + The components for each private key, in PEM format [RFC7468], can be + displayed by executing the following OpenSSL command: + + openssl pkey -text + + This command was tested with all the example keys on OpenSSL version + 1.1.1m. Note that some systems cannot produce or use all of these + keys directly and may require additional processing. All keys are + also made available in JWK format. + +B.1.1. Example RSA Key + + The following key is a 2048-bit RSA public and private key pair, + referred to in this document as test-key-rsa. This key is encoded in + PEM format, with no encryption. + + -----BEGIN RSA PUBLIC KEY----- + MIIBCgKCAQEAhAKYdtoeoy8zcAcR874L8cnZxKzAGwd7v36APp7Pv6Q2jdsPBRrw + WEBnez6d0UDKDwGbc6nxfEXAy5mbhgajzrw3MOEt8uA5txSKobBpKDeBLOsdJKFq + MGmXCQvEG7YemcxDTRPxAleIAgYYRjTSd/QBwVW9OwNFhekro3RtlinV0a75jfZg + kne/YiktSvLG34lw2zqXBDTC5NHROUqGTlML4PlNZS5Ri2U4aCNx2rUPRcKIlE0P + uKxI4T+HIaFpv8+rdV6eUgOrB2xeI1dSFFn/nnv5OoZJEIB+VmuKn3DCUcCZSFlQ + PSXSfBDiUGhwOw76WuSSsf1D4b/vLoJ10wIDAQAB + -----END RSA PUBLIC KEY----- + + -----BEGIN RSA PRIVATE KEY----- + MIIEqAIBAAKCAQEAhAKYdtoeoy8zcAcR874L8cnZxKzAGwd7v36APp7Pv6Q2jdsP + BRrwWEBnez6d0UDKDwGbc6nxfEXAy5mbhgajzrw3MOEt8uA5txSKobBpKDeBLOsd + JKFqMGmXCQvEG7YemcxDTRPxAleIAgYYRjTSd/QBwVW9OwNFhekro3RtlinV0a75 + jfZgkne/YiktSvLG34lw2zqXBDTC5NHROUqGTlML4PlNZS5Ri2U4aCNx2rUPRcKI + lE0PuKxI4T+HIaFpv8+rdV6eUgOrB2xeI1dSFFn/nnv5OoZJEIB+VmuKn3DCUcCZ + SFlQPSXSfBDiUGhwOw76WuSSsf1D4b/vLoJ10wIDAQABAoIBAG/JZuSWdoVHbi56 + vjgCgkjg3lkO1KrO3nrdm6nrgA9P9qaPjxuKoWaKO1cBQlE1pSWp/cKncYgD5WxE + CpAnRUXG2pG4zdkzCYzAh1i+c34L6oZoHsirK6oNcEnHveydfzJL5934egm6p8DW + +m1RQ70yUt4uRc0YSor+q1LGJvGQHReF0WmJBZHrhz5e63Pq7lE0gIwuBqL8SMaA + yRXtK+JGxZpImTq+NHvEWWCu09SCq0r838ceQI55SvzmTkwqtC+8AT2zFviMZkKR + Qo6SPsrqItxZWRty2izawTF0Bf5S2VAx7O+6t3wBsQ1sLptoSgX3QblELY5asI0J + YFz7LJECgYkAsqeUJmqXE3LP8tYoIjMIAKiTm9o6psPlc8CrLI9CH0UbuaA2JCOM + cCNq8SyYbTqgnWlB9ZfcAm/cFpA8tYci9m5vYK8HNxQr+8FS3Qo8N9RJ8d0U5Csw + DzMYfRghAfUGwmlWj5hp1pQzAuhwbOXFtxKHVsMPhz1IBtF9Y8jvgqgYHLbmyiu1 + mwJ5AL0pYF0G7x81prlARURwHo0Yf52kEw1dxpx+JXER7hQRWQki5/NsUEtv+8RT + qn2m6qte5DXLyn83b1qRscSdnCCwKtKWUug5q2ZbwVOCJCtmRwmnP131lWRYfj67 + B/xJ1ZA6X3GEf4sNReNAtaucPEelgR2nsN0gKQKBiGoqHWbK1qYvBxX2X3kbPDkv + 9C+celgZd2PW7aGYLCHq7nPbmfDV0yHcWjOhXZ8jRMjmANVR/eLQ2EfsRLdW69bn + f3ZD7JS1fwGnO3exGmHO3HZG+6AvberKYVYNHahNFEw5TsAcQWDLRpkGybBcxqZo + 81YCqlqidwfeO5YtlO7etx1xLyqa2NsCeG9A86UjG+aeNnXEIDk1PDK+EuiThIUa + /2IxKzJKWl1BKr2d4xAfR0ZnEYuRrbeDQYgTImOlfW6/GuYIxKYgEKCFHFqJATAG + IxHrq1PDOiSwXd2GmVVYyEmhZnbcp8CxaEMQoevxAta0ssMK3w6UsDtvUvYvF22m + qQKBiD5GwESzsFPy3Ga0MvZpn3D6EJQLgsnrtUPZx+z2Ep2x0xc5orneB5fGyF1P + WtP+fG5Q6Dpdz3LRfm+KwBCWFKQjg7uTxcjerhBWEYPmEMKYwTJF5PBG9/ddvHLQ + EQeNC8fHGg4UXU8mhHnSBt3EA10qQJfRDs15M38eG2cYwB1PZpDHScDnDA0= + -----END RSA PRIVATE KEY----- + + The same public and private key pair in JWK format: + + NOTE: '\' line wrapping per RFC 8792 + + { + "kty": "RSA", + "kid": "test-key-rsa", + "p": "sqeUJmqXE3LP8tYoIjMIAKiTm9o6psPlc8CrLI9CH0UbuaA2JCOMcCNq8Sy\ + YbTqgnWlB9ZfcAm_cFpA8tYci9m5vYK8HNxQr-8FS3Qo8N9RJ8d0U5CswDzMYfRgh\ + AfUGwmlWj5hp1pQzAuhwbOXFtxKHVsMPhz1IBtF9Y8jvgqgYHLbmyiu1mw", + "q": "vSlgXQbvHzWmuUBFRHAejRh_naQTDV3GnH4lcRHuFBFZCSLn82xQS2_7xFO\ + qfabqq17kNcvKfzdvWpGxxJ2cILAq0pZS6DmrZlvBU4IkK2ZHCac_XfWVZFh-PrsH\ + _EnVkDpfcYR_iw1F40C1q5w8R6WBHaew3SAp", + "d": "b8lm5JZ2hUduLnq-OAKCSODeWQ7Uqs7eet2bqeuAD0_2po-PG4qhZoo7VwF\ + CUTWlJan9wqdxiAPlbEQKkCdFRcbakbjN2TMJjMCHWL5zfgvqhmgeyKsrqg1wSce9\ + 7J1_Mkvn3fh6CbqnwNb6bVFDvTJS3i5FzRhKiv6rUsYm8ZAdF4XRaYkFkeuHPl7rc\ + -ruUTSAjC4GovxIxoDJFe0r4kbFmkiZOr40e8RZYK7T1IKrSvzfxx5AjnlK_OZOTC\ + q0L7wBPbMW-IxmQpFCjpI-yuoi3FlZG3LaLNrBMXQF_lLZUDHs77q3fAGxDWwum2h\ + KBfdBuUQtjlqwjQlgXPsskQ", + "e": "AQAB", + "qi": "PkbARLOwU_LcZrQy9mmfcPoQlAuCyeu1Q9nH7PYSnbHTFzmiud4Hl8bIXU\ + 9a0_58blDoOl3PctF-b4rAEJYUpCODu5PFyN6uEFYRg-YQwpjBMkXk8Eb39128ctA\ + RB40Lx8caDhRdTyaEedIG3cQDXSpAl9EOzXkzfx4bZxjAHU9mkMdJwOcMDQ", + "dp": "aiodZsrWpi8HFfZfeRs8OS_0L5x6WBl3Y9btoZgsIeruc9uZ8NXTIdxaM6\ + FdnyNEyOYA1VH94tDYR-xEt1br1ud_dkPslLV_Aac7d7EaYc7cdkb7oC9t6sphVg0\ + dqE0UTDlOwBxBYMtGmQbJsFzGpmjzVgKqWqJ3B947li2U7t63HXEvKprY2w", + "dq": "b0DzpSMb5p42dcQgOTU8Mr4S6JOEhRr_YjErMkpaXUEqvZ3jEB9HRmcRi5\ + Gtt4NBiBMiY6V9br8a5gjEpiAQoIUcWokBMAYjEeurU8M6JLBd3YaZVVjISaFmdty\ + nwLFoQxCh6_EC1rSywwrfDpSwO29S9i8Xbaap", + "n": "hAKYdtoeoy8zcAcR874L8cnZxKzAGwd7v36APp7Pv6Q2jdsPBRrwWEBnez6\ + d0UDKDwGbc6nxfEXAy5mbhgajzrw3MOEt8uA5txSKobBpKDeBLOsdJKFqMGmXCQvE\ + G7YemcxDTRPxAleIAgYYRjTSd_QBwVW9OwNFhekro3RtlinV0a75jfZgkne_YiktS\ + vLG34lw2zqXBDTC5NHROUqGTlML4PlNZS5Ri2U4aCNx2rUPRcKIlE0PuKxI4T-HIa\ + Fpv8-rdV6eUgOrB2xeI1dSFFn_nnv5OoZJEIB-VmuKn3DCUcCZSFlQPSXSfBDiUGh\ + wOw76WuSSsf1D4b_vLoJ10w" + } + +B.1.2. Example RSA-PSS Key + + The following key is a 2048-bit RSA public and private key pair, + referred to in this document as test-key-rsa-pss. This key is PKCS + #8 encoded in PEM format, with no encryption. + + -----BEGIN PUBLIC KEY----- + MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr4tmm3r20Wd/PbqvP1s2 + +QEtvpuRaV8Yq40gjUR8y2Rjxa6dpG2GXHbPfvMs8ct+Lh1GH45x28Rw3Ry53mm+ + oAXjyQ86OnDkZ5N8lYbggD4O3w6M6pAvLkhk95AndTrifbIFPNU8PPMO7OyrFAHq + gDsznjPFmTOtCEcN2Z1FpWgchwuYLPL+Wokqltd11nqqzi+bJ9cvSKADYdUAAN5W + Utzdpiy6LbTgSxP7ociU4Tn0g5I6aDZJ7A8Lzo0KSyZYoA485mqcO0GVAdVw9lq4 + aOT9v6d+nb4bnNkQVklLQ3fVAvJm+xdDOp9LCNCN48V2pnDOkFV6+U9nV5oyc6XI + 2wIDAQAB + -----END PUBLIC KEY----- + + -----BEGIN PRIVATE KEY----- + MIIEvgIBADALBgkqhkiG9w0BAQoEggSqMIIEpgIBAAKCAQEAr4tmm3r20Wd/Pbqv + P1s2+QEtvpuRaV8Yq40gjUR8y2Rjxa6dpG2GXHbPfvMs8ct+Lh1GH45x28Rw3Ry5 + 3mm+oAXjyQ86OnDkZ5N8lYbggD4O3w6M6pAvLkhk95AndTrifbIFPNU8PPMO7Oyr + FAHqgDsznjPFmTOtCEcN2Z1FpWgchwuYLPL+Wokqltd11nqqzi+bJ9cvSKADYdUA + AN5WUtzdpiy6LbTgSxP7ociU4Tn0g5I6aDZJ7A8Lzo0KSyZYoA485mqcO0GVAdVw + 9lq4aOT9v6d+nb4bnNkQVklLQ3fVAvJm+xdDOp9LCNCN48V2pnDOkFV6+U9nV5oy + c6XI2wIDAQABAoIBAQCUB8ip+kJiiZVKF8AqfB/aUP0jTAqOQewK1kKJ/iQCXBCq + pbo360gvdt05H5VZ/RDVkEgO2k73VSsbulqezKs8RFs2tEmU+JgTI9MeQJPWcP6X + aKy6LIYs0E2cWgp8GADgoBs8llBq0UhX0KffglIeek3n7Z6Gt4YFge2TAcW2WbN4 + XfK7lupFyo6HHyWRiYHMMARQXLJeOSdTn5aMBP0PO4bQyk5ORxTUSeOciPJUFktQ + HkvGbym7KryEfwH8Tks0L7WhzyP60PL3xS9FNOJi9m+zztwYIXGDQuKM2GDsITeD + 2mI2oHoPMyAD0wdI7BwSVW18p1h+jgfc4dlexKYRAoGBAOVfuiEiOchGghV5vn5N + RDNscAFnpHj1QgMr6/UG05RTgmcLfVsI1I4bSkbrIuVKviGGf7atlkROALOG/xRx + DLadgBEeNyHL5lz6ihQaFJLVQ0u3U4SB67J0YtVO3R6lXcIjBDHuY8SjYJ7Ci6Z6 + vuDcoaEujnlrtUhaMxvSfcUJAoGBAMPsCHXte1uWNAqYad2WdLjPDlKtQJK1diCm + rqmB2g8QE99hDOHItjDBEdpyFBKOIP+NpVtM2KLhRajjcL9Ph8jrID6XUqikQuVi + 4J9FV2m42jXMuioTT13idAILanYg8D3idvy/3isDVkON0X3UAVKrgMEne0hJpkPL + FYqgetvDAoGBAKLQ6JZMbSe0pPIJkSamQhsehgL5Rs51iX4m1z7+sYFAJfhvN3Q/ + OGIHDRp6HjMUcxHpHw7U+S1TETxePwKLnLKj6hw8jnX2/nZRgWHzgVcY+sPsReRx + NJVf+Cfh6yOtznfX00p+JWOXdSY8glSSHJwRAMog+hFGW1AYdt7w80XBAoGBAImR + NUugqapgaEA8TrFxkJmngXYaAqpA0iYRA7kv3S4QavPBUGtFJHBNULzitydkNtVZ + 3w6hgce0h9YThTo/nKc+OZDZbgfN9s7cQ75x0PQCAO4fx2P91Q+mDzDUVTeG30mE + t2m3S0dGe47JiJxifV9P3wNBNrZGSIF3mrORBVNDAoGBAI0QKn2Iv7Sgo4T/XjND + dl2kZTXqGAk8dOhpUiw/HdM3OGWbhHj2NdCzBliOmPyQtAr770GITWvbAI+IRYyF + S7Fnk6ZVVVHsxjtaHy1uJGFlaZzKR4AGNaUTOJMs6NadzCmGPAxNQQOCqoUjn4XR + rOjr9w349JooGXhOxbu8nOxX + -----END PRIVATE KEY----- + + The same public and private key pair in JWK format: + + NOTE: '\' line wrapping per RFC 8792 + + { + "kty": "RSA", + "kid": "test-key-rsa-pss", + "p": "5V-6ISI5yEaCFXm-fk1EM2xwAWekePVCAyvr9QbTlFOCZwt9WwjUjhtKRus\ + i5Uq-IYZ_tq2WRE4As4b_FHEMtp2AER43IcvmXPqKFBoUktVDS7dThIHrsnRi1U7d\ + HqVdwiMEMe5jxKNgnsKLpnq-4NyhoS6OeWu1SFozG9J9xQk", + "q": "w-wIde17W5Y0Cphp3ZZ0uM8OUq1AkrV2IKauqYHaDxAT32EM4ci2MMER2nI\ + UEo4g_42lW0zYouFFqONwv0-HyOsgPpdSqKRC5WLgn0VXabjaNcy6KhNPXeJ0Agtq\ + diDwPeJ2_L_eKwNWQ43RfdQBUquAwSd7SEmmQ8sViqB628M", + "d": "lAfIqfpCYomVShfAKnwf2lD9I0wKjkHsCtZCif4kAlwQqqW6N-tIL3bdOR-\ + VWf0Q1ZBIDtpO91UrG7pansyrPERbNrRJlPiYEyPTHkCT1nD-l2isuiyGLNBNnFoK\ + fBgA4KAbPJZQatFIV9Cn34JSHnpN5-2ehreGBYHtkwHFtlmzeF3yu5bqRcqOhx8lk\ + YmBzDAEUFyyXjknU5-WjAT9DzuG0MpOTkcU1EnjnIjyVBZLUB5Lxm8puyq8hH8B_E\ + 5LNC-1oc8j-tDy98UvRTTiYvZvs87cGCFxg0LijNhg7CE3g9piNqB6DzMgA9MHSOw\ + cElVtfKdYfo4H3OHZXsSmEQ", + "e": "AQAB", + "qi": "jRAqfYi_tKCjhP9eM0N2XaRlNeoYCTx06GlSLD8d0zc4ZZuEePY10LMGWI\ + 6Y_JC0CvvvQYhNa9sAj4hFjIVLsWeTplVVUezGO1ofLW4kYWVpnMpHgAY1pRM4kyz\ + o1p3MKYY8DE1BA4KqhSOfhdGs6Ov3Dfj0migZeE7Fu7yc7Fc", + "dp": "otDolkxtJ7Sk8gmRJqZCGx6GAvlGznWJfibXPv6xgUAl-G83dD84YgcNGn\ + oeMxRzEekfDtT5LVMRPF4_AoucsqPqHDyOdfb-dlGBYfOBVxj6w-xF5HE0lV_4J-H\ + rI63Od9fTSn4lY5d1JjyCVJIcnBEAyiD6EUZbUBh23vDzRcE", + "dq": "iZE1S6CpqmBoQDxOsXGQmaeBdhoCqkDSJhEDuS_dLhBq88FQa0UkcE1QvO\ + K3J2Q21VnfDqGBx7SH1hOFOj-cpz45kNluB832ztxDvnHQ9AIA7h_HY_3VD6YPMNR\ + VN4bfSYS3abdLR0Z7jsmInGJ9X0_fA0E2tkZIgXeas5EFU0M", + "n": "r4tmm3r20Wd_PbqvP1s2-QEtvpuRaV8Yq40gjUR8y2Rjxa6dpG2GXHbPfvM\ + s8ct-Lh1GH45x28Rw3Ry53mm-oAXjyQ86OnDkZ5N8lYbggD4O3w6M6pAvLkhk95An\ + dTrifbIFPNU8PPMO7OyrFAHqgDsznjPFmTOtCEcN2Z1FpWgchwuYLPL-Wokqltd11\ + nqqzi-bJ9cvSKADYdUAAN5WUtzdpiy6LbTgSxP7ociU4Tn0g5I6aDZJ7A8Lzo0KSy\ + ZYoA485mqcO0GVAdVw9lq4aOT9v6d-nb4bnNkQVklLQ3fVAvJm-xdDOp9LCNCN48V\ + 2pnDOkFV6-U9nV5oyc6XI2w" + } + +B.1.3. Example ECC P-256 Test Key + + The following key is a public and private elliptical curve key pair + over the curve P-256, referred to in this document as test-key-ecc- + p256. This key is encoded in PEM format, with no encryption. + + -----BEGIN PUBLIC KEY----- + MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEqIVYZVLCrPZHGHjP17CTW0/+D9Lf + w0EkjqF7xB4FivAxzic30tMM4GF+hR6Dxh71Z50VGGdldkkDXZCnTNnoXQ== + -----END PUBLIC KEY----- + + -----BEGIN EC PRIVATE KEY----- + MHcCAQEEIFKbhfNZfpDsW43+0+JjUr9K+bTeuxopu653+hBaXGA7oAoGCCqGSM49 + AwEHoUQDQgAEqIVYZVLCrPZHGHjP17CTW0/+D9Lfw0EkjqF7xB4FivAxzic30tMM + 4GF+hR6Dxh71Z50VGGdldkkDXZCnTNnoXQ== + -----END EC PRIVATE KEY----- + + The same public and private key pair in JWK format: + + { + "kty": "EC", + "crv": "P-256", + "kid": "test-key-ecc-p256", + "d": "UpuF81l-kOxbjf7T4mNSv0r5tN67Gim7rnf6EFpcYDs", + "x": "qIVYZVLCrPZHGHjP17CTW0_-D9Lfw0EkjqF7xB4FivA", + "y": "Mc4nN9LTDOBhfoUeg8Ye9WedFRhnZXZJA12Qp0zZ6F0" + } + +B.1.4. Example Ed25519 Test Key + + The following key is an elliptical curve key over the Edwards curve + ed25519, referred to in this document as test-key-ed25519. This key + is PKCS #8 encoded in PEM format, with no encryption. + + -----BEGIN PUBLIC KEY----- + MCowBQYDK2VwAyEAJrQLj5P/89iXES9+vFgrIy29clF9CC/oPPsw3c5D0bs= + -----END PUBLIC KEY----- + + -----BEGIN PRIVATE KEY----- + MC4CAQAwBQYDK2VwBCIEIJ+DYvh6SEqVTm50DFtMDoQikTmiCqirVv9mWG9qfSnF + -----END PRIVATE KEY----- + + The same public and private key pair in JWK format: + + { + "kty": "OKP", + "crv": "Ed25519", + "kid": "test-key-ed25519", + "d": "n4Ni-HpISpVObnQMW0wOhCKROaIKqKtW_2ZYb2p9KcU", + "x": "JrQLj5P_89iXES9-vFgrIy29clF9CC_oPPsw3c5D0bs" + } + +B.1.5. Example Shared Secret + + The following shared secret is 64 randomly generated bytes encoded in + Base64, referred to in this document as test-shared-secret: + + NOTE: '\' line wrapping per RFC 8792 + + uzvJfB4u3N0Jy4T7NZ75MDVcr8zSTInedJtkgcu46YW4XByzNJjxBdtjUkdJPBt\ + bmHhIDi6pcl8jsasjlTMtDQ== + +B.2. Test Cases + + This section provides non-normative examples that may be used as test + cases to validate implementation correctness. These examples are + based on the following HTTP messages: + + For requests, this test-request message is used: + + NOTE: '\' line wrapping per RFC 8792 + + POST /foo?param=Value&Pet=dog HTTP/1.1 + Host: example.com + Date: Tue, 20 Apr 2021 02:07:55 GMT + Content-Type: application/json + Content-Digest: sha-512=:WZDPaVn/7XgHaAy8pmojAkGWoRx2UFChF41A2svX+T\ + aPm+AbwAgBWnrIiYllu7BNNyealdVLvRwEmTHWXvJwew==: + Content-Length: 18 + + {"hello": "world"} + + For responses, this test-response message is used: + + NOTE: '\' line wrapping per RFC 8792 + + HTTP/1.1 200 OK + Date: Tue, 20 Apr 2021 02:07:56 GMT + Content-Type: application/json + Content-Digest: sha-512=:mEWXIS7MaLRuGgxOBdODa3xqM1XdEvxoYhvlCFJ41Q\ + JgJc4GTsPp29l5oGX69wWdXymyU0rjJuahq4l5aGgfLQ==: + Content-Length: 23 + + {"message": "good dog"} + +B.2.1. Minimal Signature Using rsa-pss-sha512 + + This example presents a minimal signature using the rsa-pss-sha512 + algorithm over test-request, covering none of the components of the + HTTP message but providing a timestamped signature proof of + possession of the key with a signer-provided nonce. + + The corresponding signature base is: + + NOTE: '\' line wrapping per RFC 8792 + + "@signature-params": ();created=1618884473;keyid="test-key-rsa-pss"\ + ;nonce="b3k2pp5k7z-50gnwp.yemd" + + This results in the following Signature-Input and Signature header + fields being added to the message under the signature label sig-b21: + + NOTE: '\' line wrapping per RFC 8792 + + Signature-Input: sig-b21=();created=1618884473\ + ;keyid="test-key-rsa-pss";nonce="b3k2pp5k7z-50gnwp.yemd" + Signature: sig-b21=:d2pmTvmbncD3xQm8E9ZV2828BjQWGgiwAaw5bAkgibUopem\ + LJcWDy/lkbbHAve4cRAtx31Iq786U7it++wgGxbtRxf8Udx7zFZsckzXaJMkA7ChG\ + 52eSkFxykJeNqsrWH5S+oxNFlD4dzVuwe8DhTSja8xxbR/Z2cOGdCbzR72rgFWhzx\ + 2VjBqJzsPLMIQKhO4DGezXehhWwE56YCE+O6c0mKZsfxVrogUvA4HELjVKWmAvtl6\ + UnCh8jYzuVG5WSb/QEVPnP5TmcAnLH1g+s++v6d4s8m0gCw1fV5/SITLq9mhho8K3\ + +7EPYTU8IU1bLhdxO5Nyt8C8ssinQ98Xw9Q==: + + Note that since the covered components list is empty, this signature + could be applied by an attacker to an unrelated HTTP message. In + this example, the nonce parameter is included to prevent the same + signature from being replayed more than once, but if an attacker + intercepts the signature and prevents its delivery to the verifier, + the attacker could apply this signature to another message. + Therefore, the use of an empty covered components set is discouraged. + See Section 7.2.1 for more discussion. + + Note that the RSA-PSS algorithm in use here is non-deterministic, + meaning that a different signature value will be created every time + the algorithm is run. The signature value provided here can be + validated against the given keys, but newly generated signature + values are not expected to match the example. See Section 7.3.5. + +B.2.2. Selective Covered Components Using rsa-pss-sha512 + + This example covers additional components (the authority, the + Content-Digest header field, and a single named query parameter) in + test-request using the rsa-pss-sha512 algorithm. This example also + adds a tag parameter with the application-specific value of header- + example. + + The corresponding signature base is: + + NOTE: '\' line wrapping per RFC 8792 + + "@authority": example.com + "content-digest": sha-512=:WZDPaVn/7XgHaAy8pmojAkGWoRx2UFChF41A2svX\ + +TaPm+AbwAgBWnrIiYllu7BNNyealdVLvRwEmTHWXvJwew==: + "@query-param";name="Pet": dog + "@signature-params": ("@authority" "content-digest" \ + "@query-param";name="Pet")\ + ;created=1618884473;keyid="test-key-rsa-pss"\ + ;tag="header-example" + + This results in the following Signature-Input and Signature header + fields being added to the message under the label sig-b22: + + NOTE: '\' line wrapping per RFC 8792 + + Signature-Input: sig-b22=("@authority" "content-digest" \ + "@query-param";name="Pet");created=1618884473\ + ;keyid="test-key-rsa-pss";tag="header-example" + Signature: sig-b22=:LjbtqUbfmvjj5C5kr1Ugj4PmLYvx9wVjZvD9GsTT4F7GrcQ\ + EdJzgI9qHxICagShLRiLMlAJjtq6N4CDfKtjvuJyE5qH7KT8UCMkSowOB4+ECxCmT\ + 8rtAmj/0PIXxi0A0nxKyB09RNrCQibbUjsLS/2YyFYXEu4TRJQzRw1rLEuEfY17SA\ + RYhpTlaqwZVtR8NV7+4UKkjqpcAoFqWFQh62s7Cl+H2fjBSpqfZUJcsIk4N6wiKYd\ + 4je2U/lankenQ99PZfB4jY3I5rSV2DSBVkSFsURIjYErOs0tFTQosMTAoxk//0RoK\ + UqiYY8Bh0aaUEb0rQl3/XaVe4bXTugEjHSw==: + + Note that the RSA-PSS algorithm in use here is non-deterministic, + meaning that a different signature value will be created every time + the algorithm is run. The signature value provided here can be + validated against the given keys, but newly generated signature + values are not expected to match the example. See Section 7.3.5. + +B.2.3. Full Coverage Using rsa-pss-sha512 + + This example covers all applicable message components in test-request + (including the content type and length) plus many derived components, + again using the rsa-pss-sha512 algorithm. Note that the Host header + field is not covered because the @authority derived component is + included instead. + + The corresponding signature base is: + + NOTE: '\' line wrapping per RFC 8792 + + "date": Tue, 20 Apr 2021 02:07:55 GMT + "@method": POST + "@path": /foo + "@query": ?param=Value&Pet=dog + "@authority": example.com + "content-type": application/json + "content-digest": sha-512=:WZDPaVn/7XgHaAy8pmojAkGWoRx2UFChF41A2svX\ + +TaPm+AbwAgBWnrIiYllu7BNNyealdVLvRwEmTHWXvJwew==: + "content-length": 18 + "@signature-params": ("date" "@method" "@path" "@query" \ + "@authority" "content-type" "content-digest" "content-length")\ + ;created=1618884473;keyid="test-key-rsa-pss" + + This results in the following Signature-Input and Signature header + fields being added to the message under the label sig-b23: + + NOTE: '\' line wrapping per RFC 8792 + + Signature-Input: sig-b23=("date" "@method" "@path" "@query" \ + "@authority" "content-type" "content-digest" "content-length")\ + ;created=1618884473;keyid="test-key-rsa-pss" + Signature: sig-b23=:bbN8oArOxYoyylQQUU6QYwrTuaxLwjAC9fbY2F6SVWvh0yB\ + iMIRGOnMYwZ/5MR6fb0Kh1rIRASVxFkeGt683+qRpRRU5p2voTp768ZrCUb38K0fU\ + xN0O0iC59DzYx8DFll5GmydPxSmme9v6ULbMFkl+V5B1TP/yPViV7KsLNmvKiLJH1\ + pFkh/aYA2HXXZzNBXmIkoQoLd7YfW91kE9o/CCoC1xMy7JA1ipwvKvfrs65ldmlu9\ + bpG6A9BmzhuzF8Eim5f8ui9eH8LZH896+QIF61ka39VBrohr9iyMUJpvRX2Zbhl5Z\ + JzSRxpJyoEZAFL2FUo5fTIztsDZKEgM4cUA==: + + Note in this example that the value of the Date header field and the + value of the created signature parameter need not be the same. This + is due to the fact that the Date header field is added when creating + the HTTP message and the created parameter is populated when creating + the signature over that message, and these two times could vary. If + the Date header field is covered by the signature, it is up to the + verifier to determine whether its value has to match that of the + created parameter or not. See Section 7.2.4 for more discussion. + + Note that the RSA-PSS algorithm in use here is non-deterministic, + meaning that a different signature value will be created every time + the algorithm is run. The signature value provided here can be + validated against the given keys, but newly generated signature + values are not expected to match the example. See Section 7.3.5. + +B.2.4. Signing a Response Using ecdsa-p256-sha256 + + This example covers portions of the test-response message using the + ecdsa-p256-sha256 algorithm and the key test-key-ecc-p256. + + The corresponding signature base is: + + NOTE: '\' line wrapping per RFC 8792 + + "@status": 200 + "content-type": application/json + "content-digest": sha-512=:mEWXIS7MaLRuGgxOBdODa3xqM1XdEvxoYhvlCFJ4\ + 1QJgJc4GTsPp29l5oGX69wWdXymyU0rjJuahq4l5aGgfLQ==: + "content-length": 23 + "@signature-params": ("@status" "content-type" "content-digest" \ + "content-length");created=1618884473;keyid="test-key-ecc-p256" + + This results in the following Signature-Input and Signature header + fields being added to the message under the label sig-b24: + + NOTE: '\' line wrapping per RFC 8792 + + Signature-Input: sig-b24=("@status" "content-type" \ + "content-digest" "content-length");created=1618884473\ + ;keyid="test-key-ecc-p256" + Signature: sig-b24=:wNmSUAhwb5LxtOtOpNa6W5xj067m5hFrj0XQ4fvpaCLx0NK\ + ocgPquLgyahnzDnDAUy5eCdlYUEkLIj+32oiasw==: + + Note that the ECDSA signature algorithm in use here is non- + deterministic, meaning that a different signature value will be + created every time the algorithm is run. The signature value + provided here can be validated against the given keys, but newly + generated signature values are not expected to match the example. + See Section 7.3.5. + +B.2.5. Signing a Request Using hmac-sha256 + + This example covers portions of the test-request message using the + hmac-sha256 algorithm and the secret test-shared-secret. + + The corresponding signature base is: + + NOTE: '\' line wrapping per RFC 8792 + + "date": Tue, 20 Apr 2021 02:07:55 GMT + "@authority": example.com + "content-type": application/json + "@signature-params": ("date" "@authority" "content-type")\ + ;created=1618884473;keyid="test-shared-secret" + + This results in the following Signature-Input and Signature header + fields being added to the message under the label sig-b25: + + NOTE: '\' line wrapping per RFC 8792 + + Signature-Input: sig-b25=("date" "@authority" "content-type")\ + ;created=1618884473;keyid="test-shared-secret" + Signature: sig-b25=:pxcQw6G3AjtMBQjwo8XzkZf/bws5LelbaMk5rGIGtE8=: + + Before using symmetric signatures in practice, see the discussion + regarding security trade-offs in Section 7.3.3. + +B.2.6. Signing a Request Using ed25519 + + This example covers portions of the test-request message using the + Ed25519 algorithm and the key test-key-ed25519. + + The corresponding signature base is: + + NOTE: '\' line wrapping per RFC 8792 + + "date": Tue, 20 Apr 2021 02:07:55 GMT + "@method": POST + "@path": /foo + "@authority": example.com + "content-type": application/json + "content-length": 18 + "@signature-params": ("date" "@method" "@path" "@authority" \ + "content-type" "content-length");created=1618884473\ + ;keyid="test-key-ed25519" + + This results in the following Signature-Input and Signature header + fields being added to the message under the label sig-b26: + + NOTE: '\' line wrapping per RFC 8792 + + Signature-Input: sig-b26=("date" "@method" "@path" "@authority" \ + "content-type" "content-length");created=1618884473\ + ;keyid="test-key-ed25519" + Signature: sig-b26=:wqcAqbmYJ2ji2glfAMaRy4gruYYnx2nEFN2HN6jrnDnQCK1\ + u02Gb04v9EDgwUPiu4A0w6vuQv5lIp5WPpBKRCw==: + +B.3. TLS-Terminating Proxies + + In this example, there is a TLS-terminating reverse proxy sitting in + front of the resource. The client does not sign the request but + instead uses mutual TLS to make its call. The terminating proxy + validates the TLS stream and injects a Client-Cert header field + according to [CLIENT-CERT], and then applies a signature to this + field. By signing this header field, a reverse proxy not only can + attest to its own validation of the initial request's TLS parameters + but can also authenticate itself to the backend system independently + of the client's actions. + + The client makes the following request to the TLS-terminating proxy + using mutual TLS: + + POST /foo?param=Value&Pet=dog HTTP/1.1 + Host: example.com + Date: Tue, 20 Apr 2021 02:07:55 GMT + Content-Type: application/json + Content-Length: 18 + + {"hello": "world"} + + The proxy processes the TLS connection and extracts the client's TLS + certificate to a Client-Cert header field and passes it along to the + internal service hosted at service.internal.example. This results in + the following unsigned request: + + NOTE: '\' line wrapping per RFC 8792 + + POST /foo?param=Value&Pet=dog HTTP/1.1 + Host: service.internal.example + Date: Tue, 20 Apr 2021 02:07:55 GMT + Content-Type: application/json + Content-Length: 18 + Client-Cert: :MIIBqDCCAU6gAwIBAgIBBzAKBggqhkjOPQQDAjA6MRswGQYDVQQKD\ + BJMZXQncyBBdXRoZW50aWNhdGUxGzAZBgNVBAMMEkxBIEludGVybWVkaWF0ZSBDQT\ + AeFw0yMDAxMTQyMjU1MzNaFw0yMTAxMjMyMjU1MzNaMA0xCzAJBgNVBAMMAkJDMFk\ + wEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE8YnXXfaUgmnMtOXU/IncWalRhebrXmck\ + C8vdgJ1p5Be5F/3YC8OthxM4+k1M6aEAEFcGzkJiNy6J84y7uzo9M6NyMHAwCQYDV\ + R0TBAIwADAfBgNVHSMEGDAWgBRm3WjLa38lbEYCuiCPct0ZaSED2DAOBgNVHQ8BAf\ + 8EBAMCBsAwEwYDVR0lBAwwCgYIKwYBBQUHAwIwHQYDVR0RAQH/BBMwEYEPYmRjQGV\ + 4YW1wbGUuY29tMAoGCCqGSM49BAMCA0gAMEUCIBHda/r1vaL6G3VliL4/Di6YK0Q6\ + bMjeSkC3dFCOOB8TAiEAx/kHSB4urmiZ0NX5r5XarmPk0wmuydBVoU4hBVZ1yhk=: + + {"hello": "world"} + + Without a signature, the internal service would need to trust that + the incoming connection has the right information. By signing the + Client-Cert header field and other portions of the internal request, + the internal service can be assured that the correct party, the + trusted proxy, has processed the request and presented it to the + correct service. The proxy's signature base consists of the + following: + + NOTE: '\' line wrapping per RFC 8792 + + "@path": /foo + "@query": ?param=Value&Pet=dog + "@method": POST + "@authority": service.internal.example + "client-cert": :MIIBqDCCAU6gAwIBAgIBBzAKBggqhkjOPQQDAjA6MRswGQYDVQQ\ + KDBJMZXQncyBBdXRoZW50aWNhdGUxGzAZBgNVBAMMEkxBIEludGVybWVkaWF0ZSBD\ + QTAeFw0yMDAxMTQyMjU1MzNaFw0yMTAxMjMyMjU1MzNaMA0xCzAJBgNVBAMMAkJDM\ + FkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE8YnXXfaUgmnMtOXU/IncWalRhebrXm\ + ckC8vdgJ1p5Be5F/3YC8OthxM4+k1M6aEAEFcGzkJiNy6J84y7uzo9M6NyMHAwCQY\ + DVR0TBAIwADAfBgNVHSMEGDAWgBRm3WjLa38lbEYCuiCPct0ZaSED2DAOBgNVHQ8B\ + Af8EBAMCBsAwEwYDVR0lBAwwCgYIKwYBBQUHAwIwHQYDVR0RAQH/BBMwEYEPYmRjQ\ + GV4YW1wbGUuY29tMAoGCCqGSM49BAMCA0gAMEUCIBHda/r1vaL6G3VliL4/Di6YK0\ + Q6bMjeSkC3dFCOOB8TAiEAx/kHSB4urmiZ0NX5r5XarmPk0wmuydBVoU4hBVZ1yhk=: + "@signature-params": ("@path" "@query" "@method" "@authority" \ + "client-cert");created=1618884473;keyid="test-key-ecc-p256" + + This results in the following signature: + + NOTE: '\' line wrapping per RFC 8792 + + xVMHVpawaAC/0SbHrKRs9i8I3eOs5RtTMGCWXm/9nvZzoHsIg6Mce9315T6xoklyy0y\ + zhD9ah4JHRwMLOgmizw== + + which results in the following signed request sent from the proxy to + the internal service with the proxy's signature under the label ttrp: + + NOTE: '\' line wrapping per RFC 8792 + + POST /foo?param=Value&Pet=dog HTTP/1.1 + Host: service.internal.example + Date: Tue, 20 Apr 2021 02:07:55 GMT + Content-Type: application/json + Content-Length: 18 + Client-Cert: :MIIBqDCCAU6gAwIBAgIBBzAKBggqhkjOPQQDAjA6MRswGQYDVQQKD\ + BJMZXQncyBBdXRoZW50aWNhdGUxGzAZBgNVBAMMEkxBIEludGVybWVkaWF0ZSBDQT\ + AeFw0yMDAxMTQyMjU1MzNaFw0yMTAxMjMyMjU1MzNaMA0xCzAJBgNVBAMMAkJDMFk\ + wEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE8YnXXfaUgmnMtOXU/IncWalRhebrXmck\ + C8vdgJ1p5Be5F/3YC8OthxM4+k1M6aEAEFcGzkJiNy6J84y7uzo9M6NyMHAwCQYDV\ + R0TBAIwADAfBgNVHSMEGDAWgBRm3WjLa38lbEYCuiCPct0ZaSED2DAOBgNVHQ8BAf\ + 8EBAMCBsAwEwYDVR0lBAwwCgYIKwYBBQUHAwIwHQYDVR0RAQH/BBMwEYEPYmRjQGV\ + 4YW1wbGUuY29tMAoGCCqGSM49BAMCA0gAMEUCIBHda/r1vaL6G3VliL4/Di6YK0Q6\ + bMjeSkC3dFCOOB8TAiEAx/kHSB4urmiZ0NX5r5XarmPk0wmuydBVoU4hBVZ1yhk=: + Signature-Input: ttrp=("@path" "@query" "@method" "@authority" \ + "client-cert");created=1618884473;keyid="test-key-ecc-p256" + Signature: ttrp=:xVMHVpawaAC/0SbHrKRs9i8I3eOs5RtTMGCWXm/9nvZzoHsIg6\ + Mce9315T6xoklyy0yzhD9ah4JHRwMLOgmizw==: + + {"hello": "world"} + + The internal service can validate the proxy's signature and therefore + be able to trust that the client's certificate has been appropriately + processed. + +B.4. HTTP Message Transformations + + HTTP allows intermediaries and applications to transform an HTTP + message without affecting the semantics of the message itself. HTTP + message signatures are designed to be robust against many of these + transformations in different circumstances. + + For example, the following HTTP request message has been signed using + the Ed25519 algorithm and the key test-key-ed25519: + + NOTE: '\' line wrapping per RFC 8792 + + GET /demo?name1=Value1&Name2=value2 HTTP/1.1 + Host: example.org + Date: Fri, 15 Jul 2022 14:24:55 GMT + Accept: application/json + Accept: */* + Signature-Input: transform=("@method" "@path" "@authority" \ + "accept");created=1618884473;keyid="test-key-ed25519" + Signature: transform=:ZT1kooQsEHpZ0I1IjCqtQppOmIqlJPeo7DHR3SoMn0s5J\ + Z1eRGS0A+vyYP9t/LXlh5QMFFQ6cpLt2m0pmj3NDA==: + + The signature base string for this message is: + + "@method": GET + "@path": /demo + "@authority": example.org + "accept": application/json, */* + "@signature-params": ("@method" "@path" "@authority" "accept")\ + ;created=1618884473;keyid="test-key-ed25519" + + The following message has been altered by adding the Accept-Language + header field as well as adding a query parameter. However, since + neither the Accept-Language header field nor the query is covered by + the signature, the same signature is still valid: + + NOTE: '\' line wrapping per RFC 8792 + + GET /demo?name1=Value1&Name2=value2¶m=added HTTP/1.1 + Host: example.org + Date: Fri, 15 Jul 2022 14:24:55 GMT + Accept: application/json + Accept: */* + Accept-Language: en-US,en;q=0.5 + Signature-Input: transform=("@method" "@path" "@authority" \ + "accept");created=1618884473;keyid="test-key-ed25519" + Signature: transform=:ZT1kooQsEHpZ0I1IjCqtQppOmIqlJPeo7DHR3SoMn0s5J\ + Z1eRGS0A+vyYP9t/LXlh5QMFFQ6cpLt2m0pmj3NDA==: + + The following message has been altered by removing the Date header + field, adding a Referer header field, and collapsing the Accept + header field into a single line. The Date and Referer header fields + are not covered by the signature, and the collapsing of the Accept + header field is an allowed transformation that is already accounted + for by the canonicalization algorithm for HTTP field values. The + same signature is still valid: + + NOTE: '\' line wrapping per RFC 8792 + + GET /demo?name1=Value1&Name2=value2 HTTP/1.1 + Host: example.org + Referer: https://developer.example.org/demo + Accept: application/json, */* + Signature-Input: transform=("@method" "@path" "@authority" \ + "accept");created=1618884473;keyid="test-key-ed25519" + Signature: transform=:ZT1kooQsEHpZ0I1IjCqtQppOmIqlJPeo7DHR3SoMn0s5J\ + Z1eRGS0A+vyYP9t/LXlh5QMFFQ6cpLt2m0pmj3NDA==: + + The following message has been altered by reordering the field values + of the original message but not reordering the individual Accept + header fields. The same signature is still valid: + + NOTE: '\' line wrapping per RFC 8792 + + GET /demo?name1=Value1&Name2=value2 HTTP/1.1 + Accept: application/json + Accept: */* + Date: Fri, 15 Jul 2022 14:24:55 GMT + Host: example.org + Signature-Input: transform=("@method" "@path" "@authority" \ + "accept");created=1618884473;keyid="test-key-ed25519" + Signature: transform=:ZT1kooQsEHpZ0I1IjCqtQppOmIqlJPeo7DHR3SoMn0s5J\ + Z1eRGS0A+vyYP9t/LXlh5QMFFQ6cpLt2m0pmj3NDA==: + + The following message has been altered by changing the method to POST + and the authority to "example.com" (inside the Host header field). + Since both the method and authority are covered by the signature, the + same signature is NOT still valid: + + NOTE: '\' line wrapping per RFC 8792 + + POST /demo?name1=Value1&Name2=value2 HTTP/1.1 + Host: example.com + Date: Fri, 15 Jul 2022 14:24:55 GMT + Accept: application/json + Accept: */* + Signature-Input: transform=("@method" "@path" "@authority" \ + "accept");created=1618884473;keyid="test-key-ed25519" + Signature: transform=:ZT1kooQsEHpZ0I1IjCqtQppOmIqlJPeo7DHR3SoMn0s5J\ + Z1eRGS0A+vyYP9t/LXlh5QMFFQ6cpLt2m0pmj3NDA==: + + The following message has been altered by changing the order of the + two instances of the Accept header field. Since the order of fields + with the same name is semantically significant in HTTP, this changes + the value used in the signature base, and the same signature is NOT + still valid: + + NOTE: '\' line wrapping per RFC 8792 + + GET /demo?name1=Value1&Name2=value2 HTTP/1.1 + Host: example.org + Date: Fri, 15 Jul 2022 14:24:55 GMT + Accept: */* + Accept: application/json + Signature-Input: transform=("@method" "@path" "@authority" \ + "accept");created=1618884473;keyid="test-key-ed25519" + Signature: transform=:ZT1kooQsEHpZ0I1IjCqtQppOmIqlJPeo7DHR3SoMn0s5J\ + Z1eRGS0A+vyYP9t/LXlh5QMFFQ6cpLt2m0pmj3NDA==: + +Acknowledgements + + This specification was initially based on [SIGNING-HTTP-MESSAGES]. + The editors would like to thank the authors of + [SIGNING-HTTP-MESSAGES] -- Mark Cavage and Manu Sporny -- for their + work on that Internet-Draft and their continuing contributions. This + specification also includes contributions from + [SIGNING-HTTP-REQS-OAUTH] and other similar efforts. + + The editors would also like to thank the following individuals + (listed in alphabetical order) for feedback, insight, and + implementation of this document and its predecessors: Mark Adamcin, + Mark Allen, Paul Annesley, Karl Böhlmark, Stéphane Bortzmeyer, Sarven + Capadisli, Liam Dennehy, Stephen Farrell, Phillip Hallam-Baker, Tyler + Ham, Eric Holmes, Andrey Kislyuk, Adam Knight, Dave Lehn, Ilari + Liusvaara, Dave Longley, James H. Manger, Kathleen Moriarty, Yoav + Nir, Mark Nottingham, Adrian Palmer, Lucas Pardue, Roberto Polli, + Julian Reschke, Michael Richardson, Wojciech Rygielski, Rich Salz, + Adam Scarr, Cory J. Slep, Dirk Stein, Henry Story, Lukasz Szewc, + Chris Webber, and Jeffrey Yasskin. + +Authors' Addresses + + Annabelle Backman (editor) + Amazon + P.O. Box 81226 + Seattle, WA 98108-1226 + United States of America + Email: richanna@amazon.com + URI: https://www.amazon.com/ + + + Justin Richer (editor) + Bespoke Engineering + Email: ietf@justin.richer.org + URI: https://bspk.io/ + + + Manu Sporny + Digital Bazaar + 203 Roanoke Street W. + Blacksburg, VA 24060 + United States of America + Email: msporny@digitalbazaar.com |