@tsmx/object-hmac
Advanced tools
Comparing version 1.0.1 to 1.1.0
const crypto = require('crypto'); | ||
const jt = require('@tsmx/json-traverse'); | ||
function createOrderedObjectString(obj) { | ||
let attributes = []; | ||
const callbacks = { | ||
processValue: (key, value, _level, path, _isObjectRoot, _isArrayElement, _cbSetValue) => { | ||
attributes.push((path.length > 0 ? (path.join('.') + '.') : '') + key + '=' + value); | ||
} | ||
}; | ||
jt.traverse(obj, callbacks); | ||
attributes.sort(); | ||
return attributes.join('|'); | ||
} | ||
function createHmac(obj, key, hmacAttribute = '__hmac') { | ||
@@ -10,3 +23,3 @@ const hmac = calculateHmac(obj, key); | ||
let hmac = crypto.createHmac('sha256', key); | ||
hmac.update(JSON.stringify(obj)); | ||
hmac.update(createOrderedObjectString(obj)); | ||
return hmac.digest('hex'); | ||
@@ -13,0 +26,0 @@ } |
{ | ||
"name": "@tsmx/object-hmac", | ||
"version": "1.0.1", | ||
"version": "1.1.0", | ||
"description": "Create and verify HMAC's for JSON objects", | ||
@@ -17,3 +17,3 @@ "author": "tsmx <dev@tsmx.net>", | ||
"type": "git", | ||
"url": "git+https://github.com/tsmx/object-hmac.git" | ||
"url": "https://github.com/tsmx/object-hmac.git" | ||
}, | ||
@@ -30,3 +30,6 @@ "license": "MIT", | ||
"jest": "^26.6.3" | ||
}, | ||
"dependencies": { | ||
"@tsmx/json-traverse": "^1.0.3" | ||
} | ||
} |
@@ -11,4 +11,6 @@ # [**@tsmx/object-hmac**](https://github.com/tsmx/object-hmac) | ||
Easily create and verify [HMAC's](https://en.wikipedia.org/wiki/HMAC) for your JSON objects to ensure data integrity and authenticity. | ||
Easily create and verify [keyed-hash message authentication codes (HMAC's)](https://en.wikipedia.org/wiki/HMAC) for your JSON objects to ensure data integrity and authenticity. | ||
Users of a version prior to v1.1.0 please see the [important note](#note-for-users-of-older-versions). | ||
## Usage | ||
@@ -102,2 +104,4 @@ | ||
The verification would not fail, just because the JSON's attributes order has changed. For more details see [calculateHmac](#calculateHmacobj-key). | ||
#### obj | ||
@@ -128,2 +132,24 @@ | ||
The calculation of the HMAC is independent of the order of your JSON's attributes. This means that the HMAC of content-identical objects with just another order of attributes will always by the same. | ||
```js | ||
let person = { | ||
name: 'Max', | ||
age: 32, | ||
hobbies: ['sports', 'travelling'] | ||
}; | ||
let hmac = objectHmac.calculateHmac(person, key); | ||
let person2 = { | ||
age: 32, | ||
hobbies: ['sports', 'travelling'], | ||
name: 'Max' | ||
}; | ||
let hmac2 = objectHmac.calculateHmac(person, key); | ||
/// hmac === hmac2 | ||
``` | ||
#### obj | ||
@@ -149,3 +175,10 @@ | ||
To provide a stable (attribute-order independent) representation of the JSON object, a sorted traversal using the library [@tsmx/json-traverse](https://www.npmjs.com/package/@tsmx/json-traverse) is used. | ||
### Note for users of older versions | ||
Prior to v1.1.0 the algorithm used to generate the JSON's representation for the HMAC generation didn't to 100% guarantee a deterministic behaviour which could in some cases result in a failing verification although it should succeed. | ||
Therefore it is **strongly recommended** to update to version 1.1.0 or higher. If you have any HMAC's persistently stored which where generated with a 1.0.x version you must re-calculate them with v1.1.0 or higher when upgrading. | ||
## Test | ||
@@ -152,0 +185,0 @@ |
@@ -6,3 +6,3 @@ describe('object-hmac test suite', () => { | ||
const testKeyBroken = 'HmacSecret-4711'; | ||
const testHmac = 'bb83e36f2c030af71803fd6a82b49ea638944bb6638351754a967f4f5638ac3b'; | ||
const testHmac = 'd5d182ef5b153107defbe4f96583c03ec3bd154ba38ca7ac41d0975eb15215c7'; | ||
const testHmacAttribute = '__hmac'; | ||
@@ -17,2 +17,13 @@ const testHmacAttributeDifferent = '_signature'; | ||
it('tests a successful HMAC creation and verification - end-to-end', async (done) => { | ||
let person = { | ||
name: 'Max', | ||
age: 32 | ||
} | ||
objectHmac.createHmac(person, testKey); | ||
expect(person[testHmacAttribute]).toBeDefined(); | ||
expect(objectHmac.verifyHmac(person, testKey)).toBeTruthy(); | ||
done(); | ||
}); | ||
it('tests a successful HMAC calculation', async (done) => { | ||
@@ -45,2 +56,26 @@ const hmac = objectHmac.calculateHmac(testObjects.testObject, testKey); | ||
it('test a successful HMAC verification - JSON with changed attribute order', async (done) => { | ||
expect(objectHmac.verifyHmac(testObjects.testObjectWithHmacChangedOrder, testKey)).toBeTruthy(); | ||
done(); | ||
}); | ||
it('test a successful HMAC verification - JSON with changed attribute order in a subobject', async (done) => { | ||
expect(objectHmac.verifyHmac(testObjects.testObjectWithHmacChangedSubobjectOrder, testKey)).toBeTruthy(); | ||
done(); | ||
}); | ||
it('test a successful HMAC verification - JSON loaded from a file via require', async (done) => { | ||
let testObj = require('./testobject'); | ||
expect(objectHmac.verifyHmac(testObj, testKey)).toBeTruthy(); | ||
done(); | ||
}); | ||
it('test a successful HMAC verification - JSON loaded from a file via fs', async (done) => { | ||
let fs = require('fs'); | ||
let path = require('path'); | ||
let testObj = JSON.parse(fs.readFileSync(path.resolve(__dirname, 'testobject.json'), 'utf8')); | ||
expect(objectHmac.verifyHmac(testObj, testKey)).toBeTruthy(); | ||
done(); | ||
}); | ||
it('test a successful HMAC verification with a different attribute name', async (done) => { | ||
@@ -47,0 +82,0 @@ expect(objectHmac.verifyHmac(testObjects.testObjectWithHmacDifferentAttribute, testKey, testHmacAttributeDifferent)).toBeTruthy(); |
@@ -21,5 +21,29 @@ module.exports.testObject = | ||
}, | ||
__hmac: 'bb83e36f2c030af71803fd6a82b49ea638944bb6638351754a967f4f5638ac3b' | ||
__hmac: 'd5d182ef5b153107defbe4f96583c03ec3bd154ba38ca7ac41d0975eb15215c7' | ||
} | ||
module.exports.testObjectWithHmacChangedOrder = | ||
{ | ||
title: 'Test-Object', | ||
subObject: { | ||
name: 'Max', | ||
age: 32, | ||
hobbies: ['sports', 'travelling'] | ||
}, | ||
numbers: [1, 12, 123], | ||
__hmac: 'd5d182ef5b153107defbe4f96583c03ec3bd154ba38ca7ac41d0975eb15215c7' | ||
} | ||
module.exports.testObjectWithHmacChangedSubobjectOrder = | ||
{ | ||
title: 'Test-Object', | ||
numbers: [1, 12, 123], | ||
subObject: { | ||
name: 'Max', | ||
hobbies: ['sports', 'travelling'], | ||
age: 32 | ||
}, | ||
__hmac: 'd5d182ef5b153107defbe4f96583c03ec3bd154ba38ca7ac41d0975eb15215c7' | ||
} | ||
module.exports.testObjectWithHmacDifferentAttribute = | ||
@@ -34,3 +58,3 @@ { | ||
}, | ||
_signature: 'bb83e36f2c030af71803fd6a82b49ea638944bb6638351754a967f4f5638ac3b' | ||
_signature: 'd5d182ef5b153107defbe4f96583c03ec3bd154ba38ca7ac41d0975eb15215c7' | ||
} | ||
@@ -47,3 +71,3 @@ | ||
}, | ||
__hmac: 'bb83e36f2c030af71803fd6a82b49ea638944bb6638351754a967f4f5638ac3b' | ||
__hmac: 'd5d182ef5b153107defbe4f96583c03ec3bd154ba38ca7ac41d0975eb15215c7' | ||
} | ||
@@ -61,3 +85,3 @@ | ||
}, | ||
__hmac: 'bb83e36f2c030af71803fd6a82b49ea638944bb6638351754a967f4f5638ac3b' | ||
__hmac: 'd5d182ef5b153107defbe4f96583c03ec3bd154ba38ca7ac41d0975eb15215c7' | ||
} | ||
@@ -73,3 +97,3 @@ | ||
}, | ||
__hmac: 'bb83e36f2c030af71803fd6a82b49ea638944bb6638351754a967f4f5638ac3b' | ||
__hmac: 'd5d182ef5b153107defbe4f96583c03ec3bd154ba38ca7ac41d0975eb15215c7' | ||
} | ||
@@ -79,3 +103,3 @@ | ||
{ | ||
title: 'Test-ObjectX', | ||
title: 'Test-Object', | ||
numbers: [1, 12, 123], | ||
@@ -87,3 +111,3 @@ subObject: { | ||
}, | ||
__hmac: 'bb83e36f2c030af71803fd6a82b49ea638944bb6638351754a967f4f5638aczz' | ||
__hmac: 'd5d182ef5b153107defbe4f96583c03ec3bd154ba38ca7ac41d0975eb1521xxx' | ||
} |
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Deprecated
MaintenanceThe maintainer of the package marked it as deprecated. This could indicate that a single version should not be used, or that the package is no longer maintained and any new vulnerabilities will not be fixed.
Found 1 instance in 1 package
16810
8
239
0
185
1
1
+ Added@tsmx/json-traverse@^1.0.3
+ Added@tsmx/json-traverse@1.0.8(transitive)