3 var Crypto = require('crypto');
\r
4 var Url = require('url');
\r
5 var Utils = require('./utils');
\r
13 // MAC normalization format version
\r
15 exports.headerVersion = '1'; // Prevent comparison of mac values generated with different normalized string formats
\r
18 // Supported HMAC algorithms
\r
20 exports.algorithms = ['sha1', 'sha256'];
\r
23 // Calculate the request MAC
\r
26 type: 'header', // 'header', 'bewit', 'response'
\r
28 key: 'aoijedoaijsdlaksjdl',
\r
29 algorithm: 'sha256' // 'sha1', 'sha256'
\r
33 resource: '/resource?a=1&b=2',
\r
34 host: 'example.com',
\r
38 hash: 'U4MKKSmiVxk37JCCrAVIjV/OhB3y+NdwoCr6RShbVkE=',
\r
39 ext: 'app-specific-data',
\r
40 app: 'hf48hd83qwkj', // Application id (Oz)
\r
41 dlg: 'd8djwekds9cj' // Delegated by application id (Oz), requires options.app
\r
45 exports.calculateMac = function (type, credentials, options) {
\r
47 var normalized = exports.generateNormalizedString(type, options);
\r
49 var hmac = Crypto.createHmac(credentials.algorithm, credentials.key).update(normalized);
\r
50 var digest = hmac.digest('base64');
\r
55 exports.generateNormalizedString = function (type, options) {
\r
57 var resource = options.resource || '';
\r
59 resource[0] !== '/') {
\r
61 var url = Url.parse(resource, false);
\r
62 resource = url.path; // Includes query
\r
65 var normalized = 'hawk.' + exports.headerVersion + '.' + type + '\n' +
\r
67 options.nonce + '\n' +
\r
68 (options.method || '').toUpperCase() + '\n' +
\r
70 options.host.toLowerCase() + '\n' +
\r
71 options.port + '\n' +
\r
72 (options.hash || '') + '\n';
\r
75 normalized += options.ext.replace('\\', '\\\\').replace('\n', '\\n');
\r
81 normalized += options.app + '\n' +
\r
82 (options.dlg || '') + '\n';
\r
89 exports.calculatePayloadHash = function (payload, algorithm, contentType) {
\r
91 var hash = exports.initializePayloadHash(algorithm, contentType);
\r
92 hash.update(payload || '');
\r
93 return exports.finalizePayloadHash(hash);
\r
97 exports.initializePayloadHash = function (algorithm, contentType) {
\r
99 var hash = Crypto.createHash(algorithm);
\r
100 hash.update('hawk.' + exports.headerVersion + '.payload\n');
\r
101 hash.update(Utils.parseContentType(contentType) + '\n');
\r
106 exports.finalizePayloadHash = function (hash) {
\r
109 return hash.digest('base64');
\r
113 exports.calculateTsMac = function (ts, credentials) {
\r
115 var hmac = Crypto.createHmac(credentials.algorithm, credentials.key);
\r
116 hmac.update('hawk.' + exports.headerVersion + '.ts\n' + ts + '\n');
\r
117 return hmac.digest('base64');
\r
121 exports.timestampMessage = function (credentials, localtimeOffsetMsec) {
\r
123 var now = Utils.nowSecs(localtimeOffsetMsec);
\r
124 var tsm = exports.calculateTsMac(now, credentials);
\r
125 return { ts: now, tsm: tsm };
\r