From fdf5147189d71bf8f326d4b6bb933b1e63ff406c Mon Sep 17 00:00:00 2001 From: Kagami Sascha Rosylight Date: Mon, 24 Nov 2025 16:31:29 +0100 Subject: [PATCH 1/4] Define and use the p256dh/auth internal slots --- index.html | 89 ++++++++++++++++++++++-------------------------------- 1 file changed, 36 insertions(+), 53 deletions(-) diff --git a/index.html b/index.html index 6294dfe..3ff443b 100644 --- a/index.html +++ b/index.html @@ -735,9 +735,8 @@

SHOULD attempt to refresh the push subscription before the subscription expires.

- A push subscription has internal slots for a P-256 ECDH key pair and an - authentication secret in accordance with [[RFC8291]]. These slots MUST be populated when - creating the push subscription. + A [=push subscription=] has an associated P-256 ECDH key pair and an + authentication secret in accordance with [[RFC8291]].

If the user agent has to change the keys of a [=push subscription=] for any reason @@ -757,16 +756,11 @@

  • Set |subscription|'s {{PushSubscription/options}} attribute to |options|.
  • -
  • Generate a new P-256 ECDH key pair [[ANSI-X9-62]]. Store the private key in an - internal slot on |subscription|; this value MUST NOT be made available to applications. - The public key is also stored in an internal slot and can be retrieved by calling the - {{PushSubscription/getKey()}} method of the {{PushSubscription}} with an argument of - {{PushEncryptionKeyName/"p256dh"}}. +
  • Set |subscription|'s [=P-256 ECDH key pair=] to the result of generating a new P-256 + [=ECDH=] key pair [[ANSI-X9-62]].
  • -
  • Generate a new authentication secret, which is a sequence of octets as defined in - [[RFC8291]]. Store the authentication secret in an internal slot on |subscription|. This - key can be retrieved by calling the {{PushSubscription/getKey()}} method of the - {{PushSubscription}} with an argument of {{PushEncryptionKeyName/"auth"}}. +
  • Set |subscription|'s [=authentication secret=] to the result of generating a new + authentication secret, which is a sequence of octets as defined in [[RFC8291]].
  • Request a new push subscription. Include the {{PushSubscriptionOptions/applicationServerKey}} attribute of |options| when it has been @@ -1448,11 +1442,17 @@

    PushSubscriptionJSON toJSON(); }; + + dictionary PushSubscriptionKeys + { + USVString p256dh; + USVString auth; + }; dictionary PushSubscriptionJSON { USVString endpoint; EpochTimeStamp? expirationTime = null; - record<DOMString, USVString> keys; + PushSubscriptionKeys keys; };

    @@ -1472,37 +1472,31 @@

    subscription.

    - The getKey() method retrieves keying material that can be used for encrypting - and authenticating messages. When {{PushSubscription/getKey()}} is invoked the following - process is followed: + The getKey(|name:PushEncryptionKeyName|) method retrieves keying + material that can be used for encrypting and authenticating messages. The method steps are:

      -
    1. Find the internal slot corresponding to the key named by the `name` argument. -
    2. -
    3. If a slot was not found, return `null`. -
    4. -
    5. Initialize a variable |key| with a newly instantiated {{ArrayBuffer}} instance. +
    6. Let |key| be a newly instantiated {{ArrayBuffer}} instance.
    7. -
    8. If the internal slot contains an asymmetric key pair, set the contents of |key| to the - serialized value of the public key from the key pair. This uses the serialization format - described in the specification that defines the name. For example, [[RFC8291]] specifies - that the {{PushEncryptionKeyName/"p256dh"}} public key is encoded using the uncompressed - format defined in [[ANSI-X9-62]] Annex A (that is, a 65 octet sequence that starts with a - 0x04 octet). +
    9. If |name| is {{PushEncryptionKeyName/"p256dh"}}: +
        +
      1. Set the contents of |key| to the serialized value of the public key from + [=P-256 ECDH key pair=], using the uncompressed format defined in [[ANSI-X9-62]] Annex + A (that is, a 65 octet sequence that starts with a 0x04 octet), as [[RFC8291]] + specifies. +
      2. +
    10. -
    11. Otherwise, if the internal slot contains a symmetric key, set the contents of |key| to - a copy of the value from the internal slot. For example, the `auth` parameter contains an - octet sequence used by the user agent to authenticate messages sent by an - application server. +
    12. Otherwise: +
        +
      1. [=/Assert=]: |name| is {{PushEncryptionKeyName/"auth"}}
      2. +
      3. Set the contents of |key| to a copy of the value from [=authentication secret=]. +
      4. +
    13. Return |key|.
    -

    - Keys named {{PushEncryptionKeyName/"p256dh"}} and {{PushEncryptionKeyName/"auth"}} MUST be - supported, and their values MUST correspond to those necessary for the user agent to - decrypt received push messages in accordance with [[RFC8291]]. -

    The unsubscribe() method when invoked MUST run the following steps: @@ -1544,24 +1538,13 @@

  • Set |json|["expirationTime"] to the result of [=getting the `expirationTime` attribute=] of [=this=].
  • -
  • Let |keys| be a new empty instance of `record<DOMString, USVString>` . +
  • Let |keys:PushSubscriptionKeys| be a new {{PushSubscriptionKeys}} dictionary.
  • -
  • For each identifier |i| corresponding to keys in internal slots on the - {{PushSubscription}}, ordered by the name of the key: -
      -
    1. If the internal slot corresponds to an asymmetric key pair, let |b| be the encoded - value of the public key corresponding to the key name |i|, using the encoding defined - for the key name (see {{PushSubscription/getKey()}}). -
    2. -
    3. Otherwise, let |b| be the value as returned by {{PushSubscription/getKey}}. -
    4. -
    5. Let |s| be the URL-safe base64 encoding without padding [[RFC4648]] of |b| as a - {{USVString}}. The user agent MUST use a serialization method that does not - branch based on the value of |b|. -
    6. -
    7. Set |keys|[|i|] to |s|. -
    8. -
    +
  • Set |keys|["p256dh"] be the URL-safe base64 encoding without padding [[RFC4648]] of + the value as returned by {{PushSubscription/getKey("p256dh")}}, as a {{USVString}}. +
  • +
  • Set |keys|["auth"] be the URL-safe base64 encoding without padding [[RFC4648]] of + the value as returned by {{PushSubscription/getKey("auth")}}, as a {{USVString}}.
  • Set |json|["keys"] to |keys|.
  • From a049cb291aa82b2fd13617a452af40b28a8e5a5b Mon Sep 17 00:00:00 2001 From: Kagami Sascha Rosylight Date: Tue, 25 Nov 2025 15:36:43 +0100 Subject: [PATCH 2/4] set-to and this's --- index.html | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/index.html b/index.html index 3ff443b..f113842 100644 --- a/index.html +++ b/index.html @@ -1481,16 +1481,17 @@

  • If |name| is {{PushEncryptionKeyName/"p256dh"}}:
    1. Set the contents of |key| to the serialized value of the public key from - [=P-256 ECDH key pair=], using the uncompressed format defined in [[ANSI-X9-62]] Annex - A (that is, a 65 octet sequence that starts with a 0x04 octet), as [[RFC8291]] - specifies. + [=this=]'s [=P-256 ECDH key pair=], using the uncompressed format defined in + [[ANSI-X9-62]] Annex A (that is, a 65 octet sequence that starts with a 0x04 octet), as + [[RFC8291]] specifies.
  • Otherwise:
    1. [=/Assert=]: |name| is {{PushEncryptionKeyName/"auth"}}
    2. -
    3. Set the contents of |key| to a copy of the value from [=authentication secret=]. +
    4. Set the contents of |key| to a copy of the value from [=this=]'s + [=authentication secret=].
  • @@ -1540,10 +1541,10 @@

  • Let |keys:PushSubscriptionKeys| be a new {{PushSubscriptionKeys}} dictionary.
  • -
  • Set |keys|["p256dh"] be the URL-safe base64 encoding without padding [[RFC4648]] of +
  • Set |keys|["p256dh"] to the URL-safe base64 encoding without padding [[RFC4648]] of the value as returned by {{PushSubscription/getKey("p256dh")}}, as a {{USVString}}.
  • -
  • Set |keys|["auth"] be the URL-safe base64 encoding without padding [[RFC4648]] of +
  • Set |keys|["auth"] to the URL-safe base64 encoding without padding [[RFC4648]] of the value as returned by {{PushSubscription/getKey("auth")}}, as a {{USVString}}.
  • Set |json|["keys"] to |keys|. From 9b2af846627c948191006e275693ad8794674d40 Mon Sep 17 00:00:00 2001 From: Kagami Sascha Rosylight Date: Fri, 28 Nov 2025 16:52:29 +0100 Subject: [PATCH 3/4] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Marcos Cáceres --- index.html | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/index.html b/index.html index f113842..9eecb18 100644 --- a/index.html +++ b/index.html @@ -1443,8 +1443,7 @@

    PushSubscriptionJSON toJSON(); }; - dictionary PushSubscriptionKeys - { + dictionary PushSubscriptionKeys { USVString p256dh; USVString auth; }; @@ -1475,7 +1474,7 @@

    The getKey(|name:PushEncryptionKeyName|) method retrieves keying material that can be used for encrypting and authenticating messages. The method steps are:

    -
      +
      1. Let |key| be a newly instantiated {{ArrayBuffer}} instance.
      2. If |name| is {{PushEncryptionKeyName/"p256dh"}}: From ac874e3b37fafb1c4d9c519750f9fc03b7a09ea0 Mon Sep 17 00:00:00 2001 From: Kagami Sascha Rosylight Date: Fri, 28 Nov 2025 17:07:11 +0100 Subject: [PATCH 4/4] RFC8291 section 3.2 --- index.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/index.html b/index.html index 9eecb18..e0a6626 100644 --- a/index.html +++ b/index.html @@ -760,7 +760,8 @@

        [=ECDH=] key pair [[ANSI-X9-62]].

      3. Set |subscription|'s [=authentication secret=] to the result of generating a new - authentication secret, which is a sequence of octets as defined in [[RFC8291]]. + authentication secret, which is a sequence of octets as defined in [[RFC8291]] Section + 3.2.
      4. Request a new push subscription. Include the {{PushSubscriptionOptions/applicationServerKey}} attribute of |options| when it has been