Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 38 additions & 54 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -735,9 +735,8 @@ <h2>
SHOULD attempt to <a>refresh</a> the push subscription before the subscription expires.
</p>
<p>
A <a>push subscription</a> has internal slots for a P-256 <a>ECDH</a> key pair and an
authentication secret in accordance with [[RFC8291]]. These slots MUST be populated when
creating the <a>push subscription</a>.
A [=push subscription=] has an associated <dfn>P-256 ECDH key pair</dfn> and an
<dfn>authentication secret</dfn> in accordance with [[RFC8291]].
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be nice to (eventually) define their types as well.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it's somehow opaque right now. Could try byte sequences and make it always serialized. Thoughts?

I think a separate PR would be nicer for that

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, probably best as a follow-up. It could better explain getKey and such.

</p>
<p>
If the <a>user agent</a> has to change the keys of a [=push subscription=] for any reason
Expand All @@ -757,16 +756,12 @@ <h2>
</li>
<li>Set |subscription|'s {{PushSubscription/options}} attribute to |options|.
</li>
<li>Generate a new P-256 <a>ECDH</a> 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"}}.
<li>Set |subscription|'s [=P-256 ECDH key pair=] to the result of generating a new P-256
[=ECDH=] key pair [[ANSI-X9-62]].
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If at all possible, I wonder if it's possible to link to the particular section of ANSI-X9-62 (or even if such a section exists?... I haven't checked).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But I don't understand tihs. ANSI X9.62 doesn't seem to be about ECDH, it's about ECDSA per what I see. X9.63 is about ECDH. Something to fix in a separate patch?

</li>
<li>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"}}.
<li>Set |subscription|'s [=authentication secret=] to the result of generating a new
authentication secret, which is a sequence of octets as defined in [[RFC8291]] Section
3.2.
</li>
<li>Request a new <a>push subscription</a>. Include the
{{PushSubscriptionOptions/applicationServerKey}} attribute of |options| when it has been
Expand Down Expand Up @@ -1448,11 +1443,16 @@ <h2>

PushSubscriptionJSON toJSON();
};

dictionary PushSubscriptionKeys {
USVString p256dh;
USVString auth;
};

dictionary PushSubscriptionJSON {
USVString endpoint;
EpochTimeStamp? expirationTime = null;
record&lt;DOMString, USVString&gt; keys;
PushSubscriptionKeys keys;
};
</pre>
<p>
Expand All @@ -1472,37 +1472,32 @@ <h2>
subscription</a>.
</p>
<p>
The <dfn>getKey()</dfn> method retrieves keying material that can be used for encrypting
and authenticating messages. When {{PushSubscription/getKey()}} is invoked the following
process is followed:
The <dfn>getKey</dfn><code>(|name:PushEncryptionKeyName|)</code> method retrieves keying
material that can be used for encrypting and authenticating messages. The method steps are:
</p>
<ol>
<li>Find the internal slot corresponding to the key named by the `name` argument.
</li>
<li>If a slot was not found, return `null`.
</li>
<li>Initialize a variable |key| with a newly instantiated {{ArrayBuffer}} instance.
<ol class="algorithm">
<li>Let |key| be a newly instantiated {{ArrayBuffer}} instance.
</li>
<li>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).
<li>If |name| is {{PushEncryptionKeyName/"p256dh"}}:
<ol>
<li>Set the contents of |key| to the serialized value of the public key from
[=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.
</li>
</ol>
</li>
<li>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 <a>user agent</a> to authenticate messages sent by an
<a>application server</a>.
<li>Otherwise:
<ol>
<li>[=/Assert=]: |name| is {{PushEncryptionKeyName/"auth"}}</li>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can just do:

Suggested change
<li>[=/Assert=]: |name| is {{PushEncryptionKeyName/"auth"}}</li>
<li>Assert: |name| is {{PushEncryptionKeyName/"auth"}}</li>

And if that should link to WebIDL's assert, we should probably fix that in ReSpec (can't remember if it links already or not).

Copy link
Member Author

@saschanaz saschanaz Nov 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, doesn't seem to work. Just a plaintext.

<li>Set the contents of |key| to a copy of the value from [=this=]'s
[=authentication secret=].
</li>
</ol>
</li>
<li>Return |key|.
</li>
</ol>
<p data-link-for="">
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]].
</p>
<p>
The <dfn data-lt="unsubscribed">unsubscribe()</dfn> method when invoked MUST run the
following steps:
Expand Down Expand Up @@ -1544,24 +1539,13 @@ <h2>
<li>Set |json|["expirationTime"] to the result of [=getting the `expirationTime`
attribute=] of [=this=].
</li>
<li>Let |keys| be a new empty instance of `record&lt;DOMString, USVString&gt;` .
<li>Let |keys:PushSubscriptionKeys| be a new {{PushSubscriptionKeys}} dictionary.
</li>
<li>For each identifier |i| corresponding to keys in internal slots on the
{{PushSubscription}}, ordered by the name of the key:
<ol>
<li>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()}}).
</li>
<li>Otherwise, let |b| be the value as returned by {{PushSubscription/getKey}}.
</li>
<li>Let |s| be the URL-safe base64 encoding without padding [[RFC4648]] of |b| as a
{{USVString}}. The <a>user agent</a> MUST use a serialization method that does not
branch based on the value of |b|.
</li>
<li>Set |keys|[|i|] to |s|.
</li>
</ol>
<li>Set |keys|["p256dh"] to the URL-safe base64 encoding without padding [[RFC4648]] of
the value as returned by {{PushSubscription/getKey("p256dh")}}, as a {{USVString}}.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this isn't entirely a regression, but using the public API is not great. We should have an internal "get key" for this.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I took a bit of look and I think it would be nice to fix this with key types. If we make the keys always serialized, then this step can simply retrieve that without an extra algorithm.

</li>
<li>Set |keys|["auth"] to the URL-safe base64 encoding without padding [[RFC4648]] of
the value as returned by {{PushSubscription/getKey("auth")}}, as a {{USVString}}.
</li>
<li>Set |json|["keys"] to |keys|.
</li>
Expand Down