Skip to main content

HTTP Message Signatures
RFC 9421

Document Type RFC - Proposed Standard (February 2024)
Authors Annabelle Backman , Justin Richer , Manu Sporny
Last updated 2024-02-14
RFC stream Internet Engineering Task Force (IETF)
Formats
Additional resources Mailing list discussion
IESG Responsible AD Paul Wouters
Send notices to (None)
RFC 9421
"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&param=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