From f9a0507884dc94522e8b3c75a66ecee57cd2755d Mon Sep 17 00:00:00 2001 From: Aykut Bulut Date: Tue, 6 Dec 2022 13:22:10 -0500 Subject: [PATCH] Rename Trust Token to Private State Token Update remaining parts of the explainer with the recent renaming decision. Use Private State Token instead of Trust Token. --- DEPLOYMENTS.md | 10 +++--- ISSUER_PROTOCOL.md | 68 ++++++++++++++++++++--------------------- PRIVACY_FRAMEWORK.md | 16 +++++----- README.md | 72 ++++++++++++++++++++++---------------------- 4 files changed, 83 insertions(+), 83 deletions(-) diff --git a/DEPLOYMENTS.md b/DEPLOYMENTS.md index 66af83b..05aa81b 100644 --- a/DEPLOYMENTS.md +++ b/DEPLOYMENTS.md @@ -1,4 +1,4 @@ -# Trust Token Deployment Types +# Private State Token Deployment Types ## First-Party vs Third-Party Issuance Issuers need to make a decision about what sort of information they will use as part of issuing tokens, and where issuances can happen, generally this decision is made based on where they can get good issuance signals, and we see issuers falling into two major categories. @@ -6,7 +6,7 @@ Issuers need to make a decision about what sort of information they will use as ![Issuance Types](https://raw.githubusercontent.com/wicg/trust-token-api/main/assets/deployment_issuance.png) ### First Party Issuance -First-Party issuers are instances where the issuer is the first-party site the user is interacting with, that then decides to perform a Trust Token issuance based on the first-hand information it has about the user based on the first-party interactions it sees. Some examples of this are things like an e-commerce or social media site measuring user interactions and the user having an account to derive the trust signal. +First-Party issuers are instances where the issuer is the first-party site the user is interacting with, that then decides to perform a Private State Token issuance based on the first-hand information it has about the user based on the first-party interactions it sees. Some examples of this are things like an e-commerce or social media site measuring user interactions and the user having an account to derive the trust signal. ### Third Party Issuance Third-Party issuers are instances where the actual issuer is not the same entity as the top-level site the user is interacting with, but rather some third-party entity that uses information the first-party is willing to share with it to build up an issuance decision, potentially making issuing decisions across a bunch of different origins. This sort of information sharing is acceptable, since the third-party won't be able to join the information shared with state from other first-parties (https://w3ctag.github.io/privacy-principles/#principle-identity-per-context). These sort of issuers may also use the type of token the user currently has to make decisions about providing other type of tokens when issuing in a different context. Some examples of this are things like CAPTCHA and IVT providers, where they have some sort of relation to the sites they're embedded in and provide IVT/Bot protection if tokens are available, while issuing new tokens based on challenges/data the first-party provides when they're not available. Potentially having some sort of state machine to transition between token metadata as the tokens are redeemed and issued in more locations that can increase the trust signal the issuer is willing to issue tokens to. @@ -17,10 +17,10 @@ On the redemption side, we expect issuers to fall into two categories. ![Redemption Types](https://raw.githubusercontent.com/wicg/trust-token-api/main/assets/deployment_redemption.png) ### Public Redemption -Some issuers may be willing to allow any entity to redeem their tokens, providing a general trust signal that sites can consume to improve the web ecosystem. Particularly things like device attestations (described in https://github.com/WICG/trust-token-api#non-web-sources-of-tokens), about the integrity of the device, are likely to fall into this category, where the value is in attesting to real devices and sites being able to rely on that signal. +Some issuers may be willing to allow any entity to redeem their tokens, providing a general trust signal that sites can consume to improve the web ecosystem. Particularly things like device attestations (described in https://github.com/WICG/trust-token-api#non-web-sources-of-tokens), about the integrity of the device, are likely to fall into this category, where the value is in attesting to real devices and sites being able to rely on that signal. ### Private Redemption -Most other issuers will fall into a private model, where redemption information will only be provided to their own redeemers or partners that they have a relationship with. This design allows issuers to choose where they are willing to provide trust information and avoid arbitrary sites from using their token. This doesn't affect the amount of information that a website can learn via the Trust Token API. +Most other issuers will fall into a private model, where redemption information will only be provided to their own redeemers or partners that they have a relationship with. This design allows issuers to choose where they are willing to provide trust information and avoid arbitrary sites from using their token. This doesn't affect the amount of information that a website can learn via the Private State Token API. Within this model, there are a couple of implementation methods. First, the issuer can provide the information necessary to parse and understand the redemption record directly to the partner, allowing them to asynchronously use that information to decide whether the user is 'trusted'. The second option is that the partner sends the redemption record to some endpoint that the issuer provides that then tells the partner what the redemption record means, and whether the user is trusted, certain actions should be allowed or require extra verification. The redeemer can perform this kind of redemption by checking the origin of the request for a redemption or requiring some key that the site has to allow for a redemption. @@ -30,4 +30,4 @@ Within this model, there are a couple of implementation methods. First, the issu **Third-Party Issuance, Public Redemption**: For platform issuers, they will likely be using a third-party issuance (as the non-web source isn't considered first-party to each origin), public redemption model. Platforms are more likely to want to expose their attestation/trust signals to be consumed by anyone in order to promote the ability to protect user safety on their platform. -**First-Party Issuance, Private Redemption**: Larger publishers that have associated but separate partnered sites (news websites) might use a first-party issuance, private redemption model. They are able to establish the initial trust signal based on their primary site, while wanting partners they work with to be able to consume that signal \ No newline at end of file +**First-Party Issuance, Private Redemption**: Larger publishers that have associated but separate partnered sites (news websites) might use a first-party issuance, private redemption model. They are able to establish the initial trust signal based on their primary site, while wanting partners they work with to be able to consume that signal diff --git a/ISSUER_PROTOCOL.md b/ISSUER_PROTOCOL.md index 8624bb2..1780f1f 100644 --- a/ISSUER_PROTOCOL.md +++ b/ISSUER_PROTOCOL.md @@ -1,8 +1,8 @@ -# TrustTokenV3 Issuer Protocol +# PrivateStateV3 Issuer Protocol *Version 3 is a working version and is subject to change.* -This document documents the cryptographic protocol for the "TrustTokenV3PMB" and "TrustTokenV3VOPRF" experimental version of Trust Token. An issuer needs to support maintaining a set of keys and a key commitment endpoint, as well as implementing the Issue and Redeem cryptographic functions to sign and validate Trust Tokens. Experimental versions of Trust Token are not intended to be backwards-compatible with each other and will undergo rapid design/implementation changes during the experiment timeframe. Note that there is a distinct different between the issuer protocol version and the cryptographic protocol version, with the latter describing the underlying cryptographic primitives used in the issuer protocol. +This document documents the cryptographic protocol for the "PrivateStateTokenV3PMB" and "PrivateStateTokenV3VOPRF" experimental version of Private State Token. An issuer needs to support maintaining a set of keys and a key commitment endpoint, as well as implementing the Issue and Redeem cryptographic functions to sign and validate Private State Tokens. Experimental versions of Private State Token are not intended to be backwards-compatible with each other and will undergo rapid design/implementation changes during the experiment timeframe. Note that there is a distinct different between the issuer protocol version and the cryptographic protocol version, with the latter describing the underlying cryptographic primitives used in the issuer protocol. This document uses TLS presentation language (https://tools.ietf.org/html/rfc8446#section-3) for structures and serialization. @@ -12,18 +12,18 @@ This section describes the public issuer interfaces that an issuer will need to ### Issuer Key Commitments -A Trust Token issuer should have an endpoint at a publicly accessible secure URL (HTTPS) that serves the current key commitments used in the Trust Token protocol. Requests to this endpoint should result in a JSON response of the following format: +A Private State Token issuer should have an endpoint at a publicly accessible secure URL (HTTPS) that serves the current key commitments used in the Private State Token protocol. Requests to this endpoint should result in a JSON response of the following format: ``` Key commitment result { : { - "protocol_version": , + "protocol_version": , "id": "batchsize": , "keys": { - : { "Y": , + : { "Y": , "expiry": }, @@ -44,17 +44,17 @@ and to allow comparing the freshness of key commitments (larger values indicate ### Issuing Tokens -To support the issuance of tokens made via Trust Token calls by the client, server paths that support token issuance should parse the "Sec-Trust-Token" header as a base64 binary blob. This decoded binary blob should be interpreted as a **Trust Token Issuance Request** and passed into the _Issue_ crypto protocol along with the Issuance metadata based on the rest of the request. The result of _Issue_ (a **Trust Token Issuance Response**) should be base64 encoded and returned via the "Sec-Trust-Token" header in the HTTP response. +To support the issuance of tokens made via Private State Token calls by the client, server paths that support token issuance should parse the ```Sec-Private-State-Token``` header as a base64 binary blob. This decoded binary blob should be interpreted as a **Private State Token Issuance Request** and passed into the _Issue_ crypto protocol along with the Issuance metadata based on the rest of the request. The result of _Issue_ (a **Private State Token Issuance Response**) should be base64 encoded and returned via the ```Sec-Private-State-Token``` header in the HTTP response. #### Issuance Metadata -As part of an issuance, two forms of metadata can be embedded into the token. Public metadata is embedded via the choice of key which is used as part of the issuance process and is passed into the _Issue_ method as the keypair selection. Private metadata is embedded via a cryptographically hidden bit in the signed token itself and is passed into the _Issue_ method as the private metadata boolean. TrustTokenV3VOPRF supports up to 6 buckets (keypairs) of public metadata and no private metadata, while TrustTokenV3PMB supports up to 3 buckets (keypairs) of public metadata and one bit of private metadata. +As part of an issuance, two forms of metadata can be embedded into the token. Public metadata is embedded via the choice of key which is used as part of the issuance process and is passed into the _Issue_ method as the keypair selection. Private metadata is embedded via a cryptographically hidden bit in the signed token itself and is passed into the _Issue_ method as the private metadata boolean. ```PrivateStateTokenV3VOPRF``` supports up to 6 buckets (keypairs) of public metadata and no private metadata, while ```PrivateStateTokenV3PMB``` supports up to 3 buckets (keypairs) of public metadata and one bit of private metadata. ### Redeeming Tokens -To support the redemption of tokens by the client, server paths that support token redemption should parse the "Sec-Trust-Token" header as a base64 binary blob. This decoded binary blob should be interpreted as a **Trust Token Redemption Request** and passed into the _Redeem_ crypto protocol. The result of _Redeem_ (a **Trust Token Redemption Response**) should be base64 encoded and returned via the "Sec-Trust-Token" header in the HTTP response. Additionally, the issuer should keep track of redeemed tokens to prevent token reuse from malicious clients. +To support the redemption of tokens by the client, server paths that support token redemption should parse the ```Sec-Private-State-Token``` header as a base64 binary blob. This decoded binary blob should be interpreted as a **Private State Token Redemption Request** and passed into the _Redeem_ crypto protocol. The result of _Redeem_ (a **Private State Token Redemption Response**) should be base64 encoded and returned via the ```Sec-Private-State-Token``` header in the HTTP response. Additionally, the issuer should keep track of redeemed tokens to prevent token reuse from malicious clients. #### Redemption Metadata @@ -66,20 +66,20 @@ At redemption time, the token is decoded and provided via the redemption API. Th In Version 3, the algorithm used for [request signing](https://github.com/WICG/trust-token-api#extension-trust-bound-keypair-and-request-signing) is [`ecdsa_secp256r1_sha256`](https://tools.ietf.org/html/rfc8446#section-4.2.3). -## TrustTokenV2PMB Crypto Protocol +## PrivateStateTokenV2PMB Crypto Protocol -This Trust Token crypto protocol is based on the PMBTokens design in https://eprint.iacr.org/2020/072 (appendix H) using P-384. This crypto protocol is used in both the V2 and V3 Trust Token protocol versions. The necessary keys and function mappings are described below. +This Private State Token crypto protocol is based on the PMBTokens design in https://eprint.iacr.org/2020/072 (appendix H) using P-384. This crypto protocol is used in both the V2 and V3 Private State Token protocol versions. The necessary keys and function mappings are described below. ### Keys -The Trust Token protocol primarily requires keypairs consisting of each public metadata bucket: +The Private State Token protocol primarily requires keypairs consisting of each public metadata bucket: -* TrustTokenSecretKey/TrustTokenPublicKey - A Trust Token keypair used to sign and verify Trust Tokens. +* PrivateStateTokenSecretKey/PrivateStateTokenPublicKey - A Trust Token keypair used to sign and verify Private State Tokens. -#### TrustTokenSecretKey/TrustTokenPublicKey +#### PrivateStateTokenSecretKey/PrivateStateTokenPublicKey -These are keys used in Trust Token consisting of elliptic curve scalars and points. All scalars and points are sized based on the curve choice (P-384). Up to 3 keys may be configured in parallel in the key commitment. +These are keys used in Private State Token consisting of elliptic curve scalars and points. All scalars and points are sized based on the curve choice (P-384). Up to 3 keys may be configured in parallel in the key commitment. Each keypair consist of the following: @@ -104,7 +104,7 @@ struct { ECPoint pub0; // Corresponding to the FALSE private metadata bit. ECPoint pub1; // Corresponding to the TRUE private metadata bit. ECPoint pubs; // Corresponding to the token validity check. -} TrustTokenPublicKey; +} PrivateStateTokenPublicKey; ``` ### Serialization/Hashing @@ -235,7 +235,7 @@ DLEQbatched.P((X,T,S,W,Ws),(xs, ys, xb, yb)): Input Serialization: -The Trust Token Issuance Request contains an `IssueRequest` structure defined below. +The Private State Token Issuance Request contains an `IssueRequest` structure defined below. ``` struct { @@ -246,7 +246,7 @@ struct { Output Serialization: -The Trust Token Issuance Response contains an `IssueResponse` structure defined below. +The Private State Token Issuance Response contains an `IssueResponse` structure defined below. ``` struct { @@ -281,7 +281,7 @@ The _Redeem_ function corresponds to the **AT.VerValid** and **AT.ReadBit** stag Inputs: -* token (The trust token to redeem) +* token (The private state token to redeem) * client\_data (the client data sent as part of the redemption request to include in the SRR) * secretKey (the secret key that should be used to sign this request, determined by the public metadata) * keys (dictionary from known key IDs to secret/public keys) @@ -310,7 +310,7 @@ Redeem: Input Serialization: -The Trust Token Redemption Request contains a `RedemptionRequest` structure as defined below. +The Private State Token redemption request contains a `RedemptionRequest` structure as defined below. ``` struct { @@ -331,7 +331,7 @@ struct { Output Serialization: -The Trust Token Redemption Response contains a `RedemptionResponse` structure as defined below. +The Private State Token redemption response contains a `RedemptionResponse` structure as defined below. ``` struct { @@ -339,20 +339,20 @@ struct { } RedeemResponse; ``` -## TrustTokenV2VOPRF Crypto Protocol +## PrivateStateTokenV2VOPRF Crypto Protocol -This Trust Token crypto protocol is based on the VOPRF design in https://datatracker.ietf.org/doc/draft-irtf-cfrg-voprf/. This crypto protocol is used in both the V2 and V3 Trust Token protocol versions. +This Private State Token crypto protocol is based on the VOPRF design in https://datatracker.ietf.org/doc/draft-irtf-cfrg-voprf/. This crypto protocol is used in both the V2 and V3 Private State Token protocol versions. ### Keys -The Trust Token protocol primarily requires keypairs consisting of each public metadata bucket: +The Private State Token protocol primarily requires keypairs consisting of each public metadata bucket: -* TrustTokenSecretKey/TrustTokenPublicKey - A Trust Token keypair used to sign and verify Trust Tokens. +* PrivateStateTokenSecretKey/PrivateStateTokenPublicKey - A Private State Token keypair used to sign and verify Private State Tokens. -#### TrustTokenSecretKey/TrustTokenPublicKey +#### PrivateStateTokenSecretKey/PrivateStateTokenPublicKey -These are keys used in Trust Token consisting of elliptic curve scalars and points. All scalars and points are sized based on the curve choice (P-384). Up to 6 keys may be configured in parallel in the key commitment. +These are keys used in Private State Token consisting of elliptic curve scalars and points. All scalars and points are sized based on the curve choice (P-384). Up to 6 keys may be configured in parallel in the key commitment. Each keypair consist of the following: @@ -363,11 +363,11 @@ opaque Scalar; // big-endian bytestring struct { Scalar x; -} TrustTokenSecretKey; +} PrivateStateTokenSecretKey; struct { ECPoint pub; -} TrustTokenPublicKey; +} PrivateStateTokenPublicKey; ``` ### Serialization/Hashing @@ -375,11 +375,11 @@ struct { For the VOPRF functions, the following serialization schemes and hashes are used internally using draft 07 of the hash-to-curve specification (https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-07): -`H2C(t)` is defined to be P384_XMD:SHA-512_SSWU_RO_ with a big-endian bytestring input of `t` and a dst of "TrustToken VOPRF Experiment V2 HashToGroup". +`H2C(t)` is defined to be P384_XMD:SHA-512_SSWU_RO_ with a big-endian bytestring input of `t` and a dst of "PrivateStateToken VOPRF Experiment V2 HashToGroup". The hash-to-curve document does not define hash to scalars, so `H2S(x)` is defined to be the output of the [hash_to_field](https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-07#section-5.2) function with the following parameters: -* `DST` is "TrustToken VOPRF Experiment V3 HashToScalar" +* `DST` is "PrivateStateToken VOPRF Experiment V3 HashToScalar" * `F`, `p`, and `m` are defined according to the finite field `GF(r)`, where `r` is the order of P-384. Note this is a different modulus from `hash_to_field` as used in P384_XMD:SHA-512_SSWU_RO_. * `L` is 72, derived based on P384_XMD:SHA-512_SSWU_RO_'s security parameter `k` (192), and `p` defined above. * `expand_message` uses the corresponding function from P384_XMD:SHA-512_SSWU_RO_. @@ -418,7 +418,7 @@ The _Issue_ **Blind**/**Evaluate**/**Unblind** stages of the VOPRF protocol. Input Serialization: -The Trust Token Issuance Request contains an `IssueRequest` structure defined below. +The Private State Token Issuance Request contains an `IssueRequest` structure defined below. ``` struct { @@ -429,7 +429,7 @@ struct { Output Serialization: -The Trust Token Issuance Response contains an `IssueResponse` structure defined below. +The Private State Token Issuance Response contains an `IssueResponse` structure defined below. ``` struct { @@ -457,7 +457,7 @@ The _Redeem_ function corresponds to the **VerifyFinalize** stage of the VOPRF p Input Serialization: -The Trust Token Redemption Request contains a `RedemptionRequest` structure as defined below. +The Private State Token redemption request contains a `RedemptionRequest` structure as defined below. ``` struct { @@ -476,7 +476,7 @@ struct { Output Serialization: -The Trust Token Redemption Response contains a `RedemptionResponse` structure as defined below. +The Private State Token redemption response contains a `RedemptionResponse` structure as defined below. ``` struct { diff --git a/PRIVACY_FRAMEWORK.md b/PRIVACY_FRAMEWORK.md index 7e70bbe..e1409bc 100644 --- a/PRIVACY_FRAMEWORK.md +++ b/PRIVACY_FRAMEWORK.md @@ -1,32 +1,32 @@ -# Trust Token Privacy Framework +# Private State Token Privacy Framework ## Overview/Goals -The Trust Token API provides a mechanism that allows origins to transfer a small number of bits of information to cross-site/third-party contexts, in a manner that prevents linkability to the user’s identity on the same origin when in first-party context. In conformance with the [privacy principles](https://w3ctag.github.io/privacy-principles/#principle-prevent-cross-partition-recognition) that we envision for the web, we must ensure that the mechanism cannot be misused to form cross-site tracking vectors that allows identification of individual users at scale. In order to achieve this goal, this document discusses a framework for technical mitigations, and policy-based usage recommendations. +The Private State Token API provides a mechanism that allows origins to transfer a small number of bits of information to cross-site/third-party contexts, in a manner that prevents linkability to the user’s identity on the same origin when in first-party context. In conformance with the [privacy principles](https://w3ctag.github.io/privacy-principles/#principle-prevent-cross-partition-recognition) that we envision for the web, we must ensure that the mechanism cannot be misused to form cross-site tracking vectors that allows identification of individual users at scale. In order to achieve this goal, this document discusses a framework for technical mitigations, and policy-based usage recommendations. The mitigations are generally split between those enforced on the Issuers themselves, those that the Trusted Intermediary needs to enforce, those at issuance time and those enforced at redemption time. This document is intended to be a general framework for when developing policies. -Some example limits are described below, though exact values will need to be determined as the ecosystem surrounding Trust Token continues to evolve and change. +Some example limits are described below, though exact values will need to be determined as the ecosystem surrounding Private State Token continues to evolve and change. ## Preventing Malicious use of Tokens Issuers may choose to issue tokens based on their own logic, and for the most part UAs don't have visibility into the token meaning and how issuance decisions are made, so can't enforce the particular purpose a token might be used for. For instance, issuers may use tokens to track specific sets of users or to build bitmasks across multiple tokens. In order to mitigate this, the UA should implement a number of limits to combat these uses. ### Limiting amount of Information, instead of type of information stored in Tokens -Since different issuers will store different information within their tokens based on their business logic for determining who gets issued tokens, instead of trying to limit the type of information stored in the tokens, the Trust Token API limits the amount of information (treating them as authenticated cryptographically-limited cross-site storage in terms of privacy leakage/entropy). This limitation is provided through the choice of Trust Token version and the configurations that are supported by the UA. +Since different issuers will store different information within their tokens based on their business logic for determining who gets issued tokens, instead of trying to limit the type of information stored in the tokens, the Private State Token API limits the amount of information (treating them as authenticated cryptographically-limited cross-site storage in terms of privacy leakage/entropy). This limitation is provided through the choice of Private State Token version and the configurations that are supported by the UA. ### Example Information Entropy Limit -Initial experimentation and versions of the Trust Token API are limited to a total of log2(6) bits (\~2.6 bits, 3 public metadata values and one private metadata bit) of data, representing some combination of metadata values and keys available to be used. This choice is made to minimize the amount of data available in a token while still allowing the token to be flexible enough to provide a range of values (for instance representing varying levels of trust/distrust). +Initial experimentation and versions of the Private State Token API are limited to a total of log2(6) bits (\~2.6 bits, 3 public metadata values and one private metadata bit) of data, representing some combination of metadata values and keys available to be used. This choice is made to minimize the amount of data available in a token while still allowing the token to be flexible enough to provide a range of values (for instance representing varying levels of trust/distrust). ## Prevent Fingerprint Accumulation via Token Aggregation Malicious sites/issuers can try to attack this API by trying to redeem many different tokens and use the results as a sort of bit mask to fingerprint the user. To mitigate this, UAs should place limits on the number of tokens that can be redeemed in a specific [redemption context](https://github.com/ietf-wg-privacypass/base-drafts/blob/master/draft-ietf-privacypass-architecture.md#redemption-contexts-redemption-contexts). On the web platform, these redemption contexts map to the storage sharded by the top-level site. These limits will need to be maintained across the lifetime of the top-level origins state since any redemption results can be stored in first-party storage and then paired with future aggregations. ### Example Limits on Redemption -To allow for sites to consume multiple types of trust signals and to be able to migrate between different sources of trust over time, initially each site will be allowed to redeem tokens from two different sources (issuers or number of different tokens redeemed) over a period of time. Depending on the use cases that use Trust Tokens, the UA may want to increase this limit or tie it into something like a privacy budget. +To allow for sites to consume multiple types of trust signals and to be able to migrate between different sources of trust over time, initially each site will be allowed to redeem tokens from two different sources (issuers or number of different tokens redeemed) over a period of time. Depending on the use cases that use Private State Tokens, the UA may want to increase this limit or tie it into something like a privacy budget. ## Prevent personalized Key Commitments -A key requirement of Trust Token (and the underlying Privacy Pass) is a way of ensuring that different clients all receive the same set of key commitments at a particular point in time, to prevent malicious issuers from presenting different keys to different users. This is provided by some sort of trusted intermediary (key commitment service) that is responsible for verifying the key commitments clients see are identical. Generally trusted intermediaries should allow any issuer that abides by their key rotation policy and uptime requirements. Similar to the CT ecosystem, intermediaries should have published requirements for inclusion to avoid any cherry picking of supported issuers. UAs should also consider allowing for multiple intermediaries to be used to avoid a single intermediary being a centralized single point of failure. +A key requirement of Private State Token (and the underlying Privacy Pass) is a way of ensuring that different clients all receive the same set of key commitments at a particular point in time, to prevent malicious issuers from presenting different keys to different users. This is provided by some sort of trusted intermediary (key commitment service) that is responsible for verifying the key commitments clients see are identical. Generally trusted intermediaries should allow any issuer that abides by their key rotation policy and uptime requirements. Similar to the CT ecosystem, intermediaries should have published requirements for inclusion to avoid any cherry picking of supported issuers. UAs should also consider allowing for multiple intermediaries to be used to avoid a single intermediary being a centralized single point of failure. ## Limit Key Rotation Frequency -Trust Token issuers need to rotate their keys regularly both for the security of the key material used, as well as to invalidate old tokens issued under previous epochs (to avoid large pools of tokens being gathered by malicious parties and to update issuance logic). However, each key rotation introduces additional bits of entropy as the user repeatedly visits the site that can be used to identify individual users by issuers, the key that the client generates tokens against could reveal at what point in time the client interacted with the issuer, allowing the issuer to track clients based on what epoch of tokens they use. In order to allow for the former while defending against the latter, under normal operation, the trusted intermediary should enforce maximum key rotation frequencies. The choice of these limits should be based on the security requirements for the key lifetime compared to the lifetime of first-party state that might link issuances at different keys on each site. +Private State Token issuers need to rotate their keys regularly both for the security of the key material used, as well as to invalidate old tokens issued under previous epochs (to avoid large pools of tokens being gathered by malicious parties and to update issuance logic). However, each key rotation introduces additional bits of entropy as the user repeatedly visits the site that can be used to identify individual users by issuers, the key that the client generates tokens against could reveal at what point in time the client interacted with the issuer, allowing the issuer to track clients based on what epoch of tokens they use. In order to allow for the former while defending against the latter, under normal operation, the trusted intermediary should enforce maximum key rotation frequencies. The choice of these limits should be based on the security requirements for the key lifetime compared to the lifetime of first-party state that might link issuances at different keys on each site. ### Emergency Key Rotation Mechanism Beyond the normal key rotation limits, the trusted intermediary will need to establish a mechanism for allowing ‘emergency’ key rotations in the case that an issuer’s key material is lost or stolen. This policy should be such that issuers can keep running secure systems as necessary but can’t maliciously expose their keys repeatedly to bypass the normal key rotation limits. diff --git a/README.md b/README.md index 4179389..b296282 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Private State Token API Explainer -This document is an explainer for a potential future web platform API that allows propagating trust across sites, using the [Privacy Pass](https://privacypass.github.io) protocol as an underlying primitive. +This document is an explainer for a potential future web platform API that allows propagating limited private signals across sites, using the [Privacy Pass](https://privacypass.github.io) protocol as an underlying primitive. The current version of the spec is available at [https://wicg.github.io/trust-token-api/](https://wicg.github.io/trust-token-api/). @@ -13,8 +13,8 @@ This API was formerly called the Trust Token API and the repository and API surf - [Motivation](#motivation) - [Overview](#overview) - [Potential API](#potential-api) - - [Trust Token Issuance](#trust-token-issuance) - - [Trust Token Redemption](#trust-token-redemption) + - [Private State Token Issuance](#private-state-token-issuance) + - [Private State Token Redemption](#private-state-token-redemption) - [Forwarding Redemption Attestation](#forwarding-redemption-attestation) - [Extension: Private Metadata](#extension-private-metadata) - [Privacy Considerations](#privacy-considerations) @@ -27,7 +27,7 @@ This API was formerly called the Trust Token API and the repository and API surf - [Mitigation: Per-Site Issuer Limits](#mitigation-per-site-issuer-limits) - [First Party Tracking Potential](#first-party-tracking-potential) - [Security Considerations](#security-considerations) - - [Trust Token Exhaustion](#trust-token-exhaustion) + - [Private State Token Exhaustion](#private-state-token-exhaustion) - [Double-Spend Prevention](#double-spend-prevention) - [Future Extensions](#future-extensions) - [Publicly Verifiable Tokens](#publicly-verifiable-tokens) @@ -57,14 +57,14 @@ When an origin is in a context where they trust the user, they can issue the bro ## Potential API -### Trust Token Issuance +### Private State Token Issuance -When an issuer.example context wants to provide tokens to a user (i.e. when the user is trusted), they can use a new Fetch API with the trustToken parameter: +When an issuer.example context wants to provide tokens to a user (i.e. when the user is trusted), they can use a new Fetch API with the privateToken parameter: ``` fetch('/', { - trustToken: { + privateToken: { type: 'private-state-token', version: 1, operation: 'token-request', @@ -77,28 +77,28 @@ fetch('/', { This API will invoke the [Privacy Pass](https://privacypass.github.io) Issuance protocol: * Generate a set of nonces. -* Blind them and attach them (in a `Sec-Trust-Token` header) to the HTTP request +* Blind them and attach them (in a `Sec-Private-State-Token` header) to the HTTP request * Send a POST to the provided endpoint -When a response comes back with blind signatures in a `Sec-Trust-Token` response header, they will be unblinded, stored, and associated with the unblinded nonces internally in the browser. The pairs of nonces and signatures are trust tokens that can be redeemed later. Raw tokens are never accessible to JavaScript. The issuer can store a limited amount of metadata in the signature of a nonce by choosing one of a set of keys to use to sign the nonce and providing a zero-knowledge proof that it signed the nonce using a particular key or set of keys. The browser will verify the proof and may choose to keep or drop the token based on other metadata constraints and limits from the UA. Additionally, the issuer may include an optional `Sec-Trust-Token-Clear-Data` header in the response to indicate to the UA that it should discard all previously stored tokens. If the value of the header is `all`, then all previously stored tokens should be discarded before the newly issued tokens are stored. Other values in the header should be ignored. +When a response comes back with blind signatures in a `Sec-Private-State-Token` response header, they will be unblinded, stored, and associated with the unblinded nonces internally in the browser. The pairs of nonces and signatures are private state tokens that can be redeemed later. Raw tokens are never accessible to JavaScript. The issuer can store a limited amount of metadata in the signature of a nonce by choosing one of a set of keys to use to sign the nonce and providing a zero-knowledge proof that it signed the nonce using a particular key or set of keys. The browser will verify the proof and may choose to keep or drop the token based on other metadata constraints and limits from the UA. Additionally, the issuer may include an optional `Sec-Private-State-Token-Clear-Data` header in the response to indicate to the UA that it should discard all previously stored tokens. If the value of the header is `all`, then all previously stored tokens should be discarded before the newly issued tokens are stored. Other values in the header should be ignored. -### Trust Token Redemption +### Private State Token Redemption -When the user is browsing another site (publisher.example), that site (or issuer.example embedded on that site) can optionally redeem issuer.example tokens to learn something about the trust of a user. One way to do this would be via new APIs: +When the user is browsing another site (```publisher.example```), that site (or ```issuer.example``` embedded on that site) can optionally redeem ```issuer.example``` tokens to learn something about the trust of a user. One way to do this would be via new APIs: ``` -document.hasTrustToken(, 'private-state-token') +document.hasPrivateToken(, 'private-state-token') ``` -This returns whether there are any valid trust tokens for a particular issuer, so that the publisher can decide whether to attempt a token redemption. +This returns whether there are any valid private state tokens for a particular issuer, so that the publisher can decide whether to attempt a token redemption. ``` fetch('/', { - trustToken: { + privateToken: { type: 'private-state-token', version: 1, operation: 'token-redemption', @@ -109,8 +109,8 @@ fetch('/', { ``` -If there are no tokens available for the given issuer, the returned promise rejects with an error. Otherwise, it invokes the PrivacyPass redemption protocol against the issuer, with the token (potentially, if specified by an extension, along with associated redemption metadata) attached in the `Sec-Trust-Token` request header. The issuer can either consume the token and act based on the result, optionally including a Redemption Record (RR) in the `Sec-Trust-Token` response header to provide a redemption attestation to forward to other parties. Additionally, the issuer may include the `Sec-Trust-Token-Lifetime` header in the response to indicate to the UA how long (in seconds) the RR should be cached for. When `Sec-Trust-Token-Lifetime` header value is invalid (too large, a negative number or non-numeric), UA should ignore the `Sec-Trust-Token-Lifetime` header. When `Sec-Trust-Token-Lifetime` header value is zero UA should treat the record as expired. In case of multiple `Sec-Trust-Token-Lifetime` headers, UA uses the last one. If `Sec-Trust-Token-Lifetime` header is omitted, the lifetime of the RR will be tied to the lifetime of the Trust Token verification key that confirmed the redeemed token's issuance. -The RR is HTTP-only and JavaScript is only able to access/send the RR via Trust Token Fetch APIs. It is also cached in new first-party storage accessible only by these APIs for subsequent visits to that first-party. The RR is treated as an arbitrary blob of bytes from the issuer, that may have semantic meaning to downstream consumers. +If there are no tokens available for the given issuer, the returned promise rejects with an error. Otherwise, it invokes the PrivacyPass redemption protocol against the issuer, with the token (potentially, if specified by an extension, along with associated redemption metadata) attached in the `Sec-Private-State-Token` request header. The issuer can either consume the token and act based on the result, optionally including a Redemption Record (RR) in the `Sec-Private-State-Token` response header to provide a redemption attestation to forward to other parties. Additionally, the issuer may include the `Sec-Private-State-Token-Lifetime` header in the response to indicate to the UA how long (in seconds) the RR should be cached for. When `Sec-Private-State-Token-Lifetime` header value is invalid (too large, a negative number or non-numeric), UA should ignore the `Sec-Private-State-Token-Lifetime` header. When `Sec-Private-State-Token-Lifetime` header value is zero UA should treat the record as expired. In case of multiple `Sec-Private-State-Token-Lifetime` headers, UA uses the last one. If `Sec-Private-State-Token-Lifetime` header is omitted, the lifetime of the RR will be tied to the lifetime of the Private State Token verification key that confirmed the redeemed token's issuance. +The RR is HTTP-only and JavaScript is only able to access/send the RR via Private State Token Fetch APIs. It is also cached in new first-party storage accessible only by these APIs for subsequent visits to that first-party. The RR is treated as an arbitrary blob of bytes from the issuer, that may have semantic meaning to downstream consumers. UA stores the RR obtained from the initial redemption. A publisher site can query whether a valid RR exists for a specific issuer using following API. @@ -121,7 +121,7 @@ document.hasRedemptionRecord(, 'private-state-token') This returns whether there are any valid RRs from the given issuer. -To mitigate [token exhaustion](#trust-token-exhaustion), a site can only redeem tokens for a particular issuer if they have no cached non-expired RRs from that issuer or if they are the same origin as the issuer and have set the `refresh` parameter. +To mitigate [token exhaustion](#private-state-token-exhaustion), a site can only redeem tokens for a particular issuer if they have no cached non-expired RRs from that issuer or if they are the same origin as the issuer and have set the `refresh` parameter. ### Forwarding Redemption Attestation @@ -132,7 +132,7 @@ Redemption Records are only accessible via a new option to the Fetch API: ``` fetch(, { ... - trustToken: { + privateToken: { type: 'private-state-token', version: 1, operation: 'send-redemption-record', @@ -146,18 +146,18 @@ fetch(, { The RRs will be added as a new request header `Sec-Redemption-Record`. The header contains a list of issuer and redemption record pairs corresponding to each requested redemption record. This option to Fetch is only usable in the top-level document. If there are no RRs available, the request header will be empty. -### Extension: Trust Token Versioning +### Extension: Private State Token Versioning -In order to allow multiple versions of Trust Token to be supported in the ecosystem, issuers include the version of the protocol (i.e. "TrustTokenV1") in their key commitments via the "protocol_version" field, and that is included in Trust Token requests via the Sec-Trust-Token-Version header. Trust Token operations should not be performed with issuers configured with an unknown protocol version. +In order to allow multiple versions of Private State Token to be supported in the ecosystem, issuers include the version of the protocol (i.e. "PrivateStateTokenV1") in their key commitments via the ```protocol_version``` field, and that is included in Private State Token requests via the ```Sec-Private-State-Token-Version``` header. Private State Token operations should not be performed with issuers configured with an unknown protocol version. -In addition to the core cryptographic layer, signed requests' formats (see the next section) might change from version to version. In order to make adapting to these changes easier, we could employ a mechanism like the Sec-Trust-Token-Version header, or an addition to the requests' payloads, to tell consumers the version of the client that generated the request. +In addition to the core cryptographic layer, signed requests' formats (see the next section) might change from version to version. In order to make adapting to these changes easier, we could employ a mechanism like the ```Sec-Private-State-Token-Version``` header, or an addition to the requests' payloads, to tell consumers the version of the client that generated the request. ### Extension: Metadata In addition to attesting trust in a user, an issuer may want to provide a limited amount of metadata in the token (and forward it as part of the RR) to provide limited additional information about the token. -This small change opens up a new application for Privacy Passes: embedding small amounts of information along with the token and RR. This increases the rate of cross-site information transfer somewhat, but introduces some new use-cases for trust tokens. +This small change opens up a new application for Privacy Passes: embedding small amounts of information along with the token and RR. This increases the rate of cross-site information transfer somewhat, but introduces some new use-cases for private state tokens. Once the metadata has been passed along to the redemption request, the issuer can include the value in some form in the RR for downstream partneres to read. @@ -176,7 +176,7 @@ This can be managed using the [PMBTokens construction](https://eprint.iacr.org/2 ### Extension: iframe Activation -Some resources requests are performed via iframes or other non-Fetch-based methods. One extension to support such use cases would be the addition of a `trustToken` attribute to iframes that includes the parameters specified in the Fetch API. This would allow an RR to be sent with an iframe by setting an attribute of `trustToken="{type:'private-state-token',version:1,operation:'send-redemption-record',issuer:,refreshPolicy:'refresh'}"`. +Some resources requests are performed via iframes or other non-Fetch-based methods. One extension to support such use cases would be the addition of a `privateToken` attribute to iframes that includes the parameters specified in the Fetch API. This would allow an RR to be sent with an iframe by setting an attribute of `privateToken="{type:'private-state-token',version:1,operation:'send-redemption-record',issuer:,refreshPolicy:'refresh'}"`. ## Privacy Considerations @@ -201,11 +201,11 @@ If the issuer is able to use network-level fingerprinting or other side-channels ### Cross-site Information Transfer -Trust tokens transfer information about one first-party cookie to another, and we have cryptographic guarantees that each token only contains a small amount of information. Still, if we allow many token redemptions on a single page, the first-party cookie for user U on domain A can be encoded in the trust token information channel and decoded on domain B, allowing domain B to learn the user's domain A cookie until either 1p cookie is cleared. Separate from the concern of channels allowing arbitrary communication between domains, some identification attacks---for instance, a malicious redeemer attempting to learn the exact set of issuers that have granted tokens to a particular user, which could be identifying---have similar mitigations. +Private state tokens transfer information about one first-party cookie to another, and we have cryptographic guarantees that each token only contains a small amount of information. Still, if we allow many token redemptions on a single page, the first-party cookie for user U on domain A can be encoded in the trust token information channel and decoded on domain B, allowing domain B to learn the user's domain A cookie until either 1p cookie is cleared. Separate from the concern of channels allowing arbitrary communication between domains, some identification attacks---for instance, a malicious redeemer attempting to learn the exact set of issuers that have granted tokens to a particular user, which could be identifying---have similar mitigations. #### Mitigation: Dynamic Issuance / Redemption Limits -To mitigate this attack, we place limits on both issuance and redemption. At issuance, we require [user activation](https://html.spec.whatwg.org/multipage/interaction.html#activation) with the issuing site. At redemption, we can slow down the rate of redemption by returning cached Redemption Records when an issuer attempts too many refreshes (see also the [token exhaustion](#trust-token-exhaustion) problem). These mitigations should make the attack take a longer time and require many user visits to recover a full user ID. +To mitigate this attack, we place limits on both issuance and redemption. At issuance, we require [user activation](https://html.spec.whatwg.org/multipage/interaction.html#activation) with the issuing site. At redemption, we can slow down the rate of redemption by returning cached Redemption Records when an issuer attempts too many refreshes (see also the [token exhaustion](#private-state-token-exhaustion) problem). These mitigations should make the attack take a longer time and require many user visits to recover a full user ID. #### Mitigation: Allowed/Blocked Issuer Lists @@ -215,7 +215,7 @@ To prevent abuse of the API, browsers could maintain a list of allowed or disall #### Mitigation: Per-Site Issuer Limits -The rate of identity leakage from one site to another increases with the number of tokens redeemed on a page. To avoid abuse, there should be strict limits on the number of token issuers contacted per top-level origin (e.g. 2); this limit should apply for both issuance and redemption; and the issuers used on an origin should be persisted in browser storage to avoid excessively rotating issuers on subsequent visits. This should also apply for `document.hasTrustToken`, as the presence of tokens can be used as a tracking vector. +The rate of identity leakage from one site to another increases with the number of tokens redeemed on a page. To avoid abuse, there should be strict limits on the number of token issuers contacted per top-level origin (e.g. 2); this limit should apply for both issuance and redemption; and the issuers used on an origin should be persisted in browser storage to avoid excessively rotating issuers on subsequent visits. This should also apply for `document.hasPrivateToken`, as the presence of tokens can be used as a tracking vector. ### First Party Tracking Potential @@ -230,9 +230,9 @@ In order to prevent the issuer from binding together multiple simultaneous redem ## Security Considerations -### Trust Token Exhaustion +### Private State Token Exhaustion -The goal of a token exhaustion attack is to deplete a legitimate user's supply of tokens for a given issuer, so that user is less valuable to sites who depend on the issuer’s trust tokens. +The goal of a token exhaustion attack is to deplete a legitimate user's supply of tokens for a given issuer, so that user is less valuable to sites who depend on the issuer’s private state tokens. We have a number of mitigations against this attack: @@ -244,7 +244,7 @@ We have a number of mitigations against this attack: * Browsers may choose to limit redemptions on a time-based schedule, and either return cached RRs if available, or require consumers to cache the RR. * Issuers will be able to see the Referer, subject to the page's referrer policy, for any token redemption, so they'll be able to detect if any one site is redeeming suspiciously many tokens. -When the issuer detects a site is attacking its trust token supply, it can fail redemption (before the token is revealed) based on the referring origin, and prevent browsers from spending tokens there. +When the issuer detects a site is attacking its token supply, it can fail redemption (before the token is revealed) based on the referring origin, and prevent browsers from spending tokens there. ### Double-Spend Prevention @@ -273,7 +273,7 @@ If the publisher can configure issuers in response headers (or otherwise early i ### Non-web sources of tokens -Trust token issuance could be expanded to other entities (the operating system, or native applications) capable of making an informed decision about whether to grant tokens. Naturally, this would need to take into consideration different systems' security models in order for these tokens to maintain their meaning. (For instance, on some platforms, malicious applications might routinely have similar privileges to the operating system itself, which would at best reduce the signal-to-noise ratio of tokens created on those operating systems.) +Private state token issuance could be expanded to other entities (the operating system, or native applications) capable of making an informed decision about whether to grant tokens. Naturally, this would need to take into consideration different systems' security models in order for these tokens to maintain their meaning. (For instance, on some platforms, malicious applications might routinely have similar privileges to the operating system itself, which would at best reduce the signal-to-noise ratio of tokens created on those operating systems.) ## Appendix @@ -282,22 +282,22 @@ Trust token issuance could be expanded to other entities (the operating system, ``` -areyouahuman.example - Trust Token Issuer +areyouahuman.example - Private State Token Issuer coolwebsite.example - Publisher Top-Level Site -foo.example - Site requiring a Trust Token to prove the user is trusted. +foo.example - Site requiring a Private State Token to prove the user is trusted. ``` 1. User visits `areyouahuman.example`. -1. `areyouahuman.example` verifies the user is a human, and calls `fetch('areyouahuman.example/get-human-tokens', {trustToken: {type: 'private-state-token', version: 1, operation: 'token-request', issuer: 'areyouahuman.example'}})`. +1. `areyouahuman.example` verifies the user is a human, and calls `fetch('areyouahuman.example/get-human-tokens', {privateToken: {type: 'private-state-token', version: 1, operation: 'token-request', issuer: 'areyouahuman.example'}})`. 1. The browser stores the trust tokens associated with `areyouahuman.example`. 1. Sometime later, the user visits `coolwebsite.example`. -1. `coolwebsite.example` wants to know if the user is a human, by asking `areyouahuman.example` that question, by calling `fetch('areyouahuman.example/redeem-human-token', {trustToken: {type: 'private-state-token', version: 1, operation: 'token-redemption', issuer: 'areyouahuman.example'}})`. +1. `coolwebsite.example` wants to know if the user is a human, by asking `areyouahuman.example` that question, by calling `fetch('areyouahuman.example/redeem-human-token', {privateToken: {type: 'private-state-token', version: 1, operation: 'token-redemption', issuer: 'areyouahuman.example'}})`. 1. The browser requests a redemption. 1. The issuer returns an RR (this indicates that `areyouahuman.example` at some point issued a valid token to this browser). 1. When the promise returned by the method resolves, the RR can be used in subsequent resource requests. -1. Script running code in the top level `coolwebsite.example` document can call `fetch('foo.example/get-content', {trustToken: {type: 'private-state-token', version: 1, operation: 'send-redemption-record', issuer: 'areyouahuman.example'}})` +1. Script running code in the top level `coolwebsite.example` document can call `fetch('foo.example/get-content', {privateToken: {type: 'private-state-token', version: 1, operation: 'send-redemption-record', issuer: 'areyouahuman.example'}})` 1. The third-party receives the RR, and now has some indication that `areyouahuman.example` thought this user was a human. 1. The third-party responds to this fetch request based on that fact. @@ -312,7 +312,7 @@ Different issuers/ecosystems should specify their own Redemption Record format s Publisher Origin }, Metadata: { - Trust Token Key ID + Private State Token Key ID }, Signature of the above verifiable by well-known public key of the issuer, SigAlg: ,