-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
app.js
50 lines (44 loc) · 1.55 KB
/
app.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
const bent = require('bent');
const getBuffer = bent('buffer');
const crypto = require('crypto');
const debug = require('debug')('verify-aws-sns-signature');
const parseUrl = require('parse-url');
const assert = require('assert');
async function validatePayload(payload) {
const {
SigningCertURL,
Signature,
Message,
MessageId,
SubscribeURL,
Subject,
Timestamp,
Token,
TopicArn,
Type
} = payload;
// validate SubscribeURL
const url = parseUrl(SigningCertURL);
assert.ok(/^sns\.[a-zA-Z0-9\-]{3,}\.amazonaws\.com(\.cn)?$/.test(url.resource),
`SigningCertURL host is not a valid AWS SNS host: ${SigningCertURL}`);
try {
debug(`retrieving AWS certificate from ${SigningCertURL}`);
const x509 = await getBuffer(SigningCertURL);
const publicKey = crypto.createPublicKey(x509);
const signature = Buffer.from(Signature, 'base64');
const stringToSign = ('Notification' === Type ?
[{Message}, {MessageId}, {Subject}, {Timestamp}, {TopicArn}, {Type}] :
[{Message}, {MessageId}, {SubscribeURL}, {Timestamp}, {Token}, {TopicArn}, {Type}])
.reduce((acc, el) => {
const key = el.keys()[0];
acc += key + '\n' + el[key] + '\n';
}, '');
debug(`string to sign: ${stringToSign}`);
const verified = crypto.verify('sha1WithRSAEncryption', Buffer.from(stringToSign, 'utf8'), publicKey, signature);
debug(`signature ${verified ? 'has been verified' : 'failed verification'}`);
return verified;
} catch (err) {
return false;
}
}
module.exports = {validatePayload};