Skip to content

Commit

Permalink
Merge pull request #183 from ietf-wg-privacypass/caw/truncated_key_id
Browse files Browse the repository at this point in the history
Clarify truncated key id in the TokenRequest message
  • Loading branch information
chris-wood committed Sep 16, 2022
2 parents 58eb4f6 + d7e5742 commit c8e4703
Showing 1 changed file with 34 additions and 18 deletions.
52 changes: 34 additions & 18 deletions draft-ietf-privacypass-protocol.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ Clients provide the following as input to the issuance protocol:

- Issuer name, identifying the Issuer. This is typically a host name that
can be used to construct HTTP requests to the Issuer.
- Issuer Public Key pkI, with a key identifier `key_id` computed as
- Issuer Public Key pkI, with a key identifier `token_key_id` computed as
described in {{issuer-configuration}}.
- Challenge value `challenge`, an opaque byte string. For example, this might
be provided by the redemption protocol in {{HTTP-Authentication}}.
Expand Down Expand Up @@ -208,7 +208,7 @@ with the input challenge and Issuer key identifier as described below:
~~~
nonce = random(32)
challenge_digest = SHA256(challenge)
token_input = concat(0x0001, nonce, challenge_digest, key_id)
token_input = concat(0x0001, nonce, challenge_digest, token_key_id)
blind, blinded_element = client_context.Blind(token_input)
~~~

Expand All @@ -223,7 +223,7 @@ The Client then creates a TokenRequest structured as follows:
~~~
struct {
uint16_t token_type = 0x0001;
uint8_t token_key_id;
uint8_t truncated_token_key_id;
uint8_t blinded_msg[Ne];
} TokenRequest;
~~~
Expand All @@ -232,7 +232,7 @@ The structure fields are defined as follows:

- "token_type" is a 2-octet integer, which matches the type in the challenge.

- "token_key_id" is the least significant byte of the `key_id` in network byte order (in other words, the last 8 bits of `key_id`).
- "truncated_token_key_id" is the least significant byte of the `token_key_id` in network byte order (in other words, the last 8 bits of `token_key_id`).

- "blinded_msg" is the Ne-octet blinded message defined above, computed as
`SerializeElement(blinded_element)`. Ne is as defined in {{OPRF, Section 4}}.
Expand All @@ -258,7 +258,7 @@ content-length = <Length of TokenRequest>
Upon receipt of the request, the Issuer validates the following conditions:

- The TokenRequest contains a supported token_type.
- The TokenRequest.token_key_id corresponds to a key ID of a Public Key owned by the issuer.
- The TokenRequest.truncated_token_key_id corresponds to the truncated key ID of a Public Key owned by the issuer.
- The TokenRequest.blinded_request is of the correct size.

If any of these conditions is not met, the Issuer MUST return an HTTP 400 error
Expand Down Expand Up @@ -363,13 +363,17 @@ seed = random(Ns)
(skI, pkI) = DeriveKeyPair(seed, "PrivacyPass")
~~~

The key identifier for this specific key pair, denoted `key_id`, is computed
The key identifier for this specific key pair, denoted `token_key_id`, is computed
as follows:

~~~
key_id = SHA256(concat(0x0001, SerializeElement(pkI)))
token_key_id = SHA256(concat(0x0001, SerializeElement(pkI)))
~~~

Since Clients truncate `token_key_id` in each `TokenRequest`, Issuers should ensure
that the truncated form of new key IDs do not collide with other truncated key IDs
in rotation.

# Issuance Protocol for Publicly Verifiable Tokens {#public-flow}

This section describes a variant of the issuance protocol in {{private-flow}}
Expand All @@ -396,7 +400,7 @@ Clients provide the following as input to the issuance protocol:

- Issuer name, identifying the Issuer. This is typically a host name that
can be used to construct HTTP requests to the Issuer.
- Issuer Public Key pkI, with a key identifier `key_id` computed as
- Issuer Public Key pkI, with a key identifier `token_key_id` computed as
described in {{public-issuer-configuration}}.
- Challenge value `challenge`, an opaque byte string. For example, this might
be provided by the redemption protocol in {{HTTP-Authentication}}.
Expand All @@ -412,7 +416,7 @@ The Client first creates an issuance request message for a random value
~~~
nonce = random(32)
challenge_digest = SHA256(challenge)
token_input = concat(0x0002, nonce, challenge_digest, key_id)
token_input = concat(0x0002, nonce, challenge_digest, token_key_id)
blinded_msg, blind_inv = rsabssa_blind(pkI, token_input)
~~~

Expand All @@ -426,7 +430,7 @@ The Client then creates a TokenRequest structured as follows:
~~~
struct {
uint16_t token_type = 0x0002
uint8_t token_key_id;
uint8_t truncated_token_key_id;
uint8_t blinded_msg[Nk];
} TokenRequest;
~~~
Expand All @@ -435,7 +439,7 @@ The structure fields are defined as follows:

- "token_type" is a 2-octet integer, which matches the type in the challenge.

- "token_key_id" is the least significant byte of the `key_id` in network byte order (in other words, the last 8 bits of `key_id`).
- "truncated_token_key_id" is the least significant byte of the `token_key_id` in network byte order (in other words, the last 8 bits of `token_key_id`).

- "blinded_msg" is the Nk-octet request defined above.

Expand All @@ -460,7 +464,7 @@ content-length = <Length of TokenRequest>
Upon receipt of the request, the Issuer validates the following conditions:

- The TokenRequest contains a supported token_type.
- The TokenRequest.token_key_id corresponds to a key ID of a Public Key owned by the issuer.
- The TokenRequest.truncated_token_key_id corresponds to the truncated key ID of a Public Key owned by the issuer.
- The TokenRequest.blinded_msg is of the correct size.

If any of these conditions is not met, the Issuer MUST return an HTTP 400 error
Expand Down Expand Up @@ -544,20 +548,32 @@ Issuers are configured with Private and Public Key pairs, each denoted skI and
pkI, respectively, used to produce tokens. Each key pair SHALL be generated as
as specified in FIPS 186-4 {{?DSS=DOI.10.6028/NIST.FIPS.186-4}}.

The key identifier for a keypair (skI, pkI), denoted `key_id`, is computed as
The key identifier for a keypair (skI, pkI), denoted `token_key_id`, is computed as
SHA256(encoded_key), where encoded_key is a DER-encoded SubjectPublicKeyInfo
(SPKI) object carrying pkI. The SPKI object MUST use the RSASSA-PSS OID {{!RFC5756}},
which specifies the hash algorithm and salt size. The salt size MUST match the
output size of the hash function associated with the public key and token type.

Since Clients truncate `token_key_id` in each `TokenRequest`, Issuers should ensure
that the truncated form of new key IDs do not collide with other truncated key IDs
in rotation.

# Security considerations

This document outlines how to instantiate the Issuance protocol
based on the VOPRF defined in {{OPRF}} and blind RSA protocol defnied in
{{BLINDRSA}}. All security considerations described in the VOPRF document also
apply in the Privacy Pass use-case. Considerations related to broader privacy
and security concerns in a multi-Client and multi-Issuer setting are deferred
to the Architecture document {{I-D.ietf-privacypass-architecture}}.
based on the VOPRF defined in {{OPRF}} and blind RSA protocol defined in
{{BLINDRSA}}. All security considerations described in the VOPRF and blind RSA
documents also apply in the Privacy Pass use-case. Considerations related to
broader privacy and security concerns in a multi-Client and multi-Issuer
setting are deferred to the Architecture document {{I-D.ietf-privacypass-architecture}}.

Beyond these considerations, it is worth highlighting the fact that Client TokenRequest
messages contain truncated token key IDs. This is done to minimize the chance that an Issuer
can use distinct keys for targeting specific users. Since the key ID is truncated
to a single byte, an Issuer can partition the set of Clients into at most 256 different
anonymity sets. On top of this key ID space, Clients SHOULD apply some form of key
consistency mechanism to help ensure they are not being given unique keys; see
{{?CONSISTENCY=I-D.wood-key-consistency}} for more details.

# IANA considerations

Expand Down

0 comments on commit c8e4703

Please sign in to comment.