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.
		
		
		
		
		
			
		
			
				
					127 lines
				
				3.5 KiB
			
		
		
			
		
	
	
					127 lines
				
				3.5 KiB
			| 
											3 years ago
										 | // Load modules
 | ||
|  | 
 | ||
|  | var Crypto = require('crypto'); | ||
|  | var Url = require('url'); | ||
|  | var Utils = require('./utils'); | ||
|  | 
 | ||
|  | 
 | ||
|  | // Declare internals
 | ||
|  | 
 | ||
|  | var internals = {}; | ||
|  | 
 | ||
|  | 
 | ||
|  | // MAC normalization format version
 | ||
|  | 
 | ||
|  | exports.headerVersion = '1';                        // Prevent comparison of mac values generated with different normalized string formats
 | ||
|  | 
 | ||
|  | 
 | ||
|  | // Supported HMAC algorithms
 | ||
|  | 
 | ||
|  | exports.algorithms = ['sha1', 'sha256']; | ||
|  | 
 | ||
|  | 
 | ||
|  | // Calculate the request MAC
 | ||
|  | 
 | ||
|  | /* | ||
|  |     type: 'header',                                 // 'header', 'bewit', 'response'
 | ||
|  |     credentials: { | ||
|  |         key: 'aoijedoaijsdlaksjdl', | ||
|  |         algorithm: 'sha256'                         // 'sha1', 'sha256'
 | ||
|  |     }, | ||
|  |     options: { | ||
|  |         method: 'GET', | ||
|  |         resource: '/resource?a=1&b=2', | ||
|  |         host: 'example.com', | ||
|  |         port: 8080, | ||
|  |         ts: 1357718381034, | ||
|  |         nonce: 'd3d345f', | ||
|  |         hash: 'U4MKKSmiVxk37JCCrAVIjV/OhB3y+NdwoCr6RShbVkE=', | ||
|  |         ext: 'app-specific-data', | ||
|  |         app: 'hf48hd83qwkj',                        // Application id (Oz)
 | ||
|  |         dlg: 'd8djwekds9cj'                         // Delegated by application id (Oz), requires options.app
 | ||
|  |     } | ||
|  | */ | ||
|  | 
 | ||
|  | exports.calculateMac = function (type, credentials, options) { | ||
|  | 
 | ||
|  |     var normalized = exports.generateNormalizedString(type, options); | ||
|  | 
 | ||
|  |     var hmac = Crypto.createHmac(credentials.algorithm, credentials.key).update(normalized); | ||
|  |     var digest = hmac.digest('base64'); | ||
|  |     return digest; | ||
|  | }; | ||
|  | 
 | ||
|  | 
 | ||
|  | exports.generateNormalizedString = function (type, options) { | ||
|  | 
 | ||
|  |     var resource = options.resource || ''; | ||
|  |     if (resource && | ||
|  |         resource[0] !== '/') { | ||
|  | 
 | ||
|  |         var url = Url.parse(resource, false); | ||
|  |         resource = url.path;                        // Includes query
 | ||
|  |     } | ||
|  | 
 | ||
|  |     var normalized = 'hawk.' + exports.headerVersion + '.' + type + '\n' + | ||
|  |                      options.ts + '\n' + | ||
|  |                      options.nonce + '\n' + | ||
|  |                      (options.method || '').toUpperCase() + '\n' + | ||
|  |                      resource + '\n' + | ||
|  |                      options.host.toLowerCase() + '\n' + | ||
|  |                      options.port + '\n' + | ||
|  |                      (options.hash || '') + '\n'; | ||
|  | 
 | ||
|  |     if (options.ext) { | ||
|  |         normalized += options.ext.replace('\\', '\\\\').replace('\n', '\\n'); | ||
|  |     } | ||
|  | 
 | ||
|  |     normalized += '\n'; | ||
|  | 
 | ||
|  |     if (options.app) { | ||
|  |         normalized += options.app + '\n' + | ||
|  |                       (options.dlg || '') + '\n'; | ||
|  |     } | ||
|  | 
 | ||
|  |     return normalized; | ||
|  | }; | ||
|  | 
 | ||
|  | 
 | ||
|  | exports.calculatePayloadHash = function (payload, algorithm, contentType) { | ||
|  | 
 | ||
|  |     var hash = exports.initializePayloadHash(algorithm, contentType); | ||
|  |     hash.update(payload || ''); | ||
|  |     return exports.finalizePayloadHash(hash); | ||
|  | }; | ||
|  | 
 | ||
|  | 
 | ||
|  | exports.initializePayloadHash = function (algorithm, contentType) { | ||
|  | 
 | ||
|  |     var hash = Crypto.createHash(algorithm); | ||
|  |     hash.update('hawk.' + exports.headerVersion + '.payload\n'); | ||
|  |     hash.update(Utils.parseContentType(contentType) + '\n'); | ||
|  |     return hash; | ||
|  | }; | ||
|  | 
 | ||
|  | 
 | ||
|  | exports.finalizePayloadHash = function (hash) { | ||
|  | 
 | ||
|  |     hash.update('\n'); | ||
|  |     return hash.digest('base64'); | ||
|  | }; | ||
|  | 
 | ||
|  | 
 | ||
|  | exports.calculateTsMac = function (ts, credentials) { | ||
|  | 
 | ||
|  |     var hmac = Crypto.createHmac(credentials.algorithm, credentials.key); | ||
|  |     hmac.update('hawk.' + exports.headerVersion + '.ts\n' + ts + '\n'); | ||
|  |     return hmac.digest('base64'); | ||
|  | }; | ||
|  | 
 | ||
|  | 
 | ||
|  | exports.timestampMessage = function (credentials, localtimeOffsetMsec) { | ||
|  | 
 | ||
|  |     var now = Utils.nowSecs(localtimeOffsetMsec); | ||
|  |     var tsm = exports.calculateTsMac(now, credentials); | ||
|  |     return { ts: now, tsm: tsm }; | ||
|  | }; |