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 };
							 | 
						||
| 
								 | 
							
								};
							 |