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.
79 lines
2.1 KiB
79 lines
2.1 KiB
2 months ago
|
/*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;
|