Socket
Socket
Sign inDemoInstall

hawk

Package Overview
Dependencies
Maintainers
1
Versions
85
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

hawk - npm Package Compare versions

Comparing version 0.3.0 to 0.4.0

58

lib/crypto.js

@@ -12,2 +12,7 @@ // Load modules

// MAC normalization format version
exports.headerVersion = '1'; // Prevent comparison of mac values generated with different normalized string formats
// Supported MAC algorithms

@@ -20,22 +25,25 @@

exports.calculateMAC = function (key, algorithm, timestamp, nonce, method, uri, host, port, ext) {
/*
options = {
header: 'core', // 'core', 'bewit'
key: 'aoijedoaijsdlaksjdl',
algorithm: 'hmac-sha-256', // 'hmac-sha-1', 'hmac-sha-256'
timestamp: 1357718381034,
nonce: 'd3d345f',
method: 'GET',
uri: '/resource?a=1&b=2',
host: 'example.com',
port: 8080,
ext: 'app-specific-data'
};
*/
// Parse request URI
exports.calculateMAC = function (options) {
var url = Url.parse(uri);
var normalized = exports.generateNormalizedString(options);
// Construct normalized req string
var normalized = timestamp + '\n' +
nonce + '\n' +
method.toUpperCase() + '\n' +
url.pathname + (url.search || '') + '\n' +
host.toLowerCase() + '\n' +
port + '\n' +
(ext || '') + '\n';
// Lookup hash function
var hashMethod = '';
switch (algorithm) {
switch (options.algorithm) {

@@ -49,3 +57,3 @@ case 'hmac-sha-1': hashMethod = 'sha1'; break;

var hmac = Crypto.createHmac(hashMethod, key).update(normalized);
var hmac = Crypto.createHmac(hashMethod, options.key).update(normalized);
var digest = hmac.digest('base64');

@@ -55,1 +63,21 @@ return digest;

exports.generateNormalizedString = function (options) {
// Parse request URI
var url = Url.parse(options.uri);
// Construct normalized req string
var normalized = options.header + '.' + exports.headerVersion + '\n' +
options.timestamp + '\n' +
options.nonce + '\n' +
options.method.toUpperCase() + '\n' +
url.pathname + (url.search || '') + '\n' + // Maintain trailing ?
options.host.toLowerCase() + '\n' +
options.port + '\n' +
(options.ext || '') + '\n';
return normalized;
};

@@ -186,3 +186,15 @@ // Load modules

var mac = Crypto.calculateMAC(credentials.key, credentials.algorithm, attributes.ts, attributes.nonce, req.method, req.url, host.name, host.port, attributes.ext);
var mac = Crypto.calculateMAC({
header: 'core',
key: credentials.key,
algorithm: credentials.algorithm,
timestamp: attributes.ts,
nonce: attributes.nonce,
method: req.method,
uri: req.url,
host: host.name,
port: host.port,
ext: attributes.ext
});
if (!Utils.fixedTimeComparison(mac, attributes.mac)) {

@@ -236,6 +248,17 @@ return callback(Err.unauthorized('Bad mac'), credentials, attributes.ext);

var timestamp = options.timestamp || Math.floor(now / 1000);
var nonce = options.nonce || Utils.randomString(6);
var mac = Crypto.calculateMAC(credentials.key, credentials.algorithm, timestamp, nonce, method, uri, host, port, options.ext);
var artifacts = {
header: 'core',
key: credentials.key,
algorithm: credentials.algorithm,
timestamp: options.timestamp || Math.floor(now / 1000),
nonce: options.nonce || Utils.randomString(6),
method: method,
uri: uri,
host: host,
port: port,
ext: options.ext
};
var mac = Crypto.calculateMAC(artifacts);
if (!mac) {

@@ -247,3 +270,3 @@ return '';

var header = 'Hawk id="' + credentials.id + '", ts="' + timestamp + '", nonce="' + nonce + (options.ext ? '", ext="' + Utils.escapeHeaderAttribute (options.ext) : '') + '", mac="' + mac + '"';
var header = 'Hawk id="' + credentials.id + '", ts="' + artifacts.timestamp + '", nonce="' + artifacts.nonce + (options.ext ? '", ext="' + Utils.escapeHeaderAttribute(options.ext) : '') + '", mac="' + mac + '"';
return header;

@@ -250,0 +273,0 @@ };

@@ -117,3 +117,15 @@ // Load modules

var mac = Crypto.calculateMAC(credentials.key, credentials.algorithm, bewit.exp, '', 'GET', url, host.name, host.port, bewit.ext);
var mac = Crypto.calculateMAC({
header: 'bewit',
key: credentials.key,
algorithm: credentials.algorithm,
timestamp: bewit.exp,
nonce: '',
method: 'GET',
uri: url,
host: host.name,
port: host.port,
ext: bewit.ext
});
if (!Utils.fixedTimeComparison(mac, bewit.mac)) {

@@ -159,3 +171,14 @@ return callback(Err.unauthorized('Bad mac'), credentials, bewit.ext);

var exp = Math.floor(now / 1000) + ttlSec;
var mac = Crypto.calculateMAC(credentials.key, credentials.algorithm, exp, '', 'GET', uri, host, port, options.ext);
var mac = Crypto.calculateMAC({
header: 'bewit',
key: credentials.key,
algorithm: credentials.algorithm,
timestamp: exp,
nonce: '',
method: 'GET',
uri: uri,
host: host,
port: port,
ext: options.ext
});

@@ -162,0 +185,0 @@ if (!mac) {

{
"name": "hawk",
"description": "HTTP Hawk Authentication Scheme",
"version": "0.3.0",
"version": "0.4.0",
"author": "Eran Hammer <eran@hueniverse.com> (http://hueniverse.com)",

@@ -6,0 +6,0 @@ "contributors": [],

@@ -6,3 +6,3 @@ ![hawk Logo](https://raw.github.com/hueniverse/hawk/master/images/hawk.png)

Current version: **0.3.0**
Current version: **0.4.0**

@@ -184,2 +184,3 @@ [![Build Status](https://secure.travis-ci.org/hueniverse/hawk.png)](http://travis-ci.org/hueniverse/hawk)

```
core.1
1353832234

@@ -194,2 +195,7 @@ j4h3g2

The 'core.1' normalized string header is used to prevent MAC values from being reused after a potential change in how the
protocol creates the normalized string. For example, if a future version would switch the order of nonce and timestamp, it
can create an exploit opportunity for cases where the nonce is similar in format to a timestamp. In addition, the header
prevents switching MAC values between a header request and a bewit request.
The request MAC is calculated using the specified algorithm "hmac-sha-256" and the key over the normalized request string.

@@ -199,3 +205,3 @@ The result is base64-encoded to produce the request MAC:

```
hpf5lg0G0rtKrT04CiRf0Q+IDjkGkyvKdMjtqu1XV/s=
/4mn/w+FiIx5GO0TtwLmseu2YQc3xUqRV9sJmNHqcG0=
```

@@ -209,3 +215,3 @@

Host: example.com:8000
Authorization: Hawk id="dh37fgj492je", ts="1353832234", ext="some-app-data", mac="hpf5lg0G0rtKrT04CiRf0Q+IDjkGkyvKdMjtqu1XV/s="
Authorization: Hawk id="dh37fgj492je", ts="1353832234", nonce="j4h3g2", ext="some-app-data", mac="/4mn/w+FiIx5GO0TtwLmseu2YQc3xUqRV9sJmNHqcG0="
```

@@ -420,3 +426,3 @@

It is really had to include other headers. Headers can be changed by proxies and other intermediaries and there is no
It is really hard to include other headers. Headers can be changed by proxies and other intermediaries and there is no
well-established way to normalize them. The only straight-forward solution is to include the headers in some blob (say,

@@ -423,0 +429,0 @@ bas64 encoded JSON) and include that with the request, an approach taken by JWT and other such formats. However, that

@@ -25,8 +25,57 @@ // Load modules

expect(Hawk.crypto.calculateMAC('dasdfasdf', 'hmac-sha-0', Date.now() / 1000, 'k3k4j5', 'GET', '/resource/something', 'example.com', 8080)).to.equal('');
expect(Hawk.crypto.calculateMAC({
header: 'core',
key: 'dasdfasdf',
algorithm: 'hmac-sha-0',
timestamp: Math.floor(Date.now() / 1000),
nonce: 'k3k4j5',
method: 'GET',
uri: '/resource/something',
host: 'example.com',
port: 8080
})).to.equal('');
done();
});
});
describe('#generateNormalizedString', function () {
it('should return a valid normalized string', function (done) {
expect(Hawk.crypto.generateNormalizedString({
header: 'core',
key: 'dasdfasdf',
algorithm: 'hmac-sha-256',
timestamp: 1357747017,
nonce: 'k3k4j5',
method: 'GET',
uri: '/resource/something',
host: 'example.com',
port: 8080
})).to.equal('core.1\n1357747017\nk3k4j5\nGET\n/resource/something\nexample.com\n8080\n\n');
done();
});
it('should return a valid normalized string (ext)', function (done) {
expect(Hawk.crypto.generateNormalizedString({
header: 'core',
key: 'dasdfasdf',
algorithm: 'hmac-sha-256',
timestamp: 1357747017,
nonce: 'k3k4j5',
method: 'GET',
uri: '/resource/something',
host: 'example.com',
port: 8080,
ext: 'this is some app data'
})).to.equal('core.1\n1357747017\nk3k4j5\nGET\n/resource/something\nexample.com\n8080\nthis is some app data\n');
done();
});
});
});
});

@@ -85,3 +85,3 @@ // Load modules

headers: {
authorization: 'Hawk id="1", ts="1353788437", nonce="k3j4h2", mac="qrP6b5tiS2CO330rpjUEym/USBM=", ext="hello"',
authorization: 'Hawk id="1", ts="1353788437", nonce="k3j4h2", mac="qk3onE3/tko0WylI4lQHMAra98A=", ext="hello"',
host: 'example.com:8080'

@@ -105,3 +105,3 @@ },

headers: {
authorization: 'Hawk id="dh37fgj492je", ts="1353832234", nonce="j4h3g2", mac="hpf5lg0G0rtKrT04CiRf0Q+IDjkGkyvKdMjtqu1XV/s=", ext="some-app-data"',
authorization: 'Hawk id="dh37fgj492je", ts="1353832234", nonce="j4h3g2", mac="/4mn/w+FiIx5GO0TtwLmseu2YQc3xUqRV9sJmNHqcG0=", ext="some-app-data"',
host: 'example.com:8000'

@@ -125,3 +125,3 @@ },

headers: {
authorization: 'Hawk id="dh37fgj492je", ts="1353832234", nonce="j4h3g2", mac="hpf5lg0G0rtKrT04CiRf0Q+IDjkGkyvKdMjtqu1XV/s=", ext="some-app-data"',
authorization: 'Hawk id="dh37fgj492je", ts="1353832234", nonce="j4h3g2", mac="/4mn/w+FiIx5GO0TtwLmseu2YQc3xUqRV9sJmNHqcG0=", ext="some-app-data"',
host: 'example.com:8000'

@@ -149,3 +149,3 @@ },

headers: {
authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="ZPa2zWC3WUAYXrwPzJ3DpF54xjQ2ZDLe8GF1ny6JJFI=", ext="hello"',
authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="WBOsuQGaxVMdLd3Gzz5WqsS2AB0l4VkpsvRWbfWzYK4=", ext="hello"',
host: 'example.com:8080'

@@ -622,3 +622,3 @@ },

var header = Hawk.getAuthorizationHeader(credentials, 'POST', '/somewhere/over/the/rainbow', 'example.net', 443, { ext: 'Bazinga!', timestamp: 1353809207, nonce: 'Ygvqdz' });
expect(header).to.equal('Hawk id="123456", ts="1353809207", nonce="Ygvqdz", ext="Bazinga!", mac="qSK1cZEkqPwE2ttBX8QSXxO+NE3epFMu4tyVpGKjdnU="');
expect(header).to.equal('Hawk id="123456", ts="1353809207", nonce="Ygvqdz", ext="Bazinga!", mac="VW+mnJDkcWbM+fgBBeJzfUkrKReXmcl9bRH9WY6qjPg="');
done();

@@ -625,0 +625,0 @@ });

@@ -65,3 +65,3 @@ // Load modules

method: 'GET',
url: '/resource/4?a=1&b=2&bewit=MTIzNDU2XDQ1MDk5OTE1ODJcRUQ0ZHJtYytVQzAvaFpYQWR0QzVYOFlaU1NHc2pLYWhjSDVDdEhYaFJZUT1cc29tZS1hcHAtZGF0YQ'
url: '/resource/4?a=1&b=2&bewit=MTIzNDU2XDQ1MTEzNDU4OTBcSTdWQWJqMWVtOG1vdmZLV1pLUVlvbEVlM2tsYkRlRU9yVllCYVdWMGdXRT1cc29tZS1hcHAtZGF0YQ'
};

@@ -85,3 +85,3 @@

method: 'GET',
url: '/resource/4?bewit=MTIzNDU2XDQ1MDk5OTE1ODJcRUQ0ZHJtYytVQzAvaFpYQWR0QzVYOFlaU1NHc2pLYWhjSDVDdEhYaFJZUT1cc29tZS1hcHAtZGF0YQ&a=1&b=2'
url: '/resource/4?bewit=MTIzNDU2XDQ1MTEzNDU4OTBcSTdWQWJqMWVtOG1vdmZLV1pLUVlvbEVlM2tsYkRlRU9yVllCYVdWMGdXRT1cc29tZS1hcHAtZGF0YQ&a=1&b=2'
};

@@ -105,3 +105,3 @@

method: 'GET',
url: '/resource/4?bewit=MTIzNDU2XDQ1MDk5OTE3MTlcTUE2eWkwRWRwR0pEcWRwb0JkYVdvVDJrL0hDSzA1T0Y3MkhuZlVmVy96Zz1cc29tZS1hcHAtZGF0YQ'
url: '/resource/4?bewit=MTIzNDU2XDQ1MTEzNDU5NjBcZlE5ejBiZUpzelIxMnkwR0tTYTFITEtKVm9OWVA3S0JLOVl2VXI5S0FvST1cc29tZS1hcHAtZGF0YQ'
};

@@ -132,3 +132,15 @@

var ext = 'some-app-data';
var mac = Hawk.crypto.calculateMAC(credentials.key, credentials.algorithm, exp, '', 'POST', req.url, 'example.com', 8080, ext);
var mac = Hawk.crypto.calculateMAC({
header: 'bewit',
key: credentials.key,
algorithm: credentials.algorithm,
timestamp: exp,
nonce: '',
method: 'POST',
uri: req.url,
host: 'example.com',
port: 8080,
ext: ext
});
var bewit = credentials.id + '\\' + exp + '\\' + mac + '\\' + ext;

@@ -375,3 +387,3 @@

var bewit = Hawk.uri.getBewit(credentials, '/somewhere/over/the/rainbow', 'example.com', 443, 300, { localtimeOffsetMsec: 1356420407232 - Date.now(), ext: 'xandyandz' });
expect(bewit).to.equal('MTIzNDU2XDEzNTY0MjA3MDdcT2U3TzF4ZXNSTE5GTEphODBEdGRsdlVGbURzc0RnQ0gwUDRsWWxSWWloWT1ceGFuZHlhbmR6');
expect(bewit).to.equal('MTIzNDU2XDEzNTY0MjA3MDdcTWEveU4wU2dsWWNBWmJCTEk2cDNvZEppWlVKR2VDTWcyZ043MkF3aVNwZz1ceGFuZHlhbmR6');
done();

@@ -378,0 +390,0 @@ });

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc