Comparing version 0.3.0 to 0.4.0
92
index.js
var bindings = require("bindings")("argon2_lib"), | ||
crypto = require("crypto"); | ||
exports.encrypt = function (plain, salt, options, callback) { | ||
"use strict"; | ||
var defaults = exports.defaults = Object.freeze({ | ||
timeCost: 3, | ||
memoryCost: 12, | ||
parallelism: 1, | ||
argon2d: false | ||
}); | ||
if (typeof(callback) == 'undefined') { | ||
callback = options; | ||
options = {}; | ||
} | ||
var fail = function (message, callback) { | ||
var error = new Error(message); | ||
options.timeCost = options.timeCost || 3; | ||
options.memoryCost = options.memoryCost || 12; | ||
options.parallelism = options.parallelism || 1; | ||
options.argon2d = !!options.argon2d; | ||
if (salt.length > 16) { | ||
if (typeof(callback) === "undefined") { | ||
throw error; | ||
} else { | ||
process.nextTick(function () { | ||
callback(new Error("Salt too long, maximum 16 characters."), null); | ||
callback(error, null); | ||
}); | ||
return; | ||
} | ||
}; | ||
var validate = function (salt, options, callback) { | ||
if (salt.length > 16) { | ||
fail("Salt too long, maximum 16 characters.", callback); | ||
return false; | ||
} | ||
Object.assign(options, Object.assign({}, defaults, options)); | ||
if (isNaN(options.timeCost)) { | ||
fail("Invalid time cost, must be a number.", callback); | ||
return false; | ||
} | ||
if (isNaN(options.memoryCost)) { | ||
fail("Invalid memory cost, must be a number.", callback); | ||
return false; | ||
} | ||
if (options.memoryCost >= 32) { | ||
process.nextTick(function () { | ||
callback(new Error("Memory cost too high, maximum of 32."), null); | ||
}); | ||
return; | ||
fail("Memory cost too high, maximum of 32.", callback); | ||
return false; | ||
} | ||
return bindings.encrypt(plain, salt, options.timeCost, options.memoryCost, | ||
options.parallelism, options.argon2d, callback); | ||
if (isNaN(options.parallelism)) { | ||
fail("Invalid parallelism, must be a number.", callback); | ||
return false; | ||
} | ||
options.argon2d = !!options.argon2d; | ||
return true; | ||
}; | ||
exports.encrypt = function (plain, salt, options, callback) { | ||
"use strict"; | ||
if (!callback) { | ||
callback = options; | ||
options = {}; | ||
} | ||
if (validate(salt, options, callback)) { | ||
return bindings.encrypt(plain, salt, options.timeCost, options.memoryCost, | ||
options.parallelism, options.argon2d, callback); | ||
} | ||
}; | ||
exports.encryptSync = function (plain, salt, options) { | ||
@@ -40,17 +75,6 @@ "use strict"; | ||
options.timeCost = options.timeCost || 3; | ||
options.memoryCost = options.memoryCost || 12; | ||
options.parallelism = options.parallelism || 1; | ||
options.argon2d = !!options.argon2d; | ||
if (salt.length > 16) { | ||
throw new Error("Salt too long, maximum 16 characters."); | ||
if (validate(salt, options)) { | ||
return bindings.encryptSync(plain, salt, options.timeCost, | ||
options.memoryCost, options.parallelism, options.argon2d); | ||
} | ||
if (options.memoryCost >= 32) { | ||
throw new Error("Memory cost too high, maximum of 32"); | ||
} | ||
return bindings.encryptSync(plain, salt, options.timeCost, options.memoryCost, | ||
options.parallelism, options.argon2d); | ||
}; | ||
@@ -57,0 +81,0 @@ |
{ | ||
"name": "argon2", | ||
"version": "0.3.0", | ||
"version": "0.4.0", | ||
"description": "An Argon2 library for Node", | ||
@@ -10,4 +10,3 @@ "main": "index.js", | ||
"configure": "node-gyp configure", | ||
"coveralls": "jscoverage index.js && ARGON2_COVERAGE=1 nodeunit --reporter=lcov test.spec.js | coveralls", | ||
"preinstall": "node-gyp rebuild && git submodule init && git submodule update", | ||
"preinstall": "node-gyp rebuild && git submodule update --init", | ||
"test": "npm run build && nodeunit test.spec.js" | ||
@@ -14,0 +13,0 @@ }, |
@@ -1,2 +0,2 @@ | ||
# node-argon2 [![NPM package][npm-image]][npm-url] [![Build status][travis-image]][travis-url] [![Coverage status][coveralls-image]][coveralls-url] [![Code Climate][codeclimate-image]][codeclimate-url] [![Dependencies][david-dm-image]][david-dm-url] | ||
# node-argon2 [![NPM package][npm-image]][npm-url] [![Build status][travis-image]][travis-url] [![Coverage status][coverage-image]][codeclimate-url] [![Code Climate][codeclimate-image]][codeclimate-url] [![Dependencies][david-dm-image]][david-dm-url] | ||
Bindings to the reference [Argon2](https://github.com/P-H-C/phc-winner-argon2) | ||
@@ -51,2 +51,3 @@ implementation. | ||
``` | ||
The `argon2d` option is flexible and accepts any truthy or falsy values. | ||
@@ -88,2 +89,10 @@ You can provide your own salt as the second parameter. It is recommended to use | ||
The default parameters for Argon2 can be accessed with `defaults`: | ||
```js | ||
var argon2 = require('argon2'); | ||
console.log(argon2.defaults); | ||
// => { timeCost: 3, memoryCost: 12, parallelism: 1, argon2d: false } | ||
``` | ||
To verify a password: | ||
@@ -116,11 +125,10 @@ ```js | ||
[npm-image]: https://img.shields.io/npm/v/argon2.svg | ||
[npm-image]: https://img.shields.io/npm/v/argon2.svg?style=flat-square | ||
[npm-url]: https://www.npmjs.com/package/argon2 | ||
[travis-image]: https://img.shields.io/travis/ranisalt/node-argon2.svg | ||
[travis-image]: https://img.shields.io/travis/ranisalt/node-argon2.svg?style=flat-square | ||
[travis-url]: https://travis-ci.org/ranisalt/node-argon2 | ||
[coveralls-image]: https://img.shields.io/coveralls/ranisalt/node-argon2.svg | ||
[coveralls-url]: https://coveralls.io/github/ranisalt/node-argon2 | ||
[codeclimate-image]: https://img.shields.io/codeclimate/github/ranisalt/node-argon2.svg | ||
[coverage-image]: https://img.shields.io/codeclimate/coverage/github/ranisalt/node-argon2.svg?style=flat-square | ||
[codeclimate-image]: https://img.shields.io/codeclimate/github/ranisalt/node-argon2.svg?style=flat-square | ||
[codeclimate-url]: https://codeclimate.com/github/ranisalt/node-argon2 | ||
[david-dm-image]: https://img.shields.io/david/ranisalt/node-argon2.svg | ||
[david-dm-image]: https://img.shields.io/david/ranisalt/node-argon2.svg?style=flat-square | ||
[david-dm-url]: https://david-dm.org/ranisalt/node-argon2 |
236
test.spec.js
@@ -6,2 +6,16 @@ var argon2 = process.env.ARGON2_COVERAGE | ||
module.exports = { | ||
test_defaults: function (assert) { | ||
"use strict"; | ||
assert.expect(1); | ||
assert.deepEqual(argon2.defaults, { | ||
timeCost: 3, | ||
memoryCost: 12, | ||
parallelism: 1, | ||
argon2d: false | ||
}); | ||
assert.done(); | ||
}, | ||
test_hash: function (assert) { | ||
@@ -14,5 +28,4 @@ "use strict"; | ||
assert.ok(hash, "Hash should be defined."); | ||
assert.equal(hash, "$argon2i$m=4096,t=3,p=1$c29tZXNhbHQAAAAAAAAAAA$FHF/OZ0GJpMRAlBmPTqXxw36Ftp87JllALZPcP9w9gs", | ||
"Hash should be equal to expected."); | ||
assert.equal(undefined, err, "Error should not be defined."); | ||
assert.equal(hash, "$argon2i$m=4096,t=3,p=1$c29tZXNhbHQAAAAAAAAAAA$FHF/OZ0GJpMRAlBmPTqXxw36Ftp87JllALZPcP9w9gs"); | ||
assert.equal(undefined, err); | ||
assert.done(); | ||
@@ -31,4 +44,4 @@ }); | ||
assert.ok(hash, "Hash should be defined."); | ||
assert.ok(/\$argon2d\$/.test(hash), "Hash should use argon2d signature."); | ||
assert.equal(undefined, err, "Error should not be defined."); | ||
assert.ok(/\$argon2d\$/.test(hash), "Should have argon2d signature."); | ||
assert.equal(undefined, err); | ||
assert.done(); | ||
@@ -38,2 +51,32 @@ }); | ||
test_hash_truthy_argon2d: function (assert) { | ||
"use strict"; | ||
assert.expect(3); | ||
argon2.encrypt("password", "somesalt", { | ||
argon2d: "foo" | ||
}, function (err, hash) { | ||
assert.ok(hash, "Hash should be defined."); | ||
assert.ok(/\$argon2d\$/.test(hash), "Should have argon2d signature."); | ||
assert.equal(undefined, err); | ||
assert.done(); | ||
}); | ||
}, | ||
test_hash_falsy_argon2d: function (assert) { | ||
"use strict"; | ||
assert.expect(3); | ||
argon2.encrypt("password", "somesalt", { | ||
argon2d: "" | ||
}, function (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(); | ||
}); | ||
}, | ||
test_hash_long_salt: function (assert) { | ||
@@ -46,4 +89,4 @@ "use strict"; | ||
assert.ok(err, "Error should be defined."); | ||
assert.equal(err.message, "Salt too long, maximum 16 characters.", "Error message should be equal to expected."); | ||
assert.equal(undefined, hash, "Hash should not be defined."); | ||
assert.equal(err.message, "Salt too long, maximum 16 characters."); | ||
assert.equal(undefined, hash); | ||
assert.done(); | ||
@@ -62,4 +105,4 @@ }); | ||
assert.ok(hash, "Hash should be defined."); | ||
assert.ok(/m=4096,t=4,p=1/.test(hash), "Hash should have correct time cost."); | ||
assert.equal(undefined, err, "Error should not be defined."); | ||
assert.ok(/t=4/.test(hash), "Should have correct time cost."); | ||
assert.equal(undefined, err); | ||
assert.done(); | ||
@@ -69,2 +112,17 @@ }); | ||
test_hash_invalid_time_cost: function (assert) { | ||
"use strict"; | ||
assert.expect(3); | ||
argon2.encrypt("password", "somesalt", { | ||
timeCost: "foo" | ||
}, function (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(); | ||
}); | ||
}, | ||
test_hash_memory_cost: function (assert) { | ||
@@ -79,4 +137,4 @@ "use strict"; | ||
assert.ok(hash, "Hash should be defined."); | ||
assert.ok(/m=8192,t=3,p=1/.test(hash), "Hash should have correct memory cost."); | ||
assert.equal(undefined, err, "Error should not be defined."); | ||
assert.ok(/m=8192/.test(hash), "Should have correct memory cost."); | ||
assert.equal(undefined, err); | ||
assert.done(); | ||
@@ -86,2 +144,17 @@ }); | ||
test_hash_invalid_memory_cost: function (assert) { | ||
"use strict"; | ||
assert.expect(3); | ||
argon2.encrypt("password", "somesalt", { | ||
memoryCost: "foo" | ||
}, function (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(); | ||
}); | ||
}, | ||
test_hash_high_memory_cost: function (assert) { | ||
@@ -96,4 +169,4 @@ "use strict"; | ||
assert.ok(err, "Error should be defined."); | ||
assert.equal(err.message, "Memory cost too high, maximum of 32.", "Error message should be equal to expected."); | ||
assert.equal(undefined, hash, "Hash should not be defined."); | ||
assert.equal(err.message, "Memory cost too high, maximum of 32."); | ||
assert.equal(undefined, hash); | ||
assert.done(); | ||
@@ -112,4 +185,4 @@ }); | ||
assert.ok(hash, "Hash should be defined."); | ||
assert.ok(/m=4096,t=3,p=2/.test(hash), "Hash should have correct parallelism."); | ||
assert.equal(undefined, err, "Error should not be defined."); | ||
assert.ok(/p=2/.test(hash), "Should have correct parallelism."); | ||
assert.equal(undefined, err); | ||
assert.done(); | ||
@@ -119,2 +192,17 @@ }); | ||
test_hash_invalid_parallelism: function (assert) { | ||
"use strict"; | ||
assert.expect(3); | ||
argon2.encrypt("password", "somesalt", { | ||
parallelism: "foo" | ||
}, function (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(); | ||
}); | ||
}, | ||
test_hash_all_options: function (assert) { | ||
@@ -131,4 +219,4 @@ "use strict"; | ||
assert.ok(hash, "Hash should be defined."); | ||
assert.ok(/m=8192,t=4,p=2/.test(hash), "Hash should have correct options."); | ||
assert.equal(undefined, err, "Error should not be defined."); | ||
assert.ok(/m=8192,t=4,p=2/.test(hash), "Should have correct options."); | ||
assert.equal(undefined, err); | ||
assert.done(); | ||
@@ -144,4 +232,3 @@ }); | ||
var hash = argon2.encryptSync("password", "somesalt"); | ||
assert.equal(hash, "$argon2i$m=4096,t=3,p=1$c29tZXNhbHQAAAAAAAAAAA$FHF/OZ0GJpMRAlBmPTqXxw36Ftp87JllALZPcP9w9gs", | ||
"Hash should be equal to expected."); | ||
assert.equal(hash, "$argon2i$m=4096,t=3,p=1$c29tZXNhbHQAAAAAAAAAAA$FHF/OZ0GJpMRAlBmPTqXxw36Ftp87JllALZPcP9w9gs"); | ||
assert.done(); | ||
@@ -158,6 +245,30 @@ }, | ||
}); | ||
assert.ok(/\$argon2d\$/.test(hash), "Hash should use argon2d signature."); | ||
assert.ok(/\$argon2d\$/.test(hash), "Should use argon2d signature."); | ||
assert.done(); | ||
}, | ||
test_hash_truthy_argon2d_sync: function (assert) { | ||
"use strict"; | ||
assert.expect(1); | ||
var hash = argon2.encryptSync("password", "somesalt", { | ||
argon2d: "foo" | ||
}); | ||
assert.ok(/\$argon2d\$/.test(hash), "Should use argon2d signature."); | ||
assert.done(); | ||
}, | ||
test_hash_falsy_argon2d_sync: function (assert) { | ||
"use strict"; | ||
assert.expect(1); | ||
var hash = argon2.encryptSync("password", "somesalt", { | ||
argon2d: "" | ||
}); | ||
assert.ok(/\$argon2i\$/.test(hash), "Should not use argon2d signature."); | ||
assert.done(); | ||
}, | ||
test_hash_sync_time_cost: function (assert) { | ||
@@ -171,6 +282,19 @@ "use strict"; | ||
}); | ||
assert.ok(/m=4096,t=4,p=1/.test(hash), "Hash should have correct time cost."); | ||
assert.ok(/t=4/.test(hash), "Should have correct time cost."); | ||
assert.done(); | ||
}, | ||
test_hash_sync_invalid_time_cost: function (assert) { | ||
"use strict"; | ||
assert.expect(1); | ||
assert.throws(function () { | ||
var hash = argon2.encryptSync("password", "somesalt", { | ||
timeCost: "foo" | ||
}); | ||
}); | ||
assert.done(); | ||
}, | ||
test_hash_sync_memory_cost: function (assert) { | ||
@@ -184,6 +308,19 @@ "use strict"; | ||
}); | ||
assert.ok(/m=8192,t=3,p=1/.test(hash), "Hash should have correct memory cost."); | ||
assert.ok(/m=8192/.test(hash), "Should have correct memory cost."); | ||
assert.done(); | ||
}, | ||
test_hash_sync_invalid_memory_cost: function (assert) { | ||
"use strict"; | ||
assert.expect(1); | ||
assert.throws(function () { | ||
var hash = argon2.encryptSync("password", "somesalt", { | ||
memoryCost: "foo" | ||
}); | ||
}); | ||
assert.done(); | ||
}, | ||
test_hash_sync_high_memory_cost: function (assert) { | ||
@@ -195,5 +332,5 @@ "use strict"; | ||
assert.throws(function () { | ||
var hash = argon2.encryptSync("password", "somesalt", { | ||
argon2.encryptSync("password", "somesalt", { | ||
memoryCost: 32 | ||
}, Error, "Error should be thrown."); | ||
}); | ||
}); | ||
@@ -211,6 +348,19 @@ assert.done(); | ||
}); | ||
assert.ok(/m=4096,t=3,p=2/.test(hash), "Hash should have correct parallelism."); | ||
assert.ok(/p=2/.test(hash), "Should have correct parallelism."); | ||
assert.done(); | ||
}, | ||
test_hash_sync_invalid_parallelism: function (assert) { | ||
"use strict"; | ||
assert.expect(1); | ||
assert.throws(function () { | ||
var hash = argon2.encryptSync("password", "somesalt", { | ||
parallelism: "foo" | ||
}); | ||
}); | ||
assert.done(); | ||
}, | ||
test_hash_sync_all_options: function (assert) { | ||
@@ -226,3 +376,3 @@ "use strict"; | ||
}); | ||
assert.ok(/m=8192,t=4,p=2/.test(hash), "Hash should have correct options."); | ||
assert.ok(/m=8192,t=4,p=2/.test(hash), "Should have correct options."); | ||
assert.done(); | ||
@@ -238,3 +388,3 @@ }, | ||
argon2.encryptSync("password", "somesaltwaytoobig"); | ||
}, Error, "Error should be thrown."); | ||
}); | ||
assert.done(); | ||
@@ -249,3 +399,3 @@ }, | ||
argon2.generateSalt(function (err, salt) { | ||
assert.ok(salt.length <= 16, "Generated salt length should be less than 16."); | ||
assert.ok(salt.length <= 16); | ||
assert.done(); | ||
@@ -260,3 +410,3 @@ }); | ||
assert.ok(argon2.generateSaltSync().length <= 16, "Generated salt length should be less than 16."); | ||
assert.ok(argon2.generateSaltSync().length <= 16); | ||
assert.done(); | ||
@@ -270,6 +420,5 @@ }, | ||
argon2.verify( | ||
"$argon2i$m=4096,t=3,p=1$c29tZXNhbHQAAAAAAAAAAA$FHF/OZ0GJpMRAlBmPTqXxw36Ftp87JllALZPcP9w9gs", | ||
argon2.verify(argon2.encryptSync("password", argon2.generateSaltSync()), | ||
"password", function (err) { | ||
assert.equal(undefined, err, "Error should be undefined."); | ||
assert.equal(undefined, err); | ||
assert.done(); | ||
@@ -284,4 +433,3 @@ }); | ||
argon2.verify( | ||
"$argon2i$m=4096,t=3,p=1$c29tZXNhbHQAAAAAAAAAAA$FHF/OZ0GJpMRAlBmPTqXxw36Ftp87JllALZPcP9w9gs", | ||
argon2.verify(argon2.encryptSync("password", argon2.generateSaltSync()), | ||
"passwolrd", function (err) { | ||
@@ -298,7 +446,7 @@ assert.ok(err, "Error should be defined."); | ||
argon2.encrypt("password", "somesalt", { | ||
argon2.encrypt("password", argon2.generateSaltSync(), { | ||
argon2d: true | ||
}, function (err, hash) { | ||
argon2.verify(hash, "password", function (err) { | ||
assert.equal(undefined, err, "Error should be undefined."); | ||
assert.equal(undefined, err); | ||
assert.done(); | ||
@@ -314,3 +462,3 @@ }); | ||
argon2.encrypt("password", "somesalt", { | ||
argon2.encrypt("password", argon2.generateSaltSync(), { | ||
argon2d: true | ||
@@ -330,5 +478,4 @@ }, function (err, hash) { | ||
assert.equal(true, argon2.verifySync( | ||
"$argon2i$m=4096,t=3,p=1$c29tZXNhbHQAAAAAAAAAAA$FHF/OZ0GJpMRAlBmPTqXxw36Ftp87JllALZPcP9w9gs", | ||
"password")); | ||
assert.equal(true, argon2.verifySync(argon2.encryptSync("password", | ||
argon2.generateSaltSync()), "password")); | ||
assert.done(); | ||
@@ -342,5 +489,4 @@ }, | ||
assert.equal(false, argon2.verifySync( | ||
"$argon2i$m=4096,t=3,p=1$c29tZXNhbHQAAAAAAAAAAA$FHF/OZ0GJpMRAlBmPTqXxw36Ftp87JllALZPcP9w9gs", | ||
"passwolrd")); | ||
assert.equal(false, argon2.verifySync(argon2.encryptSync("password", | ||
argon2.generateSaltSync()), "passworld")); | ||
assert.done(); | ||
@@ -354,3 +500,3 @@ }, | ||
argon2.encrypt("password", "somesalt", { | ||
argon2.encrypt("password", argon2.generateSaltSync(), { | ||
argon2d: true | ||
@@ -368,3 +514,3 @@ }, function (err, hash) { | ||
argon2.encrypt("password", "somesalt", { | ||
argon2.encrypt("password", argon2.generateSaltSync(), { | ||
argon2d: true | ||
@@ -371,0 +517,0 @@ }, function (err, hash) { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1489049
50
640
132