crypto.js
3.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
// 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 };
};