Skip to content

Commit d7dee51

Browse files
committed
Merge branch 'master' of github.com:marco-c/web-push into update_asn1.js_dep
2 parents c0408fa + 2fcd717 commit d7dee51

16 files changed

+1296
-796
lines changed

.eslintrc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
"max-len": [1, 80, 4, {"ignoreComments": true, "ignoreUrls": true}],
1515
"no-param-reassign": 0,
1616
"quote-props": 0,
17-
"wrap-iife": [2, "inside"]
17+
"wrap-iife": [2, "inside"],
18+
"import/no-unresolved": 0
1819
}
1920
}

bin/web-push.js

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
#! /usr/bin/env node
2+
const fs = require('fs');
3+
const webPush = require('web-push');
4+
webPush.setGCMAPIKey(process.env.GCM_API_KEY);
5+
6+
const argv = require('minimist')(process.argv.slice(2));
7+
8+
const usage = 'Use: web-push --endpoint=<url> --key=<browser key> ' +
9+
'[--auth=<auth secret>] [--ttl=<seconds>] [--payload=<message>] ' +
10+
'[--vapid-audience] [--vapid-subject] [--vapid-pvtkey] [--vapid-pubkey]';
11+
12+
if (!argv.endpoint || !argv.key) {
13+
console.log(usage);
14+
process.exit(1);
15+
}
16+
17+
const endpoint = argv.endpoint;
18+
const key = argv.key;
19+
const ttl = argv.ttl || 0;
20+
const payload = argv.payload || '';
21+
const auth = argv.auth || null;
22+
23+
const vapidAudience = argv['vapid-audience'] || null;
24+
const vapidSubject = argv['vapid-subject'] || null;
25+
const vapidPubKey = argv['vapid-pubkey'] || null;
26+
const vapidPvtKey = argv['vapid-pvtkey'] || null;
27+
28+
function getKeys() {
29+
if (vapidPubKey && vapidPvtKey) {
30+
const publicKey = fs.readFileSync(vapidPubKey);
31+
const privateKey = fs.readFileSync(vapidPvtKey);
32+
33+
if (publicKey && privateKey) {
34+
return {
35+
privateKey,
36+
publicKey
37+
};
38+
}
39+
}
40+
41+
return webPush.generateVAPIDKeys();
42+
}
43+
44+
let params = {
45+
TTL: ttl,
46+
payload,
47+
userPublicKey: key
48+
};
49+
if (vapidAudience && vapidSubject) {
50+
const vapidKeys = getKeys();
51+
const vapid = {
52+
audience: vapidAudience,
53+
subject: `mailto:${vapidSubject}`,
54+
privateKey: vapidKeys.privateKey,
55+
publicKey: vapidKeys.publicKey
56+
};
57+
params.vapid = vapid;
58+
}
59+
if (auth) {
60+
params.userAuth = auth;
61+
}
62+
webPush.sendNotification(endpoint, params).then(() => {
63+
console.log('Push message sent.');
64+
}, (err) => {
65+
console.log('Error sending push message: ', err);
66+
}).then(() => {
67+
process.exit(0);
68+
});

package.json

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,22 +42,24 @@
4242
},
4343
"devDependencies": {
4444
"chalk": "^1.1.3",
45-
"chromedriver": "^2.23.1",
45+
"chromedriver": "^2.24.1",
4646
"del": "^2.2.1",
4747
"dmg": "^0.1.0",
4848
"eslint": "^2.10.2",
4949
"eslint-config-airbnb": "^9.0.1",
5050
"eslint-plugin-import": "^1.11.1",
5151
"fs-extra": "^0.30.0",
52+
"geckodriver": "^1.1.2",
5253
"istanbul": "^0.4.2",
5354
"mkdirp": "^0.5.1",
5455
"mocha": "^2.4.5",
5556
"portfinder": "^1.0.2",
5657
"request": "^2.69.0",
57-
"selenium-assistant": "0.4.0",
58-
"selenium-webdriver": "~2.53.2",
58+
"selenium-assistant": "0.5.3",
59+
"selenium-webdriver": "^3.0.0-beta-2",
5960
"semver": "^5.1.0",
60-
"temp": "^0.8.3"
61+
"temp": "^0.8.3",
62+
"which": "^1.2.11"
6163
},
6264
"engines": {
6365
"node": ">= v0.10.0"

src/encryption-helper.js

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
'use strict';
2+
3+
const crypto = require('crypto');
4+
const ece = require('http_ece');
5+
const urlBase64 = require('urlsafe-base64');
6+
7+
const encrypt = function(userPublicKey, userAuth, payload) {
8+
if (!userPublicKey) {
9+
throw new Error('No user public key provided for encryption.');
10+
}
11+
12+
if (typeof userPublicKey !== 'string') {
13+
throw new Error('The subscription p256dh value must be a string.');
14+
}
15+
16+
if (urlBase64.decode(userPublicKey).length !== 65) {
17+
throw new Error('The subscription p256dh value should be 65 bytes long.');
18+
}
19+
20+
if (!userAuth) {
21+
throw new Error('No user auth provided for encryption.');
22+
}
23+
24+
if (typeof userAuth !== 'string') {
25+
throw new Error('The subscription auth key must be a string.');
26+
}
27+
28+
if (urlBase64.decode(userAuth).length < 16) {
29+
throw new Error('The subscription auth key should be at least 16 ' +
30+
'bytes long');
31+
}
32+
33+
if (typeof payload !== 'string' && !Buffer.isBuffer(payload)) {
34+
throw new Error('Payload must be either a string or a Node Buffer.');
35+
}
36+
37+
if (typeof payload === 'string' || payload instanceof String) {
38+
payload = new Buffer(payload);
39+
}
40+
41+
const localCurve = crypto.createECDH('prime256v1');
42+
const localPublicKey = localCurve.generateKeys();
43+
44+
const salt = urlBase64.encode(crypto.randomBytes(16));
45+
46+
ece.saveKey('webpushKey', localCurve, 'P-256');
47+
48+
const cipherText = ece.encrypt(payload, {
49+
keyid: 'webpushKey',
50+
dh: userPublicKey,
51+
salt: salt,
52+
authSecret: userAuth,
53+
padSize: 2
54+
});
55+
56+
return {
57+
localPublicKey: localPublicKey,
58+
salt: salt,
59+
cipherText: cipherText
60+
};
61+
};
62+
63+
module.exports = {
64+
encrypt: encrypt
65+
};

0 commit comments

Comments
 (0)