Skip to content

Commit 6f9a1a6

Browse files
committed
Removed deps
1 parent 42d8667 commit 6f9a1a6

File tree

4 files changed

+63
-235
lines changed

4 files changed

+63
-235
lines changed

package-lock.json

Lines changed: 7 additions & 206 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
11
{
22
"name": "web-push-browser",
3-
"version": "1.1.0",
3+
"version": "1.2.0",
44
"description": "Minimal library for sending notifications via the browser Push API",
55
"main": "build/index.js",
6-
"dependencies": {
7-
"jose": "^5.8.0"
8-
},
96
"devDependencies": {
107
"typescript": "^5.5.4"
118
},

src/crypto/jwt.ts

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { SignJWT } from "jose";
1+
import { toBase64Url } from "../utils/base64url";
22

33
/**
44
* Generate and sign a JWT token.
@@ -18,11 +18,44 @@ export async function createJWT(
1818
const exp = Math.floor(Date.now() / 1000) + 12 * 60 * 60; // 12 hours from now
1919
const sub = `mailto:${email}`;
2020

21-
return await new SignJWT({
22-
aud,
23-
exp,
24-
sub,
25-
})
26-
.setProtectedHeader({ alg: "ES256", typ: "JWT" })
27-
.sign(privateVapidKey);
21+
return await signJWT(
22+
{ alg: "ES256", typ: "JWT" },
23+
{
24+
aud,
25+
exp,
26+
sub,
27+
},
28+
privateVapidKey,
29+
);
30+
}
31+
32+
async function signJWT(
33+
header: object,
34+
payload: object,
35+
privateKey: CryptoKey,
36+
): Promise<string> {
37+
const encoder = new TextEncoder();
38+
39+
// Encode header and payload
40+
const encodedHeader = toBase64Url(encoder.encode(JSON.stringify(header)));
41+
const encodedPayload = toBase64Url(encoder.encode(JSON.stringify(payload)));
42+
43+
// Create the content to be signed
44+
const content = `${encodedHeader}.${encodedPayload}`;
45+
46+
// Sign the content
47+
const signature = await crypto.subtle.sign(
48+
{
49+
name: "ECDSA",
50+
hash: { name: "SHA-256" },
51+
},
52+
privateKey,
53+
encoder.encode(content),
54+
);
55+
56+
// Convert the signature to base64url
57+
const encodedSignature = toBase64Url(signature);
58+
59+
// Combine all parts to form the JWT
60+
return `${content}.${encodedSignature}`;
2861
}

src/crypto/payload.ts

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { PushNotificationSubscription } from "../types.js";
2-
import { fromBase64Url } from "../utils/base64url.js";
2+
import { fromBase64Url, toBase64Url } from "../utils/base64url.js";
33

44
type EncryptionOptions = {
55
algorithm: "aesgcm" | "aes128gcm";
@@ -100,22 +100,19 @@ export async function encryptPayload(
100100
let encrypted: ArrayBuffer;
101101

102102
if (options.algorithm === "aes128gcm") {
103-
const header = new Uint8Array([
104-
...salt,
105-
...new Uint8Array(4),
106-
...serverPublicKeyBytes,
107-
]);
108-
109-
const message = new Uint8Array([
110-
...header,
111-
...new Uint8Array(encryptedPayload),
112-
]);
113-
114-
const recordSize = new Uint32Array([encryptedPayload.byteLength]);
115-
new Uint8Array(message.buffer, 16, 4).set(
116-
new Uint8Array(recordSize.buffer),
117-
);
118-
encrypted = message.buffer;
103+
// AES128GCM header format:
104+
// Salt (16 bytes) || RS (4 bytes) || IdLen (1 byte) || PublicKey (65 bytes)
105+
const recordSize = 4096; // You can adjust this value
106+
const idLen = 65; // Length of the public key
107+
108+
const header = new Uint8Array(16 + 4 + 1 + 65);
109+
header.set(salt, 0); // Correctly setting the salt here
110+
new DataView(header.buffer).setUint32(16, recordSize, false);
111+
header[20] = idLen;
112+
header.set(serverPublicKeyBytes, 21);
113+
114+
encrypted = new Uint8Array([...header, ...new Uint8Array(encryptedPayload)])
115+
.buffer;
119116
} else {
120117
// For 'aesgcm', we don't include the header in the encrypted payload
121118
encrypted = encryptedPayload;

0 commit comments

Comments
 (0)