From 06145079ff0d772b52d1cdb6b86635ad01bc2c64 Mon Sep 17 00:00:00 2001 From: Chris Wood Date: Thu, 15 Sep 2022 12:17:09 -0400 Subject: [PATCH 1/3] Clarify truncated key id in the TokenRequest message --- draft-ietf-privacypass-protocol.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/draft-ietf-privacypass-protocol.md b/draft-ietf-privacypass-protocol.md index 77caa185..e13ed8ca 100755 --- a/draft-ietf-privacypass-protocol.md +++ b/draft-ietf-privacypass-protocol.md @@ -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; ~~~ @@ -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 `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}}. @@ -258,7 +258,7 @@ content-length = 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 @@ -426,7 +426,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; ~~~ @@ -435,7 +435,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 `key_id`). - "blinded_msg" is the Nk-octet request defined above. @@ -460,7 +460,7 @@ content-length = 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 From d6ad451ce65d8419ffe338fe97bc2d3faa17ed6f Mon Sep 17 00:00:00 2001 From: Chris Wood Date: Thu, 15 Sep 2022 12:23:23 -0400 Subject: [PATCH 2/3] Missing key_id updates --- draft-ietf-privacypass-protocol.md | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/draft-ietf-privacypass-protocol.md b/draft-ietf-privacypass-protocol.md index e13ed8ca..c9cc13ec 100755 --- a/draft-ietf-privacypass-protocol.md +++ b/draft-ietf-privacypass-protocol.md @@ -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}}. @@ -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) ~~~ @@ -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. -- "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 `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}}. @@ -363,11 +363,11 @@ 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))) ~~~ # Issuance Protocol for Publicly Verifiable Tokens {#public-flow} @@ -396,7 +396,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}}. @@ -412,7 +412,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) ~~~ @@ -435,7 +435,7 @@ The structure fields are defined as follows: - "token_type" is a 2-octet integer, which matches the type in the challenge. -- "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 `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. @@ -544,7 +544,7 @@ 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 @@ -553,11 +553,11 @@ output size of the hash function associated with the public key and token type. # 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}}. # IANA considerations From 2e13a1d2fea26682387086425a0f550dbcb2d12d Mon Sep 17 00:00:00 2001 From: Chris Wood Date: Thu, 15 Sep 2022 12:29:32 -0400 Subject: [PATCH 3/3] Add rationale for the token key ID truncation --- draft-ietf-privacypass-protocol.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/draft-ietf-privacypass-protocol.md b/draft-ietf-privacypass-protocol.md index c9cc13ec..c849751f 100755 --- a/draft-ietf-privacypass-protocol.md +++ b/draft-ietf-privacypass-protocol.md @@ -370,6 +370,10 @@ as follows: 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}} @@ -550,6 +554,10 @@ SHA256(encoded_key), where encoded_key is a DER-encoded SubjectPublicKeyInfo 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 @@ -559,6 +567,14 @@ 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 ## Token Type