UNPKG

13.9 kBMarkdownView Raw
1```
2_________________________________________________/\/\___________________
3_/\/\/\/\/\__/\/\__/\/\____/\/\/\/\__/\/\__/\/\__/\/\________/\/\/\/\___
4_____/\/\______/\/\/\____/\/\________/\/\__/\/\__/\/\/\/\____/\/\__/\/\_
5___/\/\________/\/\/\____/\/\__________/\/\/\____/\/\__/\/\__/\/\__/\/\_
6_/\/\/\/\/\__/\/\__/\/\____/\/\/\/\______/\______/\/\/\/\____/\/\__/\/\_
7________________________________________________________________________
8```
9
10[![Build Status](https://travis-ci.org/dropbox/zxcvbn.svg?branch=master)](https://travis-ci.org/dropbox/zxcvbn)
11[![Sauce Test Status](https://saucelabs.com/browser-matrix/dropbox-zxcvbn.svg)](https://saucelabs.com/u/dropbox-zxcvbn)
12
13`zxcvbn` is a password strength estimator inspired by password crackers. Through pattern matching and conservative entropy calculations, it recognizes and weighs 10k common passwords, common names and surnames according to US census data, popular English words, and other common patterns like dates, repeats (`aaa`), sequences (`abcd`), keyboard patterns (`qwertyuiop`), and l33t speak.
14
15Consider using zxcvbn as an algorithmic alternative to password policy — it is more secure, flexible, and usable when sites require a minimal complexity score in place of annoying rules like "passwords must contain three of {lower, upper, numbers, symbols}".
16
17* __More secure__: policies often fail both ways, allowing weak passwords (`P@ssword1`) and disallowing strong passwords.
18* __More flexible__: zxcvbn allows many password styles to flourish so long as it detects sufficient complexity — passphrases are rated highly given enough uncommon words, keyboard patterns are either terrible or great depending on length and number of turns, and capitalization adds more complexity when it's unpredictaBle. Neither crackers nor zxcvbn are fooled by `'@'` for `'a'` or `'0'` for `'o'`.
19* __More usable__: Dumping a list of password rules onto users hurts usability. Understanding and satisfying said rules can be time-consuming and frustrating, leading to passwords that are [harder to remember](https://xkcd.com/936/). Use zxcvbn instead to build simple, rule-free interfaces that give instant feedback.
20
21At Dropbox we use zxcvbn on our [signup page](https://www.dropbox.com/register) and change/reset password flows. zxcvbn is designed for node and the browser, but we use our [python port](https://github.com/dropbox/python-zxcvbn) inside the Dropbox desktop client, [Objective C port](https://github.com/dropbox/zxcvbn-ios) in our iOS app, and Java port (not yet open sourced) on Android.
22
23[Release notes](https://github.com/dropbox/zxcvbn/releases)
24
25For more motivation, see:
26
27http://tech.dropbox.com/?p=165
28
29# Installation
30
31zxcvbn detects and supports CommonJS (node, browserify) and AMD (RequireJS). In the absence of those, it adds a single function `zxcvbn()` to the global namespace.
32
33## Bower
34
35Install [`node`](https://nodejs.org/download/) and [`bower`](http://bower.io/) if you haven't already. This won't make your codebase dependent on node or bower.
36
37Get `zxcvbn`:
38
39``` shell
40cd /path/to/project/root
41bower install zxcvbn
42```
43
44Add this script to your `index.html`:
45
46``` html
47<script type="text/javascript" src="bower_components/zxcvbn/dist/zxcvbn.js">
48</script>
49```
50
51To make sure it loaded properly, open your html in a browser and type `zxcvbn('Tr0ub4dour&3')` into the console.
52
53To pull in updates and bug fixes:
54
55``` shell
56bower update zxcvbn
57```
58
59## Node / npm
60
61zxcvbn works identically on the server.
62
63``` shell
64$ npm install zxcvbn
65$ node
66> var zxcvbn = require('zxcvbn');
67> zxcvbn('Tr0ub4dour&3');
68```
69
70## RequireJS
71
72Add [`zxcvbn.js`](https://raw.githubusercontent.com/dropbox/zxcvbn/master/dist/zxcvbn.js) to your project (using bower, npm or direct download) and import as usual:
73
74``` javascript
75requirejs(["relpath/to/zxcvbn"], function (zxcvbn) {
76 console.log(zxcvbn('Tr0ub4dour&3'));
77});
78```
79
80## Browserify / Webpack
81
82If you're using `npm` and have `require('zxcvbn')` somewhere in your code, browserify and webpack should just work.
83
84``` shell
85$ npm install zxcvbn
86$ echo "console.log(require('zxcvbn'))" > mymodule.js
87$ browserify mymodule.js > browserify_bundle.js
88$ webpack mymodule.js webpack_bundle.js
89```
90
91But we recommend against bundling zxcvbn via tools like browserify and webpack, for three reasons:
92
93* Minified and gzipped, zxcvbn is still several hundred kilobytes. (Significantly grows bundle size.)
94* Most sites will only need zxcvbn on a few pages (registration, password reset).
95* Most sites won't need `zxcvbn()` immediately upon page load; since `zxcvbn()` is typically called in response to user events like filling in a password, there's ample time to fetch `zxcvbn.js` after initial html/css/js loads and renders.
96
97See the [performance](#perf) section below for tips on loading zxcvbn stand-alone.
98
99Tangentially, if you want to build your own standalone, consider tweaking the browserify pipeline used to generate `dist/zxcvbn.js`:
100
101``` shell
102$ browserify --debug --standalone zxcvbn \
103 -t coffeeify --extension='.coffee' \
104 -t uglifyify \
105 src/main.coffee | exorcist dist/zxcvbn.js.map >| dist/zxcvbn.js
106```
107
108* `--debug` adds an inline source map to the bundle. `exorcist` pulls it out into `dist/zxcvbn.js.map`.
109* `--standalone zxcvbn` exports a global `zxcvbn` when CommonJS/AMD isn't detected.
110* `-t coffeeify --extension='.coffee'` compiles `.coffee` to `.js` before bundling. This is convenient as it allows `.js` modules to import from `.coffee` modules and vice-versa. Instead of this transform, one could also compile everything to `.js` first (`npm run prepublish`) and point `browserify` to `lib` instead of `src`.
111* `-t uglifyify` minifies the bundle through UglifyJS, maintaining proper source mapping.
112
113## Manual installation
114
115Download [zxcvbn.js](https://raw.githubusercontent.com/dropbox/zxcvbn/master/dist/zxcvbn.js).
116
117Add to your .html:
118
119``` html
120<script type="text/javascript" src="path/to/zxcvbn.js">
121</script>
122```
123
124# Usage
125
126``` javascript
127zxcvbn(password, user_inputs=[])
128```
129
130`zxcvbn()` takes one required argument, a password, and returns a result object with several properties:
131
132``` coffee
133result.guesses # estimated guesses needed to crack password
134result.guesses_log10 # order of magnitude of result.guesses
135
136result.crack_time_seconds # dictionary of back-of-the-envelope crack time
137 # estimations, in seconds, based on a few scenarios:
138{
139 # online attack on a service that ratelimits password auth attempts.
140 online_throttling_100_per_hour
141
142 # online attack on a service that doesn't ratelimit,
143 # or where an attacker has outsmarted ratelimiting.
144 online_no_throttling_10_per_second
145
146 # offline attack. assumes multiple attackers,
147 # proper user-unique salting, and a slow hash function
148 # w/ moderate work factor, such as bcrypt, scrypt, PBKDF2.
149 offline_slow_hashing_1e4_per_second
150
151 # offline attack with user-unique salting but a fast hash
152 # function like SHA-1, SHA-256 or MD5. A wide range of
153 # reasonable numbers anywhere from one billion - one trillion
154 # guesses per second, depending on number of cores and machines.
155 # ballparking at 10B/sec.
156 offline_fast_hashing_1e10_per_second
157}
158
159result.crack_time_display # same keys as result.crack_time_seconds,
160 # with friendlier display string values:
161 # "less than a second", "3 hours", "centuries", etc.
162
163result.score # Integer from 0-4 (useful for implementing a strength bar)
164
165 0 # too guessable: risky password. (guesses < 10^3)
166
167 1 # very guessable: protection from throttled online attacks. (guesses < 10^6)
168
169 2 # somewhat guessable: protection from unthrottled online attacks. (guesses < 10^8)
170
171 3 # safely unguessable: moderate protection from offline slow-hash scenario. (guesses < 10^10)
172
173 4 # very unguessable: strong protection from offline slow-hash scenario. (guesses >= 10^10)
174
175result.feedback # verbal feedback to help choose better passwords. set when score <= 2.
176
177 result.feedback.warning # explains what's wrong, eg. 'this is a top-10 common password'.
178 # not always set -- sometimes an empty string
179
180 result.feedback.suggestions # a possibly-empty list of suggestions to help choose a less
181 # guessable password. eg. 'Add another word or two'
182
183result.sequence # the list of patterns that zxcvbn based the
184 # guess calculation on.
185
186result.calc_time # how long it took zxcvbn to calculate an answer,
187 # in milliseconds.
188````
189
190The optional `user_inputs` argument is an array of strings that zxcvbn will treat as an extra dictionary. This can be whatever list of strings you like, but is meant for user inputs from other fields of the form, like name and email. That way a password that includes a user's personal information can be heavily penalized. This list is also good for site-specific vocabulary — Acme Brick Co. might want to include ['acme', 'brick', 'acmebrick', etc].
191
192[try zxcvbn interactively](https://dl.dropboxusercontent.com/u/209/zxcvbn/test/index.html) to see these docs in action.
193
194# <a name="perf"></a>Performance
195
196## runtime latency
197
198zxcvbn operates below human perception of delay for most input: ~5-20ms for ~25 char passwords on modern browsers/CPUs, ~100ms for passwords around 100 characters. To bound runtime latency for really long passwords, consider sending `zxcvbn()` only the first 100 characters or so of user input.
199
200## script load latency
201
202`zxcvbn.js` bundled and minified is about 320kb gzipped or 680kb uncompressed, most of which is dictionaries. Consider these tips if you're noticing page load latency on your site.
203
204* Make sure your server is configured to compress static assets for browsers that support it. ([nginx tutorial](https://rtcamp.com/tutorials/nginx/enable-gzip/), [apache/IIS tutorial](http://betterexplained.com/articles/how-to-optimize-your-site-with-gzip-compression/).)
205
206Then try one of these alternatives:
207
2081. Put your `<script src="zxcvbn.js">` tag at the end of your html, just before the closing `</body>` tag. This insures your page loads and renders before the browser fetches and loads `zxcvbn.js`. The downside with this approach is `zxcvbn()` becomes available later than had it been included in `<head>` — not an issue on most signup pages where users are filling out other fields first.
209
2102. If you're using requirejs, try loading `zxcvbn.js` separately from your main bundle. Something to watch out for: if `zxcvbn.js` is required inside a keyboard handler waiting for user input, the entire script might be loaded only after the user presses their first key, creating nasty latency. Avoid this by calling your handler once upon page load, independent of user input, such that the `requirejs()` call runs earlier.
211
2123. Use the HTML5 [`async`](http://www.w3schools.com/tags/att_script_async.asp) script attribute. Downside: [doesn't work](http://caniuse.com/#feat=script-async) in IE7-9 or Opera Mini.
213
2144. Include an inline `<script>` in `<head>` that asynchronously loads `zxcvbn.js` in the background. Despite the extra code I prefer this over (3) because it works in older browsers.
215
216``` javascript
217// cross-browser asynchronous script loading for zxcvbn.
218// adapted from http://friendlybit.com/js/lazy-loading-asyncronous-javascript/
219
220(function() {
221 var ZXCVBN_SRC = 'path/to/zxcvbn.js'; // eg. for a standard bower setup, 'bower_components/zxcvbn/zxcvbn.js'
222
223 var async_load = function() {
224 var first, s;
225 s = document.createElement('script');
226 s.src = ZXCVBN_SRC;
227 s.type = 'text/javascript';
228 s.async = true;
229 first = document.getElementsByTagName('script')[0];
230 return first.parentNode.insertBefore(s, first);
231 };
232
233 if (window.attachEvent != null) {
234 window.attachEvent('onload', async_load);
235 } else {
236 window.addEventListener('load', async_load, false);
237 }
238
239}).call(this);
240```
241
242# Development
243
244Bug reports and pull requests welcome!
245
246``` shell
247git clone https://github.com/dropbox/zxcvbn.git
248```
249
250zxcvbn is built with CoffeeScript, browserify, and uglify-js. CoffeeScript source lives in `src`, which gets compiled, bundled and minified into `dist/zxcvbn.js`.
251
252``` shell
253npm run build # builds dist/zxcvbn.js
254npm run watch # same, but quickly rebuilds as changes are made in src.
255```
256
257For debugging, both `build` and `watch` output an external source map `dist/zxcvbn.js.map` that points back to the original CoffeeScript code.
258
259Two source files, `adjacency_graphs.coffee` and `frequency_lists.coffee`, are generated by python scripts in `data-scripts` that read raw data from the `data` directory.
260
261For node developers, in addition to `dist`, the zxcvbn `npm` module includes a `lib` directory (hidden from git) that includes one compiled `.js` and `.js.map` file for every `.coffee` in `src`. See `prepublish` in `package.json` to learn more.
262
263# Acknowledgments
264
265[Dropbox](https://dropbox.com) for supporting open source!
266
267Leah Culver and Ryan Pearl for porting zxcvbn to [Objective C](https://github.com/dropbox/zxcvbn-ios) and [python](https://github.com/dropbox/python-zxcvbn).
268
269Mark Burnett for releasing his [10k top passwords list](http://xato.net/passwords/more-top-worst-passwords) and for his 2005 book, [Perfect Passwords: Selection, Protection, Authentication](http://www.amazon.com/Perfect-Passwords-Selection-Protection-Authentication/dp/1597490415).
270
271Wiktionary contributors for building a [frequency list of English](http://en.wiktionary.org/wiki/Wiktionary:Frequency_lists) as used in television and movies.
272
273Researchers at Concordia University for [studying password estimation rigorously](http://www.concordia.ca/cunews/main/stories/2015/03/25/does-your-password-pass-muster.html) and recommending zxcvbn.
274
275And [xkcd](https://xkcd.com/936/) for the inspiration :+1::horse::battery::heart: