1 | //? if (typeof ISAAC === 'undefined') ISAAC = false;
|
2 | /*
|
3 | Copyright (c) 2012 Nevins Bartolomeo <nevins.bartolomeo@gmail.com>
|
4 | Copyright (c) 2012 Shane Girish <shaneGirish@gmail.com>
|
5 | Copyright (c) 2014 Daniel Wirtz <dcode@dcode.io>
|
6 |
|
7 | Redistribution and use in source and binary forms, with or without
|
8 | modification, are permitted provided that the following conditions
|
9 | are met:
|
10 | 1. Redistributions of source code must retain the above copyright
|
11 | notice, this list of conditions and the following disclaimer.
|
12 | 2. Redistributions in binary form must reproduce the above copyright
|
13 | notice, this list of conditions and the following disclaimer in the
|
14 | documentation and/or other materials provided with the distribution.
|
15 | 3. The name of the author may not be used to endorse or promote products
|
16 | derived from this software without specific prior written permission.
|
17 |
|
18 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
19 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
20 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
21 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
22 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
23 | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
27 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
28 | */
|
29 |
|
30 | /**
|
31 | //? if (ISAAC)
|
32 | * @license bcrypt-isaac.js (c) 2013 Daniel Wirtz <dcode@dcode.io>
|
33 | //? else
|
34 | * @license bcrypt.js (c) 2013 Daniel Wirtz <dcode@dcode.io>
|
35 | * Released under the Apache License, Version 2.0
|
36 | * see: https://github.com/dcodeIO/bcrypt.js for details
|
37 | */
|
38 | (function(global) {
|
39 | ;
|
40 |
|
41 | /**
|
42 | * bcrypt namespace.
|
43 | * @type {Object.<string,*>}
|
44 | */
|
45 | var bcrypt = {};
|
46 |
|
47 | /**
|
48 | * The random implementation to use as a fallback.
|
49 | * @type {?function(number):!Array.<number>}
|
50 | * @inner
|
51 | */
|
52 | var randomFallback = null;
|
53 |
|
54 | /**
|
55 | * Generates cryptographically secure random bytes.
|
56 | * @function
|
57 | * @param {number} len Bytes length
|
58 | * @returns {!Array.<number>} Random bytes
|
59 | * @throws {Error} If no random implementation is available
|
60 | * @inner
|
61 | */
|
62 | function random(len) {
|
63 | /* node */ if (typeof module !== 'undefined' && module && module['exports'])
|
64 | try {
|
65 | return require("crypto")['randomBytes'](len);
|
66 | } catch (e) {}
|
67 | /* WCA */ try {
|
68 | var a; (global['crypto']||global['msCrypto'])['getRandomValues'](a = new Uint32Array(len));
|
69 | return Array.prototype.slice.call(a);
|
70 | } catch (e) {}
|
71 | /* fallback */ if (!randomFallback)
|
72 | throw Error("Neither WebCryptoAPI nor a crypto module is available. Use bcrypt.setRandomFallback to set an alternative");
|
73 | return randomFallback(len);
|
74 | }
|
75 |
|
76 | // Test if any secure randomness source is available
|
77 | var randomAvailable = false;
|
78 | try {
|
79 | random(1);
|
80 | randomAvailable = true;
|
81 | } catch (e) {}
|
82 |
|
83 | // Default fallback, if any
|
84 | randomFallback = /*? if (ISAAC) { */function(len) {
|
85 | for (var a=[], i=0; i<len; ++i)
|
86 | a[i] = ((0.5 + isaac() * 2.3283064365386963e-10) * 256) | 0;
|
87 | return a;
|
88 | };/*? } else { */null;/*? }*/
|
89 |
|
90 |
|
91 | /**
|
92 | * Sets the pseudo random number generator to use as a fallback if neither node's `crypto` module nor the Web Crypto
|
93 | * API is available. Please note: It is highly important that the PRNG used is cryptographically secure and that it
|
94 | * is seeded properly!
|
95 | * @param {?function(number):!Array.<number>} random Function taking the number of bytes to generate as its
|
96 | * sole argument, returning the corresponding array of cryptographically secure random byte values.
|
97 | * @see http://nodejs.org/api/crypto.html
|
98 | * @see http://www.w3.org/TR/WebCryptoAPI/
|
99 | */
|
100 | bcrypt.setRandomFallback = function(random) {
|
101 | randomFallback = random;
|
102 | };
|
103 |
|
104 | /**
|
105 | * Synchronously generates a salt.
|
106 | * @param {number=} rounds Number of rounds to use, defaults to 10 if omitted
|
107 | * @param {number=} seed_length Not supported.
|
108 | * @returns {string} Resulting salt
|
109 | * @throws {Error} If a random fallback is required but not set
|
110 | * @expose
|
111 | */
|
112 | bcrypt.genSaltSync = function(rounds, seed_length) {
|
113 | if (typeof rounds === 'undefined')
|
114 | rounds = GENSALT_DEFAULT_LOG2_ROUNDS;
|
115 | else if (typeof rounds !== 'number')
|
116 | throw Error("Illegal arguments: "+(typeof rounds)+", "+(typeof seed_length));
|
117 | if (rounds < 4 || rounds > 31)
|
118 | throw Error("Illegal number of rounds (4-31): "+rounds);
|
119 | var salt = [];
|
120 | salt.push("$2a$");
|
121 | if (rounds < 10)
|
122 | salt.push("0");
|
123 | salt.push(rounds.toString());
|
124 | salt.push('$');
|
125 | salt.push(base64_encode(random(BCRYPT_SALT_LEN), BCRYPT_SALT_LEN)); // May throw
|
126 | return salt.join('');
|
127 | };
|
128 |
|
129 | /**
|
130 | * Asynchronously generates a salt.
|
131 | * @param {(number|function(Error, string=))=} rounds Number of rounds to use, defaults to 10 if omitted
|
132 | * @param {(number|function(Error, string=))=} seed_length Not supported.
|
133 | * @param {function(Error, string=)=} callback Callback receiving the error, if any, and the resulting salt
|
134 | * @expose
|
135 | */
|
136 | bcrypt.genSalt = function(rounds, seed_length, callback) {
|
137 | if (typeof seed_length === 'function')
|
138 | callback = seed_length,
|
139 | seed_length = undefined; // Not supported.
|
140 | if (typeof rounds === 'function')
|
141 | callback = rounds,
|
142 | rounds = GENSALT_DEFAULT_LOG2_ROUNDS;
|
143 | if (typeof callback !== 'function')
|
144 | throw Error("Illegal callback: "+typeof(callback));
|
145 | if (typeof rounds !== 'number') {
|
146 | nextTick(callback.bind(this, Error("Illegal arguments: "+(typeof rounds))));
|
147 | return;
|
148 | }
|
149 | nextTick(function() { // Pretty thin, but salting is fast enough
|
150 | try {
|
151 | callback(null, bcrypt.genSaltSync(rounds));
|
152 | } catch (err) {
|
153 | callback(err);
|
154 | }
|
155 | });
|
156 | };
|
157 |
|
158 | /**
|
159 | * Synchronously generates a hash for the given string.
|
160 | * @param {string} s String to hash
|
161 | * @param {(number|string)=} salt Salt length to generate or salt to use, default to 10
|
162 | * @returns {string} Resulting hash
|
163 | * @expose
|
164 | */
|
165 | bcrypt.hashSync = function(s, salt) {
|
166 | if (typeof salt === 'undefined')
|
167 | salt = GENSALT_DEFAULT_LOG2_ROUNDS;
|
168 | if (typeof salt === 'number')
|
169 | salt = bcrypt.genSaltSync(salt);
|
170 | if (typeof s !== 'string' || typeof salt !== 'string')
|
171 | throw Error("Illegal arguments: "+(typeof s)+', '+(typeof salt));
|
172 | return _hash(s, salt);
|
173 | };
|
174 |
|
175 | /**
|
176 | * Asynchronously generates a hash for the given string.
|
177 | * @param {string} s String to hash
|
178 | * @param {number|string} salt Salt length to generate or salt to use
|
179 | * @param {function(Error, string=)} callback Callback receiving the error, if any, and the resulting hash
|
180 | * @param {function(number)=} progressCallback Callback successively called with the percentage of rounds completed
|
181 | * (0.0 - 1.0), maximally once per `MAX_EXECUTION_TIME = 100` ms.
|
182 | * @expose
|
183 | */
|
184 | bcrypt.hash = function(s, salt, callback, progressCallback) {
|
185 | if (typeof callback !== 'function')
|
186 | throw Error("Illegal callback: "+typeof(callback));
|
187 | if (typeof s === 'string' && typeof salt === 'number')
|
188 | bcrypt.genSalt(salt, function(err, salt) {
|
189 | _hash(s, salt, callback, progressCallback);
|
190 | });
|
191 | else if (typeof s === 'string' && typeof salt === 'string')
|
192 | _hash(s, salt, callback, progressCallback);
|
193 | else
|
194 | nextTick(callback.bind(this, Error("Illegal arguments: "+(typeof s)+', '+(typeof salt))));
|
195 | };
|
196 |
|
197 | /**
|
198 | * Synchronously tests a string against a hash.
|
199 | * @param {string} s String to compare
|
200 | * @param {string} hash Hash to test against
|
201 | * @returns {boolean} true if matching, otherwise false
|
202 | * @throws {Error} If an argument is illegal
|
203 | * @expose
|
204 | */
|
205 | bcrypt.compareSync = function(s, hash) {
|
206 | if (typeof s !== "string" || typeof hash !== "string")
|
207 | throw Error("Illegal arguments: "+(typeof s)+', '+(typeof hash));
|
208 | if (hash.length !== 60)
|
209 | return false;
|
210 | var comp = bcrypt.hashSync(s, hash.substr(0, hash.length-31)),
|
211 | same = comp.length === hash.length,
|
212 | max_length = (comp.length < hash.length) ? comp.length : hash.length;
|
213 | // to prevent timing attacks, should check entire string
|
214 | // don't exit after found to be false
|
215 | for (var i = 0; i < max_length; ++i)
|
216 | if (comp.length >= i && hash.length >= i && comp[i] != hash[i])
|
217 | same = false;
|
218 | return same;
|
219 | };
|
220 |
|
221 | /**
|
222 | * Asynchronously compares the given data against the given hash.
|
223 | * @param {string} s Data to compare
|
224 | * @param {string} hash Data to be compared to
|
225 | * @param {function(Error, boolean)} callback Callback receiving the error, if any, otherwise the result
|
226 | * @param {function(number)=} progressCallback Callback successively called with the percentage of rounds completed
|
227 | * (0.0 - 1.0), maximally once per `MAX_EXECUTION_TIME = 100` ms.
|
228 | * @throws {Error} If the callback argument is invalid
|
229 | * @expose
|
230 | */
|
231 | bcrypt.compare = function(s, hash, callback, progressCallback) {
|
232 | if (typeof callback !== 'function')
|
233 | throw Error("Illegal callback: "+typeof(callback));
|
234 | if (typeof s !== "string" || typeof hash !== "string") {
|
235 | nextTick(callback.bind(this, Error("Illegal arguments: "+(typeof s)+', '+(typeof hash))));
|
236 | return;
|
237 | }
|
238 | bcrypt.hash(s, hash.substr(0, 29), function(err, comp) {
|
239 | callback(err, hash === comp);
|
240 | }, progressCallback);
|
241 | };
|
242 |
|
243 | /**
|
244 | * Gets the number of rounds used to encrypt the specified hash.
|
245 | * @param {string} hash Hash to extract the used number of rounds from
|
246 | * @returns {number} Number of rounds used
|
247 | * @throws {Error} If hash is not a string
|
248 | * @expose
|
249 | */
|
250 | bcrypt.getRounds = function(hash) {
|
251 | if (typeof hash !== "string")
|
252 | throw Error("Illegal arguments: "+(typeof hash));
|
253 | return parseInt(hash.split("$")[2], 10);
|
254 | };
|
255 |
|
256 | /**
|
257 | * Gets the salt portion from a hash. Does not validate the hash.
|
258 | * @param {string} hash Hash to extract the salt from
|
259 | * @returns {string} Extracted salt part
|
260 | * @throws {Error} If `hash` is not a string or otherwise invalid
|
261 | * @expose
|
262 | */
|
263 | bcrypt.getSalt = function(hash) {
|
264 | if (typeof hash !== 'string')
|
265 | throw Error("Illegal arguments: "+(typeof hash));
|
266 | if (hash.length !== 60)
|
267 | throw Error("Illegal hash length: "+hash.length+" != 60");
|
268 | return hash.substring(0, 29);
|
269 | };
|
270 |
|
271 | //? include("bcrypt/util.js");
|
272 |
|
273 | //? include("bcrypt/impl.js");
|
274 |
|
275 | //? if (ISAAC) {
|
276 | //? include("bcrypt/prng/accum.js");
|
277 |
|
278 | // Start accumulating
|
279 | if (!randomAvailable)
|
280 | accum.start();
|
281 |
|
282 | //? include("bcrypt/prng/isaac.js");
|
283 | //? }
|
284 |
|
285 | /* CommonJS */ if (typeof module !== 'undefined' && module["exports"])
|
286 | module["exports"] = bcrypt;
|
287 | /* AMD */ else if (typeof define !== 'undefined' && define["amd"])
|
288 | define(function() { return bcrypt; });
|
289 | /* Global */ else
|
290 | (global["dcodeIO"] = global["dcodeIO"] || {})["bcrypt"] = bcrypt;
|
291 |
|
292 | })(this);
|