< draft-privacypass-rate-limit-tokens-01.txt   draft-privacypass-rate-limit-tokens-02.txt >
Network Working Group S. Hendrickson Network Working Group S. Hendrickson
Internet-Draft Google LLC Internet-Draft Google LLC
Intended status: Informational J. Iyengar Intended status: Informational J. Iyengar
Expires: 7 October 2022 Fastly Expires: 3 November 2022 Fastly
T. Pauly T. Pauly
Apple Inc. Apple Inc.
S. Valdez S. Valdez
Google LLC Google LLC
C. A. Wood C. A. Wood
Cloudflare Cloudflare
5 April 2022 2 May 2022
Rate-Limited Token Issuance Protocol Rate-Limited Token Issuance Protocol
draft-privacypass-rate-limit-tokens-01 draft-privacypass-rate-limit-tokens-02
Abstract Abstract
This document specifies a variant of the Privacy Pass issuance This document specifies a variant of the Privacy Pass issuance
protocol that allows for tokens to be rate-limited on a per-origin protocol that allows for tokens to be rate-limited on a per-origin
basis. This enables origins to use tokens for use cases that need to basis. This enables origins to use tokens for use cases that need to
restrict access from anonymous clients. restrict access from anonymous clients.
Discussion Venues Discussion Venues
skipping to change at page 1, line 47 skipping to change at page 1, line 47
Internet-Drafts are working documents of the Internet Engineering Internet-Drafts are working documents of the Internet Engineering
Task Force (IETF). Note that other groups may also distribute Task Force (IETF). Note that other groups may also distribute
working documents as Internet-Drafts. The list of current Internet- working documents as Internet-Drafts. The list of current Internet-
Drafts is at https://datatracker.ietf.org/drafts/current/. Drafts is at https://datatracker.ietf.org/drafts/current/.
Internet-Drafts are draft documents valid for a maximum of six months Internet-Drafts are draft documents valid for a maximum of six months
and may be updated, replaced, or obsoleted by other documents at any and may be updated, replaced, or obsoleted by other documents at any
time. It is inappropriate to use Internet-Drafts as reference time. It is inappropriate to use Internet-Drafts as reference
material or to cite them other than as "work in progress." material or to cite them other than as "work in progress."
This Internet-Draft will expire on 7 October 2022. This Internet-Draft will expire on 3 November 2022.
Copyright Notice Copyright Notice
Copyright (c) 2022 IETF Trust and the persons identified as the Copyright (c) 2022 IETF Trust and the persons identified as the
document authors. All rights reserved. document authors. All rights reserved.
This document is subject to BCP 78 and the IETF Trust's Legal This document is subject to BCP 78 and the IETF Trust's Legal
Provisions Relating to IETF Documents (https://trustee.ietf.org/ Provisions Relating to IETF Documents (https://trustee.ietf.org/
license-info) in effect on the date of publication of this document. license-info) in effect on the date of publication of this document.
Please review these documents carefully, as they describe your rights Please review these documents carefully, as they describe your rights
skipping to change at page 2, line 33 skipping to change at page 2, line 33
1.2. Properties and Requirements . . . . . . . . . . . . . . . 4 1.2. Properties and Requirements . . . . . . . . . . . . . . . 4
2. Terminology . . . . . . . . . . . . . . . . . . . . . . . . . 6 2. Terminology . . . . . . . . . . . . . . . . . . . . . . . . . 6
3. Configuration . . . . . . . . . . . . . . . . . . . . . . . . 8 3. Configuration . . . . . . . . . . . . . . . . . . . . . . . . 8
4. Token Challenge Requirements . . . . . . . . . . . . . . . . 9 4. Token Challenge Requirements . . . . . . . . . . . . . . . . 9
5. Issuance Protocol . . . . . . . . . . . . . . . . . . . . . . 10 5. Issuance Protocol . . . . . . . . . . . . . . . . . . . . . . 10
5.1. State Requirements . . . . . . . . . . . . . . . . . . . 10 5.1. State Requirements . . . . . . . . . . . . . . . . . . . 10
5.1.1. Client State . . . . . . . . . . . . . . . . . . . . 11 5.1.1. Client State . . . . . . . . . . . . . . . . . . . . 11
5.1.2. Attester State . . . . . . . . . . . . . . . . . . . 12 5.1.2. Attester State . . . . . . . . . . . . . . . . . . . 12
5.1.3. Issuer State . . . . . . . . . . . . . . . . . . . . 12 5.1.3. Issuer State . . . . . . . . . . . . . . . . . . . . 12
5.2. Issuance HTTP Headers . . . . . . . . . . . . . . . . . . 13 5.2. Issuance HTTP Headers . . . . . . . . . . . . . . . . . . 13
5.3. Client-to-Attester Request . . . . . . . . . . . . . . . 13 5.3. Client-to-Attester Request . . . . . . . . . . . . . . . 14
5.4. Attester-to-Issuer Request . . . . . . . . . . . . . . . 16 5.4. Attester-to-Issuer Request . . . . . . . . . . . . . . . 17
5.5. Issuer-to-Attester Response . . . . . . . . . . . . . . . 18 5.5. Issuer-to-Attester Response . . . . . . . . . . . . . . . 18
5.6. Attester-to-Client Response . . . . . . . . . . . . . . . 18 5.6. Attester-to-Client Response . . . . . . . . . . . . . . . 19
6. Encrypting Origin Names . . . . . . . . . . . . . . . . . . . 19 6. Encrypting Origin Token Requests and Responses . . . . . . . 20
7. Anonymous Issuer Origin ID Computation . . . . . . . . . . . 21 6.1. Client to Issuer Encapsulation . . . . . . . . . . . . . 20
7.1. Client Behavior . . . . . . . . . . . . . . . . . . . . . 23 6.2. Issuer to Client Encapsulation . . . . . . . . . . . . . 22
7.1.1. Request Key . . . . . . . . . . . . . . . . . . . . . 23 7. Anonymous Issuer Origin ID Computation . . . . . . . . . . . 23
7.1.2. Request Signature . . . . . . . . . . . . . . . . . . 23 7.1. Client Behavior . . . . . . . . . . . . . . . . . . . . . 25
7.2. Attester Behavior (Client Request Validation) . . . . . . 24 7.1.1. Request Key . . . . . . . . . . . . . . . . . . . . . 25
7.3. Issuer Behavior . . . . . . . . . . . . . . . . . . . . . 25 7.1.2. Request Signature . . . . . . . . . . . . . . . . . . 25
7.4. Attester Behavior (Index Computation) . . . . . . . . . . 25 7.2. Attester Behavior (Client Request Validation) . . . . . . 26
8. Security Considerations . . . . . . . . . . . . . . . . . . . 26 7.3. Issuer Behavior . . . . . . . . . . . . . . . . . . . . . 26
8.1. Channel Security . . . . . . . . . . . . . . . . . . . . 26 7.4. Attester Behavior (Index Computation) . . . . . . . . . . 27
8.2. Token Request Unlinkability and Unforgeability . . . . . 26 8. Security Considerations . . . . . . . . . . . . . . . . . . . 28
8.3. Information Disclosure . . . . . . . . . . . . . . . . . 27 8.1. Channel Security . . . . . . . . . . . . . . . . . . . . 28
9. Privacy Considerations . . . . . . . . . . . . . . . . . . . 28 8.2. Token Request Unlinkability and Unforgeability . . . . . 28
9.1. Client Token State and Origin Tracking . . . . . . . . . 28 8.3. Information Disclosure . . . . . . . . . . . . . . . . . 29
9.2. Origin Verification . . . . . . . . . . . . . . . . . . . 29 9. Privacy Considerations . . . . . . . . . . . . . . . . . . . 30
9.3. Client Identification with Unique Keys . . . . . . . . . 29 9.1. Client Token State and Origin Tracking . . . . . . . . . 30
9.4. Origin Identification . . . . . . . . . . . . . . . . . . 29 9.2. Origin Verification . . . . . . . . . . . . . . . . . . . 30
9.5. Collusion Among Different Entities . . . . . . . . . . . 30 9.3. Client Identification with Unique Keys . . . . . . . . . 30
10. Deployment Considerations . . . . . . . . . . . . . . . . . . 30 9.4. Origin Identification . . . . . . . . . . . . . . . . . . 31
10.1. Token Key Management . . . . . . . . . . . . . . . . . . 30 9.5. Collusion Among Different Entities . . . . . . . . . . . 31
11. IANA considerations . . . . . . . . . . . . . . . . . . . . . 30 10. Deployment Considerations . . . . . . . . . . . . . . . . . . 32
11.1. Token Type . . . . . . . . . . . . . . . . . . . . . . . 31 10.1. Token Key Management . . . . . . . . . . . . . . . . . . 32
11.2. HTTP Headers . . . . . . . . . . . . . . . . . . . . . . 31 11. IANA considerations . . . . . . . . . . . . . . . . . . . . . 32
12. References . . . . . . . . . . . . . . . . . . . . . . . . . 31 11.1. Token Type . . . . . . . . . . . . . . . . . . . . . . . 32
12.1. Normative References . . . . . . . . . . . . . . . . . . 31 11.1.1. ECDSA-based Token Type . . . . . . . . . . . . . . . 33
12.2. Informative References . . . . . . . . . . . . . . . . . 33 11.1.2. Ed25519-based Token Type . . . . . . . . . . . . . . 34
Appendix A. Acknowledgements . . . . . . . . . . . . . . . . . . 34 11.2. HTTP Headers . . . . . . . . . . . . . . . . . . . . . . 35
Appendix B. Test Vectors . . . . . . . . . . . . . . . . . . . . 34 12. References . . . . . . . . . . . . . . . . . . . . . . . . . 35
B.1. Origin Name Encryption Test Vector . . . . . . . . . . . 34 12.1. Normative References . . . . . . . . . . . . . . . . . . 35
B.2. Anonymous Origin ID Test Vector . . . . . . . . . . . . . 35 12.2. Informative References . . . . . . . . . . . . . . . . . 37
Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 36 Appendix A. Acknowledgements . . . . . . . . . . . . . . . . . . 38
Appendix B. Test Vectors . . . . . . . . . . . . . . . . . . . . 38
B.1. Origin Name Encryption Test Vector . . . . . . . . . . . 38
B.2. Anonymous Origin ID Test Vector . . . . . . . . . . . . . 39
Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 40
1. Introduction 1. Introduction
This document specifies a variant of the Privacy Pass issuance This document specifies a variant of the Privacy Pass issuance
protocol (as defined in [ARCH]) that allows for tokens to be rate- protocol (as defined in [ARCH]) that allows for tokens to be rate-
limited on a per-origin basis. This enables origins to use tokens limited on a per-origin basis. This enables origins to use tokens
for use cases that need to restrict access from anonymous clients. for use cases that need to restrict access from anonymous clients.
The base Privacy Pass issuance protocol [ISSUANCE] defines stateless The base Privacy Pass issuance protocol [ISSUANCE] defines stateless
anonymous tokens, which can either be publicly verifiable or not. anonymous tokens, which can either be publicly verifiable or not.
skipping to change at page 7, line 28 skipping to change at page 7, line 28
Additionally, this document defines several terms that are unique to Additionally, this document defines several terms that are unique to
the rate-limited issuance protocol: the rate-limited issuance protocol:
* Issuer Policy Window: The period over which an Issuer will track * Issuer Policy Window: The period over which an Issuer will track
access policy, defined in terms of seconds and represented as a access policy, defined in terms of seconds and represented as a
uint64. The state that the Attester keeps for a Client is uint64. The state that the Attester keeps for a Client is
specific to a policy window. The effective policy window for a specific to a policy window. The effective policy window for a
specific Client starts when the Client first sends a request specific Client starts when the Client first sends a request
associated with an Issuer. associated with an Issuer.
* Origin Name Key: The public key used to encrypt values such as * Issuer Encapsulation Key: The public key used to encrypt values
Origin Name in requests from Clients to the Issuer, so that such as Origin Name in requests from Clients to the Issuer, so
Attesters cannot learn the Origin Name value. Each Origin Name that Attesters cannot learn the Origin Name value. Each Issuer
Key is used across all requests on the Issuer, for different Encapsulation Key is used across all requests on the Issuer, for
Origins. different Origins.
* Anonymous Origin ID: An identifier that is generated by the Client * Anonymous Origin ID: An identifier that is generated by the Client
and marked on requests to the Attester, which represents a and marked on requests to the Attester, which represents a
specific Origin anonymously. The Client generates a stable specific Origin anonymously. The Client generates a stable
Anonymous Origin ID for each Origin Name, to allow the Attester to Anonymous Origin ID for each Origin Name, to allow the Attester to
count token access without learning the Origin Name. count token access without learning the Origin Name.
* Client Key: A public key chosen by the Client and shared only with * Client Key: A public key chosen by the Client and shared only with
the Attester; see Section 8.2 for more details about this the Attester; see Section 8.2 for more details about this
restriction. restriction.
skipping to change at page 8, line 21 skipping to change at page 8, line 21
Issuers MUST provide three parameters for configuration: Issuers MUST provide three parameters for configuration:
1. Issuer Policy Window: a uint64 of seconds as defined in 1. Issuer Policy Window: a uint64 of seconds as defined in
Section 2. Section 2.
2. Issuer Request URI: a token request URL for generating access 2. Issuer Request URI: a token request URL for generating access
tokens. For example, an Issuer URL might be tokens. For example, an Issuer URL might be
https://issuer.example.net/token-request. This parameter uses https://issuer.example.net/token-request. This parameter uses
resource media type "text/plain". resource media type "text/plain".
3. Origin Name Key: a NameKey structure as defined below to use when 3. Issuer Encapsulation Key: a EncapsulationKey structure as defined
encrypting the Origin Name in issuance requests. This parameter below to use when encapsulating information, such as the origin
uses resource media type "application/issuer-name-key". The Npk name, to the Issuer in issuance requests. This parameter uses
resource media type "application/issuer-encap-key". The Npk
parameter corresponding to the HpkeKdfId can be found in [HPKE]. parameter corresponding to the HpkeKdfId can be found in [HPKE].
opaque HpkePublicKey[Npk]; // defined in RFC9180 opaque HpkePublicKey[Npk]; // defined in RFC9180
uint16 HpkeKemId; // defined in RFC9180 uint16 HpkeKemId; // defined in RFC9180
uint16 HpkeKdfId; // defined in RFC9180 uint16 HpkeKdfId; // defined in RFC9180
uint16 HpkeAeadId; // defined in RFC9180 uint16 HpkeAeadId; // defined in RFC9180
struct { struct {
uint8 key_id; uint8 key_id;
HpkeKemId kem_id; HpkeKemId kem_id;
HpkePublicKey public_key; HpkePublicKey public_key;
HpkeKdfId kdf_id; HpkeKdfId kdf_id;
HpkeAeadId aead_id; HpkeAeadId aead_id;
} NameKey; } EncapsulationKey;
The Issuer parameters can be obtained from an Issuer via a directory The Issuer parameters can be obtained from an Issuer via a directory
object, which is a JSON object whose field names and values are raw object, which is a JSON object whose field names and values are raw
values and URLs for the parameters. values and URLs for the parameters.
+======================+=======================================+ +======================+=======================================+
| Field Name | Value | | Field Name | Value |
+======================+=======================================+ +======================+=======================================+
| issuer-policy-window | Issuer Policy Window as a JSON number | | issuer-policy-window | Issuer Policy Window as a JSON number |
+----------------------+---------------------------------------+ +----------------------+---------------------------------------+
| issuer-request-uri | Issuer Request URI resource URL as a | | issuer-request-uri | Issuer Request URI resource URL as a |
| | JSON string | | | JSON string |
+----------------------+---------------------------------------+ +----------------------+---------------------------------------+
| origin-name-key-uri | Origin Name Key URI resource URL as a | | issuer-encap-key-uri | Issuer Encapsulation Key URI resource |
| | JSON string | | | URL as a JSON string |
+----------------------+---------------------------------------+ +----------------------+---------------------------------------+
Table 1 Table 1
As an example, the Issuer's JSON directory could look like: As an example, the Issuer's JSON directory could look like:
{ {
"issuer-token-window": 86400, "issuer-token-window": 86400,
"issuer-request-uri": "https://issuer.example.net/token-request" "issuer-request-uri": "https://issuer.example.net/token-request"
"origin-name-key-uri": "https://issuer.example.net/name-key", "issuer-encap-key-uri": "https://issuer.example.net/encap-key",
} }
Issuer directory resources have the media type "application/json" and Issuer directory resources have the media type "application/json" and
are located at the well-known location /.well-known/token-issuer- are located at the well-known location /.well-known/token-issuer-
directory. directory.
4. Token Challenge Requirements 4. Token Challenge Requirements
Clients receive challenges for tokens, as described in [AUTHSCHEME]. Clients receive challenges for tokens, as described in [AUTHSCHEME].
skipping to change at page 9, line 47 skipping to change at page 9, line 47
the Client to the Issuer. If the TokenChallenge.origin_info field the Client to the Issuer. If the TokenChallenge.origin_info field
contains a single origin name, that origin name is used. If the contains a single origin name, that origin name is used. If the
origin_info field contains multiple origin names, the client selects origin_info field contains multiple origin names, the client selects
the single origin name that presented the challenge. If the the single origin name that presented the challenge. If the
origin_info field is empty, the encrypted message is the empty string origin_info field is empty, the encrypted message is the empty string
"". "".
The HTTP authentication challenge also SHOULD contain the following The HTTP authentication challenge also SHOULD contain the following
additional attribute: additional attribute:
* "origin-name-key", which contains a base64url encoding of a * "issuer-encap-key", which contains a base64url encoding of a
NameKey as defined in Section 3 to use when encrypting the Origin EncapsulationKey as defined in Section 3 to use when encrypting
Name in issuance requests. the Origin Name in issuance requests.
5. Issuance Protocol 5. Issuance Protocol
This section describes the Issuance protocol for a Client to request This section describes the Issuance protocol for a Client to request
and receive a token from an Issuer. Token issuance involves a and receive a token from an Issuer. Token issuance involves a
Client, Attester, and Issuer, with the following steps: Client, Attester, and Issuer, with the following steps:
1. The Client sends a token request containing a token request, 1. The Client sends a token request containing a token request,
encrypted origin name, and one-time-use public key and signature encrypted origin name, and one-time-use public key and signature
to the Attester to the Attester
skipping to change at page 10, line 40 skipping to change at page 10, line 40
The Issuance protocol has a number of underlying cryptographic The Issuance protocol has a number of underlying cryptographic
dependencies for operation: dependencies for operation:
* RSA Blind Signatures [BLINDSIG], for issuing and constructing * RSA Blind Signatures [BLINDSIG], for issuing and constructing
Tokens. This support is the same as used in the base publicly Tokens. This support is the same as used in the base publicly
verifiable token issuance protocol [ISSUANCE] verifiable token issuance protocol [ISSUANCE]
* [HPKE], for encrypting the origin server name in transit between * [HPKE], for encrypting the origin server name in transit between
Client and Issuer across the Attester. Client and Issuer across the Attester.
* [ECDSA] signatures with key blinding, as described in * Signatures with key blinding, as described in [KEYBLINDING], for
[KEYBLINDING], for verifying correctness of Client requests. verifying correctness of Client requests.
Clients and Issuers are required to implement all of these Clients and Issuers are required to implement all of these
dependencies, whereas Attesters are required to implement ECDSA dependencies, whereas Attesters are required to implement signature
signature with key blinding support. with key blinding support.
5.1. State Requirements 5.1. State Requirements
The Issuance protocol requires each participating endpoint to The Issuance protocol requires each participating endpoint to
maintain some necessary state, as described in this section. maintain some necessary state, as described in this section.
5.1.1. Client State 5.1.1. Client State
A Client is required to have the following information, derived from A Client is required to have the following information, derived from
a given TokenChallenge: a given TokenChallenge:
* Origin Name, a hostname referring to the Origin [RFC6454]. This * Origin Name, a hostname referring to the Origin [RFC6454]. This
is the name of the Origin that issued the token challenge. One or is the name of the Origin that issued the token challenge. One or
more names can be listed in the TokenChallenge.origin_info field. more names can be listed in the TokenChallenge.origin_info field.
Rate-limited token issuance relies on the client selecting a Rate-limited token issuance relies on the client selecting a
single origin name from this list if multiple are present. single origin name from this list if multiple are present.
* Token Key, a blind signature public key corresponding to the * Token Key, a blind signature public key corresponding to the
Issuer identified by the TokenChallenge.issuer_name. Issuer identified by the TokenChallenge.issuer_name.
* Origin Name Key, a public key used to encrypt request information * Issuer Encapsulation Key, a public key used to encrypt request
corresponding to the Issuer identified by information corresponding to the Issuer identified by
TokenChallenge.issuer_name. TokenChallenge.issuer_name.
Clients maintain a stable Client Key that they use for all Clients maintain a stable Client Key that they use for all
communication with a specific Attester. Client Key is a public key, communication with a specific Attester. Client Key is a public key,
where the corresponding private key Client Secret is known only to where the corresponding private key Client Secret is known only to
the client. the client.
If the client loses this (Client Key, Client Secret), they may If the client loses this (Client Key, Client Secret), they may
generate a new tuple. The Attester will enforce if a client is generate a new tuple. The Attester will enforce if a client is
allowed to use this new Client Key. See Section 5.1.2 for details on allowed to use this new Client Key. See Section 5.1.2 for details on
skipping to change at page 12, line 14 skipping to change at page 12, line 14
5.1.2. Attester State 5.1.2. Attester State
An Attester is required to maintain state for every authenticated An Attester is required to maintain state for every authenticated
Client. The mechanism of identifying a Client is specific to each Client. The mechanism of identifying a Client is specific to each
Attester, and is not defined in this document. As examples, the Attester, and is not defined in this document. As examples, the
Attester could use device-specific certificates or account Attester could use device-specific certificates or account
authentication to identify a Client. authentication to identify a Client.
Attesters must enforce that Clients don't change their Client Key Attesters must enforce that Clients don't change their Client Key
frequently, to ensure Clients can't regularily evade the per-client frequently, to ensure Clients can't regularly evade the per-client
policy as seen by the issuer. Attesters MUST NOT allow Clients to policy as seen by the issuer. Attesters MUST NOT allow Clients to
change their Client Key more than once within a policy window, or in change their Client Key more than once within a policy window, or in
the subsequent policy window after a previous Client Key change. the subsequent policy window after a previous Client Key change.
Alternative schemes where the Attester stores the encrypted (Client Alternative schemes where the Attester stores the encrypted (Client
Key, Client Secret) tuple on behalf of the client are possble but not Key, Client Secret) tuple on behalf of the client are possible but
described here. not described here.
Attesters are expected to know the Issuer Policy Window for any Attesters are expected to know the Issuer Policy Window for any
Issuer Name to which they allow access. This information can be Issuer Name to which they allow access. This information can be
retrieved using the URIs defined in Section 3. retrieved using the URIs defined in Section 3.
For each Client-Issuer pair, an Attester maintains a policy window For each Client-Issuer pair, an Attester maintains a policy window
start and end time for each Issuer from which a Client requests a start and end time for each Issuer from which a Client requests a
token. token.
For each tuple of (Client Key, Anonymous Origin ID, policy window), For each tuple of (Client Key, Anonymous Origin ID, policy window),
skipping to change at page 12, line 50 skipping to change at page 12, line 50
5.1.3. Issuer State 5.1.3. Issuer State
Issuers maintain a stable Issuer Origin Secret that they use in Issuers maintain a stable Issuer Origin Secret that they use in
calculating values returned to the Attester for each origin. If this calculating values returned to the Attester for each origin. If this
value changes, it will open up a possibility for Clients to request value changes, it will open up a possibility for Clients to request
extra tokens for an Origin without being limited, within a policy extra tokens for an Origin without being limited, within a policy
window. See Section 10.1 for details about generating and rotating window. See Section 10.1 for details about generating and rotating
the Issuer Origin Secret. the Issuer Origin Secret.
Issuers are expected to have the private key that corresponds to Issuers are expected to have the private key that corresponds to
Origin Name Key, which allows them to decrypt the Origin Name values Issuer Encapsulation Key, which allows them to decrypt the Origin
in requests. Name values in requests.
Issuers also need to know the set of valid Token Key public keys and Issuers also need to know the set of valid Token Key public keys and
corresponding private key, for each Origin Name that is served by the corresponding private key, for each Origin Name that is served by the
Issuer. Origins SHOULD update their view of the Token Key regularly Issuer. Origins SHOULD update their view of the Token Key regularly
to ensure that Client requests do not fail after Token Key rotation. to ensure that Client requests do not fail after Token Key rotation.
5.2. Issuance HTTP Headers 5.2. Issuance HTTP Headers
The Issuance protocol defines four new HTTP headers that are used in The Issuance protocol defines four new HTTP headers that are used in
requests and responses between Clients, Attesters, and Issuers (see requests and responses between Clients, Attesters, and Issuers (see
skipping to change at page 13, line 37 skipping to change at page 13, line 37
Sec-Token-Client = sf-binary Sec-Token-Client = sf-binary
The "Sec-Token-Request-Blind" is an Item Structured Header [RFC8941]. The "Sec-Token-Request-Blind" is an Item Structured Header [RFC8941].
Its value MUST be a Byte Sequence. This header is sent on Client-to- Its value MUST be a Byte Sequence. This header is sent on Client-to-
Attester requests (Section 5.3), and contains a per-request nonce Attester requests (Section 5.3), and contains a per-request nonce
value. Its ABNF is: value. Its ABNF is:
Sec-Token-Request-Blind = sf-binary Sec-Token-Request-Blind = sf-binary
The "Sec-Token-Request-Key" is an Item Structured Header [RFC8941].
Its value MUST be a Byte Sequence. This header is sent on Client-to-
Attester requests (Section 5.3), and contains a per-request public
key. Its ABNF is:
Sec-Token-Request-Key = sf-binary
The "Sec-Token-Limit" is an Item Structured Header [RFC8941]. Its The "Sec-Token-Limit" is an Item Structured Header [RFC8941]. Its
value MUST be an Integer. This header is sent on Issuer-to-Attester value MUST be an Integer. This header is sent on Issuer-to-Attester
responses (Section 5.5), and contains the number of times a Client responses (Section 5.5), and contains the number of times a Client
can retrieve a token for the requested Origin within a policy window, can retrieve a token for the requested Origin within a policy window,
as set by the Issuer. Its ABNF is: as set by the Issuer. Its ABNF is:
Sec-Token-Limit = sf-integer Sec-Token-Limit = sf-integer
5.3. Client-to-Attester Request 5.3. Client-to-Attester Request
skipping to change at page 14, line 31 skipping to change at page 14, line 38
nonce = random(32) nonce = random(32)
context = SHA256(challenge) context = SHA256(challenge)
token_input = concat(0x0003, nonce, context, key_id) token_input = concat(0x0003, nonce, context, key_id)
blinded_msg, blind_inv = rsabssa_blind(pkI, token_input) blinded_msg, blind_inv = rsabssa_blind(pkI, token_input)
The Client then uses Client Key to generate its one-time-use request The Client then uses Client Key to generate its one-time-use request
public key request_key and blind request_blind as described in public key request_key and blind request_blind as described in
Section 7.1. Section 7.1.
The Client then encrypts the origin name using Origin Name Key, The Client then constructs a InnerTokenRequest value, denoted
producing encrypted_origin_name as described in Section 6. origin_token_request, combining blinded_msg, request_key, and the
origin name as follows:
struct {
uint8_t blinded_msg[Nk];
uint8_t request_key[Npk];
uint8_t padded_origin_name<0..2^16-1>;
} InnerTokenRequest;
This structure is initialized and then encrypted using Issuer
Encryption Key, producing encrypted_token_request, as described in
Section 6.
Finally, the Client uses Client Secret to produce request_signature Finally, the Client uses Client Secret to produce request_signature
as described in Section 7.1.2. as described in Section 7.1.2.
The Client then constructs a TokenRequest structure. This The Client then constructs a TokenRequest structure. This
TokenRequest structure is based on the publicly verifiable token TokenRequest structure is based on the publicly verifiable token
issuance path in [ISSUANCE], adding fields for the encrypted origin issuance path in [ISSUANCE], adding fields for the encrypted origin
name and request signature. name and request signature.
struct { struct {
uint16_t token_type = 0x0003; uint16_t token_type = 0x0003;
uint8_t token_key_id; uint8_t token_key_id;
uint8_t blinded_msg[Nk]; uint8_t issuer_encap_key_id[32];
uint8_t request_key[49]; uint8_t encrypted_token_request<1..2^16-1>;
uint8_t origin_name_key_id[32]; uint8_t request_signature[Nsig];
uint8_t encrypted_origin_name<1..2^16-1>;
uint8_t request_signature[96];
} TokenRequest; } TokenRequest;
The structure fields are defined as follows: The structure fields are defined as follows:
* "token_type" is a 2-octet integer, which matches the type in the * "token_type" is a 2-octet integer, which matches the type in the
challenge. challenge.
* "token_key_id" is the least significant byte of the Token Key key * "token_key_id" is the least significant byte of the Token Key key
ID, which is generated as SHA256(public_key), where public_key is ID, which is generated as SHA256(public_key), where public_key is
a DER-encoded SubjectPublicKeyInfo object carrying Token Key. a DER-encoded SubjectPublicKeyInfo object carrying Token Key.
* "blinded_msg" is the Nk-octet request defined above. * "issuer_encap_key_id" is a collision-resistant hash that
identifies the Issuer Encryption Key, generated as
* "request_key" is computed as described in Section 7.1.1. SHA256(EncapsulationKey).
* "origin_name_key_id" is a collision-resistant hash that identifies
the Origin Name Key, generated as SHA256(NameKey).
* "encrypted_origin_name" is an encrypted structure that contains * "encrypted_token_request" is an encrypted structure that contains
Origin Name, calculated as described in Section 6. an InnerTokenRequest value, calculated as described in Section 6.
* "request_signature" is computed as described in Section 7.1.2. * "request_signature" is computed as described in Section 7.1.2.
The Client then generates an HTTP POST request to send through the The Client then generates an HTTP POST request to send through the
Attester to the Issuer, with the TokenRequest as the body. The media Attester to the Issuer, with the TokenRequest as the body. The media
type for this request is "message/token-request". The Client type for this request is "message/token-request". The Client
includes the "Sec-Token-Origin" header, whose value is Anonymous includes the "Sec-Token-Origin" header, whose value is Anonymous
Origin ID; the "Sec-Token-Client" header, whose value is Client Key; Origin ID; the "Sec-Token-Client" header, whose value is Client Key;
and the "Sec-Token-Request-Blind" header, whose value is the "Sec-Token-Request-Blind" header, whose value is request_blind;
request_blind. The Client sends this request to the Attester's proxy and the "Sec-Token-Request-Key" header, whose value is request_key.
URI. An example request is shown below, where Nk = 512, the Issuer The Client sends this request to the Attester's proxy URI. An
Name is "issuer.net", and the Attester URI template is example request is shown below, where the Issuer Name is "issuer.net"
"https://attester.net/token-request{?issuer}" and the Attester URI template is "https://attester.net/token-
request{?issuer}"
:method = POST :method = POST
:scheme = https :scheme = https
:authority = attester.net :authority = attester.net
:path = /token-request?issuer=issuer.net :path = /token-request?issuer=issuer.net
accept = message/token-response accept = message/token-response
cache-control = no-cache, no-store cache-control = no-cache, no-store
content-type = message/token-request content-type = message/token-request
content-length = <Length of TokenRequest> content-length = <Length of TokenRequest>
sec-token-origin = Anonymous Origin ID sec-token-origin = Anonymous Origin ID
sec-token-client = Client Key sec-token-client = Client Key
sec-token-request-blind = request_blind sec-token-request-blind = request_blind
sec-token-request-key = request_key
<Bytes containing the TokenRequest> <Bytes containing the TokenRequest>
If the Attester detects a token_type in the TokenRequest that it does If the Attester detects a token_type in the TokenRequest that it does
not recognize or support, it MUST reject the request with an HTTP 400 not recognize or support, it MUST reject the request with an HTTP 400
error. error.
The Attester also checks to validate that the origin_name_key_id in The Attester also checks to validate that the issuer_encap_key_id in
the client's TokenRequest matches a known Origin Name Key public key the client's TokenRequest matches a known Issuer Encapsulation Key
for the Issuer. For example, the Attester can fetch this key using public key for the Issuer. For example, the Attester can fetch this
the API defined in Section 3. This check is done to help ensure that key using the API defined in Section 3. This check is done to help
the Client has not been given a unique key that could allow the ensure that the Client has not been given a unique key that could
Issuer to fingerprint or target the Client. If the key does not allow the Issuer to fingerprint or target the Client. If the key
match, the Attester rejects the request with an HTTP 400 error. Note does not match, the Attester rejects the request with an HTTP 400
that this can lead to failures in the event of Issuer Origin Name Key error. Note that this can lead to failures in the event of Issuer
rotation; see Section 9 for considerations. Issuer Encapsulation Key rotation; see Section 9 for considerations.
The Attester finally validates the Client's stable mapping request as The Attester finally validates the Client's stable mapping request as
described in Section 7.2. If this fails, the Attester MUST return an described in Section 7.2. If this fails, the Attester MUST return an
HTTP 400 error to the Client. HTTP 400 error to the Client.
If the Attester accepts the request, it will look up the state stored If the Attester accepts the request, it will look up the state stored
for this Client. It will look up the count of previously generate for this Client. It will look up the count of previously generate
tokens for this Client using the same Anonymous Origin ID. See tokens for this Client using the same Anonymous Origin ID. See
Section 5.1.2 for more details. Section 5.1.2 for more details.
skipping to change at page 17, line 28 skipping to change at page 17, line 39
Attesters, either via mutual TLS or another form of application-layer Attesters, either via mutual TLS or another form of application-layer
authentication. They MAY additionally use mechanisms such as TLS authentication. They MAY additionally use mechanisms such as TLS
certificate pinning, to mitigate the risk of channel compromise; see certificate pinning, to mitigate the risk of channel compromise; see
Section 8 for additional about this channel. Section 8 for additional about this channel.
Upon receipt of the forwarded request, the Issuer validates the Upon receipt of the forwarded request, the Issuer validates the
following conditions: following conditions:
* The TokenRequest contains a supported token_type * The TokenRequest contains a supported token_type
* The TokenRequest.token_key_id and TokenRequest.origin_name_key_id * The TokenRequest.token_key_id and TokenRequest.issuer_encap_key_id
correspond to known Token Keys and Origin Name Keys held by the correspond to known Token Keys and Issuer Encapsulation Keys held
Issuer. by the Issuer.
* The TokenRequest.encrypted_origin_name can be decrypted using the
Issuer's private key (the private key associated with Origin Name
Key), and matches an Origin Name that is served by the Issuer.
This name might be the empty string "", as described in Section 6,
in which case the Issuer applies a cross-origin policy if
supported. If a cross-origin policy is not supported, this
condition is not met.
* The TokenRequest.blinded_msg is of the correct size * The TokenRequest.encrypted_token_request can be decrypted using
the Issuer's private key (the private key associated with Issuer
Encapsulation Key), and contains a valid InnerTokenRequest whose
unpadded origin name matches an Origin Name that is served by the
Issuer. The Origin name associated with the InnerTokenRequest
value might be the empty string "", as described in Section 6, in
which case the Issuer applies a cross-origin policy if supported.
If a cross-origin policy is not supported, this condition is not
met.
If any of these conditions is not met, the Issuer MUST return an HTTP If any of these conditions is not met, the Issuer MUST return an HTTP
400 error to the Attester, which will forward the error to the 400 error to the Attester, which will forward the error to the
client. client.
The Issuer determines the correct Issuer Key by using the decrypted The Issuer determines the correct Issuer Key by using the decrypted
Origin Name value and TokenRequest.token_key_id. If there is no Origin Name value and TokenRequest.token_key_id. If there is no
Token Key whose truncated key ID matches TokenRequest.token_key_id, Token Key whose truncated key ID matches TokenRequest.token_key_id,
the Issuer MUST return an HTTP 401 error to Attester, which will the Issuer MUST return an HTTP 401 error to Attester, which will
forward the error to the client. The Attester learns that the forward the error to the client. The Attester learns that the
client's view of the Origin key was invalid in the process. client's view of the Origin key was invalid in the process.
5.5. Issuer-to-Attester Response 5.5. Issuer-to-Attester Response
If the Issuer is willing to give a token to the Client, the Issuer If the Issuer is willing to give a token to the Client, the Issuer
decrypts TokenRequest.encrypted_origin_name to discover "origin". If decrypts TokenRequest.encrypted_token_request to discover a
this fails, the Issuer rejects the request with a 400 error. InnerTokenRequest value. If this fails, the Issuer rejects the
Otherwise, the Issuer validates and processes the token request with request with a 400 error. Otherwise, the Issuer validates and
Issuer Origin Secret corresponding to the designated Origin as processes the token request with Issuer Origin Secret corresponding
described in Section 7.3. If this fails, the Issuer rejects the to the designated Origin as described in Section 7.3. If this fails,
request with a 400 error. Otherwise, the output is index_key. the Issuer rejects the request with a 400 error. Otherwise, the
output is index_key.
The Issuer completes the issuance flow by computing a blinded The Issuer completes the issuance flow by computing a blinded
response as follows: response as follows:
blind_sig = rsabssa_blind_sign(skP, TokenRequest.blinded_msg) blind_sig = rsabssa_blind_sign(skP, InnerTokenRequest.blinded_msg)
skP is the private key corresponding to Token Key, known only to the skP is the private key corresponding to Token Key, known only to the
Issuer. Issuer. The Issuer then encrypts blind_sig to the Client as
described in Section 6.2, yielding encrypted_token_response.
The Issuer generates an HTTP response with status code 200 whose body The Issuer generates an HTTP response with status code 200 whose body
consists of blind_sig, with the content type set as "message/token- consists of blind_sig, with the content type set as "message/token-
response", the index_key set in the "Sec-Token-Origin" header, and response", the index_key set in the "Sec-Token-Origin" header, and
the limit of tokens allowed for a Client for the Origin within a the limit of tokens allowed for a Client for the Origin within a
policy window set in the "Sec-Token-Limit" header. This limit SHOULD policy window set in the "Sec-Token-Limit" header. This limit SHOULD
NOT be unique to a specific Origin, such that the Attester could use NOT be unique to a specific Origin, such that the Attester could use
the value to infer which Origin the Client is accessing (see the value to infer which Origin the Client is accessing (see
Section 9). Section 9).
:status = 200 :status = 200
content-type = message/token-response content-type = message/token-response
content-length = <Length of blind_sig> content-length = <Length of blind_sig>
sec-token-origin = index_key sec-token-origin = index_key
sec-token-limit = Token limit sec-token-limit = Token limit
<Bytes containing the blind_sig> <Bytes containing the encrypted_token_response>
5.6. Attester-to-Client Response 5.6. Attester-to-Client Response
Upon receipt of a successful response from the Issuer, the Attester Upon receipt of a successful response from the Issuer, the Attester
extracts the "Sec-Token-Origin" header, and uses the value to extracts the "Sec-Token-Origin" header, and uses the value to
determine Anonymous Issuer Origin ID as described in Section 7.4. determine Anonymous Issuer Origin ID as described in Section 7.4.
If the "Sec-Token-Origin" is missing, or if the same Anonymous Issuer If the "Sec-Token-Origin" is missing, or if the same Anonymous Issuer
Origin ID was previously received in a response for a different Origin ID was previously received in a response for a different
Anonymous Origin ID within the same policy window, the Attester MUST Anonymous Origin ID within the same policy window, the Attester MUST
skipping to change at page 19, line 19 skipping to change at page 19, line 32
with an HTTP 429 (Too Many Requests) error. with an HTTP 429 (Too Many Requests) error.
For all other cases, the Attester forwards all HTTP responses For all other cases, the Attester forwards all HTTP responses
unmodified to the Client as the response to the original request for unmodified to the Client as the response to the original request for
this issuance. this issuance.
When the Attester detects successful token issuance, it MUST When the Attester detects successful token issuance, it MUST
increment the counter in its state for the number of tokens issued to increment the counter in its state for the number of tokens issued to
the Client for the Anonymous Origin ID. the Client for the Anonymous Origin ID.
Upon receipt, the Client handles the response and, if successful, Upon receipt, the Client decrypts the blind_sig from
processes the body as follows: encrypted_token_response as described in Section 6.2. If successful,
the Client then processes the response as follows:
authenticator = rsabssa_finalize(pkI, token_input, blind_sig, blind_inv) authenticator = rsabssa_finalize(pkI, token_input, blind_sig, blind_inv)
If this succeeds, the Client then constructs a token as described in If this succeeds, the Client then constructs a token as described in
[AUTHSCHEME] as follows: [AUTHSCHEME] as follows:
struct { struct {
uint16_t token_type = 0x0003 uint16_t token_type = 0x0003
uint8_t nonce[32]; uint8_t nonce[32];
uint8_t context[32]; uint8_t context[32];
uint8_t token_key_id[Nid]; uint8_t token_key_id[Nid];
uint8_t authenticator[Nk] uint8_t authenticator[Nk]
} Token; } Token;
6. Encrypting Origin Names 6. Encrypting Origin Token Requests and Responses
Given a NameKey (Origin Name Key), Clients produce Clients encapsulate token request information to the Issuer using the
encrypted_origin_name and authenticate the contents of the Issuer Encapsulation Key. Issuers decrypt the token request using
TokenRequest using the following values: their corresponding private key. This process yields the decrypted
token request as well as a shared encryption context between Client
and Issuer. Issuers encapsulate their token response to the Client
using an ephemeral key derived from this shared encryption context.
This process ensures that the Attester learns neither the token
request or response information.
Client to Issuer encapsulation is described in Section 6.1, and
Issuer to Client encapsulation is described in Section 6.2.
6.1. Client to Issuer Encapsulation
Given a EncapsulationKey (Issuer Encapsulation Key), Clients produce
encrypted_token_request using the following values:
* the one octet key identifier from the Name Key, keyID, with the * the one octet key identifier from the Name Key, keyID, with the
corresponding KEM identified by kemID, the public key from the corresponding KEM identified by kemID, the public key from the
configuration, pkI, and; configuration, pkI, and;
* a selected combination of KDF, identified by kdfID, and AEAD, * a selected combination of KDF, identified by kdfID, and AEAD,
identified by aeadID. identified by aeadID.
Beyond the key configuration inputs, Clients also require the Beyond the key configuration inputs, Clients also require the
following inputs defined in Section 5.3: token_key_id, blinded_msg, following inputs defined in Section 5.3: token_key_id, blinded_msg,
request_key, and origin_name_key_id. request_key, origin_name, and issuer_encap_key_id.
Together, these are used to encapsulate Origin Name (origin_name) and Together, these are used to encapsulate an InnerTokenRequest and
produce Encrypted Origin Name (encrypted_origin). produce an encrypted token request (encrypted_token_request).
origin_name contains the name of the origin that initiated the origin_name contains the name of the origin that initiated the
challenge, as taken from the TokenChallenge.origin_info field. If challenge, as taken from the TokenChallenge.origin_info field. If
the TokenChallenge.origin_info field is empty, origin_name is set to the TokenChallenge.origin_info field is empty, origin_name is set to
the empty string "". the empty string "".
The process for generating encrypted_origin from origin_name is as The process for generating encrypted_token_request from blinded_msg,
follows: request_key, and origin_name values is as follows:
1. Compute an [HPKE] context using pkI, yielding context and 1. Compute an [HPKE] context using pkI, yielding context and
encapsulation key enc. encapsulation key enc.
2. Construct associated data, aad, by concatenating the values of 2. Construct associated data, aad, by concatenating the values of
keyID, kemID, kdfID, aeadID, and all other values of the keyID, kemID, kdfID, aeadID, and all other values of the
TokenRequest structure. TokenRequest structure.
3. Pad origin_name with N zero bytes, where N = 31 - ((L - 1) % 32) 3. Pad origin_name with N zero bytes, where N = 31 - ((L - 1) % 32)
and L is the length of origin_name. Denote this padding process and L is the length of origin_name. If L is 0, N = 32. Denote
as the function pad. this padding process as the function pad.
4. Encrypt (seal) the padded origin_name with aad as associated data 4. Encrypt (seal) the padded origin_name with aad as associated data
using context, yielding ciphertext ct. using context, yielding ciphertext ct.
5. Concatenate the values of aad, enc, and ct, yielding 5. Concatenate the values of aad, enc, and ct, yielding
encrypted_origin_name. encrypted_token_request.
Note that enc is of fixed-length, so there is no ambiguity in parsing Note that enc is of fixed-length, so there is no ambiguity in parsing
this structure. this structure.
In pseudocode, this procedure is as follows: In pseudocode, this procedure is as follows:
enc, context = SetupBaseS(pkI, "TokenRequest") enc, context = SetupBaseS(pkI, "InnerTokenRequest")
aad = concat(encode(1, keyID), aad = concat(encode(1, keyID),
encode(2, kemID), encode(2, kemID),
encode(2, kdfID), encode(2, kdfID),
encode(2, aeadID), encode(2, aeadID),
encode(2, token_type), encode(2, token_type),
encode(1, token_key_id), encode(1, token_key_id),
encode(Nk, blinded_msg), encode(32, issuer_encap_key_id))
encode(49, request_key), padded_origin_name = pad(origin_name)
encode(32, origin_name_key_id)) input = concat(encode(Nk, blinded_msg),
ct = context.Seal(aad, pad(origin_name)) encode(49, request_key),
encrypted_origin_name = concat(enc, ct) encode(len(padded_origin_name), padded_origin_name))
Issuers reverse this procedure to recover the (padded) Origin Name by ct = context.Seal(aad, input)
computing the AAD as described above and decrypting encrypted_token_request = concat(enc, ct)
encrypted_origin_name with their private key skI (the private key
corresponding to pkI), and stripping off padding bytes. In
pseudocode, this procedure is as follows:
enc, ct = parse(encrypted_origin_name) Issuers reverse this procedure to recover the InnerTokenRequest value
by computing the AAD as described above and decrypting
encrypted_token_request with their private key skI (the private key
corresponding to pkI). The origin_name value is recovered from
InnerTokenRequest.padded_origin_name by stripping off padding bytes.
In pseudocode, this procedure is as follows:
enc, ct = parse(encrypted_token_request)
aad = concat(encode(1, keyID), aad = concat(encode(1, keyID),
encode(2, kemID), encode(2, kemID),
encode(2, kdfID), encode(2, kdfID),
encode(2, aeadID), encode(2, aeadID),
encode(2, token_type), encode(2, token_type),
encode(1, token_key_id), encode(1, token_key_id),
encode(Nk, blinded_msg), encode(32, issuer_encap_key_id))
encode(49, request_key), context = SetupBaseR(enc, skI, "TokenRequest")
encode(32, origin_name_key_id)) origin_token_request, error = context.Open(aad, ct)
enc, context = SetupBaseR(enc, skI, "TokenRequest") The InnerTokenRequest.blinded_msg and InnerTokenRequest.request_key
origin_name, error = context.Open(aad, ct) values, along with the unpadded origin_name value, are used by the
Issuer as described in Section 5.4.
The resulting value of origin_name is used by the Issuer to determine 6.2. Issuer to Client Encapsulation
which rate-limit values to send to the Attester for enforcement. If
the decrypted origin_name is the empty string "", the Issuer applies Given an HPKE context context computed in Section 6.1, Issuers
a cross-origin rate-limit policy, if supported. If the decrypted encapsulate their token response blind_sig, yielding an encrypted
origin_name is the empty string "" and the Issuer does not support token response encrypted_token_response, to the Client as follows:
cross-origin rate limiting, then it MUST abort the protocol as
described in Section 5.4. 1. Export a secret secret from context, using the string
"OriginTokenResponse" as context. The length of this secret is
max(Nn, Nk), where Nn and Nk are the length of AEAD key and nonce
associated with context.
2. Generate a random value of length max(Nn, Nk) bytes, called
response_nonce.
3. Extract a pseudorandom key prk using the Extract function
provided by the KDF algorithm associated with context. The ikm
input to this function is secret; the salt input is the
concatenation of enc (from enc_request) and response_nonce
4. Use the Expand function provided by the same KDF to extract an
AEAD key key, of length Nk - the length of the keys used by the
AEAD associated with context. Generating key uses a label of
"key".
5. Use the same Expand function to extract a nonce nonce of length
Nn - the length of the nonce used by the AEAD. Generating nonce
uses a label of "nonce".
6. Encrypt blind_sig, passing the AEAD function Seal the values of
key, nonce, empty aad, and a pt input of request, which yields
ct.
7. Concatenate response_nonce and ct, yielding an Encapsulated
Response enc_response. Note that response_nonce is of fixed-
length, so there is no ambiguity in parsing either response_nonce
or ct.
In pseudocode, this procedure is as follows:
secret = context.Export("OriginTokenResponse", Nk)
response_nonce = random(max(Nn, Nk))
salt = concat(enc, response_nonce)
prk = Extract(salt, secret)
aead_key = Expand(prk, "key", Nk)
aead_nonce = Expand(prk, "nonce", Nn)
ct = Seal(aead_key, aead_nonce, "", blind_sig)
encrypted_token_response = concat(response_nonce, ct)
Clients decrypt encrypted_token_response by reversing this process.
That is, they first parse enc_response into response_nonce and ct.
They then follow the same process to derive values for aead_key and
aead_nonce.
The client uses these values to decrypt ct using the Open function
provided by the AEAD. Decrypting might produce an error, as follows:
blind_sig, error = Open(aead_key, aead_nonce, "", ct)
7. Anonymous Issuer Origin ID Computation 7. Anonymous Issuer Origin ID Computation
This section describes the Client, Attester, and Issuer behavior in This section describes the Client, Attester, and Issuer behavior in
computing Anonymous Issuer Origin ID, the stable mapping based on computing Anonymous Issuer Origin ID, the stable mapping based on
client identity and origin name. At a high level, this functionality client identity and origin name. At a high level, this functionality
computes y = F(x, k), where x is a per-Client secret and k is a per- computes y = F(x, k), where x is a per-Client secret and k is a per-
Origin secret, subject to the following constraints: Origin secret, subject to the following constraints:
* The Attester only learns y if the Client in possession of x * The Attester only learns y if the Client in possession of x
skipping to change at page 22, line 21 skipping to change at page 24, line 13
<---------------------- <----------------------
The protocol for computing this functionality is divided into The protocol for computing this functionality is divided into
sections for each of the participants. Section 7.1 describes Client sections for each of the participants. Section 7.1 describes Client
behavior for initiating the computation with its per-Client secret, behavior for initiating the computation with its per-Client secret,
Section 7.2 describes Attester behavior for verifying Client Section 7.2 describes Attester behavior for verifying Client
requests, Section 7.3 describes Issuer behavior for computing the requests, Section 7.3 describes Issuer behavior for computing the
mapping with its per-Origin secret, and Section 7.4 describes the mapping with its per-Origin secret, and Section 7.4 describes the
final Attester step for computing the client-origin index. final Attester step for computing the client-origin index.
The index computation is based on ECDSA [ECDSA] instantiated with The index computation is based on a signature scheme with key
P-384 and SHA-384 and extended with key blinding support as described blinding and unblinding support, denoted BKS, as described in
in [KEYBLINDING]. It uses the following functions: [KEYBLINDING]. Such a scheme has the following functions:
* ECDSA-KeyGen(): Generate a random ECDSA private and public key * BKS-KeyGen(): Generate a random private and public key pair (sk,
pair (sk, pk). pk).
* ECDSA-BlindPublicKey(pk, r): Produce a blinded public key based on * BKS-BlindKeyGen(): Generate a random blinding key bk.
the input public key pk and blind r according to [KEYBLINDING],
Section 6.1.
* ECDSA-Verify(pk, msg, sig): Verify the DER-encoded [X690] ECDSA- * BKS-BlindPublicKey(pk, bk): Produce a blinded public key based on
Sig-Value signature sig over input message msg against the ECDSA the input public key pk and blind key bk according to
public key pk, producing a boolean value indicating success. [KEYBLINDING], Section 6.1.
* ECDSA-BlindKeySign(sk_sign, sk_blind, msg): Sign input message msg * BKS-Verify(pk, msg, sig): Verify signature sig over input message
with signing key sk_sign and blind sk_blind according to msg against the public key pk, producing a boolean value
[KEYBLINDING], Section 6.2, and serializes the resulting signature indicating success.
pair (r, s) in "raw" form, i.e., as the concatenation of two
48-byte, big endian scalars.
* ECDSA-SerializePrivatekey(sk): Serialize an ECDSA private key * BKS-BlindKeySign(sk_sign, sk_blind, msg): Sign input message msg
using the Field-Element-to-Octet-String conversion according to with signing key sk_sign and blind key sk_blind according to
[SECG]. [KEYBLINDING], Section 6.2, and produce a signature of size Nsig
bytes.
* ECDSA-DeserializePrivatekey(buf): Attempt to deserialize an ECDSA * BKS-SerializePrivatekey(sk): Serialize a private key to a byte
private key from a 48-byte string buf using Octet-String-to-Field- string of length Nsk.
Element from [SECG]. This function can fail if buf does not
represent a valid private key.
* ECDSA-SerializePublicKey(pk): Serialize an ECDSA public key using * BKS-DeserializePrivatekey(buf): Attempt to deserialize a private
the compressed Elliptic-Curve-Point-to-Octet-String method key from an Nsk-byte string buf. This function can fail if buf
according to [SECG]. does not represent a valid private key.
* ECDSA-DeserializePublicKey(buf): Attempt to deserialize a public * BKS-SerializePublicKey(pk): Serialize a public key to a byte
key using the compressed Octet-String-to-Elliptic-Curve-Point string of length Npk.
method according to [SECG], and then performs partial public-key
validation as defined in section 5.6.2.3.4 of [KEYAGREEMENT]. * BKS-DeserializePublicKey(buf): Attempt to deserialize a public key
This validation includes checking that the coordinates are in the of length Npk. This function can fail if buf does not represent a
correct range, that the point is on the curve, and that the point valid public key.
is not the point at infinity.
Additionally, each BKS scheme has a corresponding hash function,
denoted Hash. The implementation of each of these functions depends
on the issuance protocol token type. See Section 11.1 for more
details.
7.1. Client Behavior 7.1. Client Behavior
This section describes the Client behavior for generating an one- This section describes the Client behavior for generating an one-
time-use request key and signature. Clients provide their Client time-use request key and signature. Clients provide their Client
Secret as input to the request key generation step, and the rest of Secret as input to the request key generation step, and the rest of
the token request inputs to the signature generation step. the token request inputs to the signature generation step.
7.1.1. Request Key 7.1.1. Request Key
Clients produce request_key by masking Client Key and Client Secret Clients produce request_key by masking Client Key and Client Secret
with a randomly chosen blind. Let pk_sign and sk_sign denote Client with a randomly chosen blind. Let pk_sign and sk_sign denote Client
Key and Client Secret, respectively. This process is done as Key and Client Secret, respectively. This process is done as
follows: follows:
1. Generate a random ECDSA private key, sk_blind. 1. Generate a random blind key, sk_blind.
2. Blind pk_sign with sk_blind to compute a blinded public key, 2. Blind pk_sign with sk_blind to compute a blinded public key,
request_key. request_key.
3. Output the blinded public key. 3. Output the blinded public key.
In pseudocode, this is as follows: In pseudocode, this is as follows:
sk_blind = ECDSA-KeyGen() sk_blind = BKS-BlindKeyGen()
blinded_key = ECDSA-BlindPublicKey(pk_sign, sk_blind) blinded_key = BKS-BlindPublicKey(pk_sign, sk_blind)
request_key = ECDSA-SerializePublicKey(blinded_key) request_key = BKS-SerializePublicKey(blinded_key)
request_blind = ECDSA-SerializePrivatekey(sk_blind) request_blind = BKS-SerializePrivatekey(sk_blind)
7.1.2. Request Signature 7.1.2. Request Signature
Clients produce signature of their request based on the following Clients produce signature of their request based on the following
inputs defined in Section 5.3: token_key_id, blinded_msg, inputs defined in Section 5.3: token_key_id, blinded_msg,
request_key, name_key_id, encrypted_origin_name. This process request_key, issuer_encap_key_id, encrypted_token_request. This
requires the blind value sk_blind produced during the Section 7.1.1 process requires the blind value sk_blind produced during the
process. As above, let pk and sk denote Client Key and Client Section 7.1.1 process. As above, let pk and sk denote Client Key and
Secret, respectively. Given these values, this signature process Client Secret, respectively. Given these values, this signature
works as follows: process works as follows:
1. Concatenate all signature inputs to yield a message to sign. 1. Concatenate all signature inputs to yield a message to sign.
2. Compute an ECDSA signature with the blind sk_blind over the input 2. Compute a signature with the blind sk_blind over the input
message using Client Secret, sk_sign as the signing key. message using Client Secret, sk_sign as the signing key.
3. Output the signature. 3. Output the signature.
In pseudocode, this is as follows: In pseudocode, this is as follows:
context = concat(0x0003, // token_type context = concat(token_type,
token_key_id, token_key_id,
blinded_msg, issuer_encap_key_id,
request_key, encrypted_token_request)
name_key_id, request_signature = BKS-BlindKeySign(sk_sign, sk_blind, context)
encrypted_origin_name)
request_signature = ECDSA-BlindKeySign(sk_sign, sk_blind, context)
7.2. Attester Behavior (Client Request Validation) 7.2. Attester Behavior (Client Request Validation)
Given a TokenRequest request containing request_key, Given a TokenRequest request containing request_key,
request_signature, and request_blind, as well as Client Key pk_blind, request_signature, and request_blind, as well as Client Key pk_blind,
Attesters verify the signature as follows: Attesters verify the signature as follows:
1. Check that request_key is a valid ECDSA public key. If this 1. Check that request_key is a valid public key. If this fails,
fails, abort. abort.
2. Check that request_blind is a valid ECDSA private key. If this 2. Check that request_blind is a valid private key. If this fails,
fails, abort. abort.
3. Blind the Client Key pk_sign by blind sk_blind, yielding a 3. Blind the Client Key pk_sign by blind sk_blind, yielding a
blinded key. If this does not match request_key, abort. blinded key. If this does not match request_key, abort.
4. Verify request_signature over the contents of the request, 4. Verify request_signature over the contents of the request,
excluding the signature itself, using request_key. If signature excluding the signature itself, using request_key. If signature
verification fails, abort. verification fails, abort.
In pseudocode, this is as follows: In pseudocode, this is as follows:
blind_key = ECDSA-DeserializePublicKey(request_key) blind_key = BKS-DeserializePublicKey(request_key)
sk_blind = ECDSA-DeserializePrivatekey(request_blind) sk_blind = BKS-DeserializePrivatekey(request_blind)
pk_blind = ECDSA-BlindPublicKey(pk_sign, sk_blind) pk_blind = BKS-BlindPublicKey(pk_sign, sk_blind)
if pk_blind != blind_key: if pk_blind != blind_key:
raise InvalidParameterError raise InvalidParameterError
context = parse(request[..len(request)-96]) // this matches context computed during signing context = parse(request[..len(request)-Nsig]) // this matches context computed during signing
valid = ECDSA-Verify(blind_key, context, request_signature) valid = BKS-Verify(blind_key, context, request_signature)
if not valid: if not valid:
raise InvalidSignatureError raise InvalidSignatureError
7.3. Issuer Behavior 7.3. Issuer Behavior
Given an Issuer Origin Secret (denoted sk_origin) and a TokenRequest, Given an Issuer Origin Secret (denoted sk_origin) and a TokenRequest,
from which request_key and request_signature are parsed, Issuers from which request_key and request_signature are parsed, Issuers
verify the request signature and compute a response as follows: verify the request signature and compute a response as follows:
1. Check that request_key is a valid ECDSA public key. If this 1. Check that request_key is a valid public key. If this fails,
fails, abort. abort.
2. Verify request_signature over the contents of the request, 2. Verify request_signature over the contents of the request,
excluding the signature itself, using request_key. If signature excluding the signature itself, using request_key. If signature
verification fails, abort. verification fails, abort.
3. Blind request_key by Issuer Origin Secret, sk_origin, yielding an 3. Blind request_key by Issuer Origin Secret, sk_origin, yielding an
index key. index key.
4. Output the index key. 4. Output the index key.
In pseudocode, this is as follows: In pseudocode, this is as follows:
blind_key = ECDSA-DeserializePublicKey(request_key) blind_key = BKS-DeserializePublicKey(request_key)
context = parse(request[..len(request)-96]) // this matches context computed during signing context = parse(request[..len(request)-Nsig]) // this matches context computed during signing
valid = ECDSA-Verify(blind_key, context, request_signature) valid = BKS-Verify(blind_key, context, request_signature)
if not valid: if not valid:
raise InvalidSignatureError raise InvalidSignatureError
evaluated_key = ECDSA-BlindPublicKey(request_key, sk_origin) evaluated_key = BKS-BlindPublicKey(request_key, sk_origin)
index_key = ECDSA-SerializePublicKey(evaluated_key) index_key = BKS-SerializePublicKey(evaluated_key)
7.4. Attester Behavior (Index Computation) 7.4. Attester Behavior (Index Computation)
Given an Issuer response index_key, Client blind sk_blind, and Client Given an Issuer response index_key, Client blind sk_blind, and Client
Key (denoted pk_sign), Attesters complete the Anonymous Issuer Origin Key (denoted pk_sign), Attesters complete the Anonymous Issuer Origin
ID computation as follows: ID computation as follows:
1. Check that index_key is a valid ECDSA public key. If this fails, 1. Check that index_key is a valid public key. If this fails,
abort. abort.
2. Unblind the index_key using the Client blind sk_blind, yielding 2. Unblind the index_key using the Client blind sk_blind, yielding
the index result. the index result.
3. Run HKDF [RFC5869] with SHA-384 using the index result as the 3. Run HKDF [RFC5869] with the hash function corresponding to the
secret, Client Key pk_sign as the salt, and ASCII string BKS scheme, using the index result as the secret, Client Key
"anon_issuer_origin_id" as the info string, yielding Anonymous pk_sign as the salt, and ASCII string "anon_issuer_origin_id" as
Issuer Origin ID. the info string, yielding Anonymous Issuer Origin ID.
In pseudocode, this is as follows: In pseudocode, this is as follows:
evaluated_key = ECDSA-DeserializePublicKey(index_key) evaluated_key = BKS-DeserializePublicKey(index_key)
unblinded_key = ECDSA-UnblindPublicKey(evaluated_key, sk_blind) unblinded_key = BKS-UnblindPublicKey(evaluated_key, sk_blind)
index_result = ECDSA-SerializePublicKey(unblinded_key) index_result = BKS-SerializePublicKey(unblinded_key)
pk_encoded = ECDSA-SerializePublicKey(pk_sign) pk_encoded = BKS-SerializePublicKey(pk_sign)
anon_issuer_origin_id = HKDF-SHA384(secret=index_result, anon_issuer_origin_id = HKDF-Hash(secret=index_result,
salt=pk_encoded, salt=pk_encoded, info="anon_issuer_origin_id")
info="anon_issuer_origin_id")
8. Security Considerations 8. Security Considerations
This section describes security considerations relevant to the use of This section describes security considerations relevant to the use of
this protocol. this protocol.
8.1. Channel Security 8.1. Channel Security
An attacker that can act as an intermediate between Attester and An attacker that can act as an intermediate between Attester and
Issuer communication can influence or disrupt the ability for the Issuer communication can influence or disrupt the ability for the
skipping to change at page 29, line 23 skipping to change at page 31, line 5
policies in [RFC6454]. Clients MAY further limit which policies in [RFC6454]. Clients MAY further limit which
authentication challenges they are willing to respond to, for example authentication challenges they are willing to respond to, for example
by only accepting challenges when the origin is a web site to which by only accepting challenges when the origin is a web site to which
the user navigated. the user navigated.
9.3. Client Identification with Unique Keys 9.3. Client Identification with Unique Keys
Client activity could be linked if an Origin and Issuer collude to Client activity could be linked if an Origin and Issuer collude to
have unique keys targeted at specific Clients or sets of Clients. have unique keys targeted at specific Clients or sets of Clients.
To mitigate the risk of a targeted Origin Name Key, the Attester can To mitigate the risk of a targeted Issuer Encapsulation Key, the
observe and validate the token_key_id presented by the Client to the Attester can observe and validate the token_key_id presented by the
Issuer. As described in Section 5, Attesters MUST validate that the Client to the Issuer. As described in Section 5, Attesters MUST
token_key_id in the Client's TokenRequest matches a known public key validate that the token_key_id in the Client's TokenRequest matches a
for the Issuer. The Attester needs to support key rotation, but known public key for the Issuer. The Attester needs to support key
ought to disallow very rapid key changes, which could indicate that rotation, but ought to disallow very rapid key changes, which could
an Origin is colluding with an Issuer to try to rotate the key for indicate that an Origin is colluding with an Issuer to try to rotate
each new Client in order to link the client activity. the key for each new Client in order to link the client activity.
9.4. Origin Identification 9.4. Origin Identification
As stated in Section 1.2, the design of this protocol is such that As stated in Section 1.2, the design of this protocol is such that
Attesters cannot learn the identity of origins that Clients are Attesters cannot learn the identity of origins that Clients are
accessing. The Origin Name itself is encrypted in the request accessing. The Origin Name itself is encrypted in the request
between the Client and the Issuer, so the Attester cannot directly between the Client and the Issuer, so the Attester cannot directly
learn the value. However, in order to prevent the Attester from learn the value. However, in order to prevent the Attester from
inferring the value, additional constraints need to be added: inferring the value, additional constraints need to be added:
skipping to change at page 31, line 4 skipping to change at page 32, line 28
graceful updates. The RECOMMENDED rotation interval is two times the graceful updates. The RECOMMENDED rotation interval is two times the
length of the policy window for that information. During generation, length of the policy window for that information. During generation,
issuers must ensure the token_key_id (the 8-bit prefix of issuers must ensure the token_key_id (the 8-bit prefix of
SHA256(Token Key)) is different from all other token_key_id values SHA256(Token Key)) is different from all other token_key_id values
for that origin currently in rotation. One way to ensure this for that origin currently in rotation. One way to ensure this
uniqueness is via rejection sampling, where a new key is generated uniqueness is via rejection sampling, where a new key is generated
until its token_key_id is unique among all currently in rotation for until its token_key_id is unique among all currently in rotation for
the origin. the origin.
11. IANA considerations 11. IANA considerations
11.1. Token Type 11.1. Token Type
This document updates the "Token Type" Registry ([AUTHSCHEME]) with This document updates the "Token Type" Registry ([AUTHSCHEME]) with
the following value: the following value:
+======+=============+==========+========+========+===+===+=========+ +======+=============+==========+========+========+===+===+=========+
|Value |Name |Publicly |Public |Private |Nk |Nid|Reference| |Value |Name |Publicly |Public |Private |Nk |Nid|Reference|
| | |Verifiable|Metadata|Metadata| | | | | | |Verifiable|Metadata|Metadata| | | |
+======+=============+==========+========+========+===+===+=========+ +======+=============+==========+========+========+===+===+=========+
|0x0003|Rate-Limited |Y |N |N |512|32 |This | |0x0003|Rate-Limited |Y |N |N |512|32 |This |
| |Blind RSA | | | | | |document | | |Blind | | | | | |document |
| |RSA(SHA-384, | | | | | | |
| |2048-bit) | | | | | | |
| |with | | | | | | |
| |ECDSA(P-384, | | | | | | |
| |SHA-384) | | | | | | |
+------+-------------+----------+--------+--------+---+---+---------+
|0x0004|Rate-Limited |Y |N |N |512|32 |This |
| |Blind | | | | | |document |
| |RSA(SHA-384, | | | | | | |
| |2048-bit) | | | | | | |
| |with | | | | | | |
| |Ed25519(SHA- | | | | | | |
| |512) | | | | | | |
+------+-------------+----------+--------+--------+---+---+---------+ +------+-------------+----------+--------+--------+---+---+---------+
Table 2: Token Types Table 2: Token Types
The details of the signature scheme with key blinding and unblinding
functions for each token type above are described in the following
sections.
11.1.1. ECDSA-based Token Type
This section describes the implementation details of the signature
scheme with key blinding and unblinding functions introduced in
Section 7 using [ECDSA] with P-384 as the underlying elliptic curve
and SHA-384 as the corresponding hash function.
* BKS-KeyGen(): Generate a random ECDSA private and public key pair
(sk, pk).
* BKS-BlindKeyGen(): Generate a random ECDSA private key bk.
* BKS-BlindPublicKey(pk, bk): Produce a blinded public key based on
the input public key pk and blind bk according to [KEYBLINDING],
Section 6.1.
* BKS-Verify(pk, msg, sig): Verify the DER-encoded [X690] BKS-Sig-
Value signature sig over input message msg against the ECDSA
public key pk, producing a boolean value indicating success.
* BKS-BlindKeySign(sk_sign, sk_blind, msg): Sign input message msg
with signing key sk_sign and blind sk_blind according to
[KEYBLINDING], Section 6.2, and serializes the resulting signature
pair (r, s) in "raw" form, i.e., as the concatenation of two
48-byte, big endian scalars, yielding an Nsig=96 byte signature.
* BKS-SerializePrivatekey(sk): Serialize an ECDSA private key using
the Field-Element-to-Octet-String conversion according to [SECG].
* BKS-DeserializePrivatekey(buf): Attempt to deserialize an ECDSA
private key from a 48-byte string buf using Octet-String-to-Field-
Element from [SECG]. This function can fail if buf does not
represent a valid private key.
* BKS-SerializePublicKey(pk): Serialize an ECDSA public key using
the compressed Elliptic-Curve-Point-to-Octet-String method
according to [SECG].
* BKS-DeserializePublicKey(buf): Attempt to deserialize a public key
using the compressed Octet-String-to-Elliptic-Curve-Point method
according to [SECG], and then performs partial public-key
validation as defined in section 5.6.2.3.4 of [KEYAGREEMENT].
This validation includes checking that the coordinates are in the
correct range, that the point is on the curve, and that the point
is not the point at infinity.
11.1.2. Ed25519-based Token Type
This section describes the implementation details of the signature
scheme with key blinding and unblinding functions introduced in
Section 7 using Ed25519 as described in [RFC8032].
* BKS-KeyGen(): Generate a random Ed25519 private and public key
pair (sk, pk), where sk is randomly generated 32 bytes (See
[RFC4086] for information about randomness generation) and pk is
computed according to [RFC8032], Section 5.1.5.
* BKS-BlindKeyGen(): Generate and output 32 random bytes.
* BKS-BlindPublicKey(pk, bk): Produce a blinded public key based on
the input public key pk and blind bk according to [KEYBLINDING],
Section 5.1.
* BKS-Verify(pk, msg, sig): Verify the signature sig over input
message msg against the Ed25519 public key pk, as defined in
[RFC8032], Section 5.1.7, producing a boolean value indicating
success.
* BKS-BlindKeySign(sk_sign, sk_blind, msg): Sign input message msg
with signing key sk_sign and blind sk_blind according to
[KEYBLINDING], Section 5.2, yielding an Nsig=64 byte signature.
* BKS-SerializePrivatekey(sk): Identity function which outputs sk as
an Nsk=32 byte buffer.
* BKS-DeserializePrivatekey(buf): Identity function which outputs
buf interpreted as sk.
* BKS-SerializePublicKey(pk): Identity function which outputs pk as
an Npk=32 byte buffer.
* BKS-DeserializePublicKey(buf): Identity function which outputs buf
interpreted as pk.
11.2. HTTP Headers 11.2. HTTP Headers
This document registers four new headers for use on the token This document registers four new headers for use on the token
issuance path in the "Permanent Message Header Field Names" issuance path in the "Permanent Message Header Field Names"
<https://www.iana.org/assignments/message-headers>. <https://www.iana.org/assignments/message-headers>.
+-------------------------+----------+--------+---------------+ +-------------------------+----------+--------+---------------+
| Header Field Name | Protocol | Status | Reference | | Header Field Name | Protocol | Status | Reference |
+-------------------------+----------+--------+---------------+ +-------------------------+----------+--------+---------------+
| Sec-Token-Origin | http | std | This document | | Sec-Token-Origin | http | std | This document |
+-------------------------+----------+--------+---------------+ +-------------------------+----------+--------+---------------+
| Sec-Token-Client | http | std | This document | | Sec-Token-Client | http | std | This document |
+-------------------------+----------+--------+---------------+ +-------------------------+----------+--------+---------------+
| Sec-Token-Request-Blind | http | std | This document | | Sec-Token-Request-Blind | http | std | This document |
+-------------------------+----------+--------+---------------+ +-------------------------+----------+--------+---------------+
| Sec-Token-Request-Key | http | std | This document |
+-------------------------+----------+--------+---------------+
| Sec-Token-Limit | http | std | This document | | Sec-Token-Limit | http | std | This document |
+-------------------------+----------+--------+---------------+ +-------------------------+----------+--------+---------------+
Figure 1: Registered HTTP Header Figure 1: Registered HTTP Header
12. References 12. References
12.1. Normative References 12.1. Normative References
[ARCH] Davidson, A., Iyengar, J., and C. A. Wood, "Privacy Pass [ARCH] Davidson, A., Iyengar, J., and C. A. Wood, "Privacy Pass
skipping to change at page 33, line 19 skipping to change at page 37, line 19
[RFC6454] Barth, A., "The Web Origin Concept", RFC 6454, [RFC6454] Barth, A., "The Web Origin Concept", RFC 6454,
DOI 10.17487/RFC6454, December 2011, DOI 10.17487/RFC6454, December 2011,
<https://www.rfc-editor.org/rfc/rfc6454>. <https://www.rfc-editor.org/rfc/rfc6454>.
[RFC6570] Gregorio, J., Fielding, R., Hadley, M., Nottingham, M., [RFC6570] Gregorio, J., Fielding, R., Hadley, M., Nottingham, M.,
and D. Orchard, "URI Template", RFC 6570, and D. Orchard, "URI Template", RFC 6570,
DOI 10.17487/RFC6570, March 2012, DOI 10.17487/RFC6570, March 2012,
<https://www.rfc-editor.org/rfc/rfc6570>. <https://www.rfc-editor.org/rfc/rfc6570>.
[RFC8032] Josefsson, S. and I. Liusvaara, "Edwards-Curve Digital
Signature Algorithm (EdDSA)", RFC 8032,
DOI 10.17487/RFC8032, January 2017,
<https://www.rfc-editor.org/rfc/rfc8032>.
[RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC
2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174,
May 2017, <https://www.rfc-editor.org/rfc/rfc8174>. May 2017, <https://www.rfc-editor.org/rfc/rfc8174>.
[RFC8941] Nottingham, M. and P-H. Kamp, "Structured Field Values for [RFC8941] Nottingham, M. and P-H. Kamp, "Structured Field Values for
HTTP", RFC 8941, DOI 10.17487/RFC8941, February 2021, HTTP", RFC 8941, DOI 10.17487/RFC8941, February 2021,
<https://www.rfc-editor.org/rfc/rfc8941>. <https://www.rfc-editor.org/rfc/rfc8941>.
[SECG] "Elliptic Curve Cryptography, Standards for Efficient [SECG] "Elliptic Curve Cryptography, Standards for Efficient
Cryptography Group, ver. 2", 2009, Cryptography Group, ver. 2", 2009,
skipping to change at page 34, line 5 skipping to change at page 38, line 5
12.2. Informative References 12.2. Informative References
[BASIC-ISSUANCE] [BASIC-ISSUANCE]
Celi, S., Davidson, A., Faz-Hernandez, A., Valdez, S., and Celi, S., Davidson, A., Faz-Hernandez, A., Valdez, S., and
C. A. Wood, "Privacy Pass Issuance Protocol", Work in C. A. Wood, "Privacy Pass Issuance Protocol", Work in
Progress, Internet-Draft, draft-ietf-privacypass-protocol- Progress, Internet-Draft, draft-ietf-privacypass-protocol-
04, 5 April 2022, <https://datatracker.ietf.org/doc/html/ 04, 5 April 2022, <https://datatracker.ietf.org/doc/html/
draft-ietf-privacypass-protocol-04>. draft-ietf-privacypass-protocol-04>.
[RFC4086] Eastlake 3rd, D., Schiller, J., and S. Crocker,
"Randomness Requirements for Security", BCP 106, RFC 4086,
DOI 10.17487/RFC4086, June 2005,
<https://www.rfc-editor.org/rfc/rfc4086>.
Appendix A. Acknowledgements Appendix A. Acknowledgements
The authors of this document would like to acknowledge feedback from The authors of this document would like to acknowledge feedback from
contributors to the Privacy Pass working group for their help in contributors to the Privacy Pass working group for their help in
improving this document. The authors also thank Frank Denis and improving this document. The authors also thank Frank Denis and
David Schinazi for their contributions. David Schinazi for their contributions.
Appendix B. Test Vectors Appendix B. Test Vectors
This section includes test vectors for Origin Name encryption in This section includes test vectors for Origin Name encryption in
skipping to change at page 34, line 30 skipping to change at page 38, line 35
The test vector below for the procedure in Section 6 lists the The test vector below for the procedure in Section 6 lists the
following values: following values:
* origin_name: The Origin Name to encrypt, represented as a * origin_name: The Origin Name to encrypt, represented as a
hexadecimal string. hexadecimal string.
* kem_id, kdf_id, aead_id: The HPKE algorithms comprising the * kem_id, kdf_id, aead_id: The HPKE algorithms comprising the
ciphersuite DHKEM(X25519, HKDF-SHA256), HKDF-SHA256, AES-128-GCM. ciphersuite DHKEM(X25519, HKDF-SHA256), HKDF-SHA256, AES-128-GCM.
* origin_name_key_seed: The seed used to derive the private key * issuer_encap_key_seed: The seed used to derive the private key
corresponding to Origin Name Key via the DeriveKeyPair function as corresponding to Issuer Encapsulation Key via the DeriveKeyPair
defined in Section 7.1.3. of [HPKE], represented as a hexadecimal function as defined in Section 7.1.3. of [HPKE], represented as a
string.
* origin_name_key: The public Origin Name Key, represented as a
hexadecimal string. hexadecimal string.
* token_type: The type of the protocol specified in this document, * issuer_encap_key: The public Issuer Encapsulation Key, represented
0x0003. as a hexadecimal string.
* token_type: The type of the protocol specified in this document.
* token_key_id: The ID of Token Key computed as in Section 5.3, a * token_key_id: The ID of Token Key computed as in Section 5.3, a
single octet. single octet.
* blinded_msg: A random blinded_msg value, represented as a * blinded_msg: A random blinded_msg value, represented as a
hexadecimal string. hexadecimal string.
* request_key: A random request_key value, represented as a * request_key: A random request_key value, represented as a
hexadecimal string. hexadecimal string.
* origin_name_key_id: The Origin Name Key ID computed as in * issuer_encap_key_id: The Issuer Encapsulation Key ID computed as
Section 5.3, represented as a hexadecimal string. in Section 5.3, represented as a hexadecimal string.
* encrypted_origin_name: The encrypted Origin Name, represented as a * encrypted_token_request: The encrypted InnerTokenRequest,
hexadecimal string. represented as a hexadecimal string.
origin_name: 746573742e6578616d706c65 origin_name: 746573742e6578616d706c65
kem_id: 32 kem_id: 32
kdf_id: 1 kdf_id: 1
aead_id: 1 aead_id: 1
origin_name_key_seed: issuer_encap_key_seed:
ccc9e9744e7461acc6f3967757e7564b78f04ae5c9cd33f8c0c9b51ddff61f4f d2653816496f400baec656f213f1345092f4406af4f2a63e164956c4c3d240ca
origin_name_key: 010020c9a7a358ab74c0664b0cffd11a5f7090108086153d77e2824 issuer_encap_key: 010020d7b6a2c10e75c4239feb9897e8d23f3f3c377d78e7903611
72d254991fdbe1b00010001 53167736a24a9c5400010001
token_type: 3 token_type: 3
token_key_id: 104 token_key_id: 125
blinded_msg: 01a7031dbbcca4ac6acaa4650219406fd9fbceb8c264e2b3be22823a679 blinded_msg: 89da551a48270b053e53c9eb741badf89e43cb7e66366bb936e11fb2aa0
6571230f29ec01fe2dd633bbd4c208addfa0a6dbb149aeb4aca9070bafe849301076a40b d30866986a790378bb9fc6a7cf5c32b7b7584d448ffa4ced3be650e354b3136428a52ec0
442469066ef78525f16a4e8cb3596ac0c548932aa421d7294d98e86187100598e9b8a968 b27c4103c5855c2b9b4f521ad0713c800d7e6925b6c62e1a6f58b31d13335f468cf509b7
c56d2c0277132c3efdc04b6030b9800642db686254784927cfd941f8a3a1f71893e33af4 46a16e79b23862d277d0880706c3fb84b127d94faf8d6d2f3e124e681994441b19be084e
d73f71403108c882afed2129b050663839d77bbd38f9479e7242a2d31f2fbce72259aab4 c5c159bcd0abab433bbc308d90ea2cabdf4216e1b07155be66a048d686e383ca1e517ab8
acecf7da7168347a214c6e9bb77974812b363355ac8bf4703085de54e2af85e970a3a83e 0025bb4849d98beb8c3d05d045c1167cb74f4451d8f85695babb604418385464f21f9a81
2ee3d658951167fae57ab313569dcb7551c916cb0bda9c6293843fe75849eb6a33953145 5fb850ed83fd16a966130427e5637816501f7a79c0010e06adeba55781ceb50f56eae152
43bccb7e5146b618c637ffe8fc1bae2fddb102ce6d9a9c5eee0d267849a9bfb12e633fbf ebd06f3cef80dc7ab121d
ffc80b76b017ae16f70ee6c3d841b9a4b1bf88264a2d62ae564941f943001ed95b869d2f request_key: 0161d905e4e37f515cb61f863b60e5896aa9e4a17dbe238e752a144c64a
d81e82efc399507a0ed5450be2832076a40ce1dbd1e555fb0cf360e65c4087d101d87919 5412e244f0b1f75e010831e185cac023d33cb20
9180dfcecdd0a3a2340b893fd130e5d6ece273b4a646f157b344f110973403a14a5f46d3 issuer_encap_key_id:
b2ec4457e2164ce850fc395c71d4adeab69f7ec617b6b062c1afb8da558970dfea3196e9 dd2c6de3091f1873643233d229a7a0e9defe0f9fe43f6a7c42ae3a6b16f77837
b2acb58dcfd23f54fc2084373cd9a78f7c84047c6f64e7464999597267e9b6a0f95bf13f encrypted_token_request: 82ef7c068506bcabc27d068a51c7ead2cbaf600b76a15e4
634c2a23f861fc83a09d08309ad00af4abf8cf48f1f7d286f65750f20faa1310849e8aee d9df99a0da676da5a073fcc8f5ac77b25064d7379037b4e1b186977cface31eceb611978
44c4ec6abb1c846a16a222116ad94 c73c9aef38c9a0e8ae846881624fa6d454523a0a91d22b02b022891d0469deebd66a912a
request_key: 8a9ffd91064e498f0b14b4b82d65255b2859da8d349e2bb362ca7c8211e a1ab3391b203e92e0a681f0a10c2a2d59b668daf1e5219ed16227d707fa0e8e29188bd58
23fcd5cd01813ef6eb4b994d532c3520e1aa89e 7ab38b3584564ce9b6538ba82e301cfed4231a2fa4f64a67285a1b9bf648e25f3eb1644c
origin_name_key_id: 88d43552bdea6e4bfcbaef0de3ac245e0432be6b019494927fde0743b775f9efe8ca5fef
590ef89ec14ebd7cd0598c7c1e045838e7c484713265c10d923d314fa1ef433f afbf2048890d54618d408a6001fc8fb276f6828c46f4fe1381e9775eec72ee47593df738
encrypted_origin_name: b9d946ee16d9114b6d42524a1fe1e5fae9768c45d4b48ce13 95d18952440d33756d78caea4bd8218950d35afa6c46c535211eda39da277260cb8dab7c
2e758d614911c31c3c1b73a90b63735a0c53f5b94cf176c1a00392618dac727bc287d18 00c6840a745e8150a6ee4893e72b6a51382f877f8c05a15e891a2bde07049760f0f09879
78d78b97e47ecaf90a44996d724dd3720e308abbbf04f672bc5a4db573291986be191b06
03ff521accb6fa081c151c758f3092a89fc6ef591934ff4bc860896c57f83a31b237dd1b
803516c
B.2. Anonymous Origin ID Test Vector B.2. Anonymous Origin ID Test Vector
The test vector below for the procedure in Section 7 lists the The test vector below for the procedure in Section 7 lists the
following values: following values:
* sk_client: Client Secret, serialized and represented as a * sk_client: Client Secret, serialized and represented as a
hexadecimal string. hexadecimal string.
* pk_client: Client Key, serialized and represented as a hexadecimal * pk_client: Client Key, serialized and represented as a hexadecimal
skipping to change at page 36, line 14 skipping to change at page 40, line 20
* request_blind: The request_blind value computed in Section 7.1.1, * request_blind: The request_blind value computed in Section 7.1.1,
represented as a hexadecimal string. represented as a hexadecimal string.
* index_key: The index_key value computed in Section 7.3, * index_key: The index_key value computed in Section 7.3,
represented as a hexadecimal string. represented as a hexadecimal string.
* anon_issuer_origin_id: The anon_issuer_origin_id value computed in * anon_issuer_origin_id: The anon_issuer_origin_id value computed in
Section 7.4, represented as a hexadecimal string. Section 7.4, represented as a hexadecimal string.
sk_sign: a04e2a1c1a58ed8ca09419fe937507964b640981de40c6c05c14bb547b17830 sk_sign: f6e6a0c9de38663ca539ff2e6a04e4fca11dc569794dc405e2d17439d6ce4f6
d5b18c1acf236482234f0e4ed8a6a36e5 7abb2b81a1852e0db993b6a0452eb60d6
pk_sign: 03edf9e62abec27bd25f7171dcf24aeb163fbb026381cb634a8c41058b70b74 pk_sign: 032db7483c710673e6999a5fb2a2c6eac1d891f89bbf58d985ff168d182ad51
083a704177d0aee92a9be2740fd627fa3a4 605c4369280efabb7692f661162e683f03c
sk_origin: abc3bbe04e44502bb3549551a87f4f843b7d6ba2fb789bd82ccebe7e304f0 sk_origin: 85de5fbbd787da5093da0adb240eba0cc6ea90d72032fc4b6925dd7d0ab1d
77f52125a4829747bd5c68a8942500d898c a1e5ae0be27fe9f59e9ec7e1f1b15b28696
request_blind: 0d19ff14f8d24f7cceb377a0f54b27295e270624814293493d264d967 request_blind: 0698a149fb9d16bcb0a856062f74f9191e82b35e91224a57abce60f5b
c541b490d7e95ff1fbb40e4f89dfdd9e25ad997 79f03a669c6b5e093d57e647865f9fd4305b5a9
request_key: 02031027dcbe5e5607749fc6e4e0967cca89d591545c0badc640febc682 request_key: 0287b0ce6b957111263d8c6126af96d400bd5a9d0b0f62ade15ab789446
50199b87f3e60112a40425a03b9e8ac58d5bb77 06c209470ced7086d3c418dd32bf9245fd42678
index_key: 03878a9ff9e8bc58c05f8b6e71374d14f81a113f2a6828c4fa482e2d3ea50 index_key: 03188bec3dc02d2382b5251b6b4fd729d0472bbddf008c5e93b7c12270d9f
04c0d790022a71d6437f905fb5d5daf036f52 57dde111c861c13be53822a1cebb604946066
anon_issuer_origin_id: 3edd83377d6a22f5726dac066ee1864f2c0424cd4868f994b anon_issuer_origin_id: 9b0f980e5c1142fddb4401e5cd2107a87d22b73753b0d5dc9
2e16ec270f4cc4e382a5b0730ca378797171fa2aec8222f 3f9a8f5ed2ee7db78163c6a93cc41ae8158d562381c51ee
Authors' Addresses Authors' Addresses
Scott Hendrickson Scott Hendrickson
Google LLC Google LLC
Email: scott@shendrickson.com Email: scott@shendrickson.com
Jana Iyengar Jana Iyengar
Fastly Fastly
Email: jri@fastly.com Email: jri@fastly.com
 End of changes. 86 change blocks. 
292 lines changed or deleted 494 lines changed or added

This html diff was produced by rfcdiff 1.48. The latest version is available from http://tools.ietf.org/tools/rfcdiff/