When communicating over the Internet using the HTTP protocol, it can be desirable for a server or client to authenticate the sender of a particular message. It can also be desirable to ensure that the message was not tampered with during transit. This document describes a way for servers and clients to simultaneously add authentication and message integrity to HTTP messages by using a digital signature.
This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.
467 |
Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at https://datatracker.ietf.org/drafts/current/.
468 |
Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."
Copyright (c) 2019 IETF Trust and the persons identified as the document authors. All rights reserved.
472 |
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.
This protocol extension is intended to provide a simple and standard way for clients to sign HTTP messages.
563 |
HTTP Authentication defines Basic and Digest authentication mechanisms, TLS 1.2 defines cryptographically strong transport layer security, and OAuth 2.0 provides a fully-specified alternative for authorization of web service requests. Each of these approaches are employed on the Internet today with varying degrees of protection. However, none of these schemes are designed to cryptographically sign the HTTP messages themselves, which is required in order to ensure end-to-end message integrity. An added benefit of signing the HTTP message for the purposes of end-to-end message integrity is that the client can be authenticated using the same mechanism without the need for multiple round-trips.
564 |
Several web service providers have invented their own schemes for signing HTTP messages, but to date, none have been standardized. While there are no techniques in this proposal that are novel beyond the previous art, it is useful to standardize a simple and cryptographically strong mechanism for digitally signing HTTP messages.
565 |
This specification presents two mechanisms with distinct purposes:
566 |
567 |
568 |
The "Signature" scheme which is intended primarily to allow a sender to assert the contents of the message sent are correct and have not been altered during transmission or storage in a way that alters the meaning expressed in the original message as signed. Any party reading the message (the verifier) may independently confirm the validity of the message signature. This scheme is agnostic to the client/server direction and can be used to verify the contents of either HTTP requests, HTTP reponses, or both.
569 |
The "Authorization" scheme which is intended primarily to allow a sender to request access to a resource or resources by proving that they control a secret key. This specification allows for this both with a shared secret (using HMAC) or with public/private keys. The "Authorization" scheme is typically used in authentication processes and not directly for message signing. As a consequence `Authorization` header is normally generated (and the message signed) by the HTTP client and the message verified by the HTTP server.
It is common practice to protect sensitive website and API functionality via authentication mechanisms. Often, the entity accessing these APIs is a piece of automated software outside of an interactive human session. While there are mechanisms like OAuth and API secrets that are used to grant API access, each have their weaknesses such as unnecessary complexity for particular use cases or the use of shared secrets which may not be acceptable to an implementer. Shared secrets also prohibit any possibility for non-repudiation, while secure transports such as TLS do not provide for this at all.
577 |
Digital signatures are widely used to provide authentication and integrity assurances without the need for shared secrets. They also do not require a round-trip in order to authenticate the client, and allow the integrity of a message to be verified independently of the transport (e.g. TLS). A server need only have an understanding of the key (e.g. through a mapping between the key being used to sign the content and the authorized entity) to verify that a message was signed by that entity.
578 |
When optionally combined with asymmetric keys associated with an identity, this specification can also enable authentication of a client and server with or without prior knowledge of each other.
HTTP messages are routinely altered as they traverse the infrastructure of the Internet, for mostly benign reasons. Gateways and proxies add, remove and alter headers for operational reasons, so a sender cannot rely on the recipient receiving exactly the message transmitted. By allowing a sender to sign specified headers, and recipient or intermediate system can confirm that the original intent of the sender is preserved, and including a Digest header can also verify the message body is not modified. This allows any recipient to easily confirm both the sender's identity, and any incidental or malicious changes that alter the content or meaning of the message.
There are a number of components in a signature that are common between the 'Signature' HTTP Authentication Scheme and the 'Signature' HTTP Header. This section details the components of the digital signature paremeters common to both schemes.
REQUIRED. The `keyId` field is an opaque string that the server can use to look up the component they need to validate the signature. It could be an SSH key fingerprint, a URL to machine-readable key data, an LDAP DN, etc. Management of keys and assignment of `keyId` is out of scope for this document. Implementations MUST be able to discover metadata about the key from the `keyId` such that they can determine the type of digital signature algorithm to employ when creating or verifying signatures.
REQUIRED. The `signature` parameter is a base 64 encoded digital signature, as described in RFC 4648, Section 4. The client uses the `algorithm` and `headers` Signature Parameters to form a canonicalized `signing string`. This `signing string` is then signed using the key associated with the `keyId` according to its digital signature algorithm. The `signature` parameter is then set to the base 64 encoding of the signature.
RECOMMENDED. The `algorithm` parameter is used to specify the signature string construction mechanism. Valid values for this parameter can be found in the HTTP Signatures Algorithms Registry and MUST NOT be marked "deprecated". Implementers SHOULD derive the digital signature algorithm used by an implementation from the key metadata identified by the `keyId` rather than from this field. If `algorithm` is provided and differs from the key metadata identified by the `keyId`, for example `rsa-sha256` but an EdDSA key is identified via `keyId`, then an implementation MUST produce an error. Implementers should note that previous versions of the `algorithm` parameter did not use the key information to derive the digital signature type and thus could be utilized by attackers to expose security vulnerabilities.
RECOMMENDED. The `created` field expresses when the signature was created. The value MUST be a Unix timestamp integer value. A signature with a `created` timestamp value that is in the future MUST NOT be processed. Using a Unix timestamp simplifies processing and avoids timezone management required by specifications such as RFC3339. Subsecond precision is not supported. This value is useful when clients are not capable of controlling the `Date` HTTP Header such as when operating in certain web browser environments.
OPTIONAL. The `expires` field expresses when the signature ceases to be valid. The value MUST be a Unix timestamp integer value. A signature with an `expires` timestamp value that is in the past MUST NOT be processed. Using a Unix timestamp simplifies processing and avoid timezone management existing in RFC3339. Subsecod precision is allowed using decimal notation.
OPTIONAL. The `headers` parameter is used to specify the list of HTTP headers included when generating the signature for the message. If specified, it SHOULD be a lowercased, quoted list of HTTP header fields, separated by a single space character. If not specified, implementations MUST operate as if the field were specified with a single value, `(created)`, in the list of HTTP headers. Note:
615 |
616 |
617 |
The list order is important, and MUST be specified in the order the HTTP header field-value pairs are concatenated together during Signature String Construction used during signing and verifying.
618 |
A zero-length `headers` parameter value MUST NOT be used, since it results in a signature of an empty string.
If any of the parameters listed above are erroneously duplicated in the associated header field, then the the signature MUST NOT be processed. Any parameter that is not recognized as a parameter, or is not well-formed, MUST be ignored.
A signed HTTP message needs to be tolerant of some trivial alterations during transmission as it goes through gateways, proxies, and other entities. These changes are often of little consequence and very benign, but also often not visible to or detectable by either the sender or the recipient. Simply signing the entire message that was transmitted by the sender is therefore not feasible: Even very minor changes would result in a signature which cannot be verified.
630 |
This specification allows the sender to select which headers are meaningful by including their names in the `headers` Signature Parameter. The headers appearing in this parameter are then used to construct the intermediate Signature String, which is the data that is actually signed.
631 |
In order to generate the string that is signed with a key, the client MUST use the values of each HTTP header field in the `headers` Signature Parameter, in the order they appear in the `headers` Signature Parameter. It is out of scope for this document to dictate what header fields an application will want to enforce, but implementers SHOULD at minimum include the `(request-target)` and `(created)` header fields if `algorithm` does not start with `rsa`, `hmac`, or `ecdsa`. Otherwise, `(request-target)` and `date` SHOULD be included in the signature.
632 |
To include the HTTP request target in the signature calculation, use the special `(request-target)` header field name. To include the signature creation time, use the special `(created)` header field name. To include the signature expiration time, use the special `(expires)` header field name.
633 |
634 |
635 |
If the header field name is `(request-target)` then generate the header field value by concatenating the lowercased :method, an ASCII space, and the :path pseudo-headers (as specified in HTTP/2, Section 8.1.2.3). Note: For the avoidance of doubt, lowercasing only applies to the :method pseudo-header and not to the :path pseudo-header.
636 |
If the header field name is `(created)` and the `algorithm` parameter starts with `rsa`, `hmac`, or `ecdsa` an implementation MUST produce an error. If the `created` Signature Parameter is not specified, or is not an integer, an implementation MUST produce an error. Otherwise, the header field value is the integer expressed by the `created` signature parameter.
637 |
If the header field name is `(expires)` and the `algorithm` parameter starts with `rsa`, `hmac`, or `ecdsa` an implementation MUST produce an error. If the `expires` Signature Parameter is not specified, or is not an integer, an implementation MUST produce an error. Otherwise, the header field value is the integer expressed by the `created` signature parameter.
638 |
Create the header field string by concatenating the lowercased header field name followed with an ASCII colon `:`, an ASCII space ` `, and the header field value. Leading and trailing optional whitespace (OWS) in the header field value MUST be omitted (as specified in RFC7230, Section 3.2.4).
639 |
If there are multiple instances of the same header field, all header field values associated with the header field MUST be concatenated, separated by a ASCII comma and an ASCII space `, `, and used in the order in which they will appear in the transmitted HTTP message.
640 |
If the header value (after removing leading and trailing whitespace) is a zero-length string, the signature string line correlating with that header will simply be the (lowercased) header name, an ASCII colon `:`, and an ASCII space ` `.
641 |
Any other modification to the header field value MUST NOT be made.
642 |
If a header specified in the headers parameter is malformed or cannot be matched with a provided header in the message, the implementation MUST produce an error.
643 |
644 |
645 |
646 |
If value is not the last value then append an ASCII newline `\n`.
647 |
648 |
649 |
650 |
651 | GET /foo HTTP/1.1
652 | Host: example.org
653 | Date: Tue, 07 Jun 2014 20:51:35 GMT
654 | X-Example: Example header
655 | with some whitespace.
656 | X-EmptyHeader:
657 | Cache-Control: max-age=60
658 | Cache-Control: must-revalidate
659 |
660 |
To illustrate the rules specified above, assume a `headers` parameter list with the value of `(request-target) (created) host date cache-control x-emptyheader x-example` with the following HTTP request headers:
661 |
662 | (request-target): get /foo
663 | (created): 1402170695
664 | host: example.org
665 | date: Tue, 07 Jun 2014 20:51:35 GMT
666 | cache-control: max-age=60, must-revalidate
667 | x-emptyheader:
668 | x-example: Example header with some whitespace.
669 |
670 |
For the HTTP request headers above, the corresponding signature string is:
Use the `headers` and `algorithm` values as well as the contents of the HTTP message, to create the signature string.
678 |
Use the key associated with `keyId` to generate a digital signature on the signature string.
679 |
The `signature` is then generated by base 64 encoding the output of the digital signature algorithm.
680 |
681 |
682 |
683 |
For example, assume that the `algorithm` value is "hs2019" and the `keyId` refers to an EdDSA public key. This would signal to the application that the signature string construction mechanism is the one defined in Section 2.3: Signature String Construction , the signature string hashing function is SHA-512, and the signing algorithm is Ed25519 as defined in RFC 8032, Section 5.1: Ed25519ph, Ed25519ctx, and Ed25519. The result of the signature creation algorithm should result in a binary string, which is then base 64 encoded and placed into the `signature` value.
Use the received HTTP message, the `headers` value, and the Signature String Construction algorithm to recreate the signature.
691 |
The `algorithm`, `keyId`, and base 64 decoded `signature` listed in the Signature Parameters are then used to verify the authenticity of the digital signature. Note: The application verifying the signature MUST derive the digital signature algorithm from the metadata associated with the `keyId` and MUST NOT use the value of `algorithm` from the signed message.
692 |
693 |
694 |
695 |
If a header specified in the `headers` value of the Signature Parameters (or the default item `(created)` where the `headers` value is not supplied) is absent from the message, the implementation MUST produce an error.
696 |
For example, assume that the `algorithm` value was "hs2019" and and the `keyId` refers to an EdDSA public key. This would signal to the application that the signature string construction mechanism is the one defined in Section 2.3: Signature String Construction , the signature string hashing function is SHA-512, and the signing algorithm is Ed25519 as defined in RFC 8032, Section 5.1: Ed25519ph, Ed25519ctx, and Ed25519. The result of the signature verification algorithm should result in a successful verification unless the headers protected by the signature were tampered with in transit.
The "Signature" authentication scheme is based on the model that the client must authenticate itself with a digital signature produced by either a private asymmetric key (e.g., RSA) or a shared symmetric key (e.g., HMAC).
701 |
The scheme is parameterized enough such that it is not bound to any particular key type or signing algorithm.
The client is expected to send an Authorization header (as defined in RFC 7235, Section 4.1) where the "auth-scheme" is "Signature" and the "auth-param" parameters meet the requirements listed in Section 2: The Components of a Signature.
The rest of this section uses the following HTTP request as an example.
717 |
Note that the use of the `Digest` header field is per RFC 3230, Section 4.3.2 and is included merely as a demonstration of how an implementer could include information about the body of the message in the signature. The following sections also assume that the "rsa-key-1" keyId asserted by the client is an identifier meaningful to the server.
A server may notify a client when a resource is protected by requiring a signature. To initiate this process, the server will request that the client authenticate itself via a 401 response code. The server may optionally specify which HTTP headers it expects to be signed by specifying the `headers` parameter in the WWW-Authenticate header. For example:
The only difference between the RSA Example and the HMAC Example is the digital signature algorithm that is used. The client would compose the signing string in the same way as the RSA Example above:
The "Signature" HTTP Header provides a mechanism to link the headers of a message (client request or server response) to a digital signature. By including the "Digest" header with a properly formatted digest, the message body can also be linked to the signature. The signature is generated and verified either using a shared secret (e.g. HMAC) or public/private keys (e.g. RSA, EC). This allows the receiver and/or any intermediate system to immediately or later verify the integrity of the message. When the signature is generated with a private key it can also provide a measure of non-repudiation, though a full implementation of a non-repudiatable statement is beyond the scope of this specification and highly dependent on implementation.
773 |
The "Signature" scheme can also be used for authentication similar to the purpose of the 'Signature' HTTP Authentication Scheme. The scheme is parameterized enough such that it is not bound to any particular key type or signing algorithm.
The sender is expected to transmit a header (as defined in RFC 7230, Section 3.2) where the "field-name" is "Signature", and the "field-value" contains one or more "auth-param"s (as defined in RFC 7235, Section 4.1) where the "auth-param" parameters meet the requirements listed in Section 2: The Components of a Signature.
The only difference between the RSA Example and the HMAC Example is the signature algorithm that is used. The client would compose the signing string in the same way as the RSA Example above:
There are a number of security considerations to take into account when implementing or utilizing this specification. A thorough security analysis of this protocol, including its strengths and weaknesses, can be found in Security Considerations for HTTP Signatures.
This specification was designed to be simple, modular, and extensible. There are a number of other specifications that build on this one. For example, the HTTP Signature Nonces specification details how to use HTTP Signatures over a non-secured channel like HTTP and the HTTP Signature Trailers specification explains how to apply HTTP Signatures to streaming content. Developers that desire more functionality than this specification provides are urged to ensure that an extension specification doesn't already exist before implementing a proprietary extension.
896 |
897 | Signature Parameter: nonce
898 | Reference to specification: [HTTP_AUTH_SIGNATURE_NONCE], Section XYZ.
899 | Notes (optional): The HTTP Signature Nonces specification details
900 | how to use HTTP Signatures over a unsecured channel like HTTP.
901 |
902 |
If extensions to this specification are made by adding new Signature Parameters, those extension parameters MUST be registered in the Signature Authentication Scheme Registry. The registry will be created and maintained at (the suggested URI) https://www.iana.org/assignments/http-auth-scheme-signature. An example entry in this registry is included below:
The editor would like to thank the following individuals for feedback on and implementations of the specification (in alphabetical order): Mark Adamcin, Mark Allen, Paul Annesley, Karl Böhlmark, Stéphane Bortzmeyer, Sarven Capadisli, Liam Dennehy, ductm54, Stephen Farrell, Phillip Hallam-Baker, Eric Holmes, Andrey Kislyuk, Adam Knight, Dave Lehn, Dave Longley, James H. Manger, Ilari Liusvaara, Mark Nottingham, Yoav Nir, Adrian Palmer, Lucas Pardue, Roberto Polli, Julian Reschke, Michael Richardson, Wojciech Rygielski, Adam Scarr, Cory J. Slep, Dirk Stein, Henry Story, Lukasz Szewc, Chris Webber, and Jeffrey Yasskin
Authentication Scheme Name: Signature Reference: [RFC_THIS_DOCUMENT], Section 2. Notes (optional): The Signature scheme is designed for clients to authenticate themselves with a server.
The following initial entries should be added to the Canonicalization Algorithms Registry to be created and maintained at (the suggested URI) https://www.iana.org/assignments/shm-algorithms:
1024 |
Editor's note: The references in this section are problematic as many of the specifications that they refer to are too implementation specific, rather than just pointing to the proper signature and hashing specifications. A better approach might be just specifying the signature and hashing function specifications, leaving implementers to connect the dots (which are not that hard to connect).
1025 |
Algorithm Name: hs2019 Status: active Canonicalization Algorithm: [RFC_THIS_DOCUMENT], Section 2.3: Signature String Construction Hash Algorithm: RFC 6234, SHA-512 (SHA-2 with 512-bits of digest output) Digital Signature Algorithm: Derived from metadata associated with `keyId`. Recommend support for RFC 8017, Section 8.1: RSASSA-PSS, RFC 6234, Section 7.1: SHA-Based HMACs, ANSI X9.62-2005 ECDSA, P-256, and RFC 8032, Section 5.1: Ed25519ph, Ed25519ctx, and Ed25519.
1026 |
Algorithm Name: rsa-sha1 Status: deprecated, SHA-1 not secure. Canonicalization Algorithm: [RFC_THIS_DOCUMENT], Section 2.3: Signature String Construction Hash Algorithm: RFC 6234, SHA-1 (SHA-1 with 160-bits of digest output) Digital Signature Algorithm: RFC 8017, Section 8.2: RSASSA-PKCS1-v1_5
1027 |
Algorithm Name: rsa-sha256 Status: deprecated, specifying signature algorithm enables attack vector. Canonicalization Algorithm: [RFC_THIS_DOCUMENT], Section 2.3: Signature String Construction Hash Algorithm: RFC 6234, SHA-256 (SHA-2 with 256-bits of digest output) Digital Signature Algorithm: RFC 8017, Section 8.2: RSASSA-PKCS1-v1_5
1084 |
1085 |
1086 |
1087 |
--------------------------------------------------------------------------------
/CGFR/index.txt:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Network Working Group M. Cavage
6 | Internet-Draft Oracle
7 | Intended status: Standards Track M. Sporny
8 | Expires: April 3, 2020 Digital Bazaar
9 | October 1, 2019
10 |
11 |
12 | Signing HTTP Messages
13 | draft-cavage-http-signatures-12
14 |
15 | Abstract
16 |
17 | When communicating over the Internet using the HTTP protocol, it can
18 | be desirable for a server or client to authenticate the sender of a
19 | particular message. It can also be desirable to ensure that the
20 | message was not tampered with during transit. This document
21 | describes a way for servers and clients to simultaneously add
22 | authentication and message integrity to HTTP messages by using a
23 | digital signature.
24 |
25 | Feedback
26 |
27 | This specification is a joint work product of the W3C Digital
28 | Verification Community Group [1] and the W3C Credentials Community
29 | Group [2]. Feedback related to this specification should logged in
30 | the issue tracker [3] or be sent to public-credentials@w3.org [4].
31 |
32 | Status of This Memo
33 |
34 | This Internet-Draft is submitted in full conformance with the
35 | provisions of BCP 78 and BCP 79.
36 |
37 | Internet-Drafts are working documents of the Internet Engineering
38 | Task Force (IETF). Note that other groups may also distribute
39 | working documents as Internet-Drafts. The list of current Internet-
40 | Drafts is at https://datatracker.ietf.org/drafts/current/.
41 |
42 | Internet-Drafts are draft documents valid for a maximum of six months
43 | and may be updated, replaced, or obsoleted by other documents at any
44 | time. It is inappropriate to use Internet-Drafts as reference
45 | material or to cite them other than as "work in progress."
46 |
47 | This Internet-Draft will expire on April 3, 2020.
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 | Cavage & Sporny Expires April 3, 2020 [Page 1]
57 |
58 | Internet-Draft Signing HTTP Messages October 2019
59 |
60 |
61 | Copyright Notice
62 |
63 | Copyright (c) 2019 IETF Trust and the persons identified as the
64 | document authors. All rights reserved.
65 |
66 | This document is subject to BCP 78 and the IETF Trust's Legal
67 | Provisions Relating to IETF Documents
68 | (https://trustee.ietf.org/license-info) in effect on the date of
69 | publication of this document. Please review these documents
70 | carefully, as they describe your rights and restrictions with respect
71 | to this document.
72 |
73 | Table of Contents
74 |
75 | 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3
76 | 1.1. Using Signatures in HTTP Requests . . . . . . . . . . . . 4
77 | 1.2. Using Signatures in HTTP Responses . . . . . . . . . . . 4
78 | 2. The Components of a Signature . . . . . . . . . . . . . . . . 4
79 | 2.1. Signature Parameters . . . . . . . . . . . . . . . . . . 5
80 | 2.1.1. keyId . . . . . . . . . . . . . . . . . . . . . . . . 5
81 | 2.1.2. signature . . . . . . . . . . . . . . . . . . . . . . 5
82 | 2.1.3. algorithm . . . . . . . . . . . . . . . . . . . . . . 5
83 | 2.1.4. created . . . . . . . . . . . . . . . . . . . . . . . 6
84 | 2.1.5. expires . . . . . . . . . . . . . . . . . . . . . . . 6
85 | 2.1.6. headers . . . . . . . . . . . . . . . . . . . . . . . 6
86 | 2.2. Ambiguous Parameters . . . . . . . . . . . . . . . . . . 6
87 | 2.3. Signature String Construction . . . . . . . . . . . . . . 7
88 | 2.4. Creating a Signature . . . . . . . . . . . . . . . . . . 9
89 | 2.5. Verifying a Signature . . . . . . . . . . . . . . . . . . 9
90 | 3. The 'Signature' HTTP Authentication Scheme . . . . . . . . . 10
91 | 3.1. Authorization Header . . . . . . . . . . . . . . . . . . 10
92 | 3.1.1. Initiating Signature Authorization . . . . . . . . . 11
93 | 3.1.2. RSA Example . . . . . . . . . . . . . . . . . . . . . 11
94 | 3.1.3. HMAC Example . . . . . . . . . . . . . . . . . . . . 12
95 | 4. The 'Signature' HTTP Header . . . . . . . . . . . . . . . . . 12
96 | 4.1. Signature Header . . . . . . . . . . . . . . . . . . . . 12
97 | 4.1.1. RSA Example . . . . . . . . . . . . . . . . . . . . . 13
98 | 4.1.2. HMAC Example . . . . . . . . . . . . . . . . . . . . 14
99 | 5. References . . . . . . . . . . . . . . . . . . . . . . . . . 14
100 | 5.1. Normative References . . . . . . . . . . . . . . . . . . 14
101 | 5.2. Informative References . . . . . . . . . . . . . . . . . 14
102 | 5.3. URIs . . . . . . . . . . . . . . . . . . . . . . . . . . 15
103 | Appendix A. Security Considerations . . . . . . . . . . . . . . 16
104 | Appendix B. Extensions . . . . . . . . . . . . . . . . . . . . . 16
105 | Appendix C. Test Values . . . . . . . . . . . . . . . . . . . . 17
106 | C.1. Default Test . . . . . . . . . . . . . . . . . . . . . . 18
107 | C.2. Basic Test . . . . . . . . . . . . . . . . . . . . . . . 18
108 | C.3. All Headers Test . . . . . . . . . . . . . . . . . . . . 19
109 |
110 |
111 |
112 | Cavage & Sporny Expires April 3, 2020 [Page 2]
113 |
114 | Internet-Draft Signing HTTP Messages October 2019
115 |
116 |
117 | Appendix D. Acknowledgements . . . . . . . . . . . . . . . . . . 19
118 | Appendix E. IANA Considerations . . . . . . . . . . . . . . . . 20
119 | E.1. Signature Authentication Scheme . . . . . . . . . . . . . 20
120 | E.2. HTTP Signatures Algorithms Registry . . . . . . . . . . . 20
121 | Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 21
122 |
123 | 1. Introduction
124 |
125 | This protocol extension is intended to provide a simple and standard
126 | way for clients to sign HTTP messages.
127 |
128 | HTTP Authentication [RFC2617] defines Basic and Digest authentication
129 | mechanisms, TLS 1.2 [RFC5246] defines cryptographically strong
130 | transport layer security, and OAuth 2.0 [RFC6749] provides a fully-
131 | specified alternative for authorization of web service requests.
132 | Each of these approaches are employed on the Internet today with
133 | varying degrees of protection. However, none of these schemes are
134 | designed to cryptographically sign the HTTP messages themselves,
135 | which is required in order to ensure end-to-end message integrity.
136 | An added benefit of signing the HTTP message for the purposes of end-
137 | to-end message integrity is that the client can be authenticated
138 | using the same mechanism without the need for multiple round-trips.
139 |
140 | Several web service providers have invented their own schemes for
141 | signing HTTP messages, but to date, none have been standardized.
142 | While there are no techniques in this proposal that are novel beyond
143 | the previous art, it is useful to standardize a simple and
144 | cryptographically strong mechanism for digitally signing HTTP
145 | messages.
146 |
147 | This specification presents two mechanisms with distinct purposes:
148 |
149 | 1. The "Signature" scheme which is intended primarily to allow a
150 | sender to assert the contents of the message sent are correct and
151 | have not been altered during transmission or storage in a way
152 | that alters the meaning expressed in the original message as
153 | signed. Any party reading the message (the verifier) may
154 | independently confirm the validity of the message signature.
155 | This scheme is agnostic to the client/server direction and can be
156 | used to verify the contents of either HTTP requests, HTTP
157 | reponses, or both.
158 |
159 | 2. The "Authorization" scheme which is intended primarily to allow a
160 | sender to request access to a resource or resources by proving
161 | that they control a secret key. This specification allows for
162 | this both with a shared secret (using HMAC) or with public/
163 | private keys. The "Authorization" scheme is typically used in
164 | authentication processes and not directly for message signing.
165 |
166 |
167 |
168 | Cavage & Sporny Expires April 3, 2020 [Page 3]
169 |
170 | Internet-Draft Signing HTTP Messages October 2019
171 |
172 |
173 | As a consequence `Authorization` header is normally generated
174 | (and the message signed) by the HTTP client and the message
175 | verified by the HTTP server.
176 |
177 | 1.1. Using Signatures in HTTP Requests
178 |
179 | It is common practice to protect sensitive website and API
180 | functionality via authentication mechanisms. Often, the entity
181 | accessing these APIs is a piece of automated software outside of an
182 | interactive human session. While there are mechanisms like OAuth and
183 | API secrets that are used to grant API access, each have their
184 | weaknesses such as unnecessary complexity for particular use cases or
185 | the use of shared secrets which may not be acceptable to an
186 | implementer. Shared secrets also prohibit any possibility for non-
187 | repudiation, while secure transports such as TLS do not provide for
188 | this at all.
189 |
190 | Digital signatures are widely used to provide authentication and
191 | integrity assurances without the need for shared secrets. They also
192 | do not require a round-trip in order to authenticate the client, and
193 | allow the integrity of a message to be verified independently of the
194 | transport (e.g. TLS). A server need only have an understanding of
195 | the key (e.g. through a mapping between the key being used to sign
196 | the content and the authorized entity) to verify that a message was
197 | signed by that entity.
198 |
199 | When optionally combined with asymmetric keys associated with an
200 | identity, this specification can also enable authentication of a
201 | client and server with or without prior knowledge of each other.
202 |
203 | 1.2. Using Signatures in HTTP Responses
204 |
205 | HTTP messages are routinely altered as they traverse the
206 | infrastructure of the Internet, for mostly benign reasons. Gateways
207 | and proxies add, remove and alter headers for operational reasons, so
208 | a sender cannot rely on the recipient receiving exactly the message
209 | transmitted. By allowing a sender to sign specified headers, and
210 | recipient or intermediate system can confirm that the original intent
211 | of the sender is preserved, and including a Digest header can also
212 | verify the message body is not modified. This allows any recipient
213 | to easily confirm both the sender's identity, and any incidental or
214 | malicious changes that alter the content or meaning of the message.
215 |
216 | 2. The Components of a Signature
217 |
218 | There are a number of components in a signature that are common
219 | between the 'Signature' HTTP Authentication Scheme and the
220 |
221 |
222 |
223 |
224 | Cavage & Sporny Expires April 3, 2020 [Page 4]
225 |
226 | Internet-Draft Signing HTTP Messages October 2019
227 |
228 |
229 | 'Signature' HTTP Header. This section details the components of the
230 | digital signature paremeters common to both schemes.
231 |
232 | 2.1. Signature Parameters
233 |
234 | The following section details the Signature Parameters.
235 |
236 | 2.1.1. keyId
237 |
238 | REQUIRED. The `keyId` field is an opaque string that the server can
239 | use to look up the component they need to validate the signature. It
240 | could be an SSH key fingerprint, a URL to machine-readable key data,
241 | an LDAP DN, etc. Management of keys and assignment of `keyId` is out
242 | of scope for this document. Implementations MUST be able to discover
243 | metadata about the key from the `keyId` such that they can determine
244 | the type of digital signature algorithm to employ when creating or
245 | verifying signatures.
246 |
247 | 2.1.2. signature
248 |
249 | REQUIRED. The `signature` parameter is a base 64 encoded digital
250 | signature, as described in RFC 4648 [RFC4648], Section 4 [5]. The
251 | client uses the `algorithm` and `headers` Signature Parameters to
252 | form a canonicalized `signing string`. This `signing string` is then
253 | signed using the key associated with the `keyId` according to its
254 | digital signature algorithm. The `signature` parameter is then set
255 | to the base 64 encoding of the signature.
256 |
257 | 2.1.3. algorithm
258 |
259 | RECOMMENDED. The `algorithm` parameter is used to specify the
260 | signature string construction mechanism. Valid values for this
261 | parameter can be found in the HTTP Signatures Algorithms Registry [6]
262 | and MUST NOT be marked "deprecated". Implementers SHOULD derive the
263 | digital signature algorithm used by an implementation from the key
264 | metadata identified by the `keyId` rather than from this field. If
265 | `algorithm` is provided and differs from the key metadata identified
266 | by the `keyId`, for example `rsa-sha256` but an EdDSA key is
267 | identified via `keyId`, then an implementation MUST produce an error.
268 | Implementers should note that previous versions of the `algorithm`
269 | parameter did not use the key information to derive the digital
270 | signature type and thus could be utilized by attackers to expose
271 | security vulnerabilities.
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 | Cavage & Sporny Expires April 3, 2020 [Page 5]
281 |
282 | Internet-Draft Signing HTTP Messages October 2019
283 |
284 |
285 | 2.1.4. created
286 |
287 | RECOMMENDED. The `created` field expresses when the signature was
288 | created. The value MUST be a Unix timestamp integer value. A
289 | signature with a `created` timestamp value that is in the future MUST
290 | NOT be processed. Using a Unix timestamp simplifies processing and
291 | avoids timezone management required by specifications such as
292 | RFC3339. Subsecond precision is not supported. This value is useful
293 | when clients are not capable of controlling the `Date` HTTP Header
294 | such as when operating in certain web browser environments.
295 |
296 | 2.1.5. expires
297 |
298 | OPTIONAL. The `expires` field expresses when the signature ceases to
299 | be valid. The value MUST be a Unix timestamp integer value. A
300 | signature with an `expires` timestamp value that is in the past MUST
301 | NOT be processed. Using a Unix timestamp simplifies processing and
302 | avoid timezone management existing in RFC3339. Subsecod precision is
303 | allowed using decimal notation.
304 |
305 | 2.1.6. headers
306 |
307 | OPTIONAL. The `headers` parameter is used to specify the list of
308 | HTTP headers included when generating the signature for the message.
309 | If specified, it SHOULD be a lowercased, quoted list of HTTP header
310 | fields, separated by a single space character. If not specified,
311 | implementations MUST operate as if the field were specified with a
312 | single value, `(created)`, in the list of HTTP headers. Note:
313 |
314 | 1. The list order is important, and MUST be specified in the order
315 | the HTTP header field-value pairs are concatenated together
316 | during Signature String Construction (Section 2.3) used during
317 | signing and verifying.
318 |
319 | 2. A zero-length `headers` parameter value MUST NOT be used, since
320 | it results in a signature of an empty string.
321 |
322 | 2.2. Ambiguous Parameters
323 |
324 | If any of the parameters listed above are erroneously duplicated in
325 | the associated header field, then the the signature MUST NOT be
326 | processed. Any parameter that is not recognized as a parameter, or
327 | is not well-formed, MUST be ignored.
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 | Cavage & Sporny Expires April 3, 2020 [Page 6]
337 |
338 | Internet-Draft Signing HTTP Messages October 2019
339 |
340 |
341 | 2.3. Signature String Construction
342 |
343 | A signed HTTP message needs to be tolerant of some trivial
344 | alterations during transmission as it goes through gateways, proxies,
345 | and other entities. These changes are often of little consequence
346 | and very benign, but also often not visible to or detectable by
347 | either the sender or the recipient. Simply signing the entire
348 | message that was transmitted by the sender is therefore not feasible:
349 | Even very minor changes would result in a signature which cannot be
350 | verified.
351 |
352 | This specification allows the sender to select which headers are
353 | meaningful by including their names in the `headers` Signature
354 | Parameter. The headers appearing in this parameter are then used to
355 | construct the intermediate Signature String, which is the data that
356 | is actually signed.
357 |
358 | In order to generate the string that is signed with a key, the client
359 | MUST use the values of each HTTP header field in the `headers`
360 | Signature Parameter, in the order they appear in the `headers`
361 | Signature Parameter. It is out of scope for this document to dictate
362 | what header fields an application will want to enforce, but
363 | implementers SHOULD at minimum include the `(request-target)` and
364 | `(created)` header fields if `algorithm` does not start with `rsa`,
365 | `hmac`, or `ecdsa`. Otherwise, `(request-target)` and `date` SHOULD
366 | be included in the signature.
367 |
368 | To include the HTTP request target in the signature calculation, use
369 | the special `(request-target)` header field name. To include the
370 | signature creation time, use the special `(created)` header field
371 | name. To include the signature expiration time, use the special
372 | `(expires)` header field name.
373 |
374 | 1. If the header field name is `(request-target)` then generate the
375 | header field value by concatenating the lowercased :method, an
376 | ASCII space, and the :path pseudo-headers (as specified in
377 | HTTP/2, Section 8.1.2.3 [7]). Note: For the avoidance of doubt,
378 | lowercasing only applies to the :method pseudo-header and not to
379 | the :path pseudo-header.
380 |
381 | 2. If the header field name is `(created)` and the `algorithm`
382 | parameter starts with `rsa`, `hmac`, or `ecdsa` an implementation
383 | MUST produce an error. If the `created` Signature Parameter is
384 | not specified, or is not an integer, an implementation MUST
385 | produce an error. Otherwise, the header field value is the
386 | integer expressed by the `created` signature parameter.
387 |
388 |
389 |
390 |
391 |
392 | Cavage & Sporny Expires April 3, 2020 [Page 7]
393 |
394 | Internet-Draft Signing HTTP Messages October 2019
395 |
396 |
397 | 3. If the header field name is `(expires)` and the `algorithm`
398 | parameter starts with `rsa`, `hmac`, or `ecdsa` an implementation
399 | MUST produce an error. If the `expires` Signature Parameter is
400 | not specified, or is not an integer, an implementation MUST
401 | produce an error. Otherwise, the header field value is the
402 | integer expressed by the `created` signature parameter.
403 |
404 | 4. Create the header field string by concatenating the lowercased
405 | header field name followed with an ASCII colon `:`, an ASCII
406 | space ` `, and the header field value. Leading and trailing
407 | optional whitespace (OWS) in the header field value MUST be
408 | omitted (as specified in RFC7230 [RFC7230], Section 3.2.4 [8]).
409 |
410 | 1. If there are multiple instances of the same header field, all
411 | header field values associated with the header field MUST be
412 | concatenated, separated by a ASCII comma and an ASCII space
413 | `, `, and used in the order in which they will appear in the
414 | transmitted HTTP message.
415 |
416 | 2. If the header value (after removing leading and trailing
417 | whitespace) is a zero-length string, the signature string
418 | line correlating with that header will simply be the
419 | (lowercased) header name, an ASCII colon `:`, and an ASCII
420 | space ` `.
421 |
422 | 3. Any other modification to the header field value MUST NOT be
423 | made.
424 |
425 | 4. If a header specified in the headers parameter is malformed
426 | or cannot be matched with a provided header in the message,
427 | the implementation MUST produce an error.
428 |
429 | 5. If value is not the last value then append an ASCII newline `\n`.
430 |
431 | To illustrate the rules specified above, assume a `headers` parameter
432 | list with the value of `(request-target) (created) host date cache-
433 | control x-emptyheader x-example` with the following HTTP request
434 | headers:
435 |
436 | GET /foo HTTP/1.1
437 | Host: example.org
438 | Date: Tue, 07 Jun 2014 20:51:35 GMT
439 | X-Example: Example header
440 | with some whitespace.
441 | X-EmptyHeader:
442 | Cache-Control: max-age=60
443 | Cache-Control: must-revalidate
444 |
445 |
446 |
447 |
448 | Cavage & Sporny Expires April 3, 2020 [Page 8]
449 |
450 | Internet-Draft Signing HTTP Messages October 2019
451 |
452 |
453 | For the HTTP request headers above, the corresponding signature
454 | string is:
455 |
456 | (request-target): get /foo
457 | (created): 1402170695
458 | host: example.org
459 | date: Tue, 07 Jun 2014 20:51:35 GMT
460 | cache-control: max-age=60, must-revalidate
461 | x-emptyheader:
462 | x-example: Example header with some whitespace.
463 |
464 | 2.4. Creating a Signature
465 |
466 | In order to create a signature, a client MUST:
467 |
468 | 1. Use the `headers` and `algorithm` values as well as the contents
469 | of the HTTP message, to create the signature string.
470 |
471 | 2. Use the key associated with `keyId` to generate a digital
472 | signature on the signature string.
473 |
474 | 3. The `signature` is then generated by base 64 encoding the output
475 | of the digital signature algorithm.
476 |
477 | For example, assume that the `algorithm` value is "hs2019" and the
478 | `keyId` refers to an EdDSA public key. This would signal to the
479 | application that the signature string construction mechanism is the
480 | one defined in Section 2.3: Signature String Construction [9], the
481 | signature string hashing function is SHA-512, and the signing
482 | algorithm is Ed25519 as defined in RFC 8032 [RFC8032], Section 5.1:
483 | Ed25519ph, Ed25519ctx, and Ed25519. The result of the signature
484 | creation algorithm should result in a binary string, which is then
485 | base 64 encoded and placed into the `signature` value.
486 |
487 | 2.5. Verifying a Signature
488 |
489 | In order to verify a signature, a server MUST:
490 |
491 | 1. Use the received HTTP message, the `headers` value, and the
492 | Signature String Construction (Section 2.3) algorithm to recreate
493 | the signature.
494 |
495 | 2. The `algorithm`, `keyId`, and base 64 decoded `signature` listed
496 | in the Signature Parameters are then used to verify the
497 | authenticity of the digital signature. Note: The application
498 | verifying the signature MUST derive the digital signature
499 | algorithm from the metadata associated with the `keyId` and MUST
500 | NOT use the value of `algorithm` from the signed message.
501 |
502 |
503 |
504 | Cavage & Sporny Expires April 3, 2020 [Page 9]
505 |
506 | Internet-Draft Signing HTTP Messages October 2019
507 |
508 |
509 | If a header specified in the `headers` value of the Signature
510 | Parameters (or the default item `(created)` where the `headers` value
511 | is not supplied) is absent from the message, the implementation MUST
512 | produce an error.
513 |
514 | For example, assume that the `algorithm` value was "hs2019" and and
515 | the `keyId` refers to an EdDSA public key. This would signal to the
516 | application that the signature string construction mechanism is the
517 | one defined in Section 2.3: Signature String Construction [10], the
518 | signature string hashing function is SHA-512, and the signing
519 | algorithm is Ed25519 as defined in RFC 8032 [RFC8032], Section 5.1:
520 | Ed25519ph, Ed25519ctx, and Ed25519. The result of the signature
521 | verification algorithm should result in a successful verification
522 | unless the headers protected by the signature were tampered with in
523 | transit.
524 |
525 | 3. The 'Signature' HTTP Authentication Scheme
526 |
527 | The "Signature" authentication scheme is based on the model that the
528 | client must authenticate itself with a digital signature produced by
529 | either a private asymmetric key (e.g., RSA) or a shared symmetric key
530 | (e.g., HMAC).
531 |
532 | The scheme is parameterized enough such that it is not bound to any
533 | particular key type or signing algorithm.
534 |
535 | 3.1. Authorization Header
536 |
537 | The client is expected to send an Authorization header (as defined in
538 | RFC 7235 [RFC7235], Section 4.1 [11]) where the "auth-scheme" is
539 | "Signature" and the "auth-param" parameters meet the requirements
540 | listed in Section 2: The Components of a Signature.
541 |
542 | The rest of this section uses the following HTTP request as an
543 | example.
544 |
545 | POST /foo HTTP/1.1
546 | Host: example.org
547 | Date: Tue, 07 Jun 2014 20:51:35 GMT
548 | Content-Type: application/json
549 | Digest: SHA-256=X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=
550 | Content-Length: 18
551 |
552 | {"hello": "world"}
553 |
554 | Note that the use of the `Digest` header field is per RFC 3230
555 | [RFC3230], Section 4.3.2 [12] and is included merely as a
556 | demonstration of how an implementer could include information about
557 |
558 |
559 |
560 | Cavage & Sporny Expires April 3, 2020 [Page 10]
561 |
562 | Internet-Draft Signing HTTP Messages October 2019
563 |
564 |
565 | the body of the message in the signature. The following sections
566 | also assume that the "rsa-key-1" keyId asserted by the client is an
567 | identifier meaningful to the server.
568 |
569 | 3.1.1. Initiating Signature Authorization
570 |
571 | A server may notify a client when a resource is protected by
572 | requiring a signature. To initiate this process, the server will
573 | request that the client authenticate itself via a 401 response [13]
574 | code. The server may optionally specify which HTTP headers it
575 | expects to be signed by specifying the `headers` parameter in the
576 | WWW-Authenticate header. For example:
577 |
578 | HTTP/1.1 401 Unauthorized
579 | Date: Thu, 08 Jun 2014 18:32:30 GMT
580 | Content-Length: 1234
581 | Content-Type: text/html
582 | WWW-Authenticate: Signature
583 | realm="Example",headers="(request-target) (created)"
584 |
585 | ...
586 |
587 | 3.1.2. RSA Example
588 |
589 | The authorization header and signature would be generated as:
590 |
591 | Authorization: Signature keyId="rsa-key-1",algorithm="hs2019",
592 | headers="(request-target) (created) host digest content-length",
593 | signature="Base64(RSA-SHA512(signing string))"
594 |
595 | The client would compose the signing string as:
596 |
597 | (request-target): post /foo\n
598 | (created): 1402174295
599 | host: example.org\n
600 | digest: SHA-256=X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=\n
601 | content-length: 18
602 |
603 | Note that the '\n' symbols above are included to demonstrate where
604 | the new line character should be inserted. There is no new line on
605 | the final line of the signing string. Each HTTP header above is
606 | displayed on a new line to provide better readability of the example.
607 |
608 | For an RSA-based signature, the authorization header and signature
609 | would then be generated as:
610 |
611 |
612 |
613 |
614 |
615 |
616 | Cavage & Sporny Expires April 3, 2020 [Page 11]
617 |
618 | Internet-Draft Signing HTTP Messages October 2019
619 |
620 |
621 | Authorization: Signature keyId="rsa-key-1",algorithm="hs2019",
622 | headers="(request-target) (created) host digest content-length",
623 | signature="Base64(RSA-SHA512(signing string))"
624 |
625 | 3.1.3. HMAC Example
626 |
627 | For an HMAC-based signature without a list of headers specified, the
628 | authorization header and signature would be generated as:
629 |
630 | Authorization: Signature keyId="hmac-key-1",algorithm="hs2019",
631 | headers="(request-target) (created) host digest content-length",
632 | signature="Base64(HMAC-SHA512(signing string))"
633 |
634 | The only difference between the RSA Example and the HMAC Example is
635 | the digital signature algorithm that is used. The client would
636 | compose the signing string in the same way as the RSA Example above:
637 |
638 | (request-target): post /foo\n
639 | (created): 1402174295
640 | host: example.org\n
641 | digest: SHA-256=X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=\n
642 | content-length: 18
643 |
644 | 4. The 'Signature' HTTP Header
645 |
646 | The "Signature" HTTP Header provides a mechanism to link the headers
647 | of a message (client request or server response) to a digital
648 | signature. By including the "Digest" header with a properly
649 | formatted digest, the message body can also be linked to the
650 | signature. The signature is generated and verified either using a
651 | shared secret (e.g. HMAC) or public/private keys (e.g. RSA, EC).
652 | This allows the receiver and/or any intermediate system to
653 | immediately or later verify the integrity of the message. When the
654 | signature is generated with a private key it can also provide a
655 | measure of non-repudiation, though a full implementation of a non-
656 | repudiatable statement is beyond the scope of this specification and
657 | highly dependent on implementation.
658 |
659 | The "Signature" scheme can also be used for authentication similar to
660 | the purpose of the 'Signature' HTTP Authentication Scheme
661 | (Section 3). The scheme is parameterized enough such that it is not
662 | bound to any particular key type or signing algorithm.
663 |
664 | 4.1. Signature Header
665 |
666 | The sender is expected to transmit a header (as defined in RFC 7230
667 | [RFC7230], Section 3.2 [14]) where the "field-name" is "Signature",
668 | and the "field-value" contains one or more "auth-param"s (as defined
669 |
670 |
671 |
672 | Cavage & Sporny Expires April 3, 2020 [Page 12]
673 |
674 | Internet-Draft Signing HTTP Messages October 2019
675 |
676 |
677 | in RFC 7235 [RFC7235], Section 4.1 [15]) where the "auth-param"
678 | parameters meet the requirements listed in Section 2: The Components
679 | of a Signature.
680 |
681 | The rest of this section uses the following HTTP request as an
682 | example.
683 |
684 | POST /foo HTTP/1.1
685 | Host: example.org
686 | Date: Tue, 07 Jun 2014 20:51:35 GMT
687 | Content-Type: application/json
688 | Digest: SHA-256=X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=
689 | Content-Length: 18
690 |
691 | {"hello": "world"}
692 |
693 | The following sections assume that the "rsa-key-1" keyId provided by
694 | the signer is an identifier meaningful to the server.
695 |
696 | 4.1.1. RSA Example
697 |
698 | The signature header and signature would be generated as:
699 |
700 | Signature: keyId="rsa-key-1",algorithm="hs2019",
701 | created=1402170695, expires=1402170995,
702 | headers="(request-target) (created) (expires)
703 | host date digest content-length",
704 | signature="Base64(RSA-SHA256(signing string))"
705 |
706 | The client would compose the signing string as:
707 |
708 | (request-target): post /foo\n
709 | (created): 1402170695
710 | (expires): 1402170995
711 | host: example.org\n
712 | digest: SHA-256=X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=\n
713 | content-length: 18
714 |
715 | Note that the '\n' symbols above are included to demonstrate where
716 | the new line character should be inserted. There is no new line on
717 | the final line of the signing string. Each HTTP header above is
718 | displayed on a new line to provide better readability of the example.
719 |
720 | For an RSA-based signature, the authorization header and signature
721 | would then be generated as:
722 |
723 |
724 |
725 |
726 |
727 |
728 | Cavage & Sporny Expires April 3, 2020 [Page 13]
729 |
730 | Internet-Draft Signing HTTP Messages October 2019
731 |
732 |
733 | Signature: keyId="rsa-key-1",algorithm="hs2019",created=1402170695,
734 | headers="(request-target) (created) host digest content-length",
735 | signature="Base64(RSA-SHA512(signing string))"
736 |
737 | 4.1.2. HMAC Example
738 |
739 | For an HMAC-based signature without a list of headers specified, the
740 | authorization header and signature would be generated as:
741 |
742 | Signature: keyId="hmac-key-1",algorithm="hs2019",created=1402170695,
743 | headers="(request-target) (created) host digest content-length",
744 | signature="Base64(HMAC-SHA512(signing string))"
745 |
746 | The only difference between the RSA Example and the HMAC Example is
747 | the signature algorithm that is used. The client would compose the
748 | signing string in the same way as the RSA Example above:
749 |
750 | (request-target): post /foo\n
751 | (created): 1402170695
752 | host: example.org\n
753 | digest: SHA-256=X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=\n
754 | content-length: 18
755 |
756 | 5. References
757 |
758 | 5.1. Normative References
759 |
760 | [RFC4648] Josefsson, S., "The Base16, Base32, and Base64 Data
761 | Encodings", RFC 4648, DOI 10.17487/RFC4648, October 2006,
762 | .
763 |
764 | [RFC7230] Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer
765 | Protocol (HTTP/1.1): Message Syntax and Routing",
766 | RFC 7230, DOI 10.17487/RFC7230, June 2014,
767 | .
768 |
769 | [RFC7235] Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer
770 | Protocol (HTTP/1.1): Authentication", RFC 7235,
771 | DOI 10.17487/RFC7235, June 2014,
772 | .
773 |
774 | 5.2. Informative References
775 |
776 | [RFC2617] Franks, J., Hallam-Baker, P., Hostetler, J., Lawrence, S.,
777 | Leach, P., Luotonen, A., and L. Stewart, "HTTP
778 | Authentication: Basic and Digest Access Authentication",
779 | RFC 2617, DOI 10.17487/RFC2617, June 1999,
780 | .
781 |
782 |
783 |
784 | Cavage & Sporny Expires April 3, 2020 [Page 14]
785 |
786 | Internet-Draft Signing HTTP Messages October 2019
787 |
788 |
789 | [RFC3230] Mogul, J. and A. Van Hoff, "Instance Digests in HTTP",
790 | RFC 3230, DOI 10.17487/RFC3230, January 2002,
791 | .
792 |
793 | [RFC5246] Dierks, T. and E. Rescorla, "The Transport Layer Security
794 | (TLS) Protocol Version 1.2", RFC 5246,
795 | DOI 10.17487/RFC5246, August 2008,
796 | .
797 |
798 | [RFC6234] Eastlake 3rd, D. and T. Hansen, "US Secure Hash Algorithms
799 | (SHA and SHA-based HMAC and HKDF)", RFC 6234,
800 | DOI 10.17487/RFC6234, May 2011,
801 | .
802 |
803 | [RFC6749] Hardt, D., Ed., "The OAuth 2.0 Authorization Framework",
804 | RFC 6749, DOI 10.17487/RFC6749, October 2012,
805 | .
806 |
807 | [RFC8017] Moriarty, K., Ed., Kaliski, B., Jonsson, J., and A. Rusch,
808 | "PKCS #1: RSA Cryptography Specifications Version 2.2",
809 | RFC 8017, DOI 10.17487/RFC8017, November 2016,
810 | .
811 |
812 | [RFC8032] Josefsson, S. and I. Liusvaara, "Edwards-Curve Digital
813 | Signature Algorithm (EdDSA)", RFC 8032,
814 | DOI 10.17487/RFC8032, January 2017,
815 | .
816 |
817 | 5.3. URIs
818 |
819 | [1] https://w3c-dvcg.github.io/
820 |
821 | [2] https://w3c-ccg.github.io/
822 |
823 | [3] https://github.com/w3c-dvcg/http-signatures/issues
824 |
825 | [4] mailto:public-credentials@w3.org
826 |
827 | [5] https://tools.ietf.org/html/rfc4648#section-4
828 |
829 | [6] #hsa-registry
830 |
831 | [7] https://tools.ietf.org/html/rfc7540#section-8.1.2.3
832 |
833 | [8] https://tools.ietf.org/html/rfc7230#section-3.2.4
834 |
835 | [9] #canonicalization
836 |
837 |
838 |
839 |
840 | Cavage & Sporny Expires April 3, 2020 [Page 15]
841 |
842 | Internet-Draft Signing HTTP Messages October 2019
843 |
844 |
845 | [10] #canonicalization
846 |
847 | [11] https://tools.ietf.org/html/rfc7235#section-2.1
848 |
849 | [12] https://tools.ietf.org/html/rfc3230#section-4.3.2
850 |
851 | [13] https://tools.ietf.org/html/rfc7235#section-3.1
852 |
853 | [14] https://tools.ietf.org/html/rfc7230#section-3.2
854 |
855 | [15] https://tools.ietf.org/html/rfc7235#section-4.1
856 |
857 | [16] https://web-payments.org/specs/source/http-signatures-audit/
858 |
859 | [17] https://web-payments.org/specs/source/http-signature-nonces/
860 |
861 | [18] https://web-payments.org/specs/source/http-signature-trailers/
862 |
863 | [19] https://www.iana.org/assignments/http-auth-scheme-signature
864 |
865 | [20] https://www.iana.org/assignments/http-authschemes
866 |
867 | [21] https://www.iana.org/assignments/shm-algorithms
868 |
869 | [22] #canonicalization
870 |
871 | [23] #canonicalization
872 |
873 | [24] #canonicalization
874 |
875 | [25] #canonicalization
876 |
877 | [26] #canonicalization
878 |
879 | Appendix A. Security Considerations
880 |
881 | There are a number of security considerations to take into account
882 | when implementing or utilizing this specification. A thorough
883 | security analysis of this protocol, including its strengths and
884 | weaknesses, can be found in Security Considerations for HTTP
885 | Signatures [16].
886 |
887 | Appendix B. Extensions
888 |
889 | This specification was designed to be simple, modular, and
890 | extensible. There are a number of other specifications that build on
891 | this one. For example, the HTTP Signature Nonces [17] specification
892 | details how to use HTTP Signatures over a non-secured channel like
893 |
894 |
895 |
896 | Cavage & Sporny Expires April 3, 2020 [Page 16]
897 |
898 | Internet-Draft Signing HTTP Messages October 2019
899 |
900 |
901 | HTTP and the HTTP Signature Trailers [18] specification explains how
902 | to apply HTTP Signatures to streaming content. Developers that
903 | desire more functionality than this specification provides are urged
904 | to ensure that an extension specification doesn't already exist
905 | before implementing a proprietary extension.
906 |
907 | If extensions to this specification are made by adding new Signature
908 | Parameters, those extension parameters MUST be registered in the
909 | Signature Authentication Scheme Registry. The registry will be
910 | created and maintained at (the suggested URI)
911 | https://www.iana.org/assignments/http-auth-scheme-signature [19]. An
912 | example entry in this registry is included below:
913 |
914 | Signature Parameter: nonce
915 | Reference to specification: [HTTP_AUTH_SIGNATURE_NONCE], Section XYZ.
916 | Notes (optional): The HTTP Signature Nonces specification details
917 | how to use HTTP Signatures over a unsecured channel like HTTP.
918 |
919 | Appendix C. Test Values
920 |
921 | WARNING: THESE TEST VECTORS ARE OLD AND POSSIBLY WRONG. THE NEXT
922 | VERSION OF THIS SPECIFICATION WILL CONTAIN THE PROPER TEST VECTORS.
923 |
924 | The following test data uses the following RSA 2048-bit keys, which
925 | we will refer to as `keyId=Test` in the following samples:
926 |
927 | -----BEGIN PUBLIC KEY-----
928 | MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDCFENGw33yGihy92pDjZQhl0C3
929 | 6rPJj+CvfSC8+q28hxA161QFNUd13wuCTUcq0Qd2qsBe/2hFyc2DCJJg0h1L78+6
930 | Z4UMR7EOcpfdUE9Hf3m/hs+FUR45uBJeDK1HSFHD8bHKD6kv8FPGfJTotc+2xjJw
931 | oYi+1hqp1fIekaxsyQIDAQAB
932 | -----END PUBLIC KEY-----
933 |
934 | -----BEGIN RSA PRIVATE KEY-----
935 | MIICXgIBAAKBgQDCFENGw33yGihy92pDjZQhl0C36rPJj+CvfSC8+q28hxA161QF
936 | NUd13wuCTUcq0Qd2qsBe/2hFyc2DCJJg0h1L78+6Z4UMR7EOcpfdUE9Hf3m/hs+F
937 | UR45uBJeDK1HSFHD8bHKD6kv8FPGfJTotc+2xjJwoYi+1hqp1fIekaxsyQIDAQAB
938 | AoGBAJR8ZkCUvx5kzv+utdl7T5MnordT1TvoXXJGXK7ZZ+UuvMNUCdN2QPc4sBiA
939 | QWvLw1cSKt5DsKZ8UETpYPy8pPYnnDEz2dDYiaew9+xEpubyeW2oH4Zx71wqBtOK
940 | kqwrXa/pzdpiucRRjk6vE6YY7EBBs/g7uanVpGibOVAEsqH1AkEA7DkjVH28WDUg
941 | f1nqvfn2Kj6CT7nIcE3jGJsZZ7zlZmBmHFDONMLUrXR/Zm3pR5m0tCmBqa5RK95u
942 | 412jt1dPIwJBANJT3v8pnkth48bQo/fKel6uEYyboRtA5/uHuHkZ6FQF7OUkGogc
943 | mSJluOdc5t6hI1VsLn0QZEjQZMEOWr+wKSMCQQCC4kXJEsHAve77oP6HtG/IiEn7
944 | kpyUXRNvFsDE0czpJJBvL/aRFUJxuRK91jhjC68sA7NsKMGg5OXb5I5Jj36xAkEA
945 | gIT7aFOYBFwGgQAQkWNKLvySgKbAZRTeLBacpHMuQdl1DfdntvAyqpAZ0lY0RKmW
946 | G6aFKaqQfOXKCyWoUiVknQJAXrlgySFci/2ueKlIE1QqIiLSZ8V8OlpFLRnb1pzI
947 | 7U1yQXnTAEFYM560yJlzUpOb1V4cScGd365tiSMvxLOvTA==
948 | -----END RSA PRIVATE KEY-----
949 |
950 |
951 |
952 | Cavage & Sporny Expires April 3, 2020 [Page 17]
953 |
954 | Internet-Draft Signing HTTP Messages October 2019
955 |
956 |
957 | All examples use this request:
958 |
959 | POST /foo?param=value&pet=dog HTTP/1.1
960 | Host: example.com
961 | Date: Sun, 05 Jan 2014 21:31:40 GMT
962 | Content-Type: application/json
963 | Digest: SHA-256=X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=
964 | Content-Length: 18
965 |
966 | {"hello": "world"}
967 |
968 | C.1. Default Test
969 |
970 | If a list of headers is not included, the date is the only header
971 | that is signed by default for rsa-sha256. The string to sign would
972 | be:
973 |
974 | date: Sun, 05 Jan 2014 21:31:40 GMT
975 |
976 | The Authorization header would be:
977 |
978 | Authorization: Signature keyId="Test",algorithm="rsa-sha256",
979 | signature="SjWJWbWN7i0wzBvtPl8rbASWz5xQW6mcJmn+ibttBqtifLN7Sazz
980 | 6m79cNfwwb8DMJ5cou1s7uEGKKCs+FLEEaDV5lp7q25WqS+lavg7T8hc0GppauB
981 | 6hbgEKTwblDHYGEtbGmtdHgVCk9SuS13F0hZ8FD0k/5OxEPXe5WozsbM="
982 |
983 | The Signature header would be:
984 |
985 | Signature: keyId="Test",algorithm="rsa-sha256",
986 | signature="SjWJWbWN7i0wzBvtPl8rbASWz5xQW6mcJmn+ibttBqtifLN7Sazz
987 | 6m79cNfwwb8DMJ5cou1s7uEGKKCs+FLEEaDV5lp7q25WqS+lavg7T8hc0GppauB
988 | 6hbgEKTwblDHYGEtbGmtdHgVCk9SuS13F0hZ8FD0k/5OxEPXe5WozsbM="
989 |
990 | C.2. Basic Test
991 |
992 | The minimum recommended data to sign is the (request-target), host,
993 | and date. In this case, the string to sign would be:
994 |
995 | (request-target): post /foo?param=value&pet=dog
996 | host: example.com
997 | date: Sun, 05 Jan 2014 21:31:40 GMT
998 |
999 | The Authorization header would be:
1000 |
1001 |
1002 |
1003 |
1004 |
1005 |
1006 |
1007 |
1008 | Cavage & Sporny Expires April 3, 2020 [Page 18]
1009 |
1010 | Internet-Draft Signing HTTP Messages October 2019
1011 |
1012 |
1013 | Authorization: Signature keyId="Test",algorithm="rsa-sha256",
1014 | headers="(request-target) host date",
1015 | signature="qdx+H7PHHDZgy4y/Ahn9Tny9V3GP6YgBPyUXMmoxWtLbHpUnXS
1016 | 2mg2+SbrQDMCJypxBLSPQR2aAjn7ndmw2iicw3HMbe8VfEdKFYRqzic+efkb3
1017 | nndiv/x1xSHDJWeSWkx3ButlYSuBskLu6kd9Fswtemr3lgdDEmn04swr2Os0="
1018 |
1019 | C.3. All Headers Test
1020 |
1021 | A strong signature including all of the headers and a digest of the
1022 | body of the HTTP request would result in the following signing
1023 | string:
1024 |
1025 | (request-target): post /foo?param=value&pet=dog
1026 | host: example.com
1027 | date: Sun, 05 Jan 2014 21:31:40 GMT
1028 | content-type: application/json
1029 | digest: SHA-256=X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=
1030 | content-length: 18
1031 |
1032 | The Authorization header would be:
1033 |
1034 | Authorization: Signature keyId="Test",algorithm="rsa-sha256",
1035 | created=1402170695, expires=1402170699,
1036 | headers="(request-target) (created) (expires)
1037 | host date content-type digest content-length",
1038 | signature="vSdrb+dS3EceC9bcwHSo4MlyKS59iFIrhgYkz8+oVLEEzmYZZvRs
1039 | 8rgOp+63LEM3v+MFHB32NfpB2bEKBIvB1q52LaEUHFv120V01IL+TAD48XaERZF
1040 | ukWgHoBTLMhYS2Gb51gWxpeIq8knRmPnYePbF5MOkR0Zkly4zKH7s1dE="
1041 |
1042 | The Signature header would be:
1043 |
1044 | Signature: keyId="Test",algorithm="rsa-sha256",
1045 | created=1402170695, expires=1402170699,
1046 | headers="(request-target) (created) (expires)
1047 | host date content-type digest content-length",
1048 | signature="vSdrb+dS3EceC9bcwHSo4MlyKS59iFIrhgYkz8+oVLEEzmYZZvRs
1049 | 8rgOp+63LEM3v+MFHB32NfpB2bEKBIvB1q52LaEUHFv120V01IL+TAD48XaERZF
1050 | ukWgHoBTLMhYS2Gb51gWxpeIq8knRmPnYePbF5MOkR0Zkly4zKH7s1dE="
1051 |
1052 | Appendix D. Acknowledgements
1053 |
1054 | The editor would like to thank the following individuals for feedback
1055 | on and implementations of the specification (in alphabetical order):
1056 | Mark Adamcin, Mark Allen, Paul Annesley, Karl Boehlmark, Stephane
1057 | Bortzmeyer, Sarven Capadisli, Liam Dennehy, ductm54, Stephen Farrell,
1058 | Phillip Hallam-Baker, Eric Holmes, Andrey Kislyuk, Adam Knight, Dave
1059 | Lehn, Dave Longley, James H. Manger, Ilari Liusvaara, Mark
1060 | Nottingham, Yoav Nir, Adrian Palmer, Lucas Pardue, Roberto Polli,
1061 |
1062 |
1063 |
1064 | Cavage & Sporny Expires April 3, 2020 [Page 19]
1065 |
1066 | Internet-Draft Signing HTTP Messages October 2019
1067 |
1068 |
1069 | Julian Reschke, Michael Richardson, Wojciech Rygielski, Adam Scarr,
1070 | Cory J. Slep, Dirk Stein, Henry Story, Lukasz Szewc, Chris Webber,
1071 | and Jeffrey Yasskin
1072 |
1073 | Appendix E. IANA Considerations
1074 |
1075 | E.1. Signature Authentication Scheme
1076 |
1077 | The following entry should be added to the Authentication Scheme
1078 | Registry located at https://www.iana.org/assignments/http-authschemes
1079 | [20]
1080 |
1081 | Authentication Scheme Name: Signature
1082 | Reference: [RFC_THIS_DOCUMENT], Section 2.
1083 | Notes (optional): The Signature scheme is designed for clients to
1084 | authenticate themselves with a server.
1085 |
1086 | E.2. HTTP Signatures Algorithms Registry
1087 |
1088 | The following initial entries should be added to the Canonicalization
1089 | Algorithms Registry to be created and maintained at (the suggested
1090 | URI) https://www.iana.org/assignments/shm-algorithms [21]:
1091 |
1092 | Editor's note: The references in this section are problematic as many
1093 | of the specifications that they refer to are too implementation
1094 | specific, rather than just pointing to the proper signature and
1095 | hashing specifications. A better approach might be just specifying
1096 | the signature and hashing function specifications, leaving
1097 | implementers to connect the dots (which are not that hard to
1098 | connect).
1099 |
1100 | Algorithm Name: hs2019
1101 | Status: active
1102 | Canonicalization Algorithm: [RFC_THIS_DOCUMENT], Section 2.3:
1103 | Signature String Construction [22]
1104 | Hash Algorithm: RFC 6234 [RFC6234], SHA-512 (SHA-2 with 512-bits of
1105 | digest output)
1106 | Digital Signature Algorithm: Derived from metadata associated with
1107 | `keyId`. Recommend support for RFC 8017 [RFC8017], Section 8.1:
1108 | RSASSA-PSS, RFC 6234 [RFC6234], Section 7.1: SHA-Based HMACs, ANSI
1109 | X9.62-2005 ECDSA, P-256, and RFC 8032 [RFC8032], Section 5.1:
1110 | Ed25519ph, Ed25519ctx, and Ed25519.
1111 |
1112 | Algorithm Name: rsa-sha1
1113 | Status: deprecated, SHA-1 not secure.
1114 | Canonicalization Algorithm: [RFC_THIS_DOCUMENT], Section 2.3:
1115 | Signature String Construction [23]
1116 |
1117 |
1118 |
1119 |
1120 | Cavage & Sporny Expires April 3, 2020 [Page 20]
1121 |
1122 | Internet-Draft Signing HTTP Messages October 2019
1123 |
1124 |
1125 | Hash Algorithm: RFC 6234 [RFC6234], SHA-1 (SHA-1 with 160-bits of
1126 | digest output)
1127 | Digital Signature Algorithm: RFC 8017 [RFC8017], Section 8.2: RSASSA-
1128 | PKCS1-v1_5
1129 |
1130 | Algorithm Name: rsa-sha256
1131 | Status: deprecated, specifying signature algorithm enables attack
1132 | vector.
1133 | Canonicalization Algorithm: [RFC_THIS_DOCUMENT], Section 2.3:
1134 | Signature String Construction [24]
1135 | Hash Algorithm: RFC 6234 [RFC6234], SHA-256 (SHA-2 with 256-bits of
1136 | digest output)
1137 | Digital Signature Algorithm: RFC 8017 [RFC8017], Section 8.2: RSASSA-
1138 | PKCS1-v1_5
1139 |
1140 | Algorithm Name: hmac-sha256
1141 | Status: deprecated, specifying signature algorithm enables attack
1142 | vector.
1143 | Canonicalization Algorithm: [RFC_THIS_DOCUMENT], Section 2.3:
1144 | Signature String Construction [25]
1145 | Hash Algorithm: RFC 6234 [RFC6234], SHA-256 (SHA-2 with 256-bits of
1146 | digest output)
1147 | Message Authentication Code Algorithm: RFC 6234 [RFC6234],
1148 | Section 7.1: SHA-Based HMACs
1149 |
1150 | Algorithm Name: ecdsa-sha256
1151 | Status: deprecated, specifying signature algorithm enables attack
1152 | vector.
1153 | Canonicalization Algorithm: [RFC_THIS_DOCUMENT], Section 2.3:
1154 | Signature String Construction [26]
1155 | Hash Algorithm: RFC 6234 [RFC6234], SHA-256 (SHA-2 with 256-bits of
1156 | digest output)
1157 | Digital Signature Algorithm: ANSI X9.62-2005 ECDSA, P-256
1158 |
1159 | Authors' Addresses
1160 |
1161 | Mark Cavage
1162 | Oracle
1163 | 500 Oracle Parkway
1164 | Redwood Shores, CA 94065
1165 | US
1166 |
1167 | Phone: +1 415 400 0626
1168 | Email: mcavage@gmail.com
1169 | URI: https://www.oracle.com/
1170 |
1171 |
1172 |
1173 |
1174 |
1175 |
1176 | Cavage & Sporny Expires April 3, 2020 [Page 21]
1177 |
1178 | Internet-Draft Signing HTTP Messages October 2019
1179 |
1180 |
1181 | Manu Sporny
1182 | Digital Bazaar
1183 | 203 Roanoke Street W.
1184 | Blacksburg, VA 24060
1185 | US
1186 |
1187 | Phone: +1 540 961 4469
1188 | Email: msporny@digitalbazaar.com
1189 | URI: https://manu.sporny.org/
1190 |
1191 |
1192 |
1193 |
1194 |
1195 |
1196 |
1197 |
1198 |
1199 |
1200 |
1201 |
1202 |
1203 |
1204 |
1205 |
1206 |
1207 |
1208 |
1209 |
1210 |
1211 |
1212 |
1213 |
1214 |
1215 |
1216 |
1217 |
1218 |
1219 |
1220 |
1221 |
1222 |
1223 |
1224 |
1225 |
1226 |
1227 |
1228 |
1229 |
1230 |
1231 |
1232 | Cavage & Sporny Expires April 3, 2020 [Page 22]
1233 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | All Reports in this Repository are licensed by Contributors under the [W3C Software and Document
2 | License](https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document).
3 |
4 | Contributions to Specifications are made under the
5 | [W3C CLA](https://www.w3.org/community/about/agreements/cla/).
6 |
7 | Contributions to Software, including sample implementations, are under the
8 | [Apache 2.0 License](https://www.apache.org/licenses/LICENSE-2.0).
9 |
--------------------------------------------------------------------------------
/index.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | ]>
18 |
19 |
20 |
21 |
22 |
23 |
24 |
26 |
27 | Signing HTTP Messages
28 |
29 |
30 | Oracle
31 |
32 |
33 | 500 Oracle Parkway
34 | Redwood ShoresCA
35 | 94065
36 | US
37 |
38 | +1 415 400 0626
39 | mcavage@gmail.com
40 | https://www.oracle.com/
41 |
42 |
43 |
44 |
45 | Digital Bazaar
46 |
47 |
48 | 203 Roanoke Street W.
49 | BlacksburgVA
50 | 24060
51 | US
52 |
53 | +1 540 961 4469
54 | msporny@digitalbazaar.com
55 | https://manu.sporny.org/
56 |
57 |
58 |
59 |
60 | Security
61 |
62 | HTTP
63 | digital signature
64 | PKI
65 |
66 |
67 | This community specification has been moved to the IETF HTTP Working Group for
68 | standardization as the
69 | Signing HTTP Messages specification.
70 |
71 |
72 |
73 |
74 | This community specification has been moved to the IETF HTTP Working Group for
75 | standardization as the
76 | Signing HTTP Messages specification.
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 | This community specification has been moved to the IETF HTTP Working Group for
86 | standardization as the
87 | Signing HTTP Messages specification.
88 |
89 |
90 |
91 |
92 |
--------------------------------------------------------------------------------