crypto.js 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. 'use strict';
  2. // Load modules
  3. const Crypto = require('crypto');
  4. const Url = require('url');
  5. const Utils = require('./utils');
  6. // Declare internals
  7. const internals = {};
  8. // MAC normalization format version
  9. exports.headerVersion = '1'; // Prevent comparison of mac values generated with different normalized string formats
  10. // Supported HMAC algorithms
  11. exports.algorithms = ['sha1', 'sha256'];
  12. // Calculate the request MAC
  13. /*
  14. type: 'header', // 'header', 'bewit', 'response'
  15. credentials: {
  16. key: 'aoijedoaijsdlaksjdl',
  17. algorithm: 'sha256' // 'sha1', 'sha256'
  18. },
  19. options: {
  20. method: 'GET',
  21. resource: '/resource?a=1&b=2',
  22. host: 'example.com',
  23. port: 8080,
  24. ts: 1357718381034,
  25. nonce: 'd3d345f',
  26. hash: 'U4MKKSmiVxk37JCCrAVIjV/OhB3y+NdwoCr6RShbVkE=',
  27. ext: 'app-specific-data',
  28. app: 'hf48hd83qwkj', // Application id (Oz)
  29. dlg: 'd8djwekds9cj' // Delegated by application id (Oz), requires options.app
  30. }
  31. */
  32. exports.calculateMac = function (type, credentials, options) {
  33. const normalized = exports.generateNormalizedString(type, options);
  34. const hmac = Crypto.createHmac(credentials.algorithm, credentials.key).update(normalized);
  35. const digest = hmac.digest('base64');
  36. return digest;
  37. };
  38. exports.generateNormalizedString = function (type, options) {
  39. let resource = options.resource || '';
  40. if (resource &&
  41. resource[0] !== '/') {
  42. const url = Url.parse(resource, false);
  43. resource = url.path; // Includes query
  44. }
  45. let normalized = 'hawk.' + exports.headerVersion + '.' + type + '\n' +
  46. options.ts + '\n' +
  47. options.nonce + '\n' +
  48. (options.method || '').toUpperCase() + '\n' +
  49. resource + '\n' +
  50. options.host.toLowerCase() + '\n' +
  51. options.port + '\n' +
  52. (options.hash || '') + '\n';
  53. if (options.ext) {
  54. normalized = normalized + options.ext.replace('\\', '\\\\').replace('\n', '\\n');
  55. }
  56. normalized = normalized + '\n';
  57. if (options.app) {
  58. normalized = normalized + options.app + '\n' +
  59. (options.dlg || '') + '\n';
  60. }
  61. return normalized;
  62. };
  63. exports.calculatePayloadHash = function (payload, algorithm, contentType) {
  64. const hash = exports.initializePayloadHash(algorithm, contentType);
  65. hash.update(payload || '');
  66. return exports.finalizePayloadHash(hash);
  67. };
  68. exports.initializePayloadHash = function (algorithm, contentType) {
  69. const hash = Crypto.createHash(algorithm);
  70. hash.update('hawk.' + exports.headerVersion + '.payload\n');
  71. hash.update(Utils.parseContentType(contentType) + '\n');
  72. return hash;
  73. };
  74. exports.finalizePayloadHash = function (hash) {
  75. hash.update('\n');
  76. return hash.digest('base64');
  77. };
  78. exports.calculateTsMac = function (ts, credentials) {
  79. const hmac = Crypto.createHmac(credentials.algorithm, credentials.key);
  80. hmac.update('hawk.' + exports.headerVersion + '.ts\n' + ts + '\n');
  81. return hmac.digest('base64');
  82. };
  83. exports.timestampMessage = function (credentials, localtimeOffsetMsec) {
  84. const now = Utils.nowSecs(localtimeOffsetMsec);
  85. const tsm = exports.calculateTsMac(now, credentials);
  86. return { ts: now, tsm };
  87. };