credential-plus
Advanced tools
Comparing version 1.0.0 to 2.0.0
118
index.js
@@ -7,34 +7,31 @@ 'use strict'; | ||
* Creates a new 'unique' hash from a password. | ||
* @public | ||
* @param {string} password The password to hash. | ||
* @param {object} options Options to configure the hash function. | ||
* @param {hashCallback} callback Called after the hash has been computed. | ||
* @param {string} options.func The name of the hash function to use. | ||
* @returns {Promise<string>} A promise that contains a stringified object | ||
* that holds the generated hash string, the name of the function used to hash | ||
* it. | ||
*/ | ||
/** | ||
* @callback hashCallback | ||
* @param {object} err Possible error thrown. | ||
* @param {string} hash Stringified hash object that holds the generated hash | ||
* string, the name of the function used and the parameters passed to the | ||
* hash funciton needed for the verification process. | ||
*/ | ||
function toHash(password, options, callback) { | ||
if (!options || !options.func) { | ||
return callback(new Error('You must provide an hash function to use.')); | ||
} | ||
const hashFunc = funcs[options.func]; | ||
function toHash(password, options) { | ||
return new Promise((resolve, reject) => { | ||
if (!options || !options.func) { | ||
return reject(new Error('You must provide an hash function to use.')); | ||
} | ||
const hashFunc = funcs[options.func]; | ||
if (!hashFunc) { | ||
return callback(new Error(options.func + ' hash function not installed.')); | ||
} else if (typeof password !== 'string' || password.length === 0) { | ||
return callback(new Error('Password must be a non-empty string.')); | ||
} | ||
hashFunc.hash(password, options, (err, hash) => { | ||
if (err) { | ||
return callback(err); | ||
if (!hashFunc) { | ||
return reject(new Error(options.func + ' hash function not installed.')); | ||
} else if (typeof password !== 'string' || password.length === 0) { | ||
return reject(new Error('Password must be a non-empty string.')); | ||
} | ||
callback(null, JSON.stringify({ | ||
hash, | ||
func: options.func | ||
})); | ||
hashFunc.hash(password, options) | ||
.then(hash => { | ||
resolve(JSON.stringify({ | ||
hash, | ||
func: options.func | ||
})); | ||
}) | ||
.catch(reject); | ||
}); | ||
@@ -45,43 +42,43 @@ } | ||
* Determines whether or not the user's input matches the stored password. | ||
* | ||
* @public | ||
* @param {string} hash Stringified hash object generated from this package. | ||
* @param {string} input User's password input. | ||
* @param {verifyCallback} callback Called after the verification process has | ||
* been computed. | ||
* @returns {Promise<boolean>} A promise that contains a boolean that is true if | ||
* if the hash computed for the input matches. | ||
*/ | ||
/** | ||
* @callback verifyCallback | ||
* @param {object} err Possible error thrown. | ||
* @param {boolean} match True if the hash computed for the input matches. | ||
*/ | ||
function verifyHash(hash, input, callback) { | ||
let hashObj; | ||
try { | ||
hashObj = JSON.parse(hash); | ||
} catch (err) { | ||
return callback(new Error('Couldn\'t parse the provided hash.')); | ||
} | ||
if (typeof hashObj.hash !== 'string' || typeof hashObj.func !== 'string' || hashObj.hash === '' || hashObj.func === '') { | ||
return callback(new Error('The provided hash is invalid.')); | ||
} | ||
function verifyHash(hash, input) { | ||
return new Promise((resolve, reject) => { | ||
let hashObj; | ||
try { | ||
hashObj = JSON.parse(hash); | ||
} catch (err) { | ||
return reject(new Error('Couldn\'t parse the provided hash.')); | ||
} | ||
if (typeof hashObj.hash !== 'string' || typeof hashObj.func !== 'string' || hashObj.hash === '' || hashObj.func === '') { | ||
return reject(new Error('The provided hash is invalid.')); | ||
} | ||
const hashFunc = funcs[hashObj.func]; | ||
const hashFunc = funcs[hashObj.func]; | ||
if (!hashFunc) { | ||
return callback(new Error(hashObj.func + ' hash function not installed.')); | ||
} else if (typeof (input) !== 'string' || input.length === 0) { | ||
return callback(new Error('Input password must be a non-empty string.')); | ||
} | ||
if (!hashFunc) { | ||
return reject(new Error(hashObj.func + ' hash function not installed.')); | ||
} else if (typeof (input) !== 'string' || input.length === 0) { | ||
return reject(new Error('Input password must be a non-empty string.')); | ||
} | ||
hashFunc.verify(hashObj.hash, input, callback); | ||
hashFunc.verify(hashObj.hash, input) | ||
.then(resolve) | ||
.catch(reject); | ||
}); | ||
} | ||
/** | ||
* Installs an hash function plugin. | ||
* @param {object} plugin A plugin compatible with this package. | ||
* Installs an hash function hashFunction. | ||
* @public | ||
* @param {object} hashFunction An hash function compatible with this package. | ||
*/ | ||
function installPlugin(plugin) { | ||
funcs[plugin.name] = { | ||
hash: plugin.hash, | ||
verify: plugin.verify | ||
function installFunction(hashFunction) { | ||
funcs[hashFunction.name] = { | ||
hash: hashFunction.hash, | ||
verify: hashFunction.verify | ||
}; | ||
@@ -91,5 +88,6 @@ } | ||
/** | ||
* @public | ||
* @return {array} The array of the available hash functions. | ||
*/ | ||
function listPlugins() { | ||
function listFunctions() { | ||
return Object.keys(funcs); | ||
@@ -101,4 +99,4 @@ } | ||
hash: toHash, | ||
install: installPlugin, | ||
plugins: listPlugins | ||
install: installFunction, | ||
list: listFunctions | ||
}; |
{ | ||
"name": "credential-plus", | ||
"version": "1.0.0", | ||
"description": "Easy password hashing and verification in NodeJS", | ||
"version": "2.0.0", | ||
"description": "Password hashin and verification made easy!", | ||
"main": "index.js", | ||
@@ -11,3 +11,2 @@ "dependencies": {}, | ||
"nyc": "^11.0.3", | ||
"pify": "^3.0.0", | ||
"xo": "*" | ||
@@ -14,0 +13,0 @@ }, |
212
README.md
@@ -1,26 +0,51 @@ | ||
# credential-plus | ||
[![Travis CI](https://travis-ci.org/simonepri/credential-plus.svg?branch=master)](https://travis-ci.org/simonepri/credential-plus) [![Codecov](https://img.shields.io/codecov/c/github/simonepri/credential-plus/master.svg)](https://codecov.io/gh/simonepri/credential-plus) [![npm](https://img.shields.io/npm/dm/credential-plus.svg)](https://www.npmjs.com/package/credential-plus) [![npm version](https://img.shields.io/npm/v/credential-plus.svg)](https://www.npmjs.com/package/credential-plus) [![npm dependencies](https://david-dm.org/simonepri/credential-plus.svg)](https://david-dm.org/simonepri/credential-plus) [![npm dev dependencies](https://david-dm.org/simonepri/credential-plus/dev-status.svg)](https://david-dm.org/simonepri/credential-plus#info=devDependencies) | ||
> 🛡 Easy password hashing and verification in Node. Protects against brute force, rainbow tables, and timing attacks. | ||
<h1 align="center"> | ||
<img src="./media/credential-plus.png" alt="credential-plus" /> | ||
</h1> | ||
<div align="center"> | ||
<a href="https://travis-ci.org/simonepri/credential-plus"> <img src="https://travis-ci.org/simonepri/credential-plus.svg?branch=master" alt="build status"></a> | ||
<a href="https://codecov.io/gh/simonepri/credential-plus"><img src="https://img.shields.io/codecov/c/github/simonepri/credential-plus/master.svg" alt="code coverage" /></a> | ||
<a href="https://github.com/sindresorhus/xo"><img src="https://img.shields.io/badge/code_style-XO-5ed9c7.svg" alt="code style" /></a> | ||
<a href="https://www.npmjs.com/package/credential-plus"><img src="https://img.shields.io/npm/v/credential-plus.svg" alt="npm version" /></a> | ||
<a href="https://www.npmjs.com/package/credential-plus"><img src="https://img.shields.io/npm/dm/credential-plus.svg" alt="npm downloads" /></a> | ||
<a href="https://david-dm.org/simonepri/credential-plus"><img src="https://david-dm.org/simonepri/credential-plus.svg" alt="dependencies" /></a> | ||
<a href="https://david-dm.org/simonepri/credential-plus#info=devDependencies"><img src="https://david-dm.org/simonepri/credential-plus/dev-status.svg" alt="dev dependencies" /></a> | ||
<a href="LICENSE"><img src="https://img.shields.io/github/license/simonepri/credential-plus-bcrypt.svg" alt="license" /></a> | ||
</div> | ||
<br /> | ||
<div align="center"> | ||
🛡 Easy password hashing and verification in Node. | ||
</div> | ||
<div align="center"> | ||
<sub> | ||
Protects against brute force, rainbow tables, and timing attacks. | ||
</sub> | ||
</div> | ||
## Intro | ||
## Install | ||
``` | ||
```bash | ||
$ npm install --save credential-plus | ||
``` | ||
# Plugins | ||
## Hash functions | ||
This package is build with modularity in mind and supports multiple hash functions. | ||
In order to use this package you need to pick at least one of them from this list: | ||
In order to use this package you need at least one plugin. (aka hash function) | ||
You can chose one ore more of those plugins: | ||
Hash function name | Package to install | ||
-------------------|------------------- | ||
pbkdf2 | [credential-plus-pbkdf2](https://github.com/simonepri/credential-plus-pbkdf2) | ||
bcrypt | [credential-plus-bcrypt](https://github.com/simonepri/credential-plus-bcrypt) | ||
scrypt | [credential-plus-scrypt](https://github.com/simonepri/credential-plus-scrypt) | ||
argon2 | [credential-plus-argon2](https://github.com/simonepri/credential-plus-argon2) | ||
* [credential-plus-pbkdf2](https://github.com/simonepri/credential-plus-pbkdf2) | ||
* [credential-plus-bcrypt](https://github.com/simonepri/credential-plus-bcrypt) | ||
* [credential-plus-scrypt](https://github.com/simonepri/credential-plus-scrypt) | ||
* [credential-plus-argon2](https://github.com/simonepri/credential-plus-argon2) | ||
In the next section we will use `pbkdf2` for examples, replace it with your choice if differs. | ||
If you create your own plugin, please open a PR and add it to this list. | ||
```bash | ||
$ npm install --save credential-plus-pbkdf2 | ||
``` | ||
## Usage | ||
Lets call `X` the plugin package of your choice. | ||
```js | ||
@@ -30,20 +55,27 @@ const credential = require('credential-plus'); | ||
// Installs the plugin. Replace 'X' with your choice. | ||
credential.install(require('credential-plus-X')); | ||
credential.install(require('credential-plus-pbkdf2')); | ||
// Hash and verify with default configs. | ||
credential.hash('We are all humans', {func: 'X'}, (err, hash) => { | ||
console.log(hash); | ||
//=> '{"hash":"generated hash", "func":"X"}' | ||
credential.verify(hash, 'We are all humans', (match) =>{ | ||
console.log(match); | ||
//=> true | ||
}) | ||
credential.verify(hash, 'We are all unicorns', (match) =>{ | ||
console.log(match); | ||
//=> false | ||
}) | ||
}); | ||
credential.hash('We are all humans', {func: 'pbkdf2'}) | ||
.then(hash) => { | ||
console.log(hash); | ||
//=> '{"hash":"generated hash", "func":"pbkdf2"}' | ||
credential.verify(hash, 'We are all humans') | ||
.then(match) => { | ||
console.log(match); | ||
//=> true | ||
}); | ||
credential.verify(hash, 'We are all unicorns') | ||
.then(match) => { | ||
console.log(match); | ||
//=> false | ||
}); | ||
}); | ||
``` | ||
You can find more detailed usage in the ***usage*** section of each plugin: | ||
You can find more detailed usage examples in the ***usage*** section of each plugin: | ||
@@ -55,29 +87,39 @@ * [pbkdf2](https://github.com/simonepri/credential-plus-pbkdf2#usage) | ||
## API TOC | ||
<dl> | ||
<dt><a href="#hash">hash(password, options)</a> ⇒ <code>Promise.<string></code></dt> | ||
<dd><p>Creates a new 'unique' hash from a password.</p> | ||
</dd> | ||
<dt><a href="#verify">verify(hash, input)</a> ⇒ <code>Promise.<boolean></code></dt> | ||
<dd><p>Determines whether or not the user's input matches the stored password.</p> | ||
</dd> | ||
<dt><a href="#install">install(hashFunction)</a></dt> | ||
<dd><p>Installs an hash function hashFunction.</p> | ||
</dd> | ||
<dt><a href="#list">list()</a> ⇒ <code>array</code></dt> | ||
<dd></dd> | ||
</dl> | ||
## API | ||
### hash(password, options, callback) | ||
<a name="hash"></a> | ||
## hash(password, options) ⇒ <code>Promise.<string></code> | ||
Creates a new 'unique' hash from a password. | ||
#### password | ||
**Kind**: global function | ||
**Returns**: <code>Promise.<string></code> - A promise that contains a stringified object | ||
that holds the generated hash string, the name of the function used to hash | ||
it. | ||
**Access**: public | ||
Type: `string` | ||
| Param | Type | Description | | ||
| --- | --- | --- | | ||
| password | <code>string</code> | The password to hash. | | ||
| options | <code>object</code> | Options to configure the hash function. | | ||
| options.func | <code>string</code> | The name of the hash function to use. | | ||
The password to hash. | ||
#### options | ||
Type: `object` | ||
Configurations for the hash function. | ||
##### func | ||
Type: `string`<br> | ||
The name of the plugin (hash function) to use. | ||
This is the only option field required. | ||
Options available are different for each hash function.<br> | ||
See the API section of the plugin you choose for more details: | ||
See the ***API*** section of the plugin you choose for more details: | ||
@@ -89,66 +131,36 @@ * [pbkdf2](https://github.com/simonepri/credential-plus-pbkdf2#options) | ||
#### callback(err, hash) | ||
<a name="verify"></a> | ||
Type: `function` | ||
Called after the hash has been computed. | ||
#### err | ||
Type: `object` | ||
Possible error thrown. | ||
#### hash | ||
Type: `object` | ||
The generated hash. | ||
### verify(hash, input, callback) | ||
## verify(hash, input) ⇒ <code>Promise.<boolean></code> | ||
Determines whether or not the user's input matches the stored password. | ||
#### hash | ||
**Kind**: global function | ||
**Returns**: <code>Promise.<boolean></code> - A promise that contains a boolean that is true if | ||
if the hash computed for the input matches. | ||
**Access**: public | ||
Type: `string` | ||
| Param | Type | Description | | ||
| --- | --- | --- | | ||
| hash | <code>string</code> | Stringified hash object generated from this package. | | ||
| input | <code>string</code> | User's password input. | | ||
An hash generated from this package. | ||
<a name="install"></a> | ||
#### input | ||
## install(hashFunction) | ||
Installs an hash function hashFunction. | ||
Type: `string` | ||
**Kind**: global function | ||
**Access**: public | ||
User's input input. | ||
| Param | Type | Description | | ||
| --- | --- | --- | | ||
| hashFunction | <code>object</code> | An hash function compatible with this package. | | ||
#### callback(err, valid) | ||
<a name="list"></a> | ||
Type: `string` | ||
## list() ⇒ <code>array</code> | ||
**Kind**: global function | ||
**Returns**: <code>array</code> - The array of the available hash functions. | ||
**Access**: public | ||
Called after the verification process has been computed. | ||
#### err | ||
Type: `object` | ||
Possible error thrown. | ||
##### valid | ||
Type: `boolean` | ||
True if the hash computed for the input matches. | ||
### install(plugin) | ||
Installs an hash function plugin. | ||
#### plugin | ||
A plugin compatible with this package. | ||
### plugins() | ||
Returns the array of the installed plugins (hash functions). | ||
## Authors | ||
@@ -155,0 +167,0 @@ * **Simone Primarosa** - [simonepri](https://github.com/simonepri) |
102783
4
6
170
87