A public key authentication scheme for HTTP transactions, specifying a minimal HTTP extension for mutual authentication, message origin authentication, message sequence integrity, content integrity, and content ciphering.
This document is a draft specification which may undergo minor changes, both normative and presentational.
This specification describes a public key authentication scheme for HTTP transactions. It provides a minimal HTTP extension for mutual authentication and message origin authentication. It offers integrity protection of a defined set of HTTP message headers, message sequence integrity, content integrity, and content ciphering.
This scheme is designed to fit into the generic authentication framework of RFC2616 [HTTP], as exploited in RFC2617 [HTTP-Authentication].
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this specification are to be interpreted as described in RFC2119 [KEYWORDS]
"Peer" refers generically to either of the two principals acting as requester and responder in an HTTP message exchange. Formally, a peer is a logical entity that can invoke its associated private key for the purpose of that exchange. Note that user-agents and/or servers may act as (or for) a multitude of logically distinct peers, and are thus not themselves considered necessarily equivalent to those peers.
"Message" refers generically to an HTTP message, be it a request or a response.
"requester" refers to the peer sending a request message and receiving a response message.
"responder" refers to the peer receiving a request message and sending a response message.
"Encryption" is used in relation to asymmetric key operations, whereas the term "cipher" is used in relation to symmetric key operations.
The identifier for this scheme is "httpsec/1.0". This literal features in protocol headers and in
various protocol computations.
The identifier for the Content-Encoding defined for message-body
ciphering is "x-httpsec/1.0-cipher".
This specification describes a concrete syntax for a public key authentication scheme for HTTP transactions. It provides a minimal HTTP extension for mutual authentication and message origin authentication, via the integrity protection of a defined set of HTTP message headers. It offers message sequence integrity, forward secrecy, and optionally content integrity and content ciphering.
It is intended for application in situations where credential-based schemes are inappropriate for architectural reasons or are considered too weak, and also where message-layer and/or application-layer security requirements are not fulfilled by transport-layer or network-layer security protocols. It is not intended as a substitute for lower- or higher-layer security protocols, and indeed may be found to usefully coexist with these.
This scheme uses public keys for the mutual authentication of peers. More precisely, it allows one peer to authenticate a message that purports to originate from another peer.
As with all public key authentication schemes, acceptance of the authenticity of a peer is equivalent to establishing that the peer possesses the private key paired with a certain public key. The authentication model is thus predicated on the assumption that the authenticator can correctly associate a public key with the peer it is authenticating. Accordingly, a candidate purporting to be such a peer is considered authentic if it can demonstrate its ability to invoke the associated private key. This document does not address the process by which a public key is associated (correctly or not) with a peer. The protocol is intended to be able to integrate with any number of such mechanisms, from "leap of faith" type schemes such as employed by SSH, to trust-based schemes such as PKI style certification.
A peer has an associated identifier. This acts as a logical reference to the peer's public key. These peer identifiers are literals that are purposefully opaque in this specification. The combination of an identifier and the public key associated with it is the "authenticated peer" from the perspective of an other peer that authenticates it.
In some use-cases, the public key of one peer is considered to be known (or retrievable in a trusted manner) by a second peer that requires it in order to authenticate the first peer. The first peer's identifier is thus a reference that the second peer may use to retrieve the appropriate public key, for instance from a trusted local store. In other use-cases, for example those that require a bootstrapping capability, public keys are exchanged within the protocol itself.
This protocol enables, and depends on, the establishment of a shared-secret arrangement between the requester and the responder. The protocol has two distinct stages; "initialization" and "continuation". Initialization establishes a shared-secret between the requester and responder via a request/response transaction between the two. It is within this initialization transaction that the public keys of the peers are employed for mutual authentication.
Subsequent continuation transactions carry conventional message payloads. They reference the shared secret established by the initialization stage, and depend on both peers' knowledge of it for their security features. No temporal constraint is placed on the validity of the shared-secret arrangement, which may be chosen independently by either peer to be anything from very short lived to essentially permanent. (The initialization stage could in fact be effected by another process entirely outside of this specification.)
The responder is first authenticated in the initialization stage by the use of digital signatures. The requester is authenticated in each continuation transaction by the use of message authentication codes. This asymmetry allows the requester to authenticate the responder before sending it any data, while keeping all public-key and other key-exchange operations within the single initialization transaction. This mitigates the state-management requirements and ensures that computationally expensive operations are avoided in subsequent continuation messages, of which there may be an arbitrary number.
The requester begins the initialization stage by sending a request containing its initialize parameters. The responder returns with a response containing its initialize parameters. Both these messages contain the peer's identifier, ephemeral Diffie-Hellman key, and optionally their authentication public key. See Initialization Request and Initialization Response for the form these messages take.
This initialization transaction establishes an authenticated shared-secret arrangement between both peers, indexed by a token chosen by the responder. Forward secrecy is ensured by the ephemeral Diffie-Hellman shared-secret exchange. Both peers identically derive temporary message authentication keys and cipher keys from the shared-secret, to be employed in the protection of subsequent continuation messages.
Whereas the protocol mandates certain conditions under which these temporary keys must be discarded, either peer may choose to discard them according to rules of their own, for instance based on elapsed time since last usage.
Continuation requests carry a token to reference a previously initialized shared-secret arrangement. All continuation messages carry message authentication codes to determine message origin authenticity, partial sequence integrity, and optionally entity-body integrity. Continuation messages may employ optional message body ciphering at the discretion of the sending peer. In all other respects, continuation messages are conventional HTTP messages. See Continuation Request and Continuation Response for the form these messages take.
The responder may at any stage prompt initialization (or re-initialization) by returning a challenge response. See Challenge Response for the form this message takes.
All protocol parameters are carried in existing HTTP message headers. The Authorization request header
[HTTP][ Section 14.8] carries the requester's protocol parameters. The WWW-Authenticate response
header [HTTP][ Section 14.47] carries the responder's
responder's parameters. These are the headers implied wherever reference is made in this document to the passing of
protocol parameters by the respective peers.
The HTTP header definitions in this specification use the augmented Backus-Naur form of [HTTP] [Section 2.1], and use these common terminators:
base64 = *(4base64-char) [base64-terminal]
base64-char = "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" |
"I" | "J" | "K" | "L" | "M" | "N" | "O" | "P" |
"Q" | "R" | "S" | "T" | "U" | "V" | "W" | "X" |
"Y" | "Z" |
"a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" |
"i" | "j" | "k" | "l" | "m" | "n" | "o" | "p" |
"q" | "r" | "s" | "t" | "u" | "v" | "w" | "x" |
"y" | "z" |
"0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" |
"8" | "9" | "+" | "/"
base64-terminal = (2base64-char "==") | (3base64-char "=")
decimal = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
Definitions of individual header directives are given in the Protocol Directives section.
Messages containing an initialize directive assert that the sending peer is providing initialization
parameters. Successful initialization requires an initialization
request and an associated initialization response.
The Authorization header [HTTP][ 14.8] in protocol initialization
requests has the following form:
"Authorization: httpsec/1.0 initialize, " 1#( id | dh | [certificate] | url | group | nonce ) id = "id=" <URI> dh = "dh=" base64 certificate = "certificate=" <URI> url = "url=" <URI> group = "group=" <string-no-whitespace> nonce = "nonce=" base64
Example message:
HEAD http://alice.example.com/foobar.txt HTTP/1.1
Authorization: httpsec/1.0 initialize
id=bob.example.com
dh=clW9y2X5Vy+5+Ncv5lAI3W9y2X5Vgfe4y+5+Ncv5l...
certificate=http://bob.example.com/my-cert
url=http://alice.example.com/foobar.txt
group=rfc3526#14
nonce=7iqgkzgfdIe0HN35r6met2579yxetyerty7MZW...
(For legibility, the example's protocol header is extended over multiple lines, as per [HTTP][4.2]. Additionally, the values of some directives are lengthy and have therefore been abbreviated; their terminating ellipsis "..." would NOT appear in the actual value.)
An initialization request has a HEAD method [HTTP][ Section 9.4], unless it carries a certificate payload in the message entity-body (see certificate section) in which case it has a POST method [HTTP][ Section 9.5].
Its Request-URI [HTTP][ Section 5.1.2] is typically be that of a protected resource hosted by the responder and ultimately desired by the requester, but this is not normative.
The WWW-Authenticate header [HTTP][ 14.47] in protocol initialization
responses has the following form:
"WWW-Authenticate: httpsec/1.0 initialize, " 1#( id | dh | [certificate] | token | auth | signature ) token = "token=" <string-no-whitespace> id = "id=" <URI> dh = "dh=" base64 certificate = "certificate=" <URI> auth = "auth=" base64 signature = "signature=" base64
Example message:
HTTP/1.1 401 Authorization Required
Expires: Thu, 11 Aug 2005 18:20:42 GMT
Cache-Control: no-transform
WWW-Authenticate: httpsec/1.0 initialize
id=alice.example.com
dh=+NcclW9y2I3W9X5Vy+5v5lAy4X56y+Ncrwrtv5lqe...
certificate=http://alice.example.com/my-cert
token=mCa5tx1vKBY
auth=vpCNmx7MZ7iqgkzIe0HWwfyrOMeqwg0TdbpwefI...
signature=2pX3SNgzWkV3w0W9y2X5V23hhy+5b8DQmo...
(For legibility, the example's protocol header is extended over multiple lines, as per [HTTP][4.2]. Additionally, the values of some directives are lengthy and have therefore been abbreviated; their terminating ellipsis "..." would NOT appear in the actual value.)
Messages containing a continue directive assert that the message is protected by security features that
derive from a previously initialized shared-secret arrangement. A continuation transaction constitutes a continuation request and an associated continuation response.
A continuation message MUST pass Message Validation or be immediately discarded by the peer that receives it.
The Authorization header [HTTP][ 14.8] in protocol continuation
requests has the following form:
"Authorization: httpsec/1.0 continue, " 1#( token | url | count | mac | [digest] ) token = "token=" <string-no-whitespace> url = "url=" <URI> count = "count=" 1*decimal mac = "mac=" base64 digest = "digest=" base64
Example message:
GET http://alice.example.com/foobar.txt HTTP/1.1
Authorization: httpsec/1.0 continue
token=mCa5tx1vKBY
url=http://alice.example.com/foobar.txt
count=1
mac=zhHPRbxqf3KSMQpjCnpDQmyBnoqiNDMQLjRtMjxUcM=
(For legibility, the example's protocol header is extended over multiple lines, as per [HTTP][4.2].)
The WWW-Authenticate header [HTTP][ 14.47] in protocol continuation
responses has the following form:
"WWW-Authenticate: httpsec/1.0 continue, " 1#( count | mac | [digest] ) count = "count=" 1*decimal mac = "mac=" base64 digest = "digest=" base64
Example message:
HTTP/1.1 200 OK
Date: Thu, 11 Aug 2005 18:20:48 GMT
Expires: Thu, 11 Aug 2005 18:20:48 GMT
Content-Type: text/plain;charset=ISO-8859-1
Content-Length: 1234
Cache-Control: no-transform
Content-Encoding: x-httpsec/1.0-cipher
WWW-Authenticate: httpsec/1.0 continue
count=2
mac=VplDHX3SNgzWkLKgZkjZ+I5wvImOHAMptVSc/Abttps=
digest=V3w0W9y2X5Vy+5+Ncv5lAI3rb8qMlGzrOh9zjHXRHbk=
<entity-body ciphertext bytes>
(For legibility, the example's protocol header is extended over multiple lines, as per [HTTP][4.2].)
The challenge response is an assertion by the responder that the requested resource is protected by HTTPsec. It is an invitation, made by responder to requester, to make a subsequent initialization request.
In the handling of a Challenge Response, the requester SHOULD employ a method of limiting the extent of potential deadlock from a repeated series of challenge, for instance limiting them to an arbitrary number such as 3.
The WWW-Authenticate header [HTTP][ 14.47] for challenge responses has
the following form:
"WWW-Authenticate: httpsec/1.0 challenge, " 1#( id | [certificate] ) id = "id=" <URI> certificate = "certificate=" <URI>
Example message:
HTTP/1.1 401 Unauthorized
WWW-Authenticate: httpsec/1.0 challenge
id=alice.example.com
certificate=http://alice.example.com/my-cert
(For legibility, the example's protocol header is extended over multiple lines, as per [HTTP][4.2].)
This section details the conditions which regulate how requests and responses are matched, and which HTTP status codes [HTTP][ Section 10] are set by the responder.
401 Unauthorized" [HTTP][ 10.4.2] status. The requester may
subsequently send an initialization request.401 Unauthorized"
[HTTP][ 10.4.2] status.400 Bad Request" [HTTP][ 10.4.1]
status.401 Unauthorized" [HTTP][ 10.4.2].401 Unauthorized" [HTTP][ 10.4.2] status. The requester may subsequently send an initialization request.All protocol parameters feature as directives in initialization messages and continuation messages. These directives are detailed in this section.
The id directive in an initialization request is the
requester's Peer Identifier. From the responder's perspective, this acts
as a logical reference to the requester's public-key.
The id directive in an initialization response or a
challenge response is the responder's Peer Identifier. From the requester's perspective, this acts as a logical reference to the responder's
public-key.
The dh directive in an initialization request and an
initialization response provides the sending peer's ephemeral
Diffie-Hellman public key.
This directive is calculated as follows:
dh = g ^ dh-private MOD p
where the following apply:
g is the generator of the Diffie-Hellman group. The latter is chosen by the requester and identified
by the group directive in the initialization request.p is the prime modulus of the Diffie-Hellman group.private-dh is a random integer in the range: 2...q-2 where q is the
subgroup order of the Diffie-Hellman group. Note that q =
(p-1)/2 for all the MUST IMPLEMENT groups.The value of private-dh is chosen by the sending peer from a source of cryptographic-quality
randomness, and is treated as strictly private. It SHOULD be generated anew for each new initialization, in which case
it SHOULD be discarded immediately after the computation of the shared
secret. However if computational resources are limited it MAY be reused across multiple initializations, but this
will affect the effective extent of the protocol's claim to forward secrecy.
The optional certificate directive in an initialization
request and an initialization response provides the sending
peer's certificate containing its (purported) authentication public key. The directive may also be employed for
informational purposes in a challenge response. In some use-cases a
peer's public key is prior-knowledge from the perspective of the other peer, and thus the certificate
directive is not required.
If employed, its value MUST be a valid URI as specified in [URI] Section 3.
Certificates provided by the certificate directive MUST be in X509 [X509] certificate format to allow (if required) the use of a Public Key Infrastructure.
Implementations MAY support either or all of the following:
certificate=data:application/x-x509-user-cert;base64,MIGfMA0GCSqGSI...(the value is lengthy and has therefore been abbreviated; the terminating ellipsis "..." would NOT appear in an actual value)
certificate=http://alice.example.com/my-cert
this:entity-body" to indicate that the X509 certificate is carried in the
message entity-body. For example
certificate=this:entity-body
In all cases, the Mine-Type of the certificate payload MUST be "application/x-x509-user-cert".
Certificates in entity-bodies may optionally have the PEM specified header, footer and line breaks.
Note that in the first usage, the certificate payload itself features in the Initialization Transcript and its presence in the initialisation stage is thus authenticated by the signature. This may be considered favourable in some use-cases.
The url directive in an initialization request and a
continuation request is the the absolute URL of that request. The
latter is duplicated in this directive because proxies are legitimately allowed to change the Request-Line in
transit.
The responder MUST confirm that the value of this directive is equivalent to the absolute URL implied by the
request's Request-Line [HTTP] and Host [HTTP] header. Equivalence conditions for URLs are given in [URI] Section 6.
The group directive in an initialization request is
the identifier of a Diffie-Hellman modular exponential group, as chosen by the requester. It's value MUST NOT contain
whitespace.
Any or all of the following identifiers and their associated groups MAY be implemented:
"rfc3526#14" ; group #14 defined in [MODP] "rfc3526#15" ; group #15 defined in [MODP] "rfc3526#16" ; group #16 defined in [MODP] "rfc3526#17" ; group #17 defined in [MODP] "rfc3526#18" ; group #18 defined in [MODP]
Other identifiers may be also defined.
The nonce directive in an initialization request
allows the requester to send a random value to the responder. This acts as an authentication challenge to the
responder, who is challenged to posses the correct private key in order to create a valid signature directive in the initialization
response.
This value is a base64 encoded 256 bit cryptographic-quality random value, which MUST be generated afresh by the requester for each new initialization.
The auth directive in an initialization response
allows the responder to send an encrypted random value to the requester. This acts as an authentication challenge to
the requester. The random value auth-secretis encrypted in the requester's public key, yet features
unencrypted in the shared secret which must be identically known to both
parties for the authentication success of subsequent continuation
messages. The requester is thus challenged to posses the correct private key to decrypt the value of the
auth directive.
The auth directive is computed as follows:
auth = base64enc( ENC( public-key, auth-secret ) )
where the following apply:
base64enc() is base64 encoding, bytes to string.ENC( k, pt ) is encryption according to the Encryption
Scheme in public key k of plaintext pt.public-key is the public key associated
(subjectively, by the responder) with the requester.auth-secret is 256 bit cryptographic-quality random value generated by the responder, which MUST be
generated afresh by the responder for each new initialization.The requester decrypts the auth directive to retrieve the auth-secret value as
follows:
auth-secret = DEC( private-key, base64dec( auth ) )
where the following apply:
base64dec() is base64 decoding, string to bytes.DEC( k, ct ) is decryption according to the Encryption
Scheme with private key k of ciphertext value ct.private-key is the requester's private key.auth-secret is 256 bit random value.In an initialization response, the token directive
is is an opaque reference to the newly initialized shared-secret arrangement. Its value is chosen by the responder, and
MUST be unique within the responder's record of valid tokens. It's value MUST NOT contain whitespace, but its length or
other characteristics are not otherwise constrained.
In a continuation Request the token directive is
employed by the requester as a reference to a previously initialized shared-secret arrangement. From the perspective of
both the request's requester and its responder, the referenced arrangement implies the MAC keys to create or validate mac directives, and implies the
cipher keys for message body
ciphering or deciphering.
The signature directive in an initialization
response is used to verify the integrity of all the initialization directives and thus allows the requester to
authenticate the responder prior to making any continuation requests.
The signature directive is computed by the responder as follows:
signature = base64enc( SIGN( private-key, init-transcript ) )
where the following apply:
base64enc() is base64 encoding, bytes to string.SIGN(k,m) is the signature over string m using private key k according to
the Signature Scheme.private-key is the responder's authentication key private key.init-transcript is a concatenation of all the initialization directives, computed according to the
Initialization Transcript section.The signature directive is validated by the requester as follows:
VALIDATE( public-key, init-transcript, base64dec( signature ) )
where the following apply:
base64dec() is base64 decoding, string to bytes.VALIDATE(k,m,s) is the validation of a signature s over a string m using
public key k, according to the Signature Scheme.signature is the value of the received directive.public-key is the public key associated (subjectively, by the requester) with the responder. Note
that this may or may not be equivalent the public key implied by the certificate directive, depending on the trust mechanism employed by the requester.init-transcript is a concatenation of all the initialization directives, computed according to the
Initialization Transcript section.The count directive is a sequence counter for continuation messages. This directive allows the
detection of message replays and provides partial message sequence integrity. It is also required for the production of
unique initialization vectors for message body ciphering.
The value of the count directive is a decimal number. In a request, it MUST be greater than zero and
less than (2^128 - 1). In a response, it MUST be greater than one and less than or equal to (2^128 - 1).
The following constraints apply to this directive in continuation messages containing identical token directive values. Messages with identical or out-of-sequence count
directive values MUST be rejected by the receiving peer. Peers MUST validate the count directive in each
received message to establish uniqueness and correct sequence. Each peer is required to maintain a local record of the
value of the count directive employed in the last continuation message that it sent. The validity
constraints and logic for setting this directive differ slightly from the perspectives of the two peers:
count value of N+1, where N is the count value in the
associated request.count value N MUST be strictly greater than the count value
that the responder sent in its last response. The response MUST be given a count value of N+1.If a first request receives no response, the count directive in a second request that immediately
follows should increment by (at least) 2, to allow for the fact that the unreceived response was nevertheless sent by
the responder. In the case that the first request contained an "Expect: 100-continue" header [HTTP][14.20] the increment should be (at least) 3, as such requests may elicit two distinct responses.
The mac directive in a continuation request and a
continuation response is a keyed message authentication code computed
on the values of protocol directives and specific HTTP headers present in that continuation transaction. It employs a
MAC Key derived from the Shared
Secret.
To create a message authentication code for a message either prior to sending it or in order to validate it, the appropriate computation is made as follows:
Request: mac = base64enc( HMAC( request-mac-key, request-transcript ) ) Response: mac = base64enc( HMAC( response-mac-key, response-transcript ) )
where the following apply:
base64enc() is base64 encoding, bytes to string.HMAC(k,d) is the Hashed Message Authentication Code [HMAC]
using key k applied to byte data d, employed using the Hash Algorithm.request-mac-key and response-mac-key are as derived in the section MAC Keys.request-transcript is computed according to the Continuation Request Transcript section.response-transcript is computed according to the Continuation Response Transcript section.The message authentication codes are formulated so as to provide the following:
The sender of a message computes and provides the message authentication code for that message. To validate it, the
recipient of the message also computes its message authentication code and compares the received value with the
computed value. If (1) they are strictly equal, and (2) the digest
directive (if present) is confirmed to indeed equal the hash of the message entity-body, then the above authentication
characteristics are considered to be established. If not, the message MUST be rejected. This two stage process permits
computationally inexpensive invalidity checks to be performed before embarking on the potentially expensive process of
computing the digest over an arbitrary length entity-body.
The the optional digest directive in a continuation
request or a continuation response is a hash digest of the
message entity-body. It's role is to enable message entity-body authentication: its value is an input to the
computation of the mac directive (via the appropriate message transcript).
This directive SHOULD be present in any continuation message for which it is feasible to calculate a hash digest of the
entity-body (including, trivially, all those with an empty entity-body).
The value of the digest directive is a hash of the entity-body, computed using the Hash Algorithm. The hash MUST be computed on the entity-body as manifest
after all encodings declared in the Content-Encoding [HTTP][ 14.11] header (including the cipher
encoding with the identifier "x-httpsec/1.0-cipher" defined in the Message Body Ciphering section) and before Transfer-Encoding [HTTP][ 14.41].
The absence of the digest directive implies that the message entity-body is not authenticated. This may
be the case if the entity-body cannot be hashed for some reason by the message sender, for instance if it is a stream
of indeterminate length.
The value of the digest directive MUST be base64 encoded. For empty message bodies, it is the following
constant (being the Base64 representation of the hash of zero bytes):
47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=
This specification impacts on certain other HTTP header field definitions, as detailed in this section.
The Content-Encoding header [HTTP][ 14.11] MAY contain the value
"x-httpsec/1.0-cipher" in its enumeration of applied encodings, to indicate that the message entity body
is ciphered according to this specification - see the Message_Body_Ciphering section for details.
The Cache-Control header [HTTP][ 14.9] MUST be present in every
initialization response and continuation response. It MUST contain at minimum the no-transform directive [HTTP][ 14.9.5]. See the Cache Considerations section for
additional discussion.
The Expires header [HTTP][ 14.21] MUST be present in every
initialization response and continuation response. responses. Its value MUST be the system clock time, current at the time of the
preparation of the response's WWW-Authenticate: httpsec/1.0 continue header. Whist the value of this
header appears in the computation of the mac directive, it has no explicit role in
message validation. See also the Cache Considerations section for additional discussion.
Wherever they are referred to in this specification, the cryptographic primitives defined in this section MUST be employed.
SHA-256 [SHA].
RSA [PKCS#1] asymmetric key encryption. The modulus of key MUST be 1024 bits or greater.
RSA Optimal Asymmetric Encryption Padding (RSAES-OAEP) [PKCS#1], using hash function SHA-1, mask generation function MGF1 (with SHA-1), and the empty-string for the "label" parameter.
Note: whereas SHA-256 is specified as the Hash Algorithm primitive for employment elsewhere in the protocol, the choice of the SHA-1 here is made for the following reasons:
RSA Probabilistic Signature Scheme (RSASSA-PSS) [PKCS#1], using hash function SHA-256, mask generation function MGF1 (with SHA-256), and salt length of 32 bytes.
Advanced Encryption Standard [AES], 256 bit key length.
Cipher Block Chaining mode [CBC], with PKCS#5 [PKCS#5 ] padding, applied to the Block Cipher.
The values of various HTTP headers [HTTP][ 4.2] other than the protocol headers also feature in protocol computations, notably the signature and message authentication codes. The values of these headers MUST first undergo the following canonicalization transformations, applied in strict order:
;") and/or commas
(",");") any internal substring that consists only of semicolons
(";") and/or commas (",").For example, the (albeit unlikely) header field-value ";foo,, ; bar;; foo bar;" becomes
"foo;bar;foobar".
Note that this canonicalization is strictly a pre-processing step for the purpose of protocol computations only. It is not a constraint on the actual header field-values that may appear in a message.
The initialization transcript is an input to signature creation and validation, and shared secret computations. It is itself computed as follows:
init-transcript =
"httpsec/1.0" || ":" ||
id || ":" || ; from request
dh || ":" || ; from request
certificate || ":" || ; from request
url || ":" || ; from request
group || ":" || ; from request
nonce || ":" || ; from request
id || ":" || ; from response
dh || ":" || ; from response
certificate || ":" || ; from response
token || ":" || ; from response
auth || ":" || ; from response
Expires ; from response
where the following apply:
id, dh, certificate, url, group,
token, and auth refer to the directives contained in the Initialization Messages. They are the directives' literal US-ASCII encoded values exactly as they
appear in those headers.Expires is the value of [HTTP][ 4.2] header of that name, having
undergone canonicalization as detailed in the Header
Canonicalization section.The continuation request transcript is an input to mac directive creation and validation. It is itself computed as follows:
request-transcript =
"httpsec/1.0" || ":"
|| token || ":"
|| count || ":"
|| url || ":"
|| digest || ":"
|| Method || ":"
|| Content-MD5 || ":"
|| Content-Encoding || ":"
|| Content-Range || ":"
|| Content-Type
where the following apply:
token, count, url, and digest refer to the protocol directives with those names. They are the directives' literal
US-ASCII encoded values exactly as they appear in those headers.Method is the Method [HTTP][ 5.1.1] from the request's
Request-Line [HTTP][ 5.1].Content-MD5, Content-Encoding, Content-Range, and
Content-Type refer to [HTTP][ 4.2] headers. Their values MUST first
undergo canonicalization as detailed in the Header
Canonicalization section.The continuation response transcript is an input to mac directive creation and validation. It is itself computed as follows:
response-transcript =
"httpsec/1.0" || ":"
|| token || ":" ; from request
|| count || ":"
|| url || ":" ; from request
|| digest || ":"
|| Method || ":" ; from request
|| Status-Code || ":"
|| Content-Location || ":"
|| Content-MD5 || ":"
|| ETag || ":"
|| Last-Modified || ":"
|| Expires || ":"
|| Content-Encoding || ":"
|| Content-Range || ":"
|| Content-Type
where the following apply:
token, count, url, and digest refer to the protocol directives with those names. They are the directives' literal
US-ASCII encoded values exactly as they appear in those headers.Method is the Method [HTTP][ 5.1.1] from the request's
Request-Line [HTTP][ 5.1].Status-Code is the three digit Status Code [HTTP][ 6.1.1] from the response's
Status-Line [HTTP][ 6.1].Content-Location, Content-MD5, ETag, Last-Modified,
Expires, Content-Encoding, Content-Range, and Content-Type refer
to [HTTP][ 4.2] headers. Their values MUST first
undergo canonicalization as detailed in the Header
Canonicalization section.The security of the protocol depends on the requester and responder establishing an (authenticated) shared secret. Continuation messages employ keys that are derived from this secret value.
The value shared-secret is computed as follows:
shared-secret = H(H( dh-shared-secret || auth-secret || init-transcript ))
where the following apply:
dh-shared-secret is calculated by the requester as follows:
dh-shared-secret = dh ^ dh-private MOD pwhere
dh is from the
initialization response, dh-private is the requester's private Diffie-Hellman value (see dh ) and p is the prime modulus of the Diffie-Hellman group chosen
by the requester.
dh-shared-secret is calculated by the responder as follows:
dh-shared-secret = dh ^ dh-private MOD pwhere
dh is from the
initialization request, dh-private is the responders's private Diffie-Hellman value (see dh ) and p is the prime modulus of the Diffie-Hellman group
identified by the group directive in the initialization request.
auth-secret is the 256 bit random value generated by the responder. It is passed in encrypted form
to the requester via the auth directive in the initialization response.init-transcript is a concatenation of all the initialization directives, computed according to the
Initialization Transcript section.H(H()) is the Hash Algorithm iteratively applied
twice.From the Shared Secret, both peers derive identical MAC keys and Cipher Keys. Since the Shared Secret is static throughout the lifetime of a particular shared secret arrangement, the keys may be computed once from the shared-secret by each peer and stored for the lifetime of that arrangement. The shared-secret SHOULD be discarded immediately thereafter.
The MAC keys for computing mac directives are produced as follows:
request-mac-key = H(H( shared-secret || "request MAC key" )) response-mac-key = H(H( shared-secret || "response MAC key" ))
where the following apply:
shared-secret is computed according to the Shared Secret
section.H(H()) is the Hash Algorithm iteratively applied
twice.The keys required for message body ciphering are computed as follows:
request-cipher-key = H(H( shared-secret || "request cipher key" )) response-cipher-key = H(H( shared-secret || "response cipher key" ))
where the following apply:
shared-secret is computed according to the Shared Secret
section.H(H()) is the Hash Algorithm iteratively applied
twice.Message entity-body ciphering may be be applied to any continuation message, at the discretion of the sending peer.
If entity-body ciphering is applied, this MUST be indicated by the presence of the "x-httpsec/1.0-cipher"
identifier in the enumeration of applied encodings declared by the Content-Encoding header. The order of operations is "cipher-then-authenticate", i.e. if used ciphering MUST
be applied before the digest computation.
The ciphering of messages whose entity-body is empty will cause the entity-body to become non-empty as an artifact of padding scheme specified in the Block Cipher Mode. This should be taken into consideration when preparing messages for which it is illegal to have an entity body, such as GET requests, HEAD requests, and HEAD responses.
It is important to note that message entity-body ciphering in the absence of message authentication provides no
detection of tampering during message transport. Entity-bodies are "ciphered but not authenticated" if they declare
"x-httpsec/1.0-cipher" in the Content-Encoding header, but
have no digest directive. This outcome SHOULD be restricted to
circumstances where it is unfeasible to compute the digest hash, for
instance when the entity-body is a stream of indeterminate length.
Request entity-bodies are enciphered and deciphered as follows:
Encipher: <body-cipher> = ENCIPHER-MODE( request-cipher-key, IV, <body-plain> ) Decipher: <body-plain> = DECIPHER-MODE( request-cipher-key, IV, <body-cipher> ) where: IV = ENCIPHER( request-cipher-key, Bytes16( count ) )
Response entity-bodies are enciphered and deciphered as follows:
Encipher: <body-cipher> = ENCIPHER-MODE( response-cipher-key, IV, <body-plain> ) Decipher: <body-plain> = DECIPHER-MODE( response-cipher-key, IV, <body-cipher> ) where: IV = ENCIPHER( request-cipher-key, Bytes16( count ) )
The following are defined and apply to both requests and responses:
request-cipher-key and response-cipher-key are as derived in the section Cipher Keys.count is the numerical value implied by the count
directive of the message being enciphered/deciphered.Bytes16(x) is the value x encoded with leading zeros in exactly 16 bytes, most
significant bits first, most significant byte first.ENCIPHER(k,b) is the block enciphering function employing this specification's Block Cipher, using key k, applied to input block b.
Lengths are as follows: k is 32 bytes, and b is 16 bytes.ENCIPHER-MODE(k,iv,t) is the chained enciphering function employing this specification's Block Cipher Mode, using key k, initialization vector
iv, applied to input text t. Lengths are as follows: k is 32 bytes,
n is 16 bytes, t is of arbitrary length.DECIPHER-MODE(k,iv,t) is the chained deciphering function employing this specification's Block Cipher Mode, using key k, initialization vector
iv, applied to input text t. Lengths are as follows: k is 32 bytes,
n is 16 bytes, t is of arbitrary length.<body-plain> is the plaintext bytes of the message entity-body, as manifest after all
encoding declared in the Content-Encoding [HTTP][ 14.11] header are applied.<body-cipher> is the ciphertext bytes of the message entity-body, as manifest before
any encodings declared in the Transfer-Encoding [HTTP][ 14.41] header are applied.Validity conditions are given in this section for all protocol messages. Messages MUST satisfy all their respective conditions. The conditions are presented in suggested processing order determined by their increasing computational burden. The failure of any condition should immediately cause processing to terminate and the message to be discarded.
An initialization request message MUST meet all the following conditions to be considered valid by the responder that receives it:
url directive satisfies its equivalence condition.dh directive meets these conditions:
dh > 1dh < pdh ^ q MOD p = 1p and q are from the Diffie-Hellman group indicated by the accompanying
group directive.
certificate directive, if present and if considered by
the responder, provides a public key that is valid according to the Public Key Algorithm specification, notably regarding minimum key size.certificate directive, if present and if considered by
the responder, satisfies locally determined validation constraints, typically with respect to installed certification
authority root certificates.A initialization response message MUST meet all the following conditions to be considered valid by the requester that receives it:
dh directive meets these conditions:
dh > 1dh < pdh ^ q MOD p = 1p and q are from the Diffie-Hellman group indicated by the group directive in the initialization
request.
certificate directive, if present and if considered by
the requester, provides a public key that is valid according to the Public Key Algorithm specification, notably regarding minimum key size.certificate directive, if present and if considered by
the requester, satisfies locally determined validation constraints, typically with respect to installed certification
authority root certificates.signature directive value is valid. See signature section for details of the validation procedure.A continuation request message MUST meet all the following conditions to be considered valid by the responder that receives it:
token directive references an existing shared secret
arrangement.url directive satisfies its equivalence condition.count directive satisfies its uniqueness conditions.mac directive's value equals the result of the re-computation
over the message, using the request MAC key indexed by the
token directive.digest directive is present, its value equals the result
of hashing the entity-body according to this specification's Hash
Algorithm.A request that fails validation SHOULD cause the responder to flush all state associated with the shared secret
arrangement indexed by the token directive, notably the MAC keys and Cipher keys.
A continuation response message MUST meet all the following conditions to be considered valid by the requester that receives it:
count directive satisfies the sequence and uniqueness
conditions.mac directive's value equals the result of the re-computation
over the message, using the response MAC key indexed by the token stated in the associated request.digest directive is present, its value equals the result
of hashing the entity-body according to this specification's Hash
Algorithm.A response that fails validation SHOULD cause the requester to flush all state associated with the shared secret
arrangement indexed by the token directive in the associated request,
notably the MAC keys and Cipher keys.
Implementers should be aware of how authenticated transactions interact with proxy caches. The HTTP/1.1 [HTTP] [ 14.8] specifies that when a shared cache has received a request containing an Authorization header and a response from relaying that request, it MUST NOT return that response as a reply to any other request.
Note also that whereas the HTTP/1.1 specification presents three exceptions to this rule, none of these exceptions are applicable to the authentication scheme here described. This is a result of the per-message uniqueness constraints introduced by various protocol directives.
Consequently, to make the non-cacheability of messages explicit the Expires response header [HTTP][ 14.21] MUST be set by the responder to the current system clock time, during the preparation of a response's
"WWW-Authenticate: httpsec/1.0 continue" header directives. This is necessary for subsequent response validation, as the value of the Expires
response header features in the computation of mac directives.
Also, the requirement that the no-transform directive [HTTP][
14.9.5] MUST be set in a
mandatory Cache-Control response header [HTTP][ 14.9]
enforces specific modification constraints on transparent proxies that apply to certain headers - see [HTTP][ 13.5.2].
This entire specification discusses a secure authentication system that protects HTTP messages transmitted across an untrusted network.
Normative references:
Stephan Fowler
secarta.com
Ferroners' House
Shaftesbury Place
London EC2Y 8AA
T +44 20 7796 2527
F +44 20 7796 3539
Email: stephan.fowler@secarta.com