UNPKG

2.75 kBJavaScriptView Raw
1'use strict'
2
3var crypto = require('crypto')
4
5function randomString (size) {
6 var bits = (size + 1) * 6
7 var buffer = crypto.randomBytes(Math.ceil(bits / 8))
8 var string = buffer.toString('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '')
9 return string.slice(0, size)
10}
11
12function calculatePayloadHash (payload, algorithm, contentType) {
13 var hash = crypto.createHash(algorithm)
14 hash.update('hawk.1.payload\n')
15 hash.update((contentType ? contentType.split(';')[0].trim().toLowerCase() : '') + '\n')
16 hash.update(payload || '')
17 hash.update('\n')
18 return hash.digest('base64')
19}
20
21exports.calculateMac = function (credentials, opts) {
22 var normalized = 'hawk.1.header\n' +
23 opts.ts + '\n' +
24 opts.nonce + '\n' +
25 (opts.method || '').toUpperCase() + '\n' +
26 opts.resource + '\n' +
27 opts.host.toLowerCase() + '\n' +
28 opts.port + '\n' +
29 (opts.hash || '') + '\n'
30
31 if (opts.ext) {
32 normalized = normalized + opts.ext.replace('\\', '\\\\').replace('\n', '\\n')
33 }
34
35 normalized = normalized + '\n'
36
37 if (opts.app) {
38 normalized = normalized + opts.app + '\n' + (opts.dlg || '') + '\n'
39 }
40
41 var hmac = crypto.createHmac(credentials.algorithm, credentials.key).update(normalized)
42 var digest = hmac.digest('base64')
43 return digest
44}
45
46exports.header = function (uri, method, opts) {
47 var timestamp = opts.timestamp || Math.floor((Date.now() + (opts.localtimeOffsetMsec || 0)) / 1000)
48 var credentials = opts.credentials
49 if (!credentials || !credentials.id || !credentials.key || !credentials.algorithm) {
50 return ''
51 }
52
53 if (['sha1', 'sha256'].indexOf(credentials.algorithm) === -1) {
54 return ''
55 }
56
57 var artifacts = {
58 ts: timestamp,
59 nonce: opts.nonce || randomString(6),
60 method: method,
61 resource: uri.pathname + (uri.search || ''),
62 host: uri.hostname,
63 port: uri.port || (uri.protocol === 'http:' ? 80 : 443),
64 hash: opts.hash,
65 ext: opts.ext,
66 app: opts.app,
67 dlg: opts.dlg
68 }
69
70 if (!artifacts.hash && (opts.payload || opts.payload === '')) {
71 artifacts.hash = calculatePayloadHash(opts.payload, credentials.algorithm, opts.contentType)
72 }
73
74 var mac = exports.calculateMac(credentials, artifacts)
75
76 var hasExt = artifacts.ext !== null && artifacts.ext !== undefined && artifacts.ext !== ''
77 var header = 'Hawk id="' + credentials.id +
78 '", ts="' + artifacts.ts +
79 '", nonce="' + artifacts.nonce +
80 (artifacts.hash ? '", hash="' + artifacts.hash : '') +
81 (hasExt ? '", ext="' + artifacts.ext.replace(/\\/g, '\\\\').replace(/"/g, '\\"') : '') +
82 '", mac="' + mac + '"'
83
84 if (artifacts.app) {
85 header = header + ', app="' + artifacts.app + (artifacts.dlg ? '", dlg="' + artifacts.dlg : '') + '"'
86 }
87
88 return header
89}