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
			| 
											3 years 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; |