bcrypt.js 54 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379
  1. /*
  2. Copyright (c) 2012 Nevins Bartolomeo <nevins.bartolomeo@gmail.com>
  3. Copyright (c) 2012 Shane Girish <shaneGirish@gmail.com>
  4. Copyright (c) 2014 Daniel Wirtz <dcode@dcode.io>
  5. Redistribution and use in source and binary forms, with or without
  6. modification, are permitted provided that the following conditions
  7. are met:
  8. 1. Redistributions of source code must retain the above copyright
  9. notice, this list of conditions and the following disclaimer.
  10. 2. Redistributions in binary form must reproduce the above copyright
  11. notice, this list of conditions and the following disclaimer in the
  12. documentation and/or other materials provided with the distribution.
  13. 3. The name of the author may not be used to endorse or promote products
  14. derived from this software without specific prior written permission.
  15. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  16. IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  17. OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  18. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  19. INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  20. NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  21. DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  22. THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  23. (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  24. THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. */
  26. /**
  27. * @license bcrypt.js (c) 2013 Daniel Wirtz <dcode@dcode.io>
  28. * Released under the Apache License, Version 2.0
  29. * see: https://github.com/dcodeIO/bcrypt.js for details
  30. */
  31. (function(global, factory) {
  32. /* AMD */ if (typeof define === 'function' && define["amd"])
  33. define([], factory);
  34. /* CommonJS */ else if (typeof require === 'function' && typeof module === "object" && module && module["exports"])
  35. module["exports"] = factory();
  36. /* Global */ else
  37. (global["dcodeIO"] = global["dcodeIO"] || {})["bcrypt"] = factory();
  38. }(this, function() {
  39. "use strict";
  40. /**
  41. * bcrypt namespace.
  42. * @type {Object.<string,*>}
  43. */
  44. var bcrypt = {};
  45. /**
  46. * The random implementation to use as a fallback.
  47. * @type {?function(number):!Array.<number>}
  48. * @inner
  49. */
  50. var randomFallback = null;
  51. /**
  52. * Generates cryptographically secure random bytes.
  53. * @function
  54. * @param {number} len Bytes length
  55. * @returns {!Array.<number>} Random bytes
  56. * @throws {Error} If no random implementation is available
  57. * @inner
  58. */
  59. function random(len) {
  60. /* node */ if (typeof module !== 'undefined' && module && module['exports'])
  61. try {
  62. return require("crypto")['randomBytes'](len);
  63. } catch (e) {}
  64. /* WCA */ try {
  65. var a; (self['crypto']||self['msCrypto'])['getRandomValues'](a = new Uint32Array(len));
  66. return Array.prototype.slice.call(a);
  67. } catch (e) {}
  68. /* fallback */ if (!randomFallback)
  69. throw Error("Neither WebCryptoAPI nor a crypto module is available. Use bcrypt.setRandomFallback to set an alternative");
  70. return randomFallback(len);
  71. }
  72. // Test if any secure randomness source is available
  73. var randomAvailable = false;
  74. try {
  75. random(1);
  76. randomAvailable = true;
  77. } catch (e) {}
  78. // Default fallback, if any
  79. randomFallback = null;
  80. /**
  81. * Sets the pseudo random number generator to use as a fallback if neither node's `crypto` module nor the Web Crypto
  82. * API is available. Please note: It is highly important that the PRNG used is cryptographically secure and that it
  83. * is seeded properly!
  84. * @param {?function(number):!Array.<number>} random Function taking the number of bytes to generate as its
  85. * sole argument, returning the corresponding array of cryptographically secure random byte values.
  86. * @see http://nodejs.org/api/crypto.html
  87. * @see http://www.w3.org/TR/WebCryptoAPI/
  88. */
  89. bcrypt.setRandomFallback = function(random) {
  90. randomFallback = random;
  91. };
  92. /**
  93. * Synchronously generates a salt.
  94. * @param {number=} rounds Number of rounds to use, defaults to 10 if omitted
  95. * @param {number=} seed_length Not supported.
  96. * @returns {string} Resulting salt
  97. * @throws {Error} If a random fallback is required but not set
  98. * @expose
  99. */
  100. bcrypt.genSaltSync = function(rounds, seed_length) {
  101. rounds = rounds || GENSALT_DEFAULT_LOG2_ROUNDS;
  102. if (typeof rounds !== 'number')
  103. throw Error("Illegal arguments: "+(typeof rounds)+", "+(typeof seed_length));
  104. if (rounds < 4)
  105. rounds = 4;
  106. else if (rounds > 31)
  107. rounds = 31;
  108. var salt = [];
  109. salt.push("$2a$");
  110. if (rounds < 10)
  111. salt.push("0");
  112. salt.push(rounds.toString());
  113. salt.push('$');
  114. salt.push(base64_encode(random(BCRYPT_SALT_LEN), BCRYPT_SALT_LEN)); // May throw
  115. return salt.join('');
  116. };
  117. /**
  118. * Asynchronously generates a salt.
  119. * @param {(number|function(Error, string=))=} rounds Number of rounds to use, defaults to 10 if omitted
  120. * @param {(number|function(Error, string=))=} seed_length Not supported.
  121. * @param {function(Error, string=)=} callback Callback receiving the error, if any, and the resulting salt
  122. * @returns {!Promise} If `callback` has been omitted
  123. * @throws {Error} If `callback` is present but not a function
  124. * @expose
  125. */
  126. bcrypt.genSalt = function(rounds, seed_length, callback) {
  127. if (typeof seed_length === 'function')
  128. callback = seed_length,
  129. seed_length = undefined; // Not supported.
  130. if (typeof rounds === 'function')
  131. callback = rounds,
  132. rounds = undefined;
  133. if (typeof rounds === 'undefined')
  134. rounds = GENSALT_DEFAULT_LOG2_ROUNDS;
  135. else if (typeof rounds !== 'number')
  136. throw Error("illegal arguments: "+(typeof rounds));
  137. function _async(callback) {
  138. nextTick(function() { // Pretty thin, but salting is fast enough
  139. try {
  140. callback(null, bcrypt.genSaltSync(rounds));
  141. } catch (err) {
  142. callback(err);
  143. }
  144. });
  145. }
  146. if (callback) {
  147. if (typeof callback !== 'function')
  148. throw Error("Illegal callback: "+typeof(callback));
  149. _async(callback);
  150. } else
  151. return new Promise(function(resolve, reject) {
  152. _async(function(err, res) {
  153. if (err) {
  154. reject(err);
  155. return;
  156. }
  157. resolve(res);
  158. });
  159. });
  160. };
  161. /**
  162. * Synchronously generates a hash for the given string.
  163. * @param {string} s String to hash
  164. * @param {(number|string)=} salt Salt length to generate or salt to use, default to 10
  165. * @returns {string} Resulting hash
  166. * @expose
  167. */
  168. bcrypt.hashSync = function(s, salt) {
  169. if (typeof salt === 'undefined')
  170. salt = GENSALT_DEFAULT_LOG2_ROUNDS;
  171. if (typeof salt === 'number')
  172. salt = bcrypt.genSaltSync(salt);
  173. if (typeof s !== 'string' || typeof salt !== 'string')
  174. throw Error("Illegal arguments: "+(typeof s)+', '+(typeof salt));
  175. return _hash(s, salt);
  176. };
  177. /**
  178. * Asynchronously generates a hash for the given string.
  179. * @param {string} s String to hash
  180. * @param {number|string} salt Salt length to generate or salt to use
  181. * @param {function(Error, string=)=} callback Callback receiving the error, if any, and the resulting hash
  182. * @param {function(number)=} progressCallback Callback successively called with the percentage of rounds completed
  183. * (0.0 - 1.0), maximally once per `MAX_EXECUTION_TIME = 100` ms.
  184. * @returns {!Promise} If `callback` has been omitted
  185. * @throws {Error} If `callback` is present but not a function
  186. * @expose
  187. */
  188. bcrypt.hash = function(s, salt, callback, progressCallback) {
  189. function _async(callback) {
  190. if (typeof s === 'string' && typeof salt === 'number')
  191. bcrypt.genSalt(salt, function(err, salt) {
  192. _hash(s, salt, callback, progressCallback);
  193. });
  194. else if (typeof s === 'string' && typeof salt === 'string')
  195. _hash(s, salt, callback, progressCallback);
  196. else
  197. nextTick(callback.bind(this, Error("Illegal arguments: "+(typeof s)+', '+(typeof salt))));
  198. }
  199. if (callback) {
  200. if (typeof callback !== 'function')
  201. throw Error("Illegal callback: "+typeof(callback));
  202. _async(callback);
  203. } else
  204. return new Promise(function(resolve, reject) {
  205. _async(function(err, res) {
  206. if (err) {
  207. reject(err);
  208. return;
  209. }
  210. resolve(res);
  211. });
  212. });
  213. };
  214. /**
  215. * Compares two strings of the same length in constant time.
  216. * @param {string} known Must be of the correct length
  217. * @param {string} unknown Must be the same length as `known`
  218. * @returns {boolean}
  219. * @inner
  220. */
  221. function safeStringCompare(known, unknown) {
  222. var right = 0,
  223. wrong = 0;
  224. for (var i=0, k=known.length; i<k; ++i) {
  225. if (known.charCodeAt(i) === unknown.charCodeAt(i))
  226. ++right;
  227. else
  228. ++wrong;
  229. }
  230. // Prevent removal of unused variables (never true, actually)
  231. if (right < 0)
  232. return false;
  233. return wrong === 0;
  234. }
  235. /**
  236. * Synchronously tests a string against a hash.
  237. * @param {string} s String to compare
  238. * @param {string} hash Hash to test against
  239. * @returns {boolean} true if matching, otherwise false
  240. * @throws {Error} If an argument is illegal
  241. * @expose
  242. */
  243. bcrypt.compareSync = function(s, hash) {
  244. if (typeof s !== "string" || typeof hash !== "string")
  245. throw Error("Illegal arguments: "+(typeof s)+', '+(typeof hash));
  246. if (hash.length !== 60)
  247. return false;
  248. return safeStringCompare(bcrypt.hashSync(s, hash.substr(0, hash.length-31)), hash);
  249. };
  250. /**
  251. * Asynchronously compares the given data against the given hash.
  252. * @param {string} s Data to compare
  253. * @param {string} hash Data to be compared to
  254. * @param {function(Error, boolean)=} callback Callback receiving the error, if any, otherwise the result
  255. * @param {function(number)=} progressCallback Callback successively called with the percentage of rounds completed
  256. * (0.0 - 1.0), maximally once per `MAX_EXECUTION_TIME = 100` ms.
  257. * @returns {!Promise} If `callback` has been omitted
  258. * @throws {Error} If `callback` is present but not a function
  259. * @expose
  260. */
  261. bcrypt.compare = function(s, hash, callback, progressCallback) {
  262. function _async(callback) {
  263. if (typeof s !== "string" || typeof hash !== "string") {
  264. nextTick(callback.bind(this, Error("Illegal arguments: "+(typeof s)+', '+(typeof hash))));
  265. return;
  266. }
  267. if (hash.length !== 60) {
  268. nextTick(callback.bind(this, null, false));
  269. return;
  270. }
  271. bcrypt.hash(s, hash.substr(0, 29), function(err, comp) {
  272. if (err)
  273. callback(err);
  274. else
  275. callback(null, safeStringCompare(comp, hash));
  276. }, progressCallback);
  277. }
  278. if (callback) {
  279. if (typeof callback !== 'function')
  280. throw Error("Illegal callback: "+typeof(callback));
  281. _async(callback);
  282. } else
  283. return new Promise(function(resolve, reject) {
  284. _async(function(err, res) {
  285. if (err) {
  286. reject(err);
  287. return;
  288. }
  289. resolve(res);
  290. });
  291. });
  292. };
  293. /**
  294. * Gets the number of rounds used to encrypt the specified hash.
  295. * @param {string} hash Hash to extract the used number of rounds from
  296. * @returns {number} Number of rounds used
  297. * @throws {Error} If `hash` is not a string
  298. * @expose
  299. */
  300. bcrypt.getRounds = function(hash) {
  301. if (typeof hash !== "string")
  302. throw Error("Illegal arguments: "+(typeof hash));
  303. return parseInt(hash.split("$")[2], 10);
  304. };
  305. /**
  306. * Gets the salt portion from a hash. Does not validate the hash.
  307. * @param {string} hash Hash to extract the salt from
  308. * @returns {string} Extracted salt part
  309. * @throws {Error} If `hash` is not a string or otherwise invalid
  310. * @expose
  311. */
  312. bcrypt.getSalt = function(hash) {
  313. if (typeof hash !== 'string')
  314. throw Error("Illegal arguments: "+(typeof hash));
  315. if (hash.length !== 60)
  316. throw Error("Illegal hash length: "+hash.length+" != 60");
  317. return hash.substring(0, 29);
  318. };
  319. /**
  320. * Continues with the callback on the next tick.
  321. * @function
  322. * @param {function(...[*])} callback Callback to execute
  323. * @inner
  324. */
  325. var nextTick = typeof process !== 'undefined' && process && typeof process.nextTick === 'function'
  326. ? (typeof setImmediate === 'function' ? setImmediate : process.nextTick)
  327. : setTimeout;
  328. /**
  329. * Converts a JavaScript string to UTF8 bytes.
  330. * @param {string} str String
  331. * @returns {!Array.<number>} UTF8 bytes
  332. * @inner
  333. */
  334. function stringToBytes(str) {
  335. var out = [],
  336. i = 0;
  337. utfx.encodeUTF16toUTF8(function() {
  338. if (i >= str.length) return null;
  339. return str.charCodeAt(i++);
  340. }, function(b) {
  341. out.push(b);
  342. });
  343. return out;
  344. }
  345. // A base64 implementation for the bcrypt algorithm. This is partly non-standard.
  346. /**
  347. * bcrypt's own non-standard base64 dictionary.
  348. * @type {!Array.<string>}
  349. * @const
  350. * @inner
  351. **/
  352. var BASE64_CODE = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".split('');
  353. /**
  354. * @type {!Array.<number>}
  355. * @const
  356. * @inner
  357. **/
  358. var BASE64_INDEX = [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  359. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  360. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0,
  361. 1, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, -1, -1, -1, -1, -1, -1,
  362. -1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
  363. 20, 21, 22, 23, 24, 25, 26, 27, -1, -1, -1, -1, -1, -1, 28, 29, 30,
  364. 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
  365. 48, 49, 50, 51, 52, 53, -1, -1, -1, -1, -1];
  366. /**
  367. * @type {!function(...number):string}
  368. * @inner
  369. */
  370. var stringFromCharCode = String.fromCharCode;
  371. /**
  372. * Encodes a byte array to base64 with up to len bytes of input.
  373. * @param {!Array.<number>} b Byte array
  374. * @param {number} len Maximum input length
  375. * @returns {string}
  376. * @inner
  377. */
  378. function base64_encode(b, len) {
  379. var off = 0,
  380. rs = [],
  381. c1, c2;
  382. if (len <= 0 || len > b.length)
  383. throw Error("Illegal len: "+len);
  384. while (off < len) {
  385. c1 = b[off++] & 0xff;
  386. rs.push(BASE64_CODE[(c1 >> 2) & 0x3f]);
  387. c1 = (c1 & 0x03) << 4;
  388. if (off >= len) {
  389. rs.push(BASE64_CODE[c1 & 0x3f]);
  390. break;
  391. }
  392. c2 = b[off++] & 0xff;
  393. c1 |= (c2 >> 4) & 0x0f;
  394. rs.push(BASE64_CODE[c1 & 0x3f]);
  395. c1 = (c2 & 0x0f) << 2;
  396. if (off >= len) {
  397. rs.push(BASE64_CODE[c1 & 0x3f]);
  398. break;
  399. }
  400. c2 = b[off++] & 0xff;
  401. c1 |= (c2 >> 6) & 0x03;
  402. rs.push(BASE64_CODE[c1 & 0x3f]);
  403. rs.push(BASE64_CODE[c2 & 0x3f]);
  404. }
  405. return rs.join('');
  406. }
  407. /**
  408. * Decodes a base64 encoded string to up to len bytes of output.
  409. * @param {string} s String to decode
  410. * @param {number} len Maximum output length
  411. * @returns {!Array.<number>}
  412. * @inner
  413. */
  414. function base64_decode(s, len) {
  415. var off = 0,
  416. slen = s.length,
  417. olen = 0,
  418. rs = [],
  419. c1, c2, c3, c4, o, code;
  420. if (len <= 0)
  421. throw Error("Illegal len: "+len);
  422. while (off < slen - 1 && olen < len) {
  423. code = s.charCodeAt(off++);
  424. c1 = code < BASE64_INDEX.length ? BASE64_INDEX[code] : -1;
  425. code = s.charCodeAt(off++);
  426. c2 = code < BASE64_INDEX.length ? BASE64_INDEX[code] : -1;
  427. if (c1 == -1 || c2 == -1)
  428. break;
  429. o = (c1 << 2) >>> 0;
  430. o |= (c2 & 0x30) >> 4;
  431. rs.push(stringFromCharCode(o));
  432. if (++olen >= len || off >= slen)
  433. break;
  434. code = s.charCodeAt(off++);
  435. c3 = code < BASE64_INDEX.length ? BASE64_INDEX[code] : -1;
  436. if (c3 == -1)
  437. break;
  438. o = ((c2 & 0x0f) << 4) >>> 0;
  439. o |= (c3 & 0x3c) >> 2;
  440. rs.push(stringFromCharCode(o));
  441. if (++olen >= len || off >= slen)
  442. break;
  443. code = s.charCodeAt(off++);
  444. c4 = code < BASE64_INDEX.length ? BASE64_INDEX[code] : -1;
  445. o = ((c3 & 0x03) << 6) >>> 0;
  446. o |= c4;
  447. rs.push(stringFromCharCode(o));
  448. ++olen;
  449. }
  450. var res = [];
  451. for (off = 0; off<olen; off++)
  452. res.push(rs[off].charCodeAt(0));
  453. return res;
  454. }
  455. /**
  456. * utfx-embeddable (c) 2014 Daniel Wirtz <dcode@dcode.io>
  457. * Released under the Apache License, Version 2.0
  458. * see: https://github.com/dcodeIO/utfx for details
  459. */
  460. var utfx = function() {
  461. "use strict";
  462. /**
  463. * utfx namespace.
  464. * @inner
  465. * @type {!Object.<string,*>}
  466. */
  467. var utfx = {};
  468. /**
  469. * Maximum valid code point.
  470. * @type {number}
  471. * @const
  472. */
  473. utfx.MAX_CODEPOINT = 0x10FFFF;
  474. /**
  475. * Encodes UTF8 code points to UTF8 bytes.
  476. * @param {(!function():number|null) | number} src Code points source, either as a function returning the next code point
  477. * respectively `null` if there are no more code points left or a single numeric code point.
  478. * @param {!function(number)} dst Bytes destination as a function successively called with the next byte
  479. */
  480. utfx.encodeUTF8 = function(src, dst) {
  481. var cp = null;
  482. if (typeof src === 'number')
  483. cp = src,
  484. src = function() { return null; };
  485. while (cp !== null || (cp = src()) !== null) {
  486. if (cp < 0x80)
  487. dst(cp&0x7F);
  488. else if (cp < 0x800)
  489. dst(((cp>>6)&0x1F)|0xC0),
  490. dst((cp&0x3F)|0x80);
  491. else if (cp < 0x10000)
  492. dst(((cp>>12)&0x0F)|0xE0),
  493. dst(((cp>>6)&0x3F)|0x80),
  494. dst((cp&0x3F)|0x80);
  495. else
  496. dst(((cp>>18)&0x07)|0xF0),
  497. dst(((cp>>12)&0x3F)|0x80),
  498. dst(((cp>>6)&0x3F)|0x80),
  499. dst((cp&0x3F)|0x80);
  500. cp = null;
  501. }
  502. };
  503. /**
  504. * Decodes UTF8 bytes to UTF8 code points.
  505. * @param {!function():number|null} src Bytes source as a function returning the next byte respectively `null` if there
  506. * are no more bytes left.
  507. * @param {!function(number)} dst Code points destination as a function successively called with each decoded code point.
  508. * @throws {RangeError} If a starting byte is invalid in UTF8
  509. * @throws {Error} If the last sequence is truncated. Has an array property `bytes` holding the
  510. * remaining bytes.
  511. */
  512. utfx.decodeUTF8 = function(src, dst) {
  513. var a, b, c, d, fail = function(b) {
  514. b = b.slice(0, b.indexOf(null));
  515. var err = Error(b.toString());
  516. err.name = "TruncatedError";
  517. err['bytes'] = b;
  518. throw err;
  519. };
  520. while ((a = src()) !== null) {
  521. if ((a&0x80) === 0)
  522. dst(a);
  523. else if ((a&0xE0) === 0xC0)
  524. ((b = src()) === null) && fail([a, b]),
  525. dst(((a&0x1F)<<6) | (b&0x3F));
  526. else if ((a&0xF0) === 0xE0)
  527. ((b=src()) === null || (c=src()) === null) && fail([a, b, c]),
  528. dst(((a&0x0F)<<12) | ((b&0x3F)<<6) | (c&0x3F));
  529. else if ((a&0xF8) === 0xF0)
  530. ((b=src()) === null || (c=src()) === null || (d=src()) === null) && fail([a, b, c ,d]),
  531. dst(((a&0x07)<<18) | ((b&0x3F)<<12) | ((c&0x3F)<<6) | (d&0x3F));
  532. else throw RangeError("Illegal starting byte: "+a);
  533. }
  534. };
  535. /**
  536. * Converts UTF16 characters to UTF8 code points.
  537. * @param {!function():number|null} src Characters source as a function returning the next char code respectively
  538. * `null` if there are no more characters left.
  539. * @param {!function(number)} dst Code points destination as a function successively called with each converted code
  540. * point.
  541. */
  542. utfx.UTF16toUTF8 = function(src, dst) {
  543. var c1, c2 = null;
  544. while (true) {
  545. if ((c1 = c2 !== null ? c2 : src()) === null)
  546. break;
  547. if (c1 >= 0xD800 && c1 <= 0xDFFF) {
  548. if ((c2 = src()) !== null) {
  549. if (c2 >= 0xDC00 && c2 <= 0xDFFF) {
  550. dst((c1-0xD800)*0x400+c2-0xDC00+0x10000);
  551. c2 = null; continue;
  552. }
  553. }
  554. }
  555. dst(c1);
  556. }
  557. if (c2 !== null) dst(c2);
  558. };
  559. /**
  560. * Converts UTF8 code points to UTF16 characters.
  561. * @param {(!function():number|null) | number} src Code points source, either as a function returning the next code point
  562. * respectively `null` if there are no more code points left or a single numeric code point.
  563. * @param {!function(number)} dst Characters destination as a function successively called with each converted char code.
  564. * @throws {RangeError} If a code point is out of range
  565. */
  566. utfx.UTF8toUTF16 = function(src, dst) {
  567. var cp = null;
  568. if (typeof src === 'number')
  569. cp = src, src = function() { return null; };
  570. while (cp !== null || (cp = src()) !== null) {
  571. if (cp <= 0xFFFF)
  572. dst(cp);
  573. else
  574. cp -= 0x10000,
  575. dst((cp>>10)+0xD800),
  576. dst((cp%0x400)+0xDC00);
  577. cp = null;
  578. }
  579. };
  580. /**
  581. * Converts and encodes UTF16 characters to UTF8 bytes.
  582. * @param {!function():number|null} src Characters source as a function returning the next char code respectively `null`
  583. * if there are no more characters left.
  584. * @param {!function(number)} dst Bytes destination as a function successively called with the next byte.
  585. */
  586. utfx.encodeUTF16toUTF8 = function(src, dst) {
  587. utfx.UTF16toUTF8(src, function(cp) {
  588. utfx.encodeUTF8(cp, dst);
  589. });
  590. };
  591. /**
  592. * Decodes and converts UTF8 bytes to UTF16 characters.
  593. * @param {!function():number|null} src Bytes source as a function returning the next byte respectively `null` if there
  594. * are no more bytes left.
  595. * @param {!function(number)} dst Characters destination as a function successively called with each converted char code.
  596. * @throws {RangeError} If a starting byte is invalid in UTF8
  597. * @throws {Error} If the last sequence is truncated. Has an array property `bytes` holding the remaining bytes.
  598. */
  599. utfx.decodeUTF8toUTF16 = function(src, dst) {
  600. utfx.decodeUTF8(src, function(cp) {
  601. utfx.UTF8toUTF16(cp, dst);
  602. });
  603. };
  604. /**
  605. * Calculates the byte length of an UTF8 code point.
  606. * @param {number} cp UTF8 code point
  607. * @returns {number} Byte length
  608. */
  609. utfx.calculateCodePoint = function(cp) {
  610. return (cp < 0x80) ? 1 : (cp < 0x800) ? 2 : (cp < 0x10000) ? 3 : 4;
  611. };
  612. /**
  613. * Calculates the number of UTF8 bytes required to store UTF8 code points.
  614. * @param {(!function():number|null)} src Code points source as a function returning the next code point respectively
  615. * `null` if there are no more code points left.
  616. * @returns {number} The number of UTF8 bytes required
  617. */
  618. utfx.calculateUTF8 = function(src) {
  619. var cp, l=0;
  620. while ((cp = src()) !== null)
  621. l += utfx.calculateCodePoint(cp);
  622. return l;
  623. };
  624. /**
  625. * Calculates the number of UTF8 code points respectively UTF8 bytes required to store UTF16 char codes.
  626. * @param {(!function():number|null)} src Characters source as a function returning the next char code respectively
  627. * `null` if there are no more characters left.
  628. * @returns {!Array.<number>} The number of UTF8 code points at index 0 and the number of UTF8 bytes required at index 1.
  629. */
  630. utfx.calculateUTF16asUTF8 = function(src) {
  631. var n=0, l=0;
  632. utfx.UTF16toUTF8(src, function(cp) {
  633. ++n; l += utfx.calculateCodePoint(cp);
  634. });
  635. return [n,l];
  636. };
  637. return utfx;
  638. }();
  639. Date.now = Date.now || function() { return +new Date; };
  640. /**
  641. * @type {number}
  642. * @const
  643. * @inner
  644. */
  645. var BCRYPT_SALT_LEN = 16;
  646. /**
  647. * @type {number}
  648. * @const
  649. * @inner
  650. */
  651. var GENSALT_DEFAULT_LOG2_ROUNDS = 10;
  652. /**
  653. * @type {number}
  654. * @const
  655. * @inner
  656. */
  657. var BLOWFISH_NUM_ROUNDS = 16;
  658. /**
  659. * @type {number}
  660. * @const
  661. * @inner
  662. */
  663. var MAX_EXECUTION_TIME = 100;
  664. /**
  665. * @type {Array.<number>}
  666. * @const
  667. * @inner
  668. */
  669. var P_ORIG = [
  670. 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822,
  671. 0x299f31d0, 0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377,
  672. 0xbe5466cf, 0x34e90c6c, 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5,
  673. 0xb5470917, 0x9216d5d9, 0x8979fb1b
  674. ];
  675. /**
  676. * @type {Array.<number>}
  677. * @const
  678. * @inner
  679. */
  680. var S_ORIG = [
  681. 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed,
  682. 0x6a267e96, 0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7,
  683. 0x0801f2e2, 0x858efc16, 0x636920d8, 0x71574e69, 0xa458fea3,
  684. 0xf4933d7e, 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee,
  685. 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, 0xc5d1b023,
  686. 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e,
  687. 0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda,
  688. 0x55605c60, 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
  689. 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, 0xa15486af,
  690. 0x7c72e993, 0xb3ee1411, 0x636fbc2a, 0x2ba9c55d, 0x741831f6,
  691. 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c, 0x7a325381,
  692. 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
  693. 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d,
  694. 0xe98575b1, 0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5,
  695. 0x0f6d6ff3, 0x83f44239, 0x2e0b4482, 0xa4842004, 0x69c8f04a,
  696. 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
  697. 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, 0x6eef0b6c,
  698. 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176,
  699. 0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3,
  700. 0x3b8b5ebe, 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6,
  701. 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, 0x37d0d724,
  702. 0xd00a1248, 0xdb0fead3, 0x49f1c09b, 0x075372c9, 0x80991b7b,
  703. 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b, 0x976ce0bd,
  704. 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
  705. 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f,
  706. 0x9b30952c, 0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd,
  707. 0x660f2807, 0x192e4bb3, 0xc0cba857, 0x45c8740f, 0xd20b5f39,
  708. 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279,
  709. 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, 0x3c7516df,
  710. 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760,
  711. 0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e,
  712. 0xdf1769db, 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
  713. 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98,
  714. 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, 0x9a53e479, 0xb6f84565,
  715. 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341,
  716. 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
  717. 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0,
  718. 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64,
  719. 0x8888b812, 0x900df01c, 0x4fad5ea0, 0x688fc31c, 0xd1cff191,
  720. 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
  721. 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, 0xb4a84fe0,
  722. 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705,
  723. 0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5,
  724. 0xfb9d35cf, 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49,
  725. 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af, 0x2464369b,
  726. 0xf009b91e, 0x5563911d, 0x59dfa6aa, 0x78c14389, 0xd95a537f,
  727. 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9, 0x11c81968,
  728. 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
  729. 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5,
  730. 0x571be91f, 0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6,
  731. 0xff34052e, 0xc5855664, 0x53b02d5d, 0xa99f8fa1, 0x08ba4799,
  732. 0x6e85076a, 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623,
  733. 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266, 0xecaa8c71,
  734. 0x699a17ff, 0x5664526c, 0xc2b19ee1, 0x193602a5, 0x75094c29,
  735. 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65, 0x6b8fe4d6,
  736. 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
  737. 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f,
  738. 0x3ebaefc9, 0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286,
  739. 0xb79c5305, 0xaa500737, 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec,
  740. 0x5716f2b8, 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff,
  741. 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, 0xd19113f9,
  742. 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc,
  743. 0xc8b57634, 0x9af3dda7, 0xa9446146, 0x0fd0030e, 0xecc8c73e,
  744. 0xa4751e41, 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
  745. 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, 0x2cb81290,
  746. 0x24977c79, 0x5679b072, 0xbcaf89af, 0xde9a771f, 0xd9930810,
  747. 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124, 0x501adde6,
  748. 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
  749. 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847,
  750. 0x3215d908, 0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451,
  751. 0x50940002, 0x133ae4dd, 0x71dff89e, 0x10314e55, 0x81ac77d6,
  752. 0x5f11199b, 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
  753. 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, 0x86e34570,
  754. 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa,
  755. 0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978,
  756. 0x9c10b36a, 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4,
  757. 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960, 0x5223a708,
  758. 0xf71312b6, 0xebadfe6e, 0xeac31f66, 0xe3bc4595, 0xa67bc883,
  759. 0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5, 0x65582185,
  760. 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
  761. 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830,
  762. 0xeb61bd96, 0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239,
  763. 0xd59e9e0b, 0xcbaade14, 0xeecc86bc, 0x60622ca7, 0x9cab5cab,
  764. 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50,
  765. 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, 0x9b540b19,
  766. 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77,
  767. 0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1,
  768. 0x7858ba99, 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
  769. 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef,
  770. 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, 0x5d4a14d9, 0xe864b7e3,
  771. 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15,
  772. 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
  773. 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2,
  774. 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492,
  775. 0x47848a0b, 0x5692b285, 0x095bbf00, 0xad19489d, 0x1462b174,
  776. 0x23820e00, 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
  777. 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, 0x7cde3759,
  778. 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e,
  779. 0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc,
  780. 0x800bcadc, 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9,
  781. 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340, 0xc5c43465,
  782. 0x713e38d8, 0x3d28f89e, 0xf16dff20, 0x153e21e7, 0x8fb03d4a,
  783. 0xe6e39f2b, 0xdb83adf7, 0xe93d5a68, 0x948140f7, 0xf64c261c,
  784. 0x94692934, 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
  785. 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, 0x1e39f62e,
  786. 0x97244546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af,
  787. 0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0,
  788. 0x31cb8504, 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a,
  789. 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb, 0x68dc1462,
  790. 0xd7486900, 0x680ec0a4, 0x27a18dee, 0x4f3ffea2, 0xe887ad8c,
  791. 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec, 0xce78a399,
  792. 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
  793. 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74,
  794. 0xdd5b4332, 0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397,
  795. 0x454056ac, 0xba489527, 0x55533a3a, 0x20838d87, 0xfe6ba9b7,
  796. 0xd096954b, 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33,
  797. 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, 0xfdf8e802,
  798. 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22,
  799. 0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f, 0x404779a4,
  800. 0x5d886e17, 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
  801. 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2,
  802. 0x02e1329e, 0xaf664fd1, 0xcad18115, 0x6b2395e0, 0x333e92e1,
  803. 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99, 0xde720c8c,
  804. 0x2da2f728, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
  805. 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x0a476341,
  806. 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8,
  807. 0x991be14c, 0xdb6e6b0d, 0xc67b5510, 0x6d672c37, 0x2765d43b,
  808. 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
  809. 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, 0xbb132f88,
  810. 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979,
  811. 0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc,
  812. 0x782ef11c, 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350,
  813. 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9, 0x44421659,
  814. 0x0a121386, 0xd90cec6e, 0xd5abea2a, 0x64af674e, 0xda86a85f,
  815. 0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086, 0x60787bf8,
  816. 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
  817. 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be,
  818. 0xbde8ae24, 0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2,
  819. 0xf474ef38, 0x8789bdc2, 0x5366f9c3, 0xc8b38e74, 0xb475f255,
  820. 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2,
  821. 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, 0xb90bace1,
  822. 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09,
  823. 0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c, 0x4a99a025,
  824. 0x1d6efe10, 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
  825. 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01,
  826. 0xa70683fa, 0xa002b5c4, 0x0de6d027, 0x9af88c27, 0x773f8641,
  827. 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0, 0x006058aa,
  828. 0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
  829. 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0x6f05e409,
  830. 0x4b7c0188, 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9,
  831. 0x1ac15bb4, 0xd39eb8fc, 0xed545578, 0x08fca5b5, 0xd83d7cd3,
  832. 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
  833. 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, 0xd79a3234,
  834. 0x92638212, 0x670efa8e, 0x406000e0, 0x3a39ce37, 0xd3faf5cf,
  835. 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742, 0xd3822740,
  836. 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
  837. 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f,
  838. 0xbc946e79, 0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d,
  839. 0xd5730a1d, 0x4cd04dc6, 0x2939bbdb, 0xa9ba4650, 0xac9526e8,
  840. 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
  841. 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, 0x83c061ba,
  842. 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1,
  843. 0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69,
  844. 0x77fa0a59, 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593,
  845. 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a,
  846. 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, 0x1f9f25cf, 0xadf2b89b,
  847. 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6, 0x47b0acfd,
  848. 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
  849. 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4,
  850. 0x88f46dba, 0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2,
  851. 0x97271aec, 0xa93a072a, 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb,
  852. 0x26dcf319, 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb,
  853. 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, 0x4de81751,
  854. 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce,
  855. 0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369,
  856. 0x6413e680, 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
  857. 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd,
  858. 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, 0xdda26a7e, 0x3a59ff45,
  859. 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb, 0x8d6612ae,
  860. 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
  861. 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08,
  862. 0x4eb4e2cc, 0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d,
  863. 0x06b89fb4, 0xce6ea048, 0x6f3f3b82, 0x3520ab82, 0x011a1d4b,
  864. 0x277227f8, 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
  865. 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, 0xe01cc87e,
  866. 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a,
  867. 0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c,
  868. 0xe0b12b4f, 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c,
  869. 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525, 0xfae59361,
  870. 0xceb69ceb, 0xc2a86459, 0x12baa8d1, 0xb6c1075e, 0xe3056a0c,
  871. 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be,
  872. 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
  873. 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d,
  874. 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891,
  875. 0xce6279cf, 0xcd3e7e6f, 0x1618b166, 0xfd2c1d05, 0x848fd2c5,
  876. 0xf6fb2299, 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02,
  877. 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, 0xde966292,
  878. 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a,
  879. 0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2,
  880. 0x35bdd2f6, 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
  881. 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, 0xba38209c,
  882. 0xf746ce76, 0x77afa1c5, 0x20756060, 0x85cbfe4e, 0x8ae88dd8,
  883. 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c, 0x01c36ae4,
  884. 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
  885. 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6
  886. ];
  887. /**
  888. * @type {Array.<number>}
  889. * @const
  890. * @inner
  891. */
  892. var C_ORIG = [
  893. 0x4f727068, 0x65616e42, 0x65686f6c, 0x64657253, 0x63727944,
  894. 0x6f756274
  895. ];
  896. /**
  897. * @param {Array.<number>} lr
  898. * @param {number} off
  899. * @param {Array.<number>} P
  900. * @param {Array.<number>} S
  901. * @returns {Array.<number>}
  902. * @inner
  903. */
  904. function _encipher(lr, off, P, S) { // This is our bottleneck: 1714/1905 ticks / 90% - see profile.txt
  905. var n,
  906. l = lr[off],
  907. r = lr[off + 1];
  908. l ^= P[0];
  909. /*
  910. for (var i=0, k=BLOWFISH_NUM_ROUNDS-2; i<=k;)
  911. // Feistel substitution on left word
  912. n = S[l >>> 24],
  913. n += S[0x100 | ((l >> 16) & 0xff)],
  914. n ^= S[0x200 | ((l >> 8) & 0xff)],
  915. n += S[0x300 | (l & 0xff)],
  916. r ^= n ^ P[++i],
  917. // Feistel substitution on right word
  918. n = S[r >>> 24],
  919. n += S[0x100 | ((r >> 16) & 0xff)],
  920. n ^= S[0x200 | ((r >> 8) & 0xff)],
  921. n += S[0x300 | (r & 0xff)],
  922. l ^= n ^ P[++i];
  923. */
  924. //The following is an unrolled version of the above loop.
  925. //Iteration 0
  926. n = S[l >>> 24];
  927. n += S[0x100 | ((l >> 16) & 0xff)];
  928. n ^= S[0x200 | ((l >> 8) & 0xff)];
  929. n += S[0x300 | (l & 0xff)];
  930. r ^= n ^ P[1];
  931. n = S[r >>> 24];
  932. n += S[0x100 | ((r >> 16) & 0xff)];
  933. n ^= S[0x200 | ((r >> 8) & 0xff)];
  934. n += S[0x300 | (r & 0xff)];
  935. l ^= n ^ P[2];
  936. //Iteration 1
  937. n = S[l >>> 24];
  938. n += S[0x100 | ((l >> 16) & 0xff)];
  939. n ^= S[0x200 | ((l >> 8) & 0xff)];
  940. n += S[0x300 | (l & 0xff)];
  941. r ^= n ^ P[3];
  942. n = S[r >>> 24];
  943. n += S[0x100 | ((r >> 16) & 0xff)];
  944. n ^= S[0x200 | ((r >> 8) & 0xff)];
  945. n += S[0x300 | (r & 0xff)];
  946. l ^= n ^ P[4];
  947. //Iteration 2
  948. n = S[l >>> 24];
  949. n += S[0x100 | ((l >> 16) & 0xff)];
  950. n ^= S[0x200 | ((l >> 8) & 0xff)];
  951. n += S[0x300 | (l & 0xff)];
  952. r ^= n ^ P[5];
  953. n = S[r >>> 24];
  954. n += S[0x100 | ((r >> 16) & 0xff)];
  955. n ^= S[0x200 | ((r >> 8) & 0xff)];
  956. n += S[0x300 | (r & 0xff)];
  957. l ^= n ^ P[6];
  958. //Iteration 3
  959. n = S[l >>> 24];
  960. n += S[0x100 | ((l >> 16) & 0xff)];
  961. n ^= S[0x200 | ((l >> 8) & 0xff)];
  962. n += S[0x300 | (l & 0xff)];
  963. r ^= n ^ P[7];
  964. n = S[r >>> 24];
  965. n += S[0x100 | ((r >> 16) & 0xff)];
  966. n ^= S[0x200 | ((r >> 8) & 0xff)];
  967. n += S[0x300 | (r & 0xff)];
  968. l ^= n ^ P[8];
  969. //Iteration 4
  970. n = S[l >>> 24];
  971. n += S[0x100 | ((l >> 16) & 0xff)];
  972. n ^= S[0x200 | ((l >> 8) & 0xff)];
  973. n += S[0x300 | (l & 0xff)];
  974. r ^= n ^ P[9];
  975. n = S[r >>> 24];
  976. n += S[0x100 | ((r >> 16) & 0xff)];
  977. n ^= S[0x200 | ((r >> 8) & 0xff)];
  978. n += S[0x300 | (r & 0xff)];
  979. l ^= n ^ P[10];
  980. //Iteration 5
  981. n = S[l >>> 24];
  982. n += S[0x100 | ((l >> 16) & 0xff)];
  983. n ^= S[0x200 | ((l >> 8) & 0xff)];
  984. n += S[0x300 | (l & 0xff)];
  985. r ^= n ^ P[11];
  986. n = S[r >>> 24];
  987. n += S[0x100 | ((r >> 16) & 0xff)];
  988. n ^= S[0x200 | ((r >> 8) & 0xff)];
  989. n += S[0x300 | (r & 0xff)];
  990. l ^= n ^ P[12];
  991. //Iteration 6
  992. n = S[l >>> 24];
  993. n += S[0x100 | ((l >> 16) & 0xff)];
  994. n ^= S[0x200 | ((l >> 8) & 0xff)];
  995. n += S[0x300 | (l & 0xff)];
  996. r ^= n ^ P[13];
  997. n = S[r >>> 24];
  998. n += S[0x100 | ((r >> 16) & 0xff)];
  999. n ^= S[0x200 | ((r >> 8) & 0xff)];
  1000. n += S[0x300 | (r & 0xff)];
  1001. l ^= n ^ P[14];
  1002. //Iteration 7
  1003. n = S[l >>> 24];
  1004. n += S[0x100 | ((l >> 16) & 0xff)];
  1005. n ^= S[0x200 | ((l >> 8) & 0xff)];
  1006. n += S[0x300 | (l & 0xff)];
  1007. r ^= n ^ P[15];
  1008. n = S[r >>> 24];
  1009. n += S[0x100 | ((r >> 16) & 0xff)];
  1010. n ^= S[0x200 | ((r >> 8) & 0xff)];
  1011. n += S[0x300 | (r & 0xff)];
  1012. l ^= n ^ P[16];
  1013. lr[off] = r ^ P[BLOWFISH_NUM_ROUNDS + 1];
  1014. lr[off + 1] = l;
  1015. return lr;
  1016. }
  1017. /**
  1018. * @param {Array.<number>} data
  1019. * @param {number} offp
  1020. * @returns {{key: number, offp: number}}
  1021. * @inner
  1022. */
  1023. function _streamtoword(data, offp) {
  1024. for (var i = 0, word = 0; i < 4; ++i)
  1025. word = (word << 8) | (data[offp] & 0xff),
  1026. offp = (offp + 1) % data.length;
  1027. return { key: word, offp: offp };
  1028. }
  1029. /**
  1030. * @param {Array.<number>} key
  1031. * @param {Array.<number>} P
  1032. * @param {Array.<number>} S
  1033. * @inner
  1034. */
  1035. function _key(key, P, S) {
  1036. var offset = 0,
  1037. lr = [0, 0],
  1038. plen = P.length,
  1039. slen = S.length,
  1040. sw;
  1041. for (var i = 0; i < plen; i++)
  1042. sw = _streamtoword(key, offset),
  1043. offset = sw.offp,
  1044. P[i] = P[i] ^ sw.key;
  1045. for (i = 0; i < plen; i += 2)
  1046. lr = _encipher(lr, 0, P, S),
  1047. P[i] = lr[0],
  1048. P[i + 1] = lr[1];
  1049. for (i = 0; i < slen; i += 2)
  1050. lr = _encipher(lr, 0, P, S),
  1051. S[i] = lr[0],
  1052. S[i + 1] = lr[1];
  1053. }
  1054. /**
  1055. * Expensive key schedule Blowfish.
  1056. * @param {Array.<number>} data
  1057. * @param {Array.<number>} key
  1058. * @param {Array.<number>} P
  1059. * @param {Array.<number>} S
  1060. * @inner
  1061. */
  1062. function _ekskey(data, key, P, S) {
  1063. var offp = 0,
  1064. lr = [0, 0],
  1065. plen = P.length,
  1066. slen = S.length,
  1067. sw;
  1068. for (var i = 0; i < plen; i++)
  1069. sw = _streamtoword(key, offp),
  1070. offp = sw.offp,
  1071. P[i] = P[i] ^ sw.key;
  1072. offp = 0;
  1073. for (i = 0; i < plen; i += 2)
  1074. sw = _streamtoword(data, offp),
  1075. offp = sw.offp,
  1076. lr[0] ^= sw.key,
  1077. sw = _streamtoword(data, offp),
  1078. offp = sw.offp,
  1079. lr[1] ^= sw.key,
  1080. lr = _encipher(lr, 0, P, S),
  1081. P[i] = lr[0],
  1082. P[i + 1] = lr[1];
  1083. for (i = 0; i < slen; i += 2)
  1084. sw = _streamtoword(data, offp),
  1085. offp = sw.offp,
  1086. lr[0] ^= sw.key,
  1087. sw = _streamtoword(data, offp),
  1088. offp = sw.offp,
  1089. lr[1] ^= sw.key,
  1090. lr = _encipher(lr, 0, P, S),
  1091. S[i] = lr[0],
  1092. S[i + 1] = lr[1];
  1093. }
  1094. /**
  1095. * Internaly crypts a string.
  1096. * @param {Array.<number>} b Bytes to crypt
  1097. * @param {Array.<number>} salt Salt bytes to use
  1098. * @param {number} rounds Number of rounds
  1099. * @param {function(Error, Array.<number>=)=} callback Callback receiving the error, if any, and the resulting bytes. If
  1100. * omitted, the operation will be performed synchronously.
  1101. * @param {function(number)=} progressCallback Callback called with the current progress
  1102. * @returns {!Array.<number>|undefined} Resulting bytes if callback has been omitted, otherwise `undefined`
  1103. * @inner
  1104. */
  1105. function _crypt(b, salt, rounds, callback, progressCallback) {
  1106. var cdata = C_ORIG.slice(),
  1107. clen = cdata.length,
  1108. err;
  1109. // Validate
  1110. if (rounds < 4 || rounds > 31) {
  1111. err = Error("Illegal number of rounds (4-31): "+rounds);
  1112. if (callback) {
  1113. nextTick(callback.bind(this, err));
  1114. return;
  1115. } else
  1116. throw err;
  1117. }
  1118. if (salt.length !== BCRYPT_SALT_LEN) {
  1119. err =Error("Illegal salt length: "+salt.length+" != "+BCRYPT_SALT_LEN);
  1120. if (callback) {
  1121. nextTick(callback.bind(this, err));
  1122. return;
  1123. } else
  1124. throw err;
  1125. }
  1126. rounds = (1 << rounds) >>> 0;
  1127. var P, S, i = 0, j;
  1128. //Use typed arrays when available - huge speedup!
  1129. if (Int32Array) {
  1130. P = new Int32Array(P_ORIG);
  1131. S = new Int32Array(S_ORIG);
  1132. } else {
  1133. P = P_ORIG.slice();
  1134. S = S_ORIG.slice();
  1135. }
  1136. _ekskey(salt, b, P, S);
  1137. /**
  1138. * Calcualtes the next round.
  1139. * @returns {Array.<number>|undefined} Resulting array if callback has been omitted, otherwise `undefined`
  1140. * @inner
  1141. */
  1142. function next() {
  1143. if (progressCallback)
  1144. progressCallback(i / rounds);
  1145. if (i < rounds) {
  1146. var start = Date.now();
  1147. for (; i < rounds;) {
  1148. i = i + 1;
  1149. _key(b, P, S);
  1150. _key(salt, P, S);
  1151. if (Date.now() - start > MAX_EXECUTION_TIME)
  1152. break;
  1153. }
  1154. } else {
  1155. for (i = 0; i < 64; i++)
  1156. for (j = 0; j < (clen >> 1); j++)
  1157. _encipher(cdata, j << 1, P, S);
  1158. var ret = [];
  1159. for (i = 0; i < clen; i++)
  1160. ret.push(((cdata[i] >> 24) & 0xff) >>> 0),
  1161. ret.push(((cdata[i] >> 16) & 0xff) >>> 0),
  1162. ret.push(((cdata[i] >> 8) & 0xff) >>> 0),
  1163. ret.push((cdata[i] & 0xff) >>> 0);
  1164. if (callback) {
  1165. callback(null, ret);
  1166. return;
  1167. } else
  1168. return ret;
  1169. }
  1170. if (callback)
  1171. nextTick(next);
  1172. }
  1173. // Async
  1174. if (typeof callback !== 'undefined') {
  1175. next();
  1176. // Sync
  1177. } else {
  1178. var res;
  1179. while (true)
  1180. if (typeof(res = next()) !== 'undefined')
  1181. return res || [];
  1182. }
  1183. }
  1184. /**
  1185. * Internally hashes a string.
  1186. * @param {string} s String to hash
  1187. * @param {?string} salt Salt to use, actually never null
  1188. * @param {function(Error, string=)=} callback Callback receiving the error, if any, and the resulting hash. If omitted,
  1189. * hashing is perormed synchronously.
  1190. * @param {function(number)=} progressCallback Callback called with the current progress
  1191. * @returns {string|undefined} Resulting hash if callback has been omitted, otherwise `undefined`
  1192. * @inner
  1193. */
  1194. function _hash(s, salt, callback, progressCallback) {
  1195. var err;
  1196. if (typeof s !== 'string' || typeof salt !== 'string') {
  1197. err = Error("Invalid string / salt: Not a string");
  1198. if (callback) {
  1199. nextTick(callback.bind(this, err));
  1200. return;
  1201. }
  1202. else
  1203. throw err;
  1204. }
  1205. // Validate the salt
  1206. var minor, offset;
  1207. if (salt.charAt(0) !== '$' || salt.charAt(1) !== '2') {
  1208. err = Error("Invalid salt version: "+salt.substring(0,2));
  1209. if (callback) {
  1210. nextTick(callback.bind(this, err));
  1211. return;
  1212. }
  1213. else
  1214. throw err;
  1215. }
  1216. if (salt.charAt(2) === '$')
  1217. minor = String.fromCharCode(0),
  1218. offset = 3;
  1219. else {
  1220. minor = salt.charAt(2);
  1221. if ((minor !== 'a' && minor !== 'b' && minor !== 'y') || salt.charAt(3) !== '$') {
  1222. err = Error("Invalid salt revision: "+salt.substring(2,4));
  1223. if (callback) {
  1224. nextTick(callback.bind(this, err));
  1225. return;
  1226. } else
  1227. throw err;
  1228. }
  1229. offset = 4;
  1230. }
  1231. // Extract number of rounds
  1232. if (salt.charAt(offset + 2) > '$') {
  1233. err = Error("Missing salt rounds");
  1234. if (callback) {
  1235. nextTick(callback.bind(this, err));
  1236. return;
  1237. } else
  1238. throw err;
  1239. }
  1240. var r1 = parseInt(salt.substring(offset, offset + 1), 10) * 10,
  1241. r2 = parseInt(salt.substring(offset + 1, offset + 2), 10),
  1242. rounds = r1 + r2,
  1243. real_salt = salt.substring(offset + 3, offset + 25);
  1244. s += minor >= 'a' ? "\x00" : "";
  1245. var passwordb = stringToBytes(s),
  1246. saltb = base64_decode(real_salt, BCRYPT_SALT_LEN);
  1247. /**
  1248. * Finishes hashing.
  1249. * @param {Array.<number>} bytes Byte array
  1250. * @returns {string}
  1251. * @inner
  1252. */
  1253. function finish(bytes) {
  1254. var res = [];
  1255. res.push("$2");
  1256. if (minor >= 'a')
  1257. res.push(minor);
  1258. res.push("$");
  1259. if (rounds < 10)
  1260. res.push("0");
  1261. res.push(rounds.toString());
  1262. res.push("$");
  1263. res.push(base64_encode(saltb, saltb.length));
  1264. res.push(base64_encode(bytes, C_ORIG.length * 4 - 1));
  1265. return res.join('');
  1266. }
  1267. // Sync
  1268. if (typeof callback == 'undefined')
  1269. return finish(_crypt(passwordb, saltb, rounds));
  1270. // Async
  1271. else {
  1272. _crypt(passwordb, saltb, rounds, function(err, bytes) {
  1273. if (err)
  1274. callback(err, null);
  1275. else
  1276. callback(null, finish(bytes));
  1277. }, progressCallback);
  1278. }
  1279. }
  1280. /**
  1281. * Encodes a byte array to base64 with up to len bytes of input, using the custom bcrypt alphabet.
  1282. * @function
  1283. * @param {!Array.<number>} b Byte array
  1284. * @param {number} len Maximum input length
  1285. * @returns {string}
  1286. * @expose
  1287. */
  1288. bcrypt.encodeBase64 = base64_encode;
  1289. /**
  1290. * Decodes a base64 encoded string to up to len bytes of output, using the custom bcrypt alphabet.
  1291. * @function
  1292. * @param {string} s String to decode
  1293. * @param {number} len Maximum output length
  1294. * @returns {!Array.<number>}
  1295. * @expose
  1296. */
  1297. bcrypt.decodeBase64 = base64_decode;
  1298. return bcrypt;
  1299. }));