Skip to content

Commit 19aaf5b

Browse files
authored
Merge pull request #9 from jeskew/Yurko-Fedoriv-master
Yurko fedoriv master
2 parents 9648af7 + 48eb4c4 commit 19aaf5b

File tree

4 files changed

+57
-47
lines changed

4 files changed

+57
-47
lines changed

.travis.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ node_js:
44
- "0.12"
55
- "4.0"
66
- "4.1"
7+
- "4.2"
8+
- "4.3"
9+
- "4.4"
10+
- "6.0"
11+
- "6.1"
712

813
script:
914
- npm test

index.js

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
var url = require('url'),
44
https = require('https'),
55
crypto = require('crypto'),
6+
defaultEncoding = 'utf8',
67
defaultHostPattern = /^sns\.[a-zA-Z0-9\-]{3,}\.amazonaws\.com(\.cn)?$/,
78
certCache = {},
89
subscriptionControlKeys = ['SubscribeURL', 'Token'],
@@ -86,6 +87,11 @@ var getCertificate = function (certUrl, cb) {
8687

8788
https.get(certUrl, function (res) {
8889
var chunks = [];
90+
91+
if(res.statusCode !== 200){
92+
return cb(new Error('Certificate could not be retrieved'));
93+
}
94+
8995
res
9096
.on('data', function (data) {
9197
chunks.push(data.toString());
@@ -124,11 +130,14 @@ var validateSignature = function (message, cb, encoding) {
124130
cb(err);
125131
return;
126132
}
127-
128-
if (verifier.verify(certificate, message['Signature'], 'base64')) {
129-
cb(null, message);
130-
} else {
131-
cb(new Error('The message signature is invalid.'));
133+
try {
134+
if (verifier.verify(certificate, message['Signature'], 'base64')) {
135+
cb(null, message);
136+
} else {
137+
cb(new Error('The message signature is invalid.'));
138+
}
139+
} catch (e) {
140+
cb(e);
132141
}
133142
});
134143
};
@@ -138,10 +147,11 @@ var validateSignature = function (message, cb, encoding) {
138147
*
139148
* @constructor
140149
* @param {RegExp} [hostPattern=/^sns\.[a-zA-Z0-9\-]{3,}\.amazonaws\.com(\.cn)?$/] - A pattern used to validate that a message's certificate originates from a trusted domain.
150+
* @param {String} [encoding='utf8'] - The encoding of the messages being signed.
141151
*/
142152
function MessageValidator(hostPattern, encoding) {
143153
this.hostPattern = hostPattern || defaultHostPattern;
144-
this.encoding = encoding;
154+
this.encoding = encoding || defaultEncoding;
145155
}
146156

147157
/**

package.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,12 @@
1111
"test": "test"
1212
},
1313
"devDependencies": {
14-
"mocha": "^2.3.3",
1514
"chai": "^3.3.0",
16-
"underscore": "^1.8.3",
15+
"mocha": "^2.3.3",
1716
"pem": "^1.8.1",
18-
"rewire": "^2.3.4"
17+
"rewire": "^2.3.4",
18+
"sinon": "^1.17.6",
19+
"underscore": "^1.8.3"
1920
},
2021
"scripts": {
2122
"test": "node_modules/mocha/bin/mocha"

test/validator.js

Lines changed: 32 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
var chai = require('chai'),
2+
crypto = require('crypto'),
3+
sandbox = require('sinon').sandbox.create(),
24
expect = chai.expect,
35
should = chai.should,
46
rewire = require('rewire'),
@@ -24,15 +26,9 @@ var chai = require('chai'),
2426
SubscribeURL: 'https://www.amazonaws.com',
2527
Type: 'SubscriptionConfirmation'
2628
}),
27-
utf8Message = {
28-
Type: 'Notification',
29-
MessageId: '1',
30-
TopicArn: 'arn',
29+
utf8Message = _.extend({}, validMessage, {
3130
Message: 'A Message For you!',
32-
Timestamp: (new Date).toISOString(),
33-
SignatureVersion: '1',
34-
SigningCertURL: "https://localhost:56789/cert.pem"
35-
},
31+
}),
3632
utf8SubscriptionControlMessage = _.extend({}, utf8Message, {
3733
Token: 'Nonce',
3834
SubscribeURL: 'https://www.amazonaws.com',
@@ -48,15 +44,20 @@ describe('Message Validator', function () {
4844
if (err) throw err;
4945

5046
var crypto = require('crypto'),
51-
validMessages = [validMessage, validSubscriptionControlMessage];
47+
validMessages = [
48+
validMessage,
49+
validSubscriptionControlMessage,
50+
utf8Message,
51+
utf8SubscriptionControlMessage
52+
];
5253

5354
for (var i = 0; i < validMessages.length; i++) {
5455
var signer = crypto.createSign('RSA-SHA1');
5556

5657
for (var j = 0; j < signableKeysForSubscription.length; j++) {
5758
if (signableKeysForSubscription[j] in validMessages[i]) {
5859
signer.update(signableKeysForSubscription[j] + "\n"
59-
+ validMessages[i][signableKeysForSubscription[j]] + "\n");
60+
+ validMessages[i][signableKeysForSubscription[j]] + "\n", 'utf8');
6061
}
6162
}
6263

@@ -71,6 +72,10 @@ describe('Message Validator', function () {
7172
});
7273
});
7374

75+
afterEach(function () {
76+
sandbox.restore();
77+
});
78+
7479
describe('validator interface', function () {
7580
it('should call the provided callback with the validated message', function (done) {
7681
(new MessageValidator(/^localhost:56789$/))
@@ -198,38 +203,27 @@ describe('Message Validator', function () {
198203
});
199204

200205
describe('UTF8 message validation', function () {
201-
before(function (done) {
202-
pem.createCertificate({}, function (err, certHash) {
203-
if (err) throw err;
204-
205-
var crypto = require('crypto'),
206-
validMessages = [utf8Message, utf8SubscriptionControlMessage];
207-
208-
for (var i = 0; i < validMessages.length; i++) {
209-
var signer = crypto.createSign('RSA-SHA1');
210-
211-
for (var j = 0; j < signableKeysForSubscription.length; j++) {
212-
if (signableKeysForSubscription[j] in validMessages[i]) {
213-
signer.update(signableKeysForSubscription[j] + "\n"
214-
+ validMessages[i][signableKeysForSubscription[j]] + "\n", 'utf8');
215-
}
216-
}
217-
218-
validMessages[i]['Signature']
219-
= signer.sign(certHash.serviceKey, 'base64');
220-
}
221-
222-
MessageValidator.__set__('getCertificate', function (url, cb) {
223-
cb(null, certHash.certificate);
224-
});
225-
226-
done();
227-
});
228-
});
229206

230207
it('should accept a valid UTF8 message', function (done) {
231208
(new MessageValidator(/^localhost:56789$/, 'utf8'))
232209
.validate(utf8Message, done);
233210
});
234211
});
212+
213+
describe('invalid signing cert', function () {
214+
it('should catch any errors thrown during verification', function (done) {
215+
var verifier = {
216+
update: sandbox.spy(),
217+
verify: sandbox.stub().throws()
218+
};
219+
sandbox.stub(crypto, 'createVerify').returns(verifier);
220+
221+
(new MessageValidator(/^localhost:56789$/, 'utf8'))
222+
.validate(utf8Message, function (err, result) {
223+
expect(err).not.to.be.undefined;
224+
expect(result).to.be.undefined;
225+
done();
226+
});
227+
});
228+
});
235229
});

0 commit comments

Comments
 (0)