You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
|
/*global module*/ var Buffer = require('safe-buffer').Buffer; var DataStream = require('./data-stream'); var jwa = require('jwa'); var Stream = require('stream'); var toString = require('./tostring'); var util = require('util'); var JWS_REGEX = /^[a-zA-Z0-9\-_]+?\.[a-zA-Z0-9\-_]+?\.([a-zA-Z0-9\-_]+)?$/;
function isObject(thing) { return Object.prototype.toString.call(thing) === '[object Object]'; }
function safeJsonParse(thing) { if (isObject(thing)) return thing; try { return JSON.parse(thing); } catch (e) { return undefined; } }
function headerFromJWS(jwsSig) { var encodedHeader = jwsSig.split('.', 1)[0]; return safeJsonParse(Buffer.from(encodedHeader, 'base64').toString('binary')); }
function securedInputFromJWS(jwsSig) { return jwsSig.split('.', 2).join('.'); }
function signatureFromJWS(jwsSig) { return jwsSig.split('.')[2]; }
function payloadFromJWS(jwsSig, encoding) { encoding = encoding || 'utf8'; var payload = jwsSig.split('.')[1]; return Buffer.from(payload, 'base64').toString(encoding); }
function isValidJws(string) { return JWS_REGEX.test(string) && !!headerFromJWS(string); }
function jwsVerify(jwsSig, algorithm, secretOrKey) { if (!algorithm) { var err = new Error("Missing algorithm parameter for jws.verify"); err.code = "MISSING_ALGORITHM"; throw err; } jwsSig = toString(jwsSig); var signature = signatureFromJWS(jwsSig); var securedInput = securedInputFromJWS(jwsSig); var algo = jwa(algorithm); return algo.verify(securedInput, signature, secretOrKey); }
function jwsDecode(jwsSig, opts) { opts = opts || {}; jwsSig = toString(jwsSig);
if (!isValidJws(jwsSig)) return null;
var header = headerFromJWS(jwsSig);
if (!header) return null;
var payload = payloadFromJWS(jwsSig); if (header.typ === 'JWT' || opts.json) payload = JSON.parse(payload, opts.encoding);
return { header: header, payload: payload, signature: signatureFromJWS(jwsSig) }; }
function VerifyStream(opts) { opts = opts || {}; var secretOrKey = opts.secret||opts.publicKey||opts.key; var secretStream = new DataStream(secretOrKey); this.readable = true; this.algorithm = opts.algorithm; this.encoding = opts.encoding; this.secret = this.publicKey = this.key = secretStream; this.signature = new DataStream(opts.signature); this.secret.once('close', function () { if (!this.signature.writable && this.readable) this.verify(); }.bind(this));
this.signature.once('close', function () { if (!this.secret.writable && this.readable) this.verify(); }.bind(this)); } util.inherits(VerifyStream, Stream); VerifyStream.prototype.verify = function verify() { try { var valid = jwsVerify(this.signature.buffer, this.algorithm, this.key.buffer); var obj = jwsDecode(this.signature.buffer, this.encoding); this.emit('done', valid, obj); this.emit('data', valid); this.emit('end'); this.readable = false; return valid; } catch (e) { this.readable = false; this.emit('error', e); this.emit('close'); } };
VerifyStream.decode = jwsDecode; VerifyStream.isValid = isValidJws; VerifyStream.verify = jwsVerify;
module.exports = VerifyStream;
|