123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129 |
- 'use strict';
- // Load modules
- const Crypto = require('crypto');
- const Url = require('url');
- const Utils = require('./utils');
- // Declare internals
- const 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) {
- const normalized = exports.generateNormalizedString(type, options);
- const hmac = Crypto.createHmac(credentials.algorithm, credentials.key).update(normalized);
- const digest = hmac.digest('base64');
- return digest;
- };
- exports.generateNormalizedString = function (type, options) {
- let resource = options.resource || '';
- if (resource &&
- resource[0] !== '/') {
- const url = Url.parse(resource, false);
- resource = url.path; // Includes query
- }
- let 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 = normalized + options.ext.replace('\\', '\\\\').replace('\n', '\\n');
- }
- normalized = normalized + '\n';
- if (options.app) {
- normalized = normalized + options.app + '\n' +
- (options.dlg || '') + '\n';
- }
- return normalized;
- };
- exports.calculatePayloadHash = function (payload, algorithm, contentType) {
- const hash = exports.initializePayloadHash(algorithm, contentType);
- hash.update(payload || '');
- return exports.finalizePayloadHash(hash);
- };
- exports.initializePayloadHash = function (algorithm, contentType) {
- const 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) {
- const 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) {
- const now = Utils.nowSecs(localtimeOffsetMsec);
- const tsm = exports.calculateTsMac(now, credentials);
- return { ts: now, tsm };
- };
|