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.
78 lines
2.1 KiB
78 lines
2.1 KiB
/*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'); |
|
|
|
function base64url(string, encoding) { |
|
return Buffer |
|
.from(string, encoding) |
|
.toString('base64') |
|
.replace(/=/g, '') |
|
.replace(/\+/g, '-') |
|
.replace(/\//g, '_'); |
|
} |
|
|
|
function jwsSecuredInput(header, payload, encoding) { |
|
encoding = encoding || 'utf8'; |
|
var encodedHeader = base64url(toString(header), 'binary'); |
|
var encodedPayload = base64url(toString(payload), encoding); |
|
return util.format('%s.%s', encodedHeader, encodedPayload); |
|
} |
|
|
|
function jwsSign(opts) { |
|
var header = opts.header; |
|
var payload = opts.payload; |
|
var secretOrKey = opts.secret || opts.privateKey; |
|
var encoding = opts.encoding; |
|
var algo = jwa(header.alg); |
|
var securedInput = jwsSecuredInput(header, payload, encoding); |
|
var signature = algo.sign(securedInput, secretOrKey); |
|
return util.format('%s.%s', securedInput, signature); |
|
} |
|
|
|
function SignStream(opts) { |
|
var secret = opts.secret||opts.privateKey||opts.key; |
|
var secretStream = new DataStream(secret); |
|
this.readable = true; |
|
this.header = opts.header; |
|
this.encoding = opts.encoding; |
|
this.secret = this.privateKey = this.key = secretStream; |
|
this.payload = new DataStream(opts.payload); |
|
this.secret.once('close', function () { |
|
if (!this.payload.writable && this.readable) |
|
this.sign(); |
|
}.bind(this)); |
|
|
|
this.payload.once('close', function () { |
|
if (!this.secret.writable && this.readable) |
|
this.sign(); |
|
}.bind(this)); |
|
} |
|
util.inherits(SignStream, Stream); |
|
|
|
SignStream.prototype.sign = function sign() { |
|
try { |
|
var signature = jwsSign({ |
|
header: this.header, |
|
payload: this.payload.buffer, |
|
secret: this.secret.buffer, |
|
encoding: this.encoding |
|
}); |
|
this.emit('done', signature); |
|
this.emit('data', signature); |
|
this.emit('end'); |
|
this.readable = false; |
|
return signature; |
|
} catch (e) { |
|
this.readable = false; |
|
this.emit('error', e); |
|
this.emit('close'); |
|
} |
|
}; |
|
|
|
SignStream.sign = jwsSign; |
|
|
|
module.exports = SignStream;
|
|
|