• Stars
    star
    348
  • Rank 121,840 (Top 3 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created over 11 years ago
  • Updated about 2 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Easy password hashing and verification in Node. Protects against brute force, rainbow tables, and timing attacks.

Credential

Travis-CI

Warning!

Passwords are obsolete. It is not safe to manage user passwords in your own app, even if you use a well-tested, professionally audited library like Credential.

Please consider one of these alternative solutions from dedicated authentication security experts, instead of rolling your own password management:

I strongly recommend Magic, a passwordless authentication solution with a strong focus on user experience, developer experience, and cost savings. (Operating your own password hashing, security audits, or dealing with the fallout of data breaches can be extremely expensive).

It is irresponsible to the safety of your users to implement password authentication.

User password credential management is extremely risky and should not be attempted by most apps. Storing any user passwords on your servers is a threat to your user's personal and financial security. All app builders should delegate authentication to dedicated security experts.

I wrote Credential years ago because I could not find an adequately secure password hashing library for Node. Between the time I wrote it and now, cracked passwords have been responsible for more than 80% of hacking-related breaches and virtually every active login username in the world has been leaked along with corresponding passwords by one or more major password database thefts.

It's a really bad idea to use or write a library like this one yourself -- even one that wraps pbkdf2 or a similar work unit spec. Every new API opens up new attack vectors. Older APIs have had time to be examined by security experts. Prior to publishing Credential, I had it reviewed by all the security experts I could find, and opened it up to peer review in public security forums. I trust it more than any other password hashing library for JavaScript, but I would not trust it (or any other password-based alternative) to secure my own applications or users.

If you are in the business of storing hashed passwords, it's only a matter of time before the black hats own your system.

This library is deprecated and no longer maintained.

All other password libraries should also be considered obsolete.

What is Credential?

Easy password hashing and verification in Node. Credential accounts for brute force, rainbow tables, and timing attacks.

Credential employs cryptographically secure, per password salts to prevent rainbow table attacks. Key stretching is used to make brute force attacks impractical. A constant time verification check prevents variable response time attacks.

Installing

$ npm install --save credential

Examples

.hash()

var credential = require('credential'),
  pw = credential(),
  newPassword = 'I have a really great password.';

pw.hash(newPassword, function (err, hash) {
  if (err) { throw err; }
  console.log('Store the password hash.', hash);
});

.verify()

var credential = require('credential'),
  pw = credential(),
  storedHash = '{"hash":"gNofnhlBl36AdRyktwATxKoqWKa6hsIEzwCmW/YXN//7PtiJwCRbepV9fUKu0L9TJELCKoDiBy6rGM8ov7lg2yLY","salt":"yyN3KUzlr4KrKWMM2K3d2Ddxf8OTq+vkKG+mtnmQVIibxSJz8drfzkYzqcH0EM+PVKR/1nClRr/CPDuJsq+FOcIw","keyLength":66,"hashMethod":"pbkdf2","iterations":181019}',
  userInput = 'I have a really great password.';

pw.verify(storedHash, userInput, function (err, isValid) {
  var msg;
  if (err) { throw err; }
  msg = isValid ? 'Passwords match!' : 'Wrong password.';
  console.log(msg);
});

API

var pw = credential([options])

Return an instance of credential

Warning: Decreasing keyLength or work can make your password database less secure.

  • @param {Object} options Options object.
  • @param {Number} options.keyLength
  • @param {Number} options.work
  • @return {Object} credential object

pw.hash(password[, callback]) callback(err, hashJSON)

Takes a new password and creates a unique hash. Passes a JSON encoded object to the callback.

  • @param {[type]} password
  • @param {Function} callback If callback is not provided, hash returns a Promise

callback(err, hashJSON)

  • @param {Error} Error Error or null
  • @param {JSON} hashObject
  • @param {String} hashObject.hash
  • @param {String} hashObject.salt
  • @param {Number} hashObject.keyLength Bytes in hash
  • @param {String} hashObject.hashMethod
  • @param {Number} hashObject.iterations

pw.verify(hash, input[, callback]) callback(err, isValid)

Takes a stored hash, password input from the user, and a callback, and determines whether or not the user's input matches the stored password.

  • @param {String} hash A stored password hash
  • @param {String} input User's password input
  • @param {Function} callback If callback is not provided, verify returns a Promise

pw.expired(hash[, days = 90])

Takes a stored hash and a number of days, and determines if the hash is older than the specified days.

  • @param {String} hash A stored password hash
  • @param {Number} days Days before expiry

CLI

See CLI docs

Motivation

Several other libraries claim to do the same thing, but fall short. Several fail to use cryptographically secure salts, which make salt guessing possible. Others fail to use either a long enough salt, or a long enough hash. The salt should be the same size as the hash. No shorter, and no longer.

Others fail to use key stretching, or fail to use enough iterations (taking into account processor speeds, and clustered attacks, while balancing that against user experience).

Background

Passwords should be stored with a one way encryption hash, so that even if a malicious intruder obtains access to the user database, they still won't have access to user passwords.

The hash should be sufficiently long not just to prevent an attack from a single machine, but to prevent an attack from a large cluster of machines.

Worms targeting vulnerable versions of popular website platforms such as WordPress and Drupal have become common. Once such a worm takes control of a website and installs its payload, it can recruit all of the site's traffic into a JavaScript botnet, and, among other things, use visitor CPU power to crack stolen password databases which fail to implement the security precautions outlined here.

There are botnets that exist today with over 90,000 nodes. Such botnets could crack MD5 password hashes at a rate of nine billion per second.

Passwords are vulnerable to the following common attacks:

  • Rainbow tables
  • Brute force
  • Passwords stolen from third parties

Rainbow tables

Rainbow tables are precomputed tables used to look up passwords using stolen hashes. Once bad guys get their hands on user passwords, they'll attempt to attack popular services such as email and bank accounts -- which spells very bad PR for your service.

There are rainbow tables that exist today which can discover almost every possible password up to 14 characters. To prevent password theft by rainbow table, users should choose passwords of at least 14 characters. Sadly, such passwords are definitely not convenient, particularly on mobile devices. In other words, you should not rely on users to select appropriate passwords.

Rainbow tables can significantly reduce the time it takes to find a password, at the cost of memory, but with terabyte hard drives and gigabytes of RAM, it's a trade off that is easily made.

Password Salts

One defence you can employ against rainbow tables is password salting. A salt is a sequence of random characters that gets paired with a password during the hashing process. Salts should be cryptographically secure random values of a length equal to the hash size. Salts are not secrets, and can be safely stored in plaintext alongside the user's other credentials.

Salting can protect passwords in a couple of ways.

First: A uniquely generated salt can protect your password databases against existing rainbow tables. Using a random salt makes your site immune from these attacks. However, if you use the same salt for every password, a new rainbow table can be generated to attack the password database.

Second: If two different users use the same password, the compromised password will grant access to both user accounts. To prevent that, you must use a unique salt for each password. Doing so makes a rainbow table attack impractical.

Brute force

Rainbow tables get all the blogger attention, but Moore's Law is alive and well, and brute force has become a very real threat. Attackers are employing GPUs, super computing clusters that cost less than $2,000, and JavaScript botnets comprised of tens of thousands of browsers visiting infected websites.

A brute force attack will attempt to crack a password by attempting a match using every possible character combination. A simple single-iteration hash can be tested at the rate of millions of hashes per second on modern systems.

One way to thwart brute force attacks is to programmatically lock a user's account after a handful of failed login attempts. However, that strategy won't protect passwords if an attacker gains access to the password database.

Key stretching can make brute force attacks impractical by increasing the time it takes to hash the password. This can be done by applying the hash function in a loop. The delay will be relatively unnoticed by a user trying to sign in, but will significantly hamper an attacker attempting to discover a password through brute force.

For example, I discovered 100 hashes in less than 1ms using a simple MD5 algorithm, and then tried the same thing with Node's built-in crypto.pbkdf2() function (HMAC-SHA1) set to 80,000 iterations. PBKDF2 took 15.48 seconds. To a user performing a single login attempt per response, the slow down is barely noticed, but it slows brute force to a crawl.

Variable vs constant time equality

If it takes your service longer to say no to a slightly wrong password than a mostly wrong password, attackers can use that data to guess the password, similar to how you guess a word playing hangman. You might think that random time delays and network timing jitter would sufficiently mask those timing differences, but it turns out an attacker just needs to take more timing samples to filter out the noise and obtain statistically relevant timing data:

From Crosby et al. "Opportunities And Limits Of Remote Timing Attacks":

We have shown that, even though the Internet induces significant timing jitter, we can reliably distinguish remote timing differences as low as 20µs. A LAN environment has lower timing jitter, allowing us to reliably distinguish remote timing differences as small as 100ns (possibly even smaller). These precise timing differences can be distinguished with only hundreds or possibly thousands of measurements.

The best way to beat these attacks is to use a constant time hash equality check, rather than an optimized check. That is easily achieved by iterating through the full hash before returning the answer, regardless of how soon the answer is known.

Read more from Coda Hale's "A Lesson in Timing Attacks".

Created by Eric Elliott for the book, "Programming JavaScript Applications" (O'Reilly)

More Repositories

1

rtype

Intuitive structural type notation for JavaScript.
JavaScript
1,129
star
2

react-pure-component-starter

A pure component dev starter kit for React.
JavaScript
792
star
3

autodux

Automate the Redux boilerplate.
JavaScript
592
star
4

h5Validate

An HTML5 form validation plugin for jQuery. Works on all major browsers, both new and old. Implements inline, realtime validation best practices (based on surveys and usability studies). Developed for production use in e-commerce. Currently in production with millions of users.
JavaScript
577
star
5

moneysafe

Convenient, safe money calculations in JS
JavaScript
452
star
6

rfx

Self documenting runtime interfaces.
JavaScript
277
star
7

redux-dsm

Declarative state machines for Redux: Reduce your async-state boilerplate.
JavaScript
222
star
8

speculation

JavaScript promises are made to be broken. Speculations are cancellable promises.
JavaScript
197
star
9

irecord

An immutable store that exposes an RxJS observable. Great for React.
JavaScript
192
star
10

the-software-developers-library

The Software Developer's Library: a treasure trove of books for people who love code. Curated by Eric Elliott
192
star
11

react-things

A exploratory list of React ecosystem solutions
174
star
12

express-error-handler

A graceful error handler for Express and Restify applications.
JavaScript
168
star
13

feature-toggle

A painless feature toggle system in JavaScript. Decouple development and deployment.
JavaScript
155
star
14

ogen

Write synchronous looking code & mix synchronous & asynchronous results using generators & observables.
JavaScript
129
star
15

tdd-es6-react

Examples of TDD in ES6 with React
95
star
16

react-hello

A hello world example React app
JavaScript
63
star
17

fluentjs1

Talk - Fluent JavaScript Part 1: Prototypal OO. Learn to code like a JS native. Take advantage of JavaScript's distinguishing features in order to write better code.
JavaScript
53
star
18

neurolib

Neuron emulation tools
JavaScript
52
star
19

the-two-pillars-of-javascript-talk

References from "The Two Pillars of JavaScript" talk
51
star
20

maybearray

Native JavaScript Maybes built with arrays.
JavaScript
49
star
21

qconf

Painless configuration with defaults file, environment variables, arguments, function parameters.
JavaScript
45
star
22

object-list

Treat arrays of objects like a db you can query.
JavaScript
43
star
23

gql-validate

Validate a JS object against a GraphQL schema
JavaScript
33
star
24

bunyan-request-logger

Automated request logging middleware for Express. Powered by Bunyan.
JavaScript
29
star
25

tinyapp

A minimal, modular, client-side application framework.
JavaScript
28
star
26

arraygen

Turn any array into a generator.
JavaScript
28
star
27

dpath

Dot Path - FP sugar for immutables
JavaScript
22
star
28

rootrequire

npm install --save rootrequire # then `var root = require('rootrequire'), myLib = require(root + '/path/to/lib.js');`
JavaScript
19
star
29

siren-resource

Resourceful routing with siren+json hypermedia for Express.
JavaScript
18
star
30

version-healthcheck

A plug-and-play /version route for the Node.js Express framework.
JavaScript
17
star
31

react-easy-universal

Universal Routing & Rendering with React & Redux was too hard. Now it's easy.
JavaScript
16
star
32

odotjs

A prototypal OO library for JavaScript
JavaScript
13
star
33

todotasks

TodoMVC for task runners. Not sure which task runner to use? Take a look at some reference implementations.
JavaScript
12
star
34

react-test-demo

React Test Demo
CSS
12
star
35

react-faves

Favorite React Tools
12
star
36

jiron

Make your API self documenting and your clients adaptable to API changes.
11
star
37

saas-questions

SaaS Questions: The most important questions every SaaS company should have answers to.
10
star
38

applitude

JavaScript application namespacing and module management.
JavaScript
8
star
39

grange

Generate all sorts of values based on a range of numbers.
JavaScript
7
star
40

talks-and-interviews

A list of my talks and interviews.
7
star
41

tinyerror

Easy custom errors in browsers, Node, and Applitude
JavaScript
7
star
42

jQuery.outerHTML

A tiny outerHTML shim for jQuery
JavaScript
6
star
43

connect-cache-control

Connect middleware to prevent the browser from caching the response.
JavaScript
6
star
44

nfdata

NFData - A metadata proposal for NFT interoperability
5
star
45

xforms

xforms
JavaScript
5
star
46

sparkly

Ignite Learning, Inspire Creation
CSS
5
star
47

clctr

Event emitting collections with iterators (like Backbone.Collection).
JavaScript
3
star
48

ofilter

Array.prototype.filter for objects.
JavaScript
3
star
49

rejection

You gotta lose to win.
JavaScript
3
star
50

colab

A project collaboration platform centered on live video streaming and monetization.
CSS
3
star
51

slides-intro-to-js-objects

A basic (and short) overview of objects in JavaScript.
JavaScript
2
star
52

slides-modular-javascript

Modular JavaScript With npm and Node Modules
CoffeeScript
2
star
53

testling-jasmine

run jasmine tests in all the browsers with testling
JavaScript
2
star
54

hifi

Flow based programming for Node services.
1
star
55

resource-acl

An ACL intended for use with express-resource.
1
star
56

pja-guestlist-client

The browser client for Guestlist. A demo app for Programming JavaScript Applications.
JavaScript
1
star
57

course-primer

A primer for the "Learn JavaScript with Eric Elliott" course series. Prerequisite for all courses.
1
star
58

mapall

Given an array of promises, map to a same-ordered array of resolutions or rejections.
1
star
59

pja-sections

Draft sections for "Programming JavaScript Applications"
1
star
60

maybe-assign

Like Object.assign, but skip null or undefined props.
1
star