Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 7880050

Browse filesBrowse files
committed
pulled functionality out into unique files
1 parent d72fc3f commit 7880050
Copy full SHA for 7880050

File tree

Expand file treeCollapse file tree

5 files changed

+237
-211
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

5 files changed

+237
-211
lines changed
Open diff view settings
Collapse file

‎index.js‎

Copy file name to clipboardExpand all lines: index.js
+8-211Lines changed: 8 additions & 211 deletions
Original file line numberDiff line numberDiff line change
@@ -1,221 +1,18 @@
1-
/*global process, exports*/
2-
const Buffer = require('buffer').Buffer;
3-
const Stream = require('stream');
4-
const util = require('util');
5-
const base64url = require('base64url');
6-
const jwa = require('jwa');
1+
/*global exports*/
2+
const SignStream = require('./lib/sign-stream');
3+
const VerifyStream = require('./lib/verify-stream');
74

85
const ALGORITHMS = [
96
'HS256', 'HS384', 'HS512',
107
'RS256', 'RS384', 'RS512',
11-
'ES256', 'ES384', 'ES512',
8+
'ES256', 'ES384', 'ES512'
129
];
1310

14-
function toString(obj) {
15-
if (typeof obj === 'string')
16-
return obj;
17-
if (typeof obj === 'number' || Buffer.isBuffer(obj))
18-
return obj.toString();
19-
return JSON.stringify(obj);
20-
}
21-
22-
function jwsSecuredInput(header, payload) {
23-
const encodedHeader = base64url(toString(header), 'binary');
24-
const encodedPayload = base64url(toString(payload), 'binary');
25-
return util.format('%s.%s', encodedHeader, encodedPayload);
26-
}
27-
28-
function jwsSign(opts) {
29-
const header = opts.header;
30-
const payload = opts.payload;
31-
const secretOrKey = opts.secret || opts.privateKey;
32-
const algo = jwa(header.alg);
33-
const securedInput = jwsSecuredInput(header, payload);
34-
const signature = algo.sign(securedInput, secretOrKey);
35-
return util.format('%s.%s', securedInput, signature);
36-
}
37-
38-
function isObject(thing) {
39-
return Object.prototype.toString.call(thing) === '[object Object]';
40-
}
41-
42-
function safeJsonParse(thing) {
43-
if (isObject(thing))
44-
return thing;
45-
try { return JSON.parse(thing) }
46-
catch (e) { return undefined }
47-
}
48-
49-
function headerFromJWS(jwsSig) {
50-
const encodedHeader = jwsSig.split('.', 1)[0];
51-
return safeJsonParse(base64url.decode(encodedHeader, 'binary'));
52-
}
53-
54-
function securedInputFromJWS(jwsSig) {
55-
return jwsSig.split('.', 2).join('.');
56-
}
57-
58-
function algoFromJWS(jwsSig) {
59-
var err;
60-
const header = headerFromJWS(jwsSig);
61-
if (typeof header != 'object') {
62-
err = new Error("Invalid token: no header in signature '" + jwsSig + "'");
63-
err.code = "MISSING_HEADER";
64-
err.signature = jwsSig;
65-
throw err;
66-
}
67-
if (!header.alg) {
68-
err = new Error("Missing `alg` field in header for signature '"+ jwsSig +"'");
69-
err.code = "MISSING_ALGORITHM";
70-
err.header = header;
71-
err.signature = jwsSig;
72-
throw err;
73-
}
74-
return header.alg;
75-
}
76-
77-
function signatureFromJWS(jwsSig) {
78-
return jwsSig.split('.')[2];
79-
}
80-
81-
function payloadFromJWS(jwsSig) {
82-
const payload = jwsSig.split('.')[1];
83-
return base64url.decode(payload, 'binary');
84-
}
85-
86-
const JWS_REGEX = /^[a-zA-Z0-9\-_]+?\.[a-zA-Z0-9\-_]+?\.([a-zA-Z0-9\-_]+)?$/;
87-
function isValidJws(string) {
88-
if (!JWS_REGEX.test(string))
89-
return false;
90-
if (!headerFromJWS(string))
91-
return false;
92-
return true;
93-
}
94-
95-
function jwsVerify(jwsSig, secretOrKey) {
96-
jwsSig = toString(jwsSig);
97-
const signature = signatureFromJWS(jwsSig);
98-
const securedInput = securedInputFromJWS(jwsSig);
99-
const algo = jwa(algoFromJWS(jwsSig));
100-
return algo.verify(securedInput, signature, secretOrKey);
101-
}
102-
103-
function jwsDecode(jwsSig, opts) {
104-
opts = opts || {};
105-
jwsSig = toString(jwsSig);
106-
if (!isValidJws(jwsSig))
107-
return null;
108-
const header = headerFromJWS(jwsSig);
109-
if (!header)
110-
return null;
111-
var payload = payloadFromJWS(jwsSig);
112-
if (header.typ === 'JWT' || opts.json)
113-
payload = JSON.parse(payload);
114-
return {
115-
header: header,
116-
payload: payload,
117-
signature: signatureFromJWS(jwsSig),
118-
};
119-
}
120-
121-
function SignStream(opts) {
122-
const secret = opts.secret||opts.privateKey||opts.key;
123-
const secretStream = new DataStream(secret);
124-
this.readable = true;
125-
this.header = opts.header;
126-
this.secret = this.privateKey = this.key = secretStream;
127-
this.payload = new DataStream(opts.payload);
128-
this.secret.once('close', function () {
129-
if (!this.payload.writable && this.readable)
130-
this.sign();
131-
}.bind(this));
132-
133-
this.payload.once('close', function () {
134-
if (!this.secret.writable && this.readable)
135-
this.sign();
136-
}.bind(this));
137-
}
138-
util.inherits(SignStream, Stream);
139-
SignStream.prototype.sign = function sign() {
140-
const signature = jwsSign({
141-
header: this.header,
142-
payload: this.payload.buffer,
143-
secret: this.secret.buffer,
144-
});
145-
this.emit('done', signature);
146-
this.emit('data', signature);
147-
this.emit('end');
148-
this.readable = false;
149-
return signature;
150-
};
151-
152-
function VerifyStream(opts) {
153-
opts = opts || {};
154-
const secretOrKey = opts.secret||opts.publicKey||opts.key;
155-
const secretStream = new DataStream(secretOrKey);
156-
this.readable = true;
157-
this.secret = this.publicKey = this.key = secretStream;
158-
this.signature = new DataStream(opts.signature);
159-
this.secret.once('close', function () {
160-
if (!this.signature.writable && this.readable)
161-
this.verify();
162-
}.bind(this));
163-
164-
this.signature.once('close', function () {
165-
if (!this.secret.writable && this.readable)
166-
this.verify();
167-
}.bind(this));
168-
}
169-
util.inherits(VerifyStream, Stream);
170-
VerifyStream.prototype.verify = function verify() {
171-
const valid = jwsVerify(this.signature.buffer, this.key.buffer);
172-
const obj = jwsDecode(this.signature.buffer);
173-
this.emit('done', valid, obj);
174-
this.emit('data', valid);
175-
this.emit('end');
176-
this.readable = false;
177-
return valid;
178-
};
179-
180-
function DataStream(data) {
181-
this.buffer = Buffer(data||0);
182-
this.writable = true;
183-
this.readable = true;
184-
if (!data)
185-
return this;
186-
if (typeof data.pipe === 'function')
187-
data.pipe(this);
188-
else if (data.length) {
189-
this.writable = false;
190-
process.nextTick(function () {
191-
this.buffer = data;
192-
this.emit('end', data);
193-
this.readable = false;
194-
this.emit('close');
195-
}.bind(this));
196-
}
197-
}
198-
util.inherits(DataStream, Stream);
199-
200-
DataStream.prototype.write = function write(data) {
201-
this.buffer = Buffer.concat([this.buffer, Buffer(data)]);
202-
this.emit('data', data);
203-
};
204-
205-
DataStream.prototype.end = function end(data) {
206-
if (data)
207-
this.write(data);
208-
this.emit('end', data);
209-
this.emit('close');
210-
this.writable = false;
211-
this.readable = false;
212-
};
213-
21411
exports.ALGORITHMS = ALGORITHMS;
215-
exports.sign = jwsSign;
216-
exports.verify = jwsVerify;
217-
exports.decode = jwsDecode;
218-
exports.isValid = isValidJws;
12+
exports.sign = SignStream.sign;
13+
exports.verify = VerifyStream.verify;
14+
exports.decode = VerifyStream.decode;
15+
exports.isValid = VerifyStream.isValid;
21916
exports.createSign = function createSign(opts) {
22017
return new SignStream(opts);
22118
};
Collapse file

‎lib/data-stream.js‎

Copy file name to clipboard
+40Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*global module, process*/
2+
const Buffer = require('buffer').Buffer;
3+
const Stream = require('stream');
4+
const util = require('util');
5+
6+
function DataStream(data) {
7+
this.buffer = Buffer(data||0);
8+
this.writable = true;
9+
this.readable = true;
10+
if (!data)
11+
return this;
12+
if (typeof data.pipe === 'function')
13+
data.pipe(this);
14+
else if (data.length) {
15+
this.writable = false;
16+
process.nextTick(function () {
17+
this.buffer = data;
18+
this.emit('end', data);
19+
this.readable = false;
20+
this.emit('close');
21+
}.bind(this));
22+
}
23+
}
24+
util.inherits(DataStream, Stream);
25+
26+
DataStream.prototype.write = function write(data) {
27+
this.buffer = Buffer.concat([this.buffer, Buffer(data)]);
28+
this.emit('data', data);
29+
};
30+
31+
DataStream.prototype.end = function end(data) {
32+
if (data)
33+
this.write(data);
34+
this.emit('end', data);
35+
this.emit('close');
36+
this.writable = false;
37+
this.readable = false;
38+
};
39+
40+
module.exports = DataStream;
Collapse file

‎lib/sign-stream.js‎

Copy file name to clipboard
+59Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*global module*/
2+
const base64url = require('base64url');
3+
const DataStream = require('./data-stream');
4+
const jwa = require('jwa');
5+
const Stream = require('stream');
6+
const toString = require('./tostring');
7+
const util = require('util');
8+
9+
function jwsSecuredInput(header, payload) {
10+
const encodedHeader = base64url(toString(header), 'binary');
11+
const encodedPayload = base64url(toString(payload), 'binary');
12+
return util.format('%s.%s', encodedHeader, encodedPayload);
13+
}
14+
15+
function jwsSign(opts) {
16+
const header = opts.header;
17+
const payload = opts.payload;
18+
const secretOrKey = opts.secret || opts.privateKey;
19+
const algo = jwa(header.alg);
20+
const securedInput = jwsSecuredInput(header, payload);
21+
const signature = algo.sign(securedInput, secretOrKey);
22+
return util.format('%s.%s', securedInput, signature);
23+
}
24+
25+
function SignStream(opts) {
26+
const secret = opts.secret||opts.privateKey||opts.key;
27+
const secretStream = new DataStream(secret);
28+
this.readable = true;
29+
this.header = opts.header;
30+
this.secret = this.privateKey = this.key = secretStream;
31+
this.payload = new DataStream(opts.payload);
32+
this.secret.once('close', function () {
33+
if (!this.payload.writable && this.readable)
34+
this.sign();
35+
}.bind(this));
36+
37+
this.payload.once('close', function () {
38+
if (!this.secret.writable && this.readable)
39+
this.sign();
40+
}.bind(this));
41+
}
42+
util.inherits(SignStream, Stream);
43+
44+
SignStream.prototype.sign = function sign() {
45+
const signature = jwsSign({
46+
header: this.header,
47+
payload: this.payload.buffer,
48+
secret: this.secret.buffer
49+
});
50+
this.emit('done', signature);
51+
this.emit('data', signature);
52+
this.emit('end');
53+
this.readable = false;
54+
return signature;
55+
};
56+
57+
SignStream.sign = jwsSign;
58+
59+
module.exports = SignStream;
Collapse file

‎lib/tostring.js‎

Copy file name to clipboard
+10Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/*global module*/
2+
const Buffer = require('buffer').Buffer;
3+
4+
module.exports = function toString(obj) {
5+
if (typeof obj === 'string')
6+
return obj;
7+
if (typeof obj === 'number' || Buffer.isBuffer(obj))
8+
return obj.toString();
9+
return JSON.stringify(obj);
10+
};

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.