Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

argon2

Package Overview
Dependencies
Maintainers
1
Versions
78
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

argon2 - npm Package Compare versions

Comparing version 0.8.0 to 0.9.0

src/argon2_node.h

33

argon2/README.md
# Argon2
[![Build Status](https://travis-ci.org/P-H-C/phc-winner-argon2.svg?branch=master)](https://travis-ci.org/P-H-C/phc-winner-argon2)
[![codecov.io](https://codecov.io/github/P-H-C/phc-winner-argon2/coverage.svg?branch=master)](https://codecov.io/github/P-H-C/phc-winner-argon2?branch=master)
This is the reference C implementation of Argon2, the password-hashing

@@ -7,11 +10,21 @@ function that won the [Password Hashing Competition

You should use Argon2 whenever you need to hash passwords for credential
storage, key derivation, or other applications.
Argon2 is a password-hashing function that summarizes the state of the
art in the design of memory-hard functions and can be used to hash
passwords for credential storage, key derivation, or other applications.
There are two main versions of Argon2, **Argon2i** and **Argon2d**. Argon2i
is the safest against side-channel attacks, while Argon2d provides the
highest resistance against GPU cracking attacks.
It has a simple design aimed at the highest memory filling rate and
effective use of multiple computing units, while still providing defense
against tradeoff attacks (by exploiting the cache and memory organization
of the recent processors).
Argon2i and Argon2d are parametrized by
Argon2 has two variants: Argon2d and Argon2i. Argon2d is faster and
uses data-depending memory access, which makes it highly resistant
against GPU cracking attacks and suitable for applications with no threats
from side-channel timing attacks (eg. cryptocurrencies). Argon2i instead
uses data-independent memory access, which is preferred for password
hashing and password-based key derivation, but it is slower as it makes
more passes over the memory to protect from tradeoff attacks.
Argon2i and Argon2d are parametrized by:
* A **time** cost, which defines the amount of computation realized and

@@ -198,2 +211,10 @@ therefore the execution time, given in number of iterations

## Test Suite
There are two sets of test suites. One is a low level test for the hash
function, the other tests the higher level API. Both of these are built and
executed by running:
`make test`
## Intellectual property

@@ -200,0 +221,0 @@

132

index.js

@@ -11,3 +11,5 @@ const bindings = require('bindings')('argon2');

const fail = (message, callback) => {
const limits = Object.freeze(bindings.limits);
const fail = (message, reject) => {
'use strict';

@@ -17,58 +19,36 @@

if (typeof callback === 'undefined') {
if (typeof reject === 'function') {
process.nextTick(reject.bind(null, error));
} else {
throw error;
} else {
process.nextTick(() => {
callback(error, null);
});
}
};
const validate = (salt, options, callback) => {
const validate = (salt, options, resolve, reject) => {
'use strict';
if (salt.length !== 16) {
fail('Invalid salt length, must be 16 bytes.', callback);
if (!Buffer.isBuffer(salt) || salt.length < 8) {
fail('Invalid salt, must be a buffer with 8 or more bytes.', reject);
return false;
}
for (const key of Object.keys(defaults)) {
options[key] = options[key] || defaults[key];
if (options.parallelism === 'auto') {
options.parallelism = require('os').cpus().length;
}
if (isNaN(options.timeCost)) {
fail('Invalid time cost, must be a number.', callback);
return false;
} else if (options.timeCost <= 0) {
fail('Time cost too low, minimum of 1.', callback);
return false;
} else if (options.timeCost >= 4294967296) {
fail('Time cost too high, maximum of 4294967295.', callback);
return false;
// TODO: replace var with const https://github.com/tapjs/node-tap/issues/236
for (var key of Object.keys(limits)) {
var max = limits[key].max;
var min = limits[key].min;
var value = options[key];
if (!Number.isInteger(value) || value > max || value < min) {
fail(`Invalid ${key}, must be an integer between ${min} and ${max}.`, reject);
return false;
}
}
if (isNaN(options.memoryCost)) {
fail('Invalid memory cost, must be a number.', callback);
return false;
} else if (options.memoryCost <= 0) {
fail('Memory cost too low, minimum of 1.', callback);
return false;
} else if (options.memoryCost >= 32) {
fail('Memory cost too high, maximum of 31.', callback);
return false;
if (typeof resolve === 'function') {
resolve();
}
if (isNaN(options.parallelism)) {
fail('Invalid parallelism, must be a number.', callback);
return false;
} else if (options.parallelism <= 0) {
fail('Parallelism too low, minimum of 1.', callback);
return false;
} else if (options.parallelism >= 4294967296) {
fail('Parallelism too high, maximum of 4294967295.', callback);
return false;
}
options.argon2d = !!options.argon2d;
return true;

@@ -78,33 +58,28 @@ };

module.exports = {
defaults,
defaults, limits,
hash (plain, salt, options, callback) {
hash(plain, salt, options) {
'use strict';
if (!Buffer.isBuffer(salt)) {
salt = new Buffer(salt);
}
options = Object.assign({}, defaults, options);
if (!callback) {
callback = options;
options = defaults;
if (!Buffer.isBuffer(plain)) {
plain = new Buffer(plain);
}
options = Object.assign({}, options);
if (validate(salt, options, callback)) {
return bindings.hash(plain, salt, options.timeCost, options.memoryCost,
options.parallelism, options.argon2d, callback);
}
return new Promise(validate.bind(null, salt, options))
.then(bindings.hash.bind(null, plain, salt, options.timeCost,
options.memoryCost, options.parallelism, options.argon2d));
},
hashSync (plain, salt, options) {
hashSync(plain, salt, options) {
'use strict';
if (!Buffer.isBuffer(salt)) {
salt = new Buffer(salt);
console.warn('The synchronous API is deprecated, use ES6 await instead.');
options = Object.assign({}, defaults, options);
if (!Buffer.isBuffer(plain)) {
plain = new Buffer(plain);
}
options = Object.assign({}, options || defaults);
if (validate(salt, options)) {

@@ -116,25 +91,46 @@ return bindings.hashSync(plain, salt, options.timeCost,

generateSalt (callback) {
generateSalt(length) {
'use strict';
return crypto.randomBytes(16, callback);
length = typeof length === 'undefined' ? 16 : length;
return new Promise((resolve, reject) => {
crypto.randomBytes(length, (err, salt) => {
/* istanbul ignore if */
if (err) {
return reject(err);
}
return resolve(salt);
});
});
},
generateSaltSync () {
generateSaltSync(length) {
'use strict';
return crypto.randomBytes(16);
console.warn('The synchronous API is deprecated, use ES6 await instead.');
length = typeof length === 'undefined' ? 16 : length;
return crypto.randomBytes(length);
},
verify (hash, plain, callback) {
verify(hash, plain) {
'use strict';
return bindings.verify(hash, plain, /argon2d/.test(hash), callback);
if (!Buffer.isBuffer(plain)) {
plain = new Buffer(plain);
}
return bindings.verify(hash, plain, /argon2d/.test(hash));
},
verifySync (hash, plain) {
verifySync(hash, plain) {
'use strict';
console.warn('The synchronous API is deprecated, use ES6 await instead.');
if (!Buffer.isBuffer(plain)) {
plain = new Buffer(plain);
}
return bindings.verifySync(hash, plain, /argon2d/.test(hash));
}
};
{
"name": "argon2",
"version": "0.8.0",
"version": "0.9.0",
"description": "An Argon2 library for Node",

@@ -9,3 +9,3 @@ "main": "index.js",

"clean": "node-gyp clean",
"test": "nodeunit test.spec.js"
"test": "xo && tap test.spec.js --reporter=list"
},

@@ -36,7 +36,11 @@ "repository": {

"async-benchmark": "^1.0.1",
"nodeunit": "^0.9.1"
"tap": "^5.7.0",
"xo": "^0.12.1"
},
"engines": {
"node": ">=4.0.0"
"node": ">=4.0.0"
},
"xo": {
"space": 2
}
}
# node-argon2 [![NPM package][npm-image]][npm-url] [![Build status][travis-image]][travis-url] [![Coverage status][coverage-image]][coverage-url] [![Code Quality][codequality-image]][codequality-url] [![Dependencies][david-dm-image]][david-dm-url]
Bindings to the reference [Argon2](https://github.com/P-H-C/phc-winner-argon2)
Bindings to the reference [Argon2](https://github.com/P-H-C/phc-winner-argon2)
implementation.

@@ -12,15 +12,13 @@

and async, and to verify if a password matches a hash, and also generate random
cryptographically-safe salts. Salts **must** be exactly 16-byte long buffers
but strings will automatically be converted (this is **deprecated** and should
NOT be relied upon).
cryptographically-safe salts. Salts **must** be at least 8-byte long buffers.
To hash a password:
```js
var argon2 = require('argon2');
const argon2 = require('argon2');
const salt = new Buffer('somesalt');
argon2.hash('password', 'somesalt', function (err, hash) {
if (err) // hashing failure
throw err;
doSomethingWith(hash);
argon2.hash('password', salt).then(hash => {
// ...
}).catch(err => {
// ...
});

@@ -31,16 +29,21 @@

try {
var hash = argon2.hashSync('password', 'somesaltwith16ch');
const hash = argon2.hashSync('password', salt);
} catch (err) {
console.log(err);
//...
}
// ES6
try {
const hash = await argon2.hash('password', salt);
} catch (err) {
//...
}
```
Resultant hashes will be 90 characters long. You can choose between Argon2i and
Argon2d by passing an object as the third argument with the `argon2d` key set to
whether or not you want Argon2d:
You can choose between Argon2i and Argon2d by passing an object as the third
argument with the `argon2d` key set to whether or not you want Argon2d:
```js
var argon2 = require('argon2');
argon2.hash('password', 'somesalt', {
argon2.hash('password', salt, {
argon2d: true
}, function (err, hash) {
}.then(hash => {
// ...

@@ -52,3 +55,3 @@ });

try {
var hash = argon2.hashSync('password', 'somesaltwith16ch', {
const hash = argon2.hashSync('password', salt, {
argon2d: true

@@ -59,12 +62,21 @@ });

}
// ES6
try {
const hash = await argon2.hash('password', salt, {
argon2d: true
});
} catch (err) {
// ...
}
```
The `argon2d` option is flexible and accepts any truthy or falsy values.
You can provide your own salt as the second parameter. It is recommended to use
the salt generating methods instead of a hardcoded, constant salt:
You can provide your own salt as the second parameter. It is **highly**
recommended to use the salt generating methods instead of a hardcoded, constant
salt:
```js
var argon2 = require('argon2');
argon2.generateSalt(function (err, salt) {
doSomethingWith(salt);
argon2.generateSalt().then(salt => {
// ...
});

@@ -75,4 +87,26 @@

var salt = argon2.generateSaltSync();
// ES6
const salt = await argon2.generateSalt();
```
You can also pass a desired salt length as parameter. Although the default of 16
is enough and very safe, Argon2 will use all salt bytes.
```js
argon2.generateSalt(32).then(salt => {
// ...
});
// OR
var salt = argon2.generateSaltSync(32);
// ES6
const salt = await argon2.generateSalt(32);
```
Please keep in mind synchronous salt generation is blocking, since it waits for
entropy when enough is not available, so please refrain from using sync version.
You can also modify time, memory and parallelism constraints passing the object

@@ -82,8 +116,8 @@ as the third parameter, with keys `timeCost`, `memoryCost` and `parallelism`,

```js
var argon2 = require('argon2');
const options = {
timeCost: 4, memoryCost: 13, parallelism: 2, argon2d: true
};
argon2.generateSalt(function (err, salt) {
argon2.hash('password', salt, {
timeCost: 4, memoryCost: 13, parallelism: 2
}, function (err, hash) {
argon2.generateSalt().then(salt => {
argon2.hash('password', salt, options).then(hash => {
// ...

@@ -95,5 +129,7 @@ });

var hash = argon2.hashSync('password', argon2.generateSaltSync(), {
timeCost: 4, memoryCost: 13, parallelism: 2
});
var hash = argon2.hashSync('password', argon2.generateSaltSync(), options);
// ES6
var hash = await argon2.hash('password', await argon2.generateSalt(), options);
```

@@ -103,4 +139,2 @@

```js
var argon2 = require('argon2');
console.log(argon2.defaults);

@@ -112,9 +146,6 @@ // => { timeCost: 3, memoryCost: 12, parallelism: 1, argon2d: false }

```js
var argon2 = require('argon2');
argon2.verify('<big long hash>', 'password', function (err) {
if (err) // password did not match
throw err;
authenticate();
argon2.verify('<big long hash>', 'password').then(() => {
// password match
}).catch(() => {
// password did not match
});

@@ -125,6 +156,15 @@

if (argon2.verifySync('<big long hash>', 'password')) {
authenticate();
// password match
} else {
fail();
// password did not match
}
// ES6
try {
await argon2.verify('<big long hash>', 'password');
// password match
} catch (err) {
// password did not match
}
```

@@ -131,0 +171,0 @@ First parameter must have been generated by an Argon2 encoded hashing method,

@@ -1,635 +0,671 @@

const argon2 = process.env.COVERAGE
? require('./index-cov')
: require('./index');
const argon2 = require('./index');
const t = require('tap');
const password = 'password';
const salt = new Buffer(16);
salt.fill(0).write('somesalt');
const salt = new Buffer('somesalt');
const saltWithNull = new Buffer('\0abcdefghijklmno');
module.exports = {
testDefaults (assert) {
'use strict';
// Like argon2's modified base64 implementation, this function truncates any
// trailing '=' characters for a more compact representation.
const truncatedBase64 = (buffer) => {
return buffer.toString('base64').replace(/\=*$/, '');
};
assert.expect(1);
// hashes for argon2i and argon2d with default options
const hashes = Object.freeze({
argon2i: '$argon2i$m=4096,t=3,p=1$c29tZXNhbHQ$vpOd0mbc3AzXEHMgcTb1CrZt5XuoRQuz1kQtGBv7ejk',
argon2d: '$argon2d$m=4096,t=3,p=1$c29tZXNhbHQ$/rwrGjZ1NrS+TEgQxricD7B57yJMKGQ/uov96abC6ko'
});
assert.deepEqual(argon2.defaults, {
timeCost: 3,
memoryCost: 12,
parallelism: 1,
argon2d: false
});
assert.done();
},
const limits = argon2.limits;
console.warn = () => {};
testHash (assert) {
'use strict';
t.test('defaults', t => {
'use strict';
assert.expect(3);
t.equivalent(argon2.defaults, {
timeCost: 3,
memoryCost: 12,
parallelism: 1,
argon2d: false
});
t.end();
});
argon2.hash(password, salt, (err, hash) => {
assert.ok(hash, 'Hash should be defined.');
assert.equal(hash, '$argon2i$m=4096,t=3,p=1$c29tZXNhbHQAAAAAAAAAAA$FHF/OZ0GJpMRAlBmPTqXxw36Ftp87JllALZPcP9w9gs');
assert.equal(undefined, err);
assert.done();
});
},
t.test('basic async hash', t => {
'use strict';
testHashArgon2d (assert) {
'use strict';
t.plan(1);
assert.expect(3);
return argon2.hash(password, salt).then(hash => {
t.equal(hash, hashes.argon2i);
});
}).catch(t.threw);
argon2.hash(password, salt, {
argon2d: true
}, (err, hash) => {
assert.ok(hash, 'Hash should be defined.');
assert.ok(/\$argon2d\$/.test(hash), 'Should have argon2d signature.');
assert.equal(undefined, err);
assert.done();
});
},
t.test('async hash with null in password', t => {
'use strict';
testHashTruthyArgon2d (assert) {
'use strict';
t.plan(1);
assert.expect(3);
return argon2.hash('pass\0word', salt).then(hash => {
t.equal(hash, '$argon2i$m=4096,t=3,p=1$c29tZXNhbHQ$tcauj48oAe6NE/VLzTawLTQtmX848wkNs1d7z53ahNE');
});
}).catch(t.threw);
argon2.hash(password, salt, {
argon2d: 'foo'
}, (err, hash) => {
assert.ok(hash, 'Hash should be defined.');
assert.ok(/\$argon2d\$/.test(hash), 'Should have argon2d signature.');
assert.equal(undefined, err);
assert.done();
});
},
t.test('async hash with null in salt', t => {
'use strict';
testHashFalsyArgon2d (assert) {
'use strict';
t.plan(1);
assert.expect(3);
return argon2.hash(password, saltWithNull).then(hash => {
const saltBase64 = hash.substring(24, 46);
t.equal(saltBase64, truncatedBase64(saltWithNull));
});
}).catch(t.threw);
argon2.hash(password, salt, {
argon2d: ''
}, (err, hash) => {
assert.ok(hash, 'Hash should be defined.');
assert.ok(/\$argon2i\$/.test(hash), 'Should not have argon2d signature.');
assert.equal(undefined, err);
assert.done();
t.test('async hash with longer salt', t => {
'use strict';
t.plan(1);
/* intentionally using a length that is not multiple of 3 */
return argon2.generateSalt(500).then(salt => {
return argon2.hash('password', salt).then(hash => {
t.match(hash, /.*\$.{667}\$/, 'Hash should use the entire salt');
return argon2.verify(hash, 'password').then(t.end);
});
},
});
}).catch(t.threw);
testHashLongSalt (assert) {
'use strict';
t.test('async hash with argon2d', t => {
'use strict';
assert.expect(3);
t.plan(2);
argon2.hash(password, 'somesaltwaytoobig', (err, hash) => {
assert.ok(err, 'Error should be defined.');
assert.equal(err.message, 'Invalid salt length, must be 16 bytes.');
assert.equal(undefined, hash);
assert.done();
});
},
return argon2.hash(password, salt, {
argon2d: true
}).then(hash => {
t.match(hash, /\$argon2d\$/, 'Should have argon2d signature.');
t.equal(hash, hashes.argon2d);
});
}).catch(t.threw);
testHashTimeCost (assert) {
'use strict';
t.test('async hash with truthy argon2d', t => {
'use strict';
assert.expect(3);
t.plan(1);
argon2.hash(password, salt, {
timeCost: 4
}, (err, hash) => {
assert.ok(hash, 'Hash should be defined.');
assert.ok(/t=4/.test(hash), 'Should have correct time cost.');
assert.equal(undefined, err);
assert.done();
});
},
return argon2.hash(password, salt, {
argon2d: 'foo'
}).then(hash => {
t.match(hash, /\$argon2d\$/, 'Should have argon2d signature.');
});
}).catch(t.threw);
testHashInvalidTimeCost (assert) {
'use strict';
t.test('async hash with falsy argon2d', t => {
'use strict';
assert.expect(3);
t.plan(1);
argon2.hash(password, salt, {
timeCost: 'foo'
}, (err, hash) => {
assert.ok(err, 'Error should be defined.');
assert.equal(err.message, 'Invalid time cost, must be a number.');
assert.equal(undefined, hash);
assert.done();
});
},
return argon2.hash(password, salt, {
argon2d: ''
}).then(hash => {
t.notMatch(hash, /\$argon2d\$/, 'Should not have argon2d signature.');
});
}).catch(t.threw);
testHashLowTimeCost (assert) {
'use strict';
t.test('async hash with invalid salt', t => {
'use strict';
assert.expect(3);
t.plan(1);
argon2.hash(password, salt, {
timeCost: -4294967290
}, (err, hash) => {
assert.ok(err, 'Error should be defined.');
assert.equal(err.message, 'Time cost too low, minimum of 1.');
assert.equal(undefined, hash);
assert.done();
});
},
return argon2.hash(password, 'stringsalt').catch(err => {
t.match(err.message, /invalid salt.+must be a buffer/i);
});
});
testHashHighTimeCost (assert) {
'use strict';
t.test('async hash with short salt', t => {
'use strict';
assert.expect(3);
t.plan(1);
argon2.hash(password, salt, {
timeCost: 4294967297
}, (err, hash) => {
assert.ok(err, 'Error should be defined.');
assert.equal(err.message, 'Time cost too high, maximum of 4294967295.');
assert.equal(undefined, hash);
assert.done();
});
},
return argon2.hash(password, salt.slice(0, 7)).catch(err => {
t.match(err.message, /invalid salt.+with 8 or more bytes/i);
});
});
testHashMemoryCost (assert) {
'use strict';
t.test('async hash with time cost', t => {
'use strict';
assert.expect(3);
t.plan(1);
argon2.hash(password, salt, {
memoryCost: 13
}, (err, hash) => {
assert.ok(hash, 'Hash should be defined.');
assert.ok(/m=8192/.test(hash), 'Should have correct memory cost.');
assert.equal(undefined, err);
assert.done();
});
},
return argon2.hash(password, salt, {
timeCost: 4
}).then(hash => {
t.match(hash, /t=4/, 'Should have correct time cost.');
});
}).catch(t.threw);
testHashInvalidMemoryCost (assert) {
'use strict';
t.test('async hash with invalid time cost', t => {
'use strict';
assert.expect(3);
t.plan(1);
argon2.hash(password, salt, {
memoryCost: 'foo'
}, (err, hash) => {
assert.ok(err, 'Error should be defined.');
assert.equal(err.message, 'Invalid memory cost, must be a number.');
assert.equal(undefined, hash);
assert.done();
});
},
return argon2.hash(password, salt, {
timeCost: 'foo'
}).catch(err => {
t.match(err.message, /invalid timeCost.+must be an integer/i);
});
});
testHashLowMemoryCost (assert) {
'use strict';
t.test('async hash with low time cost', t => {
'use strict';
assert.expect(3);
t.plan(1);
argon2.hash(password, salt, {
memoryCost: -4294967290
}, (err, hash) => {
assert.ok(err, 'Error should be defined.');
assert.equal(err.message, 'Memory cost too low, minimum of 1.');
assert.equal(undefined, hash);
assert.done();
});
},
return argon2.hash(password, salt, {
timeCost: limits.timeCost.min - 1
}).catch(err => {
t.match(err.message, /invalid timeCost.+between \d+ and \d+/i);
});
});
testHashHighMemoryCost (assert) {
'use strict';
t.test('async hash with high time cost', t => {
'use strict';
assert.expect(3);
t.plan(1);
argon2.hash(password, salt, {
memoryCost: 32
}, (err, hash) => {
assert.ok(err, 'Error should be defined.');
assert.equal(err.message, 'Memory cost too high, maximum of 31.');
assert.equal(undefined, hash);
assert.done();
});
},
return argon2.hash(password, salt, {
timeCost: limits.timeCost.max + 1
}).catch(err => {
t.match(err.message, /invalid timeCost.+between \d+ and \d+/i);
});
});
testHashParallelism (assert) {
'use strict';
t.test('async hash with memory cost', t => {
'use strict';
assert.expect(3);
t.plan(1);
argon2.hash(password, salt, {
parallelism: 2
}, (err, hash) => {
assert.ok(hash, 'Hash should be defined.');
assert.ok(/p=2/.test(hash), 'Should have correct parallelism.');
assert.equal(undefined, err);
assert.done();
});
},
return argon2.hash(password, salt, {
memoryCost: 13
}).then(hash => {
t.match(hash, /m=8192/, 'Should have correct memory cost.');
});
}).catch(t.threw);
testHashInvalidParallelism (assert) {
'use strict';
t.test('async hash with invalid time cost', t => {
'use strict';
assert.expect(3);
t.plan(1);
argon2.hash(password, salt, {
parallelism: 'foo'
}, (err, hash) => {
assert.ok(err, 'Error should be defined.');
assert.equal(err.message, 'Invalid parallelism, must be a number.');
assert.equal(undefined, hash);
assert.done();
});
},
return argon2.hash(password, salt, {
memoryCost: 'foo'
}).catch(err => {
t.match(err.message, /invalid memoryCost.+must be an integer/i);
});
});
testHashLowParallelism (assert) {
'use strict';
t.test('async hash with low time cost', t => {
'use strict';
assert.expect(3);
t.plan(1);
argon2.hash(password, salt, {
parallelism: -4294967290
}, (err, hash) => {
assert.ok(err, 'Error should be defined.');
assert.equal(err.message, 'Parallelism too low, minimum of 1.');
assert.equal(undefined, hash);
assert.done();
});
},
return argon2.hash(password, salt, {
memoryCost: limits.memoryCost.min - 1
}).catch(err => {
t.match(err.message, /invalid memoryCost.+between \d+ and \d+/i);
});
});
testHashHighParallelism (assert) {
'use strict';
t.test('async hash with high time cost', t => {
'use strict';
assert.expect(3);
t.plan(1);
argon2.hash(password, salt, {
parallelism: 4294967297
}, (err, hash) => {
assert.ok(err, 'Error should be defined.');
assert.equal(err.message, 'Parallelism too high, maximum of 4294967295.');
assert.equal(undefined, hash);
assert.done();
});
},
return argon2.hash(password, salt, {
memoryCost: limits.memoryCost.max + 1
}).catch(err => {
t.match(err.message, /invalid memoryCost.+between \d+ and \d+/i);
});
});
testHashAllOptions (assert) {
'use strict';
t.test('async hash with parallelism', t => {
'use strict';
assert.expect(3);
t.plan(1);
argon2.hash(password, salt, {
timeCost: 4,
memoryCost: 13,
parallelism: 2
}, (err, hash) => {
assert.ok(hash, 'Hash should be defined.');
assert.ok(/m=8192,t=4,p=2/.test(hash), 'Should have correct options.');
assert.equal(undefined, err);
assert.done();
});
},
return argon2.hash(password, salt, {
parallelism: 2
}).then(hash => {
t.match(hash, /p=2/, 'Should have correct parallelism.');
});
}).catch(t.threw);
testHashSync (assert) {
'use strict';
t.test('async hash with invalid parallelism', t => {
'use strict';
assert.expect(1);
t.plan(1);
const hash = argon2.hashSync(password, salt);
assert.equal(hash, '$argon2i$m=4096,t=3,p=1$c29tZXNhbHQAAAAAAAAAAA$FHF/OZ0GJpMRAlBmPTqXxw36Ftp87JllALZPcP9w9gs');
assert.done();
},
return argon2.hash(password, salt, {
parallelism: 'foo'
}).catch(err => {
t.match(err.message, /invalid parallelism, must be an integer/i);
});
});
testHashArgon2dSync (assert) {
'use strict';
t.test('async hash with low parallelism', t => {
'use strict';
assert.expect(1);
t.plan(1);
const hash = argon2.hashSync(password, salt, {
argon2d: true
});
assert.ok(/\$argon2d\$/.test(hash), 'Should use argon2d signature.');
assert.done();
},
return argon2.hash(password, salt, {
parallelism: limits.parallelism.min - 1
}).catch(err => {
t.match(err.message, /invalid parallelism.+between \d+ and \d+/i);
});
});
testHashTruthyArgon2dSync (assert) {
'use strict';
t.test('async hash with high parallelism', t => {
'use strict';
assert.expect(1);
t.plan(1);
const hash = argon2.hashSync(password, salt, {
argon2d: 'foo'
});
assert.ok(/\$argon2d\$/.test(hash), 'Should use argon2d signature.');
assert.done();
},
return argon2.hash(password, salt, {
parallelism: limits.parallelism.max + 1
}).catch(err => {
t.match(err.message, /invalid parallelism.+between \d+ and \d+/i);
});
});
testHashFalsyArgon2dSync (assert) {
'use strict';
t.test('async hash with all options', t => {
'use strict';
assert.expect(1);
t.plan(1);
const hash = argon2.hashSync(password, salt, {
argon2d: ''
});
assert.ok(/\$argon2i\$/.test(hash), 'Should not use argon2d signature.');
assert.done();
},
return argon2.hash(password, salt, {
timeCost: 4,
memoryCost: 13,
parallelism: 2
}).then(hash => {
t.match(hash, /m=8192,t=4,p=2/, 'Should have correct options.');
});
}).catch(t.threw);
testHashSyncTimeCost (assert) {
'use strict';
t.test('basic sync hash', t => {
'use strict';
assert.expect(1);
const hash = argon2.hashSync(password, salt);
t.equal(hash, hashes.argon2i);
t.end();
});
const hash = argon2.hashSync(password, salt, {
timeCost: 4
});
assert.ok(/t=4/.test(hash), 'Should have correct time cost.');
assert.done();
},
t.test('sync hash with null in password', t => {
'use strict';
testHashSyncInvalidTimeCost (assert) {
'use strict';
const hash = argon2.hashSync('pass\0word', salt);
t.equal(hash, '$argon2i$m=4096,t=3,p=1$c29tZXNhbHQ$tcauj48oAe6NE/VLzTawLTQtmX848wkNs1d7z53ahNE');
t.end();
});
assert.expect(1);
t.test('sync hash with null in salt', t => {
'use strict';
assert.throws(() => {
argon2.hashSync(password, salt, {
timeCost: 'foo'
});
}, /invalid/i);
assert.done();
},
const hash = argon2.hashSync(password, saltWithNull);
const saltBase64 = hash.substring(24, 46);
t.equal(saltBase64, truncatedBase64(saltWithNull));
t.end();
});
testHashSyncLowTimeCost (assert) {
'use strict';
t.test('sync hash with longer salt', t => {
'use strict';
assert.expect(1);
t.plan(1);
assert.throws(() => {
argon2.hashSync(password, salt, {
timeCost: -4294967290
});
}, /too low/);
assert.done();
},
return argon2.generateSalt(32).then(salt => {
const hash = argon2.hashSync('password', salt);
return argon2.verify(hash, 'password').then(t.pass);
});
}).catch(t.threw);
testHashSyncHighTimeCost (assert) {
'use strict';
t.test('sync hash with argon2d', t => {
'use strict';
assert.expect(1);
const hash = argon2.hashSync(password, salt, {
argon2d: true
});
t.match(hash, /\$argon2d\$/, 'Should use argon2d signature.');
t.equal(hash, hashes.argon2d);
t.end();
});
assert.throws(() => {
argon2.hashSync(password, salt, {
timeCost: 4294967297
});
}, /too high/);
assert.done();
},
t.test('sync hash with truthy argon2d', t => {
'use strict';
testHashSyncMemoryCost (assert) {
'use strict';
const hash = argon2.hashSync(password, salt, {
argon2d: 'foo'
});
t.match(hash, /\$argon2d\$/, 'Should use argon2d signature.');
t.end();
});
assert.expect(1);
t.test('sync hash with falsy argon2d', t => {
'use strict';
const hash = argon2.hashSync(password, salt, {
memoryCost: 13
});
assert.ok(/m=8192/.test(hash), 'Should have correct memory cost.');
assert.done();
},
const hash = argon2.hashSync(password, salt, {
argon2d: ''
});
t.match(hash, /\$argon2i\$/, 'Should not use argon2d signature.');
t.end();
});
testHashSyncInvalidMemoryCost (assert) {
'use strict';
t.test('sync hash with invalid salt', t => {
'use strict';
assert.expect(1);
t.throws(() => {
argon2.hashSync(password, 'stringsalt');
}, /invalid salt.+must be a buffer/i);
t.end();
});
assert.throws(() => {
argon2.hashSync(password, salt, {
memoryCost: 'foo'
});
}, /invalid/i);
assert.done();
},
t.test('sync hash with short salt', t => {
'use strict';
testHashSyncLowMemoryCost (assert) {
'use strict';
t.throws(() => {
argon2.hashSync(password, salt.slice(0, 7));
}, /invalid salt.+with 8 or more bytes/i);
t.end();
});
assert.expect(1);
t.test('sync hash with time cost', t => {
'use strict';
assert.throws(() => {
argon2.hashSync(password, salt, {
memoryCost: -4294967290
});
}, /too low/);
assert.done();
},
const hash = argon2.hashSync(password, salt, {
timeCost: 4
});
t.match(hash, /t=4/, 'Should have correct time cost.');
t.end();
});
testHashSyncHighMemoryCost (assert) {
'use strict';
t.test('sync hash with invalid time cost', t => {
'use strict';
assert.expect(1);
t.throws(() => {
argon2.hashSync(password, salt, {
timeCost: 'foo'
});
}, /invalid timeCost.+must be an integer/i);
t.end();
});
assert.throws(() => {
argon2.hashSync(password, salt, {
memoryCost: 32
});
}, /too high/);
assert.done();
},
t.test('sync hash with low time cost', t => {
'use strict';
testHashSyncParallelism (assert) {
'use strict';
t.throws(() => {
argon2.hashSync(password, salt, {
timeCost: limits.timeCost.min - 1
});
}, /invalid timeCost.+between \d+ and \d+/i);
t.end();
});
assert.expect(1);
t.test('sync hash with high time cost', t => {
'use strict';
const hash = argon2.hashSync(password, salt, {
parallelism: 2
t.throws(() => {
argon2.hashSync(password, salt, {
timeCost: limits.timeCost.max + 1
});
assert.ok(/p=2/.test(hash), 'Should have correct parallelism.');
assert.done();
},
}, /invalid timeCost.+between \d+ and \d+/i);
t.end();
});
testHashSyncInvalidParallelism (assert) {
'use strict';
t.test('sync hash with memory cost', t => {
'use strict';
assert.expect(1);
const hash = argon2.hashSync(password, salt, {
memoryCost: 13
});
t.match(hash, /m=8192/, 'Should have correct memory cost.');
t.end();
});
assert.throws(() => {
argon2.hashSync(password, salt, {
parallelism: 'foo'
});
}, /invalid/i);
assert.done();
},
t.test('sync hash with invalid memory cost', t => {
'use strict';
testHashSyncLowParallelism (assert) {
'use strict';
t.throws(() => {
argon2.hashSync(password, salt, {
memoryCost: 'foo'
});
}, /invalid memoryCost.+must be an integer/i);
t.end();
});
assert.expect(1);
t.test('sync hash with low memory cost', t => {
'use strict';
assert.throws(() => {
argon2.hashSync(password, salt, {
parallelism: -4294967290
});
}, /too low/);
assert.done();
},
t.throws(() => {
argon2.hashSync(password, salt, {
memoryCost: limits.memoryCost.min - 1
});
}, /invalid memoryCost.+between \d+ and \d+/i);
t.end();
});
testHashSyncHighParallelism (assert) {
'use strict';
t.test('sync hash with high memory cost', t => {
'use strict';
assert.expect(1);
t.throws(() => {
argon2.hashSync(password, salt, {
memoryCost: limits.memoryCost.max + 1
});
}, /invalid memoryCost.+between \d+ and \d+/i);
t.end();
});
assert.throws(() => {
argon2.hashSync(password, salt, {
parallelism: 4294967297
});
}, /too high/);
assert.done();
},
t.test('sync hash with parallelism', t => {
'use strict';
testHashSyncAllOptions (assert) {
'use strict';
const hash = argon2.hashSync(password, salt, {
parallelism: 2
});
t.match(hash, /p=2/, 'Should have correct parallelism.');
t.end();
});
assert.expect(1);
t.test('sync hash with invalid parallelism', t => {
'use strict';
const hash = argon2.hashSync(password, salt, {
timeCost: 4,
memoryCost: 13,
parallelism: 2
t.throws(() => {
argon2.hashSync(password, salt, {
parallelism: 'foo'
});
assert.ok(/m=8192,t=4,p=2/.test(hash), 'Should have correct options.');
assert.done();
},
}, /invalid parallelism, must be an integer/i);
t.end();
});
testHashSyncLongSalt (assert) {
'use strict';
t.test('sync hash with low parallelism', t => {
'use strict';
assert.expect(1);
t.throws(() => {
argon2.hashSync(password, salt, {
parallelism: limits.parallelism.min - 1
});
}, /invalid parallelism.+between \d+ and \d+/i);
t.end();
});
assert.throws(() => {
argon2.hashSync(password, 'somesaltwaytoobig');
t.test('sync hash with high parallelism', t => {
'use strict';
t.throws(() => {
argon2.hashSync(password, salt, {
parallelism: limits.parallelism.max + 1
});
assert.done();
},
}, /invalid parallelism.+between \d+ and \d+/i);
t.end();
});
testGenerateSalt (assert) {
'use strict';
t.test('sync hash with all options', t => {
'use strict';
assert.expect(1);
const hash = argon2.hashSync(password, salt, {
timeCost: 4,
memoryCost: 13,
parallelism: 2
});
t.match(hash, /m=8192,t=4,p=2/, 'Should have correct options.');
t.end();
});
argon2.generateSalt((err, salt) => {
assert.ok(salt.length <= 16);
assert.done();
});
},
t.test('async generate salt with default length', t => {
'use strict';
testGenerateSaltSync (assert) {
'use strict';
t.plan(1);
assert.expect(1);
return argon2.generateSalt().then(salt => {
t.equal(salt.length, 16);
});
}).catch(t.threw);
assert.ok(argon2.generateSaltSync().length <= 16);
assert.done();
},
t.test('async generate salt with specified length', t => {
'use strict';
testVerifyOk (assert) {
'use strict';
t.plan(1);
assert.expect(1);
return argon2.generateSalt(32).then(salt => {
t.equal(salt.length, 32);
});
}).catch(t.threw);
argon2.verify(argon2.hashSync(password, argon2.generateSaltSync()),
password, (err) => {
assert.equal(undefined, err);
assert.done();
});
},
t.test('sync generate salt with default length', t => {
'use strict';
testVerifyFail (assert) {
'use strict';
t.equal(argon2.generateSaltSync().length, 16);
t.end();
});
assert.expect(1);
t.test('sync generate salt with specified length', t => {
'use strict';
argon2.verify(argon2.hashSync(password, argon2.generateSaltSync()),
'passwolrd', (err) => {
assert.ok(err, 'Error should be defined.');
assert.done();
});
},
t.equal(argon2.generateSaltSync(32).length, 32);
t.end();
});
testVerifyArgon2dOk (assert) {
'use strict';
t.test('async verify correct password', t => {
'use strict';
assert.expect(1);
return argon2.generateSalt().then(salt => {
return argon2.hash(password, salt).then(hash => {
return argon2.verify(hash, password).then(t.pass);
});
});
}).catch(t.threw);
argon2.hash(password, argon2.generateSaltSync(), {
argon2d: true
}, (err, hash) => {
argon2.verify(hash, password, (err) => {
assert.equal(undefined, err);
assert.done();
});
t.test('async verify wrong password', t => {
'use strict';
return argon2.generateSalt().then(salt => {
return argon2.hash(password, salt).then(hash => {
return argon2.verify(hash, 'passworld').catch(t.pass);
});
},
});
}).catch(t.threw);
testVerifyArgon2dFail (assert) {
'use strict';
t.test('async verify with null in password', t => {
'use strict';
assert.expect(1);
return argon2.generateSalt().then(salt => {
return argon2.hash('pass\0word', salt).then(hash => {
return argon2.verify(hash, 'pass\0word').then(t.pass);
});
});
}).catch(t.threw);
argon2.hash(password, argon2.generateSaltSync(), {
t.test('async verify argon2d correct password', t => {
'use strict';
return argon2.generateSalt().then(salt => {
return argon2.hash(password, salt, {
argon2d: true
}, (err, hash) => {
argon2.verify(hash, 'passwolrd', (err) => {
assert.ok(err, 'Error should be defined.');
assert.done();
});
}).then(hash => {
return argon2.verify(hash, password).then(t.pass);
});
},
});
}).catch(t.threw);
testVerifySyncOk (assert) {
'use strict';
t.test('async verify argon2d wrong password', t => {
'use strict';
assert.expect(1);
return argon2.generateSalt().then(salt => {
return argon2.hash(password, salt, {
argon2d: true
}).then(hash => {
return argon2.verify(hash, 'passwolrd').catch(t.pass);
});
});
}).catch(t.threw);
assert.equal(true, argon2.verifySync(argon2.hashSync(password,
argon2.generateSaltSync()), password));
assert.done();
},
t.test('sync verify correct password', t => {
'use strict';
testVerifySyncFail (assert) {
'use strict';
t.plan(1);
assert.expect(1);
return argon2.generateSalt().then(salt => {
return argon2.hash(password, salt).then(hash => {
t.true(argon2.verifySync(hash, password));
});
});
}).catch(t.threw);
assert.equal(false, argon2.verifySync(argon2.hashSync(password,
argon2.generateSaltSync()), 'passworld'));
assert.done();
},
t.test('sync verify wrong password', t => {
'use strict';
testVerifyArgon2dSyncOk (assert) {
'use strict';
t.plan(1);
assert.expect(1);
return argon2.generateSalt().then(salt => {
return argon2.hash(password, salt).then(hash => {
t.false(argon2.verifySync(hash, 'passworld'));
});
});
}).catch(t.threw);
argon2.hash(password, argon2.generateSaltSync(), {
t.test('sync verify with null in password', t => {
'use strict';
t.plan(1);
return argon2.generateSalt().then(salt => {
return argon2.hash('pass\0word', salt).then(hash => {
t.true(argon2.verifySync(hash, 'pass\0word'));
});
});
}).catch(t.threw);
t.test('sync verify argon2d correct password', t => {
'use strict';
t.plan(1);
return argon2.generateSalt().then(salt => {
return argon2.hash(password, salt, {
argon2d: true
}, (err, hash) => {
assert.equal(true, argon2.verifySync(hash, password));
assert.done();
}).then(hash => {
t.true(argon2.verifySync(hash, password));
});
},
});
}).catch(t.threw);
testVerifyArgon2dSyncFail (assert) {
'use strict';
t.test('sync verify argon2d wrong password', t => {
'use strict';
assert.expect(1);
t.plan(1);
argon2.hash(password, argon2.generateSaltSync(), {
return argon2.generateSalt().then(salt => {
return argon2.hash(password, salt, {
argon2d: true
}, (err, hash) => {
assert.equal(false, argon2.verifySync(hash, 'passwolrd'));
assert.done();
}).then(hash => {
t.false(argon2.verifySync(hash, 'passwolrd'));
});
}
};
});
}).catch(t.threw);

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

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