Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

What are the interfaces for the setMatchKey and getEncryptedMatchKey APIs? #52

Open
richajaindce opened this issue Mar 15, 2023 · 5 comments

Comments

@richajaindce
Copy link
Contributor

richajaindce commented Mar 15, 2023

This PR tries to define the interface of the two client-side APIs: getEncryptedMatchKey and getHelperNetworks . These would be the interfaces user-agents (like Chromium, Gecko, Webkit etc) would expose to developers.

Proposed API surface

[SecureContext]
interface PrivateAttribution {
  // Retrieve an encryption of a secret-sharing of the match key that was previously set by a 
  // given match key provider. This encryption will be specific to the site (i.e. registrable domain) 
  // at the time when this function is invoked
  Promise<PrivateAttributionEncryptedMatchKey> getEncryptedMatchKey(
     // Report collector origin who is collecting the events
     required DOMString reportCollector, 

      // other arguments which are needed to generate encryptions
     required PrivateAttributionOptions options
  );
  
  // Get the set of helpers that the browser is willing to encrypt match keys towards.
  Promise<sequence<PrivateAttributionNetwork>>
    getHelperNetworks();
};

dictionary PrivateAttributionOptions {
     // Is this a source or trigger event
      required PrivateAttributionEventType eventType,

      // Which helper party network do you want to encrypt towards
      required PrivateAttributionNetwork helperNetwork

      // TODO add more parameters, such as
      // binding to a report collector for partial budget allocation.
      // See: https://github.com/patcg/docs-and-reports/tree/main/threat-model#33-privacy-parameters
};

interface PrivateAttributionNetwork {
  sequence<DOMString> origins;
};

enum PrivateAttributionEventType {
  "source",
  "trigger",
}

[Exposed=Window]
partial interface Window {
  attribute PrivateAttribution attribution;
};

getEncryptedMatchKey

getEncryptedMatchKey API allows retrieval of an encryption of secret-shares of the match key that was previously set. If not found, this API also generates a random value for the matchkey, and stores it.

API arguments

eventType: specifies if this is a source or a trigger event
helperNetwork: Helper party network towards which the match keys should be encrypted
options: Optional arguments which might be required to be passed

API implementation detail

Step 1: Find the correct match_key

  • If a match_key is found in the storage, it will be used.
  • If the user has enabled “private browsing”, it will return a secret-sharing of a random value.
  • There may be a user setting to disable this API. If the user has disabled this API, this API will return a secret-sharing of a random value.
  • Else, a match_key will be set on-device and used to serve as match key

Step 2: Split match_key into 3 shares

  • match_key from the previous step will be split into 3 shares. The shares are obtained by generating 2 random shares and then doing an XOR of match key with these two shares.

Step 3: Prefix eventType to each packet

  • A bit will be prefixed to each share to indicate source event (0) or trigger event (1) (see: link).

Step 4: Encrypt packets

  • Each packet obtained from last step will be encrypted towards the helper party network
    using public encryption keys (see below in getHelperNetworks for details).
  • If no helper network is identified, one will be chosen for the site.

Please note that

  • Calls to this API on different sites should return different secret sharing of the underlying match key to ensure there is no cross-site link-ability introduced.
  • The browser will only cache the raw shares it created upon first invocation and store that against the calling “site” (note: not origin, see: link).
  • Each time this API is called, on the same site, during the same epoch a new set of encrypted shares will be created using the public keys and associated data. This is to avoid learning distribution of same users across source and trigger site.

API return type

This has been covered in detail in #50

getHelperNetworks

The third API, getHelperNetworks returns a list of the helper party networks towards which the browser is willing to encrypt match keys.

About public encryption keys: Browsers will need to know which public keys to use when encrypting data inside getEncryptedMatchKey(). This can be hard-coded into the browser, part of some sort of configuration system, or periodically downloaded from helpers. This needs to be globally consistent to prevent the choice of key from being used to identify users; see https://datatracker.ietf.org/doc/html/draft-ietf-privacypass-key-consistency

About PrivateAttributionNetwork: We won’t provide a constructor for PrivateAttributionNetwork, so that only values that the browser supports can be passed to the options parameter.

Additional Note

  • These APIs would only be available in foreground and not work in background by default. As an example, from Chromium they won’t be available for “Workers” by default.
  • Chromium implementation details can be found in this doc.
@martinthomson
Copy link
Collaborator

In #38 (comment) @bmcase reminds us that we need to have the site pick whether the event is a source or trigger event. That means

enum PrivateAttributionEventType {
  "source",
  "trigger",
}

Adding that as an argument to getEncryptedMatchKey outside of the options is probably the right answer.

@csharrison
Copy link
Contributor

I'm looking through the minutes and I'm not sure we aligned on the interface for getEncryptedMatchKey. I.e. do we want PrivateAttributionOptions to have a mandatory field for the helper party network or have the helper party network exist out of the options dict?

@richajaindce
Copy link
Contributor Author

I'm looking through the minutes and I'm not sure we aligned on the interface for getEncryptedMatchKey. I.e. do we want PrivateAttributionOptions to have a mandatory field for the helper party network or have the helper party network exist out of the options dict?

As report collector can only trust one HPN for the given epoch, I think we decided to keep HPN as a mandatory argument for getEncryptedMatchKey. This would ensure that even if the browser trusts multiple HPN, there is no ambiguity which HPN to choose.

@martinthomson
Copy link
Collaborator

As I think we previously discussed though, it might be helpful to have the necessary information present for the browser to use, rather than have it know about things like commitments and such. The helper parties will enforce these constraints, but the process will be smoother if they are supplied, always.

@csharrison
Copy link
Contributor

Sorry I think I wasn't clear, the alternative I remember discussing was:

getEncryptedMatchKey("https://reportcollector.exmaple", {
  eventType: "source",
  helperNetwork: ["https://helper1.example", "https://helper2.example"]
});

Where both eventType and helperNetwork must be supplied. Having these as non-positional arguments is less brittle if we want to change things around here in the future.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants