Comparing version 0.12.0 to 0.13.0
@@ -51,5 +51,5 @@ # Argon2 | ||
on your system. To show usage instructions, run | ||
`./argon2` without arguments as | ||
`./argon2 -h` as | ||
``` | ||
Usage: ./argon2 salt [-d] [-t iterations] [-m memory] [-p parallelism] [-h hash length] [-e|-r] | ||
Usage: ./argon2 [-h] salt [-d] [-t iterations] [-m memory] [-p parallelism] [-l hash length] [-e|-r] | ||
Password is read from stdin | ||
@@ -62,5 +62,6 @@ Parameters: | ||
-p N Sets parallelism to N threads (default 1) | ||
-h N Sets hash output length to N bytes (default 32) | ||
-l N Sets hash output length to N bytes (default 32) | ||
-e Output only encoded hash | ||
-r Output only the raw bytes of the hash | ||
-h Print argon2 usage | ||
``` | ||
@@ -71,3 +72,3 @@ For example, to hash "password" using "somesalt" as a salt and doing 2 | ||
``` | ||
$ echo -n "password" | ./argon2 somesalt -t 2 -m 16 -p 4 -h 24 | ||
$ echo -n "password" | ./argon2 somesalt -t 2 -m 16 -p 4 -l 24 | ||
Type: Argon2i | ||
@@ -131,15 +132,22 @@ Iterations: 2 | ||
// low-level API | ||
uint32_t lanes = parallelism; | ||
uint32_t threads = parallelism; | ||
argon2_context context = { | ||
hash2, HASHLEN, | ||
pwd, pwdlen, | ||
salt, SALTLEN, | ||
NULL, 0, /* secret data */ | ||
NULL, 0, /* associated data */ | ||
hash2, /* output array, at least HASHLEN in size */ | ||
HASHLEN, /* digest length */ | ||
pwd, /* password array */ | ||
pwdlen, /* password length */ | ||
salt, /* salt array */ | ||
SALTLEN, /* salt length */ | ||
NULL, 0, /* optional secret data */ | ||
NULL, 0, /* optional associated data */ | ||
t_cost, m_cost, parallelism, parallelism, | ||
ARGON2_VERSION_13, /* algorithm version */ | ||
NULL, NULL, /* custom memory allocation / deallocation functions */ | ||
ARGON2_DEFAULT_FLAGS /* by default the password is zeroed on exit */ | ||
}; | ||
argon2i( &context ); | ||
int rc = argon2i_ctx( &context ); | ||
if(ARGON2_OK != rc) { | ||
printf("Error: %s\n", argon2_error_message(rc)); | ||
exit(1); | ||
} | ||
free(pwd); | ||
@@ -149,7 +157,8 @@ | ||
if (memcmp(hash1, hash2, HASHLEN)) { | ||
for( int i=0; i<HASHLEN; ++i ) printf( "%02x", hash2[i] ); printf( "\n" ); | ||
printf("fail\n"); | ||
for( int i=0; i<HASHLEN; ++i ) { | ||
printf( "%02x", hash2[i] ); | ||
} | ||
printf("\nfail\n"); | ||
} | ||
else printf("ok\n"); | ||
return 0; | ||
@@ -156,0 +165,0 @@ } |
72
index.js
const crypto = require('crypto') | ||
const bindings = require('bindings')('argon2') | ||
const Promise = require('any-promise') | ||
@@ -13,28 +14,18 @@ const defaults = Object.freeze({ | ||
const isValidHash = hash => { | ||
return /^\$argon2[di](\$v=\d+)?\$m=\d+,t=\d+,p=\d+(?:\$[a-zA-Z0-9+\/]+){2}$/.test(hash) | ||
} | ||
const validate = (salt, options) => { | ||
'use strict' | ||
const validate = (salt, options) => new Promise((resolve, reject) => { | ||
if (!Buffer.isBuffer(salt) || salt.length < 8) { | ||
throw new Error('Invalid salt, must be a buffer with 8 or more bytes.') | ||
reject(new Error('Invalid salt, must be a buffer with 8 or more bytes.')) | ||
} | ||
if (options.parallelism === 'auto') { | ||
/* istanbul ignore next */ | ||
options.parallelism = require('os').cpus().length | ||
} | ||
for (const key of Object.keys(limits)) { | ||
const max = limits[key].max | ||
const min = limits[key].min | ||
const {max, min} = limits[key] | ||
const value = options[key] | ||
if (!Number.isInteger(value) || value > max || value < min) { | ||
throw new Error(`Invalid ${key}, must be an integer between ${min} and ${max}.`) | ||
reject(new Error(`Invalid ${key}, must be an integer between ${min} and ${max}.`)) | ||
} | ||
} | ||
} | ||
resolve() | ||
}) | ||
module.exports = { | ||
@@ -45,32 +36,17 @@ defaults, | ||
hash(plain, salt, options) { | ||
'use strict' | ||
options = Object.assign({}, defaults, options) | ||
if (!Buffer.isBuffer(plain)) { | ||
plain = new Buffer(plain) | ||
} | ||
try { | ||
validate(salt, options) | ||
return new this.Promise((resolve, reject) => { | ||
return bindings.hash(plain, salt, options.timeCost, options.memoryCost, | ||
options.parallelism, options.argon2d, resolve, reject) | ||
}) | ||
} catch (err) { | ||
return this.Promise.reject(err) | ||
} | ||
return validate(salt, options).then(() => new Promise((resolve, reject) => { | ||
bindings.hash(new Buffer(plain), salt, options, resolve, reject) | ||
})) | ||
}, | ||
generateSalt(length) { | ||
'use strict' | ||
length = typeof length === 'undefined' ? 16 : length | ||
return new this.Promise((resolve, reject) => { | ||
crypto.randomBytes(length, (err, salt) => { | ||
return new Promise((resolve, reject) => { | ||
crypto.randomBytes(length || 16, (err, salt) => { | ||
/* istanbul ignore if */ | ||
if (err) { | ||
return reject(err) | ||
reject(err) | ||
} | ||
return resolve(salt) | ||
resolve(salt) | ||
}) | ||
@@ -81,18 +57,10 @@ }) | ||
verify(hash, plain) { | ||
'use strict' | ||
if (!isValidHash(hash)) { | ||
return this.Promise.reject(new Error('Invalid hash, must be generated by Argon2.')) | ||
if (!/^\$argon2[di](\$v=\d+)?\$m=\d+,t=\d+,p=\d+(?:\$[\w+\/]+){2}$/.test(hash)) { | ||
return Promise.reject(new Error('Invalid hash, must be generated by Argon2.')) | ||
} | ||
if (!Buffer.isBuffer(plain)) { | ||
plain = new Buffer(plain) | ||
} | ||
return new this.Promise((resolve, reject) => { | ||
bindings.verify(hash, plain, hash[7] === 'd', resolve, reject) | ||
return new Promise((resolve, reject) => { | ||
bindings.verify(new Buffer(hash), new Buffer(plain), resolve, reject) | ||
}) | ||
}, | ||
Promise | ||
} | ||
} |
{ | ||
"name": "argon2", | ||
"version": "0.12.0", | ||
"version": "0.13.0", | ||
"description": "An Argon2 library for Node", | ||
@@ -9,3 +9,3 @@ "main": "index.js", | ||
"clean": "node-gyp clean", | ||
"test": "xo && babel-tap test/*.spec.js" | ||
"test": "xo && nyc --reporter=lcov ava -r babel-register" | ||
}, | ||
@@ -30,13 +30,14 @@ "repository": { | ||
"dependencies": { | ||
"any-promise": "^1.3.0", | ||
"bindings": "^1.2.1", | ||
"nan": "^2.2.1" | ||
"nan": "^2.4.0" | ||
}, | ||
"devDependencies": { | ||
"babel-cli": "^6.9.0", | ||
"babel-preset-es2015": "^6.6.0", | ||
"babel-preset-stage-3": "^6.5.0", | ||
"babel-tap": "^5.0.0", | ||
"benchmark": "^2.1.0", | ||
"bluebird": "^3.4.0", | ||
"tap": "^5.7.2", | ||
"ava": "^0.16.0", | ||
"babel-cli": "^6.11.4", | ||
"babel-plugin-transform-async-to-generator": "^6.8.0", | ||
"babel-preset-es2015": "^6.9.0", | ||
"babel-register": "^6.11.6", | ||
"nyc": "^8.0.0", | ||
"sandra": "^0.1.0", | ||
"xo": "^0.16.0" | ||
@@ -43,0 +44,0 @@ }, |
136
README.md
@@ -1,46 +0,10 @@ | ||
# 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] | ||
# 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] [![Codewake][codewake-image]][codewake-url] | ||
Bindings to the reference [Argon2](https://github.com/P-H-C/phc-winner-argon2) | ||
implementation. | ||
**Warning: synchronous API has been removed as of 0.12, either use async/await | ||
(recommended) or keep with 0.11.x if you need it.** | ||
**Want to use it on command line? Instead check | ||
[node-argon2-cli](https://github.com/ranisalt/node-argon2-cli).** | ||
### Before installing | ||
**Don't forget to checkout submodules! Always `git clone --recursive` or run | ||
`git submodule update --init` after cloning.** | ||
You **MUST** have a **node-gyp** global install before proceeding with install, | ||
along with GCC >= 4.8 / Clang >= 3.3. On Windows, you must compile under Visual | ||
Studio 2015 or newer. | ||
**node-argon2** works only and is tested against Node >=4.0.0. | ||
#### OSX | ||
To install GCC >= 4.8 on OSX, use [homebrew](http://brew.sh/): | ||
```console | ||
$ brew install gcc | ||
``` | ||
Once you've got GCC installed and ready to run, you then need to install | ||
node-gyp, you must do this globally: | ||
```console | ||
$ npm install -g node-gyp | ||
``` | ||
Finally, once node-gyp is installed and ready to go, you can install this | ||
library, specifying the GCC or Clang binary to use: | ||
```console | ||
$ CXX=g++-5 npm install argon2 | ||
``` | ||
**NOTE**: If your GCC or Clang binary is named something different than `g++-5`, | ||
you'll need to specify that in the command. | ||
### Usage | ||
@@ -62,10 +26,2 @@ It's possible to hash a password using both Argon2i (default) and Argon2d, sync | ||
// OR | ||
try { | ||
const hash = argon2.hashSync('password', salt); | ||
} catch (err) { | ||
//... | ||
} | ||
// ES7 | ||
@@ -90,12 +46,2 @@ | ||
// OR | ||
try { | ||
const hash = argon2.hashSync('password', salt, { | ||
argon2d: true | ||
}); | ||
} catch (err) { | ||
// internal failure | ||
} | ||
// ES7 | ||
@@ -121,6 +67,2 @@ | ||
// OR | ||
var salt = argon2.generateSaltSync(); | ||
// ES7 | ||
@@ -137,6 +79,2 @@ | ||
// OR | ||
var salt = argon2.generateSaltSync(32); | ||
// ES7 | ||
@@ -147,4 +85,5 @@ | ||
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 change the Promise with | ||
[any-promise](https://www.npmjs.com/package/any-promise). Try using Bluebird or | ||
Q for enhanced functionality. | ||
@@ -165,6 +104,2 @@ You can also modify time, memory and parallelism constraints passing the object | ||
// OR | ||
const hash = argon2.hashSync('password', argon2.generateSaltSync(), options); | ||
// ES7 | ||
@@ -193,14 +128,2 @@ | ||
// OR | ||
try { | ||
if (argon2.verifySync('<big long hash>', 'password')) { | ||
// password match | ||
} else { | ||
// password did not match | ||
} | ||
} catch (err) { | ||
// internal failure | ||
} | ||
// ES7 | ||
@@ -224,2 +147,47 @@ | ||
### Differences from [node-argon2-ffi](https://github.com/cjlarose/argon2-ffi) | ||
This library is implemented natively, meaning it is an extension to the node | ||
engine. Thus, half of the code are C++ bindings, the other half are Javascript | ||
functions. node-argon2-ffi uses ffi, a mechanism to call functions from one | ||
language in another, and handles the type bindings (e.g. JS Number -> C++ int). | ||
The interface of both are very similar, notably node-argon2-ffi splits the | ||
argon2i and argon2d function set, but the differences stop there. Also, while | ||
node-argon2-ffi suggests you promisify `crypto.randomBytes`, this library has | ||
`generateSalt` which is exactly the same. | ||
Performance-wise, the libraries are equal. You can run the same benchmark suite | ||
if you are curious, but both can perform around 130 hashes/second on an Intel | ||
Core i5-4460 @ 3.2GHz with default options. | ||
### Before installing | ||
You **MUST** have a **node-gyp** global install before proceeding with install, | ||
along with GCC >= 4.8 / Clang >= 3.3. On Windows, you must compile under Visual | ||
Studio 2015 or newer. | ||
**node-argon2** works only and is tested against Node >=4.0.0. | ||
#### OSX | ||
To install GCC >= 4.8 on OSX, use [homebrew](http://brew.sh/): | ||
```console | ||
$ brew install gcc | ||
``` | ||
Once you've got GCC installed and ready to run, you then need to install | ||
node-gyp, you must do this globally: | ||
```console | ||
$ npm install -g node-gyp | ||
``` | ||
Finally, once node-gyp is installed and ready to go, you can install this | ||
library, specifying the GCC or Clang binary to use: | ||
```console | ||
$ CXX=g++-6 npm install argon2 | ||
``` | ||
**NOTE**: If your GCC or Clang binary is named something different than `g++-6`, | ||
you'll need to specify that in the command. | ||
# License | ||
@@ -240,1 +208,3 @@ Work licensed under the [MIT License](LICENSE). Please check | ||
[david-dm-url]: https://david-dm.org/ranisalt/node-argon2 | ||
[codewake-image]: https://www.codewake.com/badges/ask_question_flat_square.svg | ||
[codewake-url]: https://www.codewake.com/p/node-argon2 |
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
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
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
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
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
163570
3
29
225
202
+ Addedany-promise@^1.3.0
+ Addedany-promise@1.3.0(transitive)
Updatednan@^2.4.0