├── .DS_Store ├── examples ├── kiss.jpg ├── test.js └── index.js ├── index.js ├── package.json ├── lib ├── random.js ├── crc32.js ├── sha1.js ├── sha256.js ├── MersenneTwister.js ├── base64.js ├── md5.js └── bcrypt.js └── README.md /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Spikef/crypts/master/.DS_Store -------------------------------------------------------------------------------- /examples/kiss.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Spikef/crypts/master/examples/kiss.jpg -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | exports.md5 = require('./lib/md5'); 2 | exports.sha1 = require('./lib/sha1'); 3 | exports.sha256 = require('./lib/sha256'); 4 | exports.crc32 = require('./lib/crc32'); 5 | exports.base64 = require('./lib/base64'); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "crypts", 3 | "description": "集成一些常用的加密解密算法,如:base64、md5、sha1、sha256、crc32。", 4 | "version": "1.0.2", 5 | "author": { 6 | "name": "Spikef", 7 | "email": "Spikef@Foxmail.com", 8 | "url": "http://www.xybk.net" 9 | }, 10 | "license": "MIT", 11 | "homepage": "https://github.com/Spikef/crypts", 12 | "engines": { 13 | "node": ">= 0.10.0", 14 | "NodeAsp": ">= 0.0.1" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /examples/test.js: -------------------------------------------------------------------------------- 1 | //var c = require('crypto'); 2 | //var byts = c.randomBytes(4); 3 | //console.log(byts.toString('hex')); 4 | // 5 | //var r = require('crypts/lib/random'); 6 | //var a = r.randomBytes(4); 7 | //console.log(new Buffer(a).toString('hex')); 8 | 9 | // 10 | var b = require('crypts/lib/bcrypt'); 11 | var v = b.hashSync('bacon', 6); 12 | console.log(v); 13 | 14 | var r = b.compareSync('bacon', '$2a$06$YCZi3NX.Cf.eAv4ofQQd3OEQlzzGCsCiorKfM7Mvn1ti1MkHRtVyC'); 15 | console.log(process.uptime()) 16 | console.log(r); 17 | // 18 | //var salt = '124gft'; 19 | //var pass = 'sfdsf@3dfgg'; 20 | //var sha256 = require('crypts/lib/sha256'); 21 | //var v = sha256(pass + salt); 22 | //console.log(process.uptime()) -------------------------------------------------------------------------------- /examples/index.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var crypts = require('crypts'); 3 | var plain = path.resolve(__dirname, 'test.txt'); 4 | var image = path.resolve(__dirname, 'kiss.jpg'); 5 | var image2 = path.resolve(__dirname, 'kiss2.jpg'); 6 | 7 | var v = ''; 8 | v = crypts.md5('Spikef'); // md5加密 9 | console.log(v); 10 | // => 2966c8436b567beffed63d6b56b15b0f 11 | v = crypts.sha1('Spikef'); // sha1加密 12 | console.log(v); 13 | // => 48959ac28700f58ee721b93539fd1bb18a101a3f 14 | v = crypts.sha256('Spikef'); // sha256加密 15 | console.log(v); 16 | // => 48959ac28700f58ee721b93539fd1bb18a101a3f 17 | v = crypts.crc32(image); // 文件crc32加密 18 | console.log(v); 19 | // => 43E2B211 20 | v = crypts.base64.encode('Spikef'); // base64字符串加密 21 | console.log(v); 22 | // => U3Bpa2Vm 23 | v = crypts.base64.decode('U3Bpa2Vm'); // base64字符串解密 24 | // => Spikef 25 | console.log(v); 26 | v = crypts.base64.enfile(plain); // 文件base64加密 27 | console.log(v); 28 | // => Kg== 29 | v = crypts.base64.enfile(image); // 文件base64加密 30 | v = crypts.base64.defile(v, image2); // 文件base64解密 -------------------------------------------------------------------------------- /lib/random.js: -------------------------------------------------------------------------------- 1 | var MT = require('./MersenneTwister'); 2 | var mt = new MT(); 3 | var seedChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; 4 | 5 | exports.randomBytes = function(len) { 6 | var bytes = [], b; 7 | for (var i=0; i 2966c8436b567beffed63d6b56b15b0f 22 | v = crypts.sha1('Spikef'); // sha1加密 23 | console.log(v); 24 | // => 48959ac28700f58ee721b93539fd1bb18a101a3f 25 | v = crypts.sha256('Spikef'); // sha256加密 26 | console.log(v); 27 | // => 48959ac28700f58ee721b93539fd1bb18a101a3f 28 | v = crypts.crc32(image); // 文件crc32加密 29 | console.log(v); 30 | // => 43E2B211 31 | v = crypts.base64.encode('Spikef'); // base64字符串加密 32 | console.log(v); 33 | // => U3Bpa2Vm 34 | v = crypts.base64.decode('U3Bpa2Vm'); // base64字符串解密 35 | // => Spikef 36 | console.log(v); 37 | v = crypts.base64.enfile(plain); // 文件base64加密 38 | console.log(v); 39 | // => Kg== 40 | v = crypts.base64.enfile(image); // 文件base64加密 41 | v = crypts.base64.defile(v, image2); // 文件base64解密 42 | ``` -------------------------------------------------------------------------------- /lib/crc32.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var hashTable = getHashTable(); 3 | 4 | var crc32 = module.exports = function(filePath) { 5 | var crc = 0xFFFFFFFF; 6 | var bin = fs.readFileSync(filePath); 7 | var buf = typeof ActiveXObject === 'function' ? binToBuf(bin) : bin; 8 | 9 | for (var i=0; i> 8) & 0x00FFFFFF) ^ hashTable[(crc & 0xFF) ^ buf[i]]; 11 | } 12 | 13 | if (crc<0) { 14 | crc = -Number(crc) - 1; 15 | } else { 16 | crc = 4294967296 - crc - 1; 17 | } 18 | 19 | return crc.toString(16).toUpperCase(); 20 | }; 21 | 22 | function binToBuf(bin) { 23 | var buf = []; 24 | with (new ActiveXObject('Microsoft.XMLDOM').createElement('node')) { 25 | dataType = 'bin.hex'; 26 | nodeTypedValue = bin; 27 | var hex = text; 28 | hex.replace(/../g, function($0) { 29 | buf.push(parseInt($0, 16)); 30 | }); 31 | } 32 | 33 | return buf; 34 | } 35 | 36 | function getHashTable() { 37 | var table = new Array(256); 38 | 39 | var i, j, k; 40 | 41 | for (i=0; i<256; i++) { 42 | k = i; 43 | 44 | for (j=0; j<8; j++) { 45 | if (k & 1){ 46 | k = ((k >> 1) & 0x7FFFFFFF) ^ 0xEDB88320; 47 | }else{ 48 | k = ((k >> 1) & 0x7FFFFFFF); 49 | } 50 | } 51 | 52 | table[i] = k; 53 | } 54 | 55 | return table; 56 | } -------------------------------------------------------------------------------- /lib/sha1.js: -------------------------------------------------------------------------------- 1 | (function (mod) { 2 | if (typeof exports == "object" || typeof exports === 'function' && typeof module == "object") { 3 | module.exports = mod(); 4 | } 5 | else if (typeof define == "function" && define.amd) { 6 | return define([], mod); 7 | } 8 | else { 9 | window.sha1 = mod(); 10 | } 11 | })(function () { 12 | function hex(num) 13 | { 14 | // Static variable to store the hexadecimal convertion table 15 | var sHEXChars="0123456789abcdef"; 16 | var str=""; 17 | for(var j=7;j>=0;j--) 18 | str+=sHEXChars.charAt((num>>(j*4))&0x0F); 19 | return str; 20 | } 21 | 22 | // The standard SHA1 needs the input string to fit into a block 23 | // This function align the input string to meet the requirement 24 | function AlignSHA1(sIn){ 25 | var nblk=((sIn.length+8)>>6)+1, blks=new Array(nblk*16); 26 | for(var i=0;i>2]|=sIn.charCodeAt(i)<<(24-(i&3)*8); 29 | blks[i>>2]|=0x80<<(24-(i&3)*8); 30 | blks[nblk*16-1]=sIn.length*8; 31 | return blks; 32 | } 33 | 34 | // The int32 add function which doesn't generate overflow 35 | // exception. This is required by the algorithm 36 | function add(x,y){ 37 | var lsw=(x&0xFFFF)+(y&0xFFFF); 38 | var msw=(x>>16)+(y>>16)+(lsw>>16); 39 | return(msw<<16)|(lsw&0xFFFF); 40 | } 41 | 42 | // The int32 _asm rol :) 43 | function rol(num,cnt){ 44 | return(num<>>(32-cnt)); 45 | } 46 | 47 | // Perform the appropriate triplet combination function for the current round 48 | function ft(t,b,c,d){ 49 | if(t<20)return(b&c)|((~b)&d); 50 | if(t<40)return b^c^d; 51 | if(t<60)return(b&c)|(b&d)|(c&d); 52 | return b^c^d; 53 | } 54 | 55 | // Determine the appropriate additive constant for the current iteration 56 | function kt(t) { 57 | return(t<20)?1518500249:(t<40)?1859775393: 58 | (t<60)?-1894007588:-899497514; 59 | } 60 | 61 | // Hash the string using FIPS-180 SHA-1 62 | function SHA1(sIn) 63 | { 64 | var x=AlignSHA1(sIn); 65 | var w=new Array(80); 66 | var a=1732584193; 67 | var b=-271733879; 68 | var c=-1732584194; 69 | var d=271733878; 70 | var e=-1009589776; 71 | for(var i=0;i> 16) + (y >> 16) + (lsw >> 16); 18 | return (msw << 16) | (lsw & 0xFFFF); 19 | } 20 | function S (X, n) { return ( X >>> n ) | (X << (32 - n)); } 21 | function R (X, n) { return ( X >>> n ); } 22 | function Ch(x, y, z) { return ((x & y) ^ ((~x) & z)); } 23 | function Maj(x, y, z) { return ((x & y) ^ (x & z) ^ (y & z)); } 24 | function Sigma0256(x) { return (S(x, 2) ^ S(x, 13) ^ S(x, 22)); } 25 | function Sigma1256(x) { return (S(x, 6) ^ S(x, 11) ^ S(x, 25)); } 26 | function Gamma0256(x) { return (S(x, 7) ^ S(x, 18) ^ R(x, 3)); } 27 | function Gamma1256(x) { return (S(x, 17) ^ S(x, 19) ^ R(x, 10)); } 28 | function core_sha256 (m, l) { 29 | var K = new Array(0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, 0xE49B69C1, 0xEFBE4786, 0xFC19DC6, 0x240CA1CC, 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, 0xC6E00BF3, 0xD5A79147, 0x6CA6351, 0x14292967, 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2); 30 | var HASH = new Array(0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19); 31 | var W = new Array(64); 32 | var a, b, c, d, e, f, g, h, i, j; 33 | var T1, T2; 34 | m[l >> 5] |= 0x80 << (24 - l % 32); 35 | m[((l + 64 >> 9) << 4) + 15] = l; 36 | for ( var i = 0; i>5] |= (str.charCodeAt(i / chrsz) & mask) << (24 - i%32); 75 | } 76 | return bin; 77 | } 78 | function Utf8Encode(string) { 79 | string = string.replace(/\r\n/g,"\n"); 80 | var utftext = ""; 81 | for (var n = 0; n < string.length; n++) { 82 | var c = string.charCodeAt(n); 83 | if (c < 128) { 84 | utftext += String.fromCharCode(c); 85 | } 86 | else if((c > 127) && (c < 2048)) { 87 | utftext += String.fromCharCode((c >> 6) | 192); 88 | utftext += String.fromCharCode((c & 63) | 128); 89 | } 90 | else { 91 | utftext += String.fromCharCode((c >> 12) | 224); 92 | utftext += String.fromCharCode(((c >> 6) & 63) | 128); 93 | utftext += String.fromCharCode((c & 63) | 128); 94 | } 95 | } 96 | return utftext; 97 | } 98 | function binb2hex (binarray) { 99 | var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef"; 100 | var str = ""; 101 | for(var i = 0; i < binarray.length * 4; i++) { 102 | str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) + 103 | hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8 )) & 0xF); 104 | } 105 | return str; 106 | } 107 | s = Utf8Encode(s); 108 | return binb2hex(core_sha256(str2binb(s), s.length * chrsz)); 109 | } 110 | 111 | return SHA256; 112 | }); -------------------------------------------------------------------------------- /lib/MersenneTwister.js: -------------------------------------------------------------------------------- 1 | (function (root, factory) { 2 | 'use strict'; 3 | 4 | if (typeof exports === 'object') { 5 | module.exports = factory(); 6 | } else if (typeof define === 'function' && define.amd) { 7 | define(factory); 8 | } else { 9 | root.MersenneTwister = factory(); 10 | } 11 | }(this, function () { 12 | /** 13 | * A standalone, pure JavaScript implementation of the Mersenne Twister pseudo random number generator. Compatible 14 | * with Node.js, requirejs and browser environments. Packages are available for npm, Jam and Bower. 15 | * 16 | * @module MersenneTwister 17 | * @author Raphael Pigulla 18 | * @license See the attached LICENSE file. 19 | * @version 0.2.3 20 | */ 21 | 22 | /* 23 | * Most comments were stripped from the source. If needed you can still find them in the original C code: 24 | * http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/CODES/mt19937ar.c 25 | * 26 | * The original port to JavaScript, on which this file is based, was done by Sean McCullough. It can be found at: 27 | * https://gist.github.com/banksean/300494 28 | */ 29 | 'use strict'; 30 | 31 | var MAX_INT = 4294967296.0, 32 | N = 624, 33 | M = 397, 34 | UPPER_MASK = 0x80000000, 35 | LOWER_MASK = 0x7fffffff, 36 | MATRIX_A = 0x9908b0df; 37 | 38 | /** 39 | * Instantiates a new Mersenne Twister. 40 | * 41 | * @constructor 42 | * @alias module:MersenneTwister 43 | * @since 0.1.0 44 | * @param {number=} seed The initial seed value. 45 | */ 46 | var MersenneTwister = function (seed) { 47 | if (typeof seed === 'undefined') { 48 | seed = new Date().getTime(); 49 | } 50 | 51 | this.mt = new Array(N); 52 | this.mti = N + 1; 53 | 54 | this.seed(seed); 55 | }; 56 | 57 | /** 58 | * Initializes the state vector by using one unsigned 32-bit integer "seed", which may be zero. 59 | * 60 | * @since 0.1.0 61 | * @param {number} seed The seed value. 62 | */ 63 | MersenneTwister.prototype.seed = function (seed) { 64 | var s; 65 | 66 | this.mt[0] = seed >>> 0; 67 | 68 | for (this.mti = 1; this.mti < N; this.mti++) { 69 | s = this.mt[this.mti - 1] ^ (this.mt[this.mti - 1] >>> 30); 70 | this.mt[this.mti] = 71 | (((((s & 0xffff0000) >>> 16) * 1812433253) << 16) + (s & 0x0000ffff) * 1812433253) + this.mti; 72 | this.mt[this.mti] >>>= 0; 73 | } 74 | }; 75 | 76 | /** 77 | * Initializes the state vector by using an array key[] of unsigned 32-bit integers of the specified length. If 78 | * length is smaller than 624, then each array of 32-bit integers gives distinct initial state vector. This is 79 | * useful if you want a larger seed space than 32-bit word. 80 | * 81 | * @since 0.1.0 82 | * @param {array} vector The seed vector. 83 | */ 84 | MersenneTwister.prototype.seedArray = function (vector) { 85 | var i = 1, 86 | j = 0, 87 | k = N > vector.length ? N : vector.length, 88 | s; 89 | 90 | this.seed(19650218); 91 | 92 | for (; k > 0; k--) { 93 | s = this.mt[i-1] ^ (this.mt[i-1] >>> 30); 94 | 95 | this.mt[i] = (this.mt[i] ^ (((((s & 0xffff0000) >>> 16) * 1664525) << 16) + ((s & 0x0000ffff) * 1664525))) + 96 | vector[j] + j; 97 | this.mt[i] >>>= 0; 98 | i++; 99 | j++; 100 | if (i >= N) { 101 | this.mt[0] = this.mt[N - 1]; 102 | i = 1; 103 | } 104 | if (j >= vector.length) { 105 | j = 0; 106 | } 107 | } 108 | 109 | for (k = N - 1; k; k--) { 110 | s = this.mt[i - 1] ^ (this.mt[i - 1] >>> 30); 111 | this.mt[i] = 112 | (this.mt[i] ^ (((((s & 0xffff0000) >>> 16) * 1566083941) << 16) + (s & 0x0000ffff) * 1566083941)) - i; 113 | this.mt[i] >>>= 0; 114 | i++; 115 | if (i >= N) { 116 | this.mt[0] = this.mt[N - 1]; 117 | i = 1; 118 | } 119 | } 120 | 121 | this.mt[0] = 0x80000000; 122 | }; 123 | 124 | /** 125 | * Generates a random unsigned 32-bit integer. 126 | * 127 | * @since 0.1.0 128 | * @returns {number} 129 | */ 130 | MersenneTwister.prototype.int = function () { 131 | var y, 132 | kk, 133 | mag01 = new Array(0, MATRIX_A); 134 | 135 | if (this.mti >= N) { 136 | if (this.mti === N + 1) { 137 | this.seed(5489); 138 | } 139 | 140 | for (kk = 0; kk < N - M; kk++) { 141 | y = (this.mt[kk] & UPPER_MASK) | (this.mt[kk + 1] & LOWER_MASK); 142 | this.mt[kk] = this.mt[kk + M] ^ (y >>> 1) ^ mag01[y & 1]; 143 | } 144 | 145 | for (; kk < N - 1; kk++) { 146 | y = (this.mt[kk] & UPPER_MASK) | (this.mt[kk + 1] & LOWER_MASK); 147 | this.mt[kk] = this.mt[kk + (M - N)] ^ (y >>> 1) ^ mag01[y & 1]; 148 | } 149 | 150 | y = (this.mt[N - 1] & UPPER_MASK) | (this.mt[0] & LOWER_MASK); 151 | this.mt[N - 1] = this.mt[M - 1] ^ (y >>> 1) ^ mag01[y & 1]; 152 | this.mti = 0; 153 | } 154 | 155 | y = this.mt[this.mti++]; 156 | 157 | y ^= (y >>> 11); 158 | y ^= (y << 7) & 0x9d2c5680; 159 | y ^= (y << 15) & 0xefc60000; 160 | y ^= (y >>> 18); 161 | 162 | return y >>> 0; 163 | }; 164 | 165 | /** 166 | * Generates a random unsigned 31-bit integer. 167 | * 168 | * @since 0.1.0 169 | * @returns {number} 170 | */ 171 | MersenneTwister.prototype.int31 = function () { 172 | return this.int() >>> 1; 173 | }; 174 | 175 | /** 176 | * Generates a random real in the interval [0;1] with 32-bit resolution. 177 | * 178 | * @since 0.1.0 179 | * @returns {number} 180 | */ 181 | MersenneTwister.prototype.real = function () { 182 | return this.int() * (1.0 / (MAX_INT - 1)); 183 | }; 184 | 185 | /** 186 | * Generates a random real in the interval ]0;1[ with 32-bit resolution. 187 | * 188 | * @since 0.1.0 189 | * @returns {number} 190 | */ 191 | MersenneTwister.prototype.realx = function () { 192 | return (this.int() + 0.5) * (1.0 / MAX_INT); 193 | }; 194 | 195 | /** 196 | * Generates a random real in the interval [0;1[ with 32-bit resolution. 197 | * 198 | * @since 0.1.0 199 | * @returns {number} 200 | */ 201 | MersenneTwister.prototype.rnd = function () { 202 | return this.int() * (1.0 / MAX_INT); 203 | }; 204 | 205 | /** 206 | * Generates a random real in the interval [0;1[ with 32-bit resolution. 207 | * 208 | * Same as .rnd() method - for consistency with Math.random() interface. 209 | * 210 | * @since 0.2.0 211 | * @returns {number} 212 | */ 213 | MersenneTwister.prototype.random = MersenneTwister.prototype.rnd; 214 | 215 | /** 216 | * Generates a random real in the interval [0;1[ with 53-bit resolution. 217 | * 218 | * @since 0.1.0 219 | * @returns {number} 220 | */ 221 | MersenneTwister.prototype.rndHiRes = function () { 222 | var a = this.int() >>> 5, 223 | b = this.int() >>> 6; 224 | 225 | return (a * 67108864.0 + b) * (1.0 / 9007199254740992.0); 226 | }; 227 | 228 | var instance = new MersenneTwister(); 229 | 230 | /** 231 | * A static version of [rnd]{@link module:MersenneTwister#rnd} on a randomly seeded instance. 232 | * 233 | * @static 234 | * @function random 235 | * @memberof module:MersenneTwister 236 | * @returns {number} 237 | */ 238 | MersenneTwister.random = function () { 239 | return instance.rnd(); 240 | }; 241 | 242 | return MersenneTwister; 243 | })); -------------------------------------------------------------------------------- /lib/base64.js: -------------------------------------------------------------------------------- 1 | (function (mod) { 2 | if (typeof exports == "object" || typeof exports === 'function' && typeof module == "object") { 3 | module.exports = mod(); 4 | } 5 | else if (typeof define == "function" && define.amd) { 6 | return define([], mod); 7 | } 8 | else { 9 | window.base64 = mod(); 10 | } 11 | })(function () { 12 | var BASE64_MAPPING = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/']; 13 | var _toBinary = function(ascii) { 14 | var binary = new Array(); 15 | while (ascii > 0) { 16 | var b = ascii % 2; 17 | ascii = Math.floor(ascii / 2); 18 | binary.push(b); 19 | } 20 | binary.reverse(); 21 | return binary; 22 | }; 23 | var _toDecimal = function(binary) { 24 | var dec = 0; 25 | var p = 0; 26 | for (var i = binary.length - 1; i >= 0; --i) { 27 | var b = binary[i]; 28 | if (b == 1) { 29 | dec += Math.pow(2, p); 30 | } 31 | ++p; 32 | } 33 | return dec; 34 | }; 35 | var _toUTF8Binary = function(c, binaryArray) { 36 | var mustLen = (8 - (c + 1)) + ((c - 1) * 6); 37 | var fatLen = binaryArray.length; 38 | var diff = mustLen - fatLen; 39 | while (--diff >= 0) { 40 | binaryArray.unshift(0); 41 | } 42 | var binary = []; 43 | var _c = c; 44 | while (--_c >= 0) { 45 | binary.push(1); 46 | } 47 | binary.push(0); 48 | var i = 0, 49 | len = 8 - (c + 1); 50 | for (; i < len; ++i) { 51 | binary.push(binaryArray[i]); 52 | } 53 | for (var j = 0; j < c - 1; ++j) { 54 | binary.push(1); 55 | binary.push(0); 56 | var sum = 6; 57 | while (--sum >= 0) { 58 | binary.push(binaryArray[i++]); 59 | } 60 | } 61 | return binary; 62 | }; 63 | 64 | var Base64 = { 65 | /** 66 | * 对字符串进行base64编码 67 | * @param inputString 68 | * @returns {string} 69 | */ 70 | encode: function(inputString) { 71 | var base64_Index = []; 72 | var binaryArray = []; 73 | for (var i = 0, len = inputString.length; i < len; ++i) { 74 | var unicode = inputString.charCodeAt(i); 75 | var _tmpBinary = _toBinary(unicode); 76 | if (unicode < 0x80) { 77 | var _tmpdiff = 8 - _tmpBinary.length; 78 | while (--_tmpdiff >= 0) { 79 | _tmpBinary.unshift(0); 80 | } 81 | binaryArray = binaryArray.concat(_tmpBinary); 82 | } else if (unicode >= 0x80 && unicode <= 0x7FF) { 83 | binaryArray = binaryArray.concat(_toUTF8Binary(2, _tmpBinary)); 84 | } else if (unicode >= 0x800 && unicode <= 0xFFFF) { 85 | binaryArray = binaryArray.concat(_toUTF8Binary(3, _tmpBinary)); 86 | } else if (unicode >= 0x10000 && unicode <= 0x1FFFFF) { 87 | binaryArray = binaryArray.concat(_toUTF8Binary(4, _tmpBinary)); 88 | } else if (unicode >= 0x200000 && unicode <= 0x3FFFFFF) { 89 | binaryArray = binaryArray.concat(_toUTF8Binary(5, _tmpBinary)); 90 | } else if (unicode >= 4000000 && unicode <= 0x7FFFFFFF) { 91 | binaryArray = binaryArray.concat(_toUTF8Binary(6, _tmpBinary)); 92 | } 93 | } 94 | var extra_Zero_Count = 0; 95 | for (var i = 0, len = binaryArray.length; i < len; i += 6) { 96 | var diff = (i + 6) - len; 97 | if (diff == 2) { 98 | extra_Zero_Count = 2; 99 | } else if (diff == 4) { 100 | extra_Zero_Count = 4; 101 | } 102 | var _tmpExtra_Zero_Count = extra_Zero_Count; 103 | while (--_tmpExtra_Zero_Count >= 0) { 104 | binaryArray.push(0); 105 | } 106 | base64_Index.push(_toDecimal(binaryArray.slice(i, i + 6))); 107 | } 108 | var base64 = ''; 109 | for (var i = 0, len = base64_Index.length; i < len; ++i) { 110 | base64 += BASE64_MAPPING[base64_Index[i]]; 111 | } 112 | for (var i = 0, len = extra_Zero_Count / 2; i < len; ++i) { 113 | base64 += '='; 114 | } 115 | return base64; 116 | }, 117 | /** 118 | * 对字符串进行base64解码 119 | * @param base64String 120 | * @returns {string} 121 | */ 122 | decode: function(base64String) { 123 | var _len = base64String.length; 124 | var extra_Zero_Count = 0; 125 | if (base64String.charAt(_len - 1) == '=') { 126 | if (base64String.charAt(_len - 2) == '=') { 127 | extra_Zero_Count = 4; 128 | base64String = base64String.substring(0, _len - 2); 129 | } else { 130 | extra_Zero_Count = 2; 131 | base64String = base64String.substring(0, _len - 1); 132 | } 133 | } 134 | var binaryArray = []; 135 | for (var i = 0, len = base64String.length; i < len; ++i) { 136 | var c = base64String.charAt(i); 137 | for (var j = 0, size = BASE64_MAPPING.length; j < size; ++j) { 138 | if (c == BASE64_MAPPING[j]) { 139 | var _tmp = _toBinary(j); 140 | var _tmpLen = _tmp.length; 141 | if (6 - _tmpLen > 0) { 142 | for (var k = 6 - _tmpLen; k > 0; --k) { 143 | _tmp.unshift(0); 144 | } 145 | } 146 | binaryArray = binaryArray.concat(_tmp); 147 | break; 148 | } 149 | } 150 | } 151 | if (extra_Zero_Count > 0) { 152 | binaryArray = binaryArray.slice(0, binaryArray.length - extra_Zero_Count); 153 | } 154 | var unicode = []; 155 | var unicodeBinary = []; 156 | for (var i = 0, len = binaryArray.length; i < len;) { 157 | if (binaryArray[i] == 0) { 158 | unicode = unicode.concat(_toDecimal(binaryArray.slice(i, i + 8))); 159 | i += 8; 160 | } else { 161 | var sum = 0; 162 | while (i < len) { 163 | if (binaryArray[i] == 1) {++sum; 164 | } else { 165 | break; 166 | } 167 | ++i; 168 | } 169 | unicodeBinary = unicodeBinary.concat(binaryArray.slice(i + 1, i + 8 - sum)); 170 | i += 8 - sum; 171 | while (sum > 1) { 172 | unicodeBinary = unicodeBinary.concat(binaryArray.slice(i + 2, i + 8)); 173 | i += 8; --sum; 174 | } 175 | unicode = unicode.concat(_toDecimal(unicodeBinary)); 176 | unicodeBinary = []; 177 | } 178 | } 179 | var str = ''; 180 | for(var i = 0 , len = unicode.length ; i < len ;++i){ 181 | str += String.fromCharCode(unicode[i]); 182 | } 183 | return str; 184 | } 185 | }; 186 | 187 | /** 188 | * 对文件进行base64编码 189 | * @param filePath 190 | * @returns {String} 191 | */ 192 | Base64.enfile = function(filePath){ 193 | var bin = require('fs').readFileSync(filePath); 194 | var b64 = typeof ActiveXObject === 'function' ? base64OrBin(bin) : base64OrBuf(bin); 195 | 196 | return b64; 197 | }; 198 | 199 | /** 200 | * 对文件进行base64解码 201 | * @param content 202 | * @param filePath 203 | */ 204 | Base64.defile = function(base64String, filePath){ 205 | var bin = typeof ActiveXObject === 'function' ? base64OrBin(base64String) : base64OrBuf(base64String); 206 | require('fs').writeFileSync(filePath, bin); 207 | }; 208 | 209 | /** 210 | * base64与binary互转, 用于NodeAsp环境 211 | * @param obj 212 | * @returns {*} 213 | */ 214 | function base64OrBin(obj) { 215 | var xml = new ActiveXObject('Microsoft.XMLDOM'); 216 | var node = xml.createElement("obj"); 217 | node.dataType = "bin.base64"; 218 | obj = 'string' == typeof obj ? (node.text = obj, node.nodeTypedValue) : (node.nodeTypedValue = obj, node.text); 219 | node = xml = null; 220 | return obj; 221 | } 222 | 223 | /** 224 | * base64与buffer互转, 用于node环境 225 | * @param obj 226 | * @returns {*} 227 | */ 228 | function base64OrBuf(obj) { 229 | return typeof obj === 'string' ? new Buffer(obj, 'base64') : obj.toString('base64'); 230 | } 231 | 232 | return Base64; 233 | }); -------------------------------------------------------------------------------- /lib/md5.js: -------------------------------------------------------------------------------- 1 | (function (mod) { 2 | if (typeof exports == "object" || typeof exports === 'function' && typeof module == "object") { 3 | module.exports = mod(); 4 | } 5 | else if (typeof define == "function" && define.amd) { 6 | return define([], mod); 7 | } 8 | else { 9 | window.md5 = mod(); 10 | } 11 | })(function () { 12 | var rotateLeft = function(lValue, iShiftBits) { 13 | return (lValue << iShiftBits) | (lValue >>> (32 - iShiftBits)); 14 | } 15 | 16 | var addUnsigned = function(lX, lY) { 17 | var lX4, lY4, lX8, lY8, lResult; 18 | lX8 = (lX & 0x80000000); 19 | lY8 = (lY & 0x80000000); 20 | lX4 = (lX & 0x40000000); 21 | lY4 = (lY & 0x40000000); 22 | lResult = (lX & 0x3FFFFFFF) + (lY & 0x3FFFFFFF); 23 | if (lX4 & lY4) return (lResult ^ 0x80000000 ^ lX8 ^ lY8); 24 | if (lX4 | lY4) { 25 | if (lResult & 0x40000000) return (lResult ^ 0xC0000000 ^ lX8 ^ lY8); 26 | else return (lResult ^ 0x40000000 ^ lX8 ^ lY8); 27 | } else { 28 | return (lResult ^ lX8 ^ lY8); 29 | } 30 | } 31 | 32 | var F = function(x, y, z) { 33 | return (x & y) | ((~ x) & z); 34 | } 35 | 36 | var G = function(x, y, z) { 37 | return (x & z) | (y & (~ z)); 38 | } 39 | 40 | var H = function(x, y, z) { 41 | return (x ^ y ^ z); 42 | } 43 | 44 | var I = function(x, y, z) { 45 | return (y ^ (x | (~ z))); 46 | } 47 | 48 | var FF = function(a, b, c, d, x, s, ac) { 49 | a = addUnsigned(a, addUnsigned(addUnsigned(F(b, c, d), x), ac)); 50 | return addUnsigned(rotateLeft(a, s), b); 51 | }; 52 | 53 | var GG = function(a, b, c, d, x, s, ac) { 54 | a = addUnsigned(a, addUnsigned(addUnsigned(G(b, c, d), x), ac)); 55 | return addUnsigned(rotateLeft(a, s), b); 56 | }; 57 | 58 | var HH = function(a, b, c, d, x, s, ac) { 59 | a = addUnsigned(a, addUnsigned(addUnsigned(H(b, c, d), x), ac)); 60 | return addUnsigned(rotateLeft(a, s), b); 61 | }; 62 | 63 | var II = function(a, b, c, d, x, s, ac) { 64 | a = addUnsigned(a, addUnsigned(addUnsigned(I(b, c, d), x), ac)); 65 | return addUnsigned(rotateLeft(a, s), b); 66 | }; 67 | 68 | var convertToWordArray = function(string) { 69 | var lWordCount; 70 | var lMessageLength = string.length; 71 | var lNumberOfWordsTempOne = lMessageLength + 8; 72 | var lNumberOfWordsTempTwo = (lNumberOfWordsTempOne - (lNumberOfWordsTempOne % 64)) / 64; 73 | var lNumberOfWords = (lNumberOfWordsTempTwo + 1) * 16; 74 | var lWordArray = Array(lNumberOfWords - 1); 75 | var lBytePosition = 0; 76 | var lByteCount = 0; 77 | while (lByteCount < lMessageLength) { 78 | lWordCount = (lByteCount - (lByteCount % 4)) / 4; 79 | lBytePosition = (lByteCount % 4) * 8; 80 | lWordArray[lWordCount] = (lWordArray[lWordCount] | (string.charCodeAt(lByteCount) << lBytePosition)); 81 | lByteCount++; 82 | } 83 | lWordCount = (lByteCount - (lByteCount % 4)) / 4; 84 | lBytePosition = (lByteCount % 4) * 8; 85 | lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80 << lBytePosition); 86 | lWordArray[lNumberOfWords - 2] = lMessageLength << 3; 87 | lWordArray[lNumberOfWords - 1] = lMessageLength >>> 29; 88 | return lWordArray; 89 | }; 90 | 91 | var wordToHex = function(lValue) { 92 | var WordToHexValue = "", WordToHexValueTemp = "", lByte, lCount; 93 | for (lCount = 0; lCount <= 3; lCount++) { 94 | lByte = (lValue >>> (lCount * 8)) & 255; 95 | WordToHexValueTemp = "0" + lByte.toString(16); 96 | WordToHexValue = WordToHexValue + WordToHexValueTemp.substr(WordToHexValueTemp.length - 2, 2); 97 | } 98 | return WordToHexValue; 99 | }; 100 | 101 | var uTF8Encode = function(string) { 102 | string = string.replace(/\x0d\x0a/g, "\x0a"); 103 | var output = ""; 104 | for (var n = 0; n < string.length; n++) { 105 | var c = string.charCodeAt(n); 106 | if (c < 128) { 107 | output += String.fromCharCode(c); 108 | } else if ((c > 127) && (c < 2048)) { 109 | output += String.fromCharCode((c >> 6) | 192); 110 | output += String.fromCharCode((c & 63) | 128); 111 | } else { 112 | output += String.fromCharCode((c >> 12) | 224); 113 | output += String.fromCharCode(((c >> 6) & 63) | 128); 114 | output += String.fromCharCode((c & 63) | 128); 115 | } 116 | } 117 | return output; 118 | }; 119 | 120 | function md5(string) { 121 | var x = Array(); 122 | var k, AA, BB, CC, DD, a, b, c, d; 123 | var S11=7, S12=12, S13=17, S14=22; 124 | var S21=5, S22=9 , S23=14, S24=20; 125 | var S31=4, S32=11, S33=16, S34=23; 126 | var S41=6, S42=10, S43=15, S44=21; 127 | string = uTF8Encode(string); 128 | x = convertToWordArray(string); 129 | a = 0x67452301; b = 0xEFCDAB89; c = 0x98BADCFE; d = 0x10325476; 130 | for (k = 0; k < x.length; k += 16) { 131 | AA = a; BB = b; CC = c; DD = d; 132 | a = FF(a, b, c, d, x[k+0], S11, 0xD76AA478); 133 | d = FF(d, a, b, c, x[k+1], S12, 0xE8C7B756); 134 | c = FF(c, d, a, b, x[k+2], S13, 0x242070DB); 135 | b = FF(b, c, d, a, x[k+3], S14, 0xC1BDCEEE); 136 | a = FF(a, b, c, d, x[k+4], S11, 0xF57C0FAF); 137 | d = FF(d, a, b, c, x[k+5], S12, 0x4787C62A); 138 | c = FF(c, d, a, b, x[k+6], S13, 0xA8304613); 139 | b = FF(b, c, d, a, x[k+7], S14, 0xFD469501); 140 | a = FF(a, b, c, d, x[k+8], S11, 0x698098D8); 141 | d = FF(d, a, b, c, x[k+9], S12, 0x8B44F7AF); 142 | c = FF(c, d, a, b, x[k+10], S13, 0xFFFF5BB1); 143 | b = FF(b, c, d, a, x[k+11], S14, 0x895CD7BE); 144 | a = FF(a, b, c, d, x[k+12], S11, 0x6B901122); 145 | d = FF(d, a, b, c, x[k+13], S12, 0xFD987193); 146 | c = FF(c, d, a, b, x[k+14], S13, 0xA679438E); 147 | b = FF(b, c, d, a, x[k+15], S14, 0x49B40821); 148 | a = GG(a, b, c, d, x[k+1], S21, 0xF61E2562); 149 | d = GG(d, a, b, c, x[k+6], S22, 0xC040B340); 150 | c = GG(c, d, a, b, x[k+11], S23, 0x265E5A51); 151 | b = GG(b, c, d, a, x[k+0], S24, 0xE9B6C7AA); 152 | a = GG(a, b, c, d, x[k+5], S21, 0xD62F105D); 153 | d = GG(d, a, b, c, x[k+10], S22, 0x2441453); 154 | c = GG(c, d, a, b, x[k+15], S23, 0xD8A1E681); 155 | b = GG(b, c, d, a, x[k+4], S24, 0xE7D3FBC8); 156 | a = GG(a, b, c, d, x[k+9], S21, 0x21E1CDE6); 157 | d = GG(d, a, b, c, x[k+14], S22, 0xC33707D6); 158 | c = GG(c, d, a, b, x[k+3], S23, 0xF4D50D87); 159 | b = GG(b, c, d, a, x[k+8], S24, 0x455A14ED); 160 | a = GG(a, b, c, d, x[k+13], S21, 0xA9E3E905); 161 | d = GG(d, a, b, c, x[k+2], S22, 0xFCEFA3F8); 162 | c = GG(c, d, a, b, x[k+7], S23, 0x676F02D9); 163 | b = GG(b, c, d, a, x[k+12], S24, 0x8D2A4C8A); 164 | a = HH(a, b, c, d, x[k+5], S31, 0xFFFA3942); 165 | d = HH(d, a, b, c, x[k+8], S32, 0x8771F681); 166 | c = HH(c, d, a, b, x[k+11], S33, 0x6D9D6122); 167 | b = HH(b, c, d, a, x[k+14], S34, 0xFDE5380C); 168 | a = HH(a, b, c, d, x[k+1], S31, 0xA4BEEA44); 169 | d = HH(d, a, b, c, x[k+4], S32, 0x4BDECFA9); 170 | c = HH(c, d, a, b, x[k+7], S33, 0xF6BB4B60); 171 | b = HH(b, c, d, a, x[k+10], S34, 0xBEBFBC70); 172 | a = HH(a, b, c, d, x[k+13], S31, 0x289B7EC6); 173 | d = HH(d, a, b, c, x[k+0], S32, 0xEAA127FA); 174 | c = HH(c, d, a, b, x[k+3], S33, 0xD4EF3085); 175 | b = HH(b, c, d, a, x[k+6], S34, 0x4881D05); 176 | a = HH(a, b, c, d, x[k+9], S31, 0xD9D4D039); 177 | d = HH(d, a, b, c, x[k+12], S32, 0xE6DB99E5); 178 | c = HH(c, d, a, b, x[k+15], S33, 0x1FA27CF8); 179 | b = HH(b, c, d, a, x[k+2], S34, 0xC4AC5665); 180 | a = II(a, b, c, d, x[k+0], S41, 0xF4292244); 181 | d = II(d, a, b, c, x[k+7], S42, 0x432AFF97); 182 | c = II(c, d, a, b, x[k+14], S43, 0xAB9423A7); 183 | b = II(b, c, d, a, x[k+5], S44, 0xFC93A039); 184 | a = II(a, b, c, d, x[k+12], S41, 0x655B59C3); 185 | d = II(d, a, b, c, x[k+3], S42, 0x8F0CCC92); 186 | c = II(c, d, a, b, x[k+10], S43, 0xFFEFF47D); 187 | b = II(b, c, d, a, x[k+1], S44, 0x85845DD1); 188 | a = II(a, b, c, d, x[k+8], S41, 0x6FA87E4F); 189 | d = II(d, a, b, c, x[k+15], S42, 0xFE2CE6E0); 190 | c = II(c, d, a, b, x[k+6], S43, 0xA3014314); 191 | b = II(b, c, d, a, x[k+13], S44, 0x4E0811A1); 192 | a = II(a, b, c, d, x[k+4], S41, 0xF7537E82); 193 | d = II(d, a, b, c, x[k+11], S42, 0xBD3AF235); 194 | c = II(c, d, a, b, x[k+2], S43, 0x2AD7D2BB); 195 | b = II(b, c, d, a, x[k+9], S44, 0xEB86D391); 196 | a = addUnsigned(a, AA); 197 | b = addUnsigned(b, BB); 198 | c = addUnsigned(c, CC); 199 | d = addUnsigned(d, DD); 200 | } 201 | var tempValue = wordToHex(a) + wordToHex(b) + wordToHex(c) + wordToHex(d); 202 | return tempValue.toLowerCase(); 203 | } 204 | 205 | return md5; 206 | }); -------------------------------------------------------------------------------- /lib/bcrypt.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012 Nevins Bartolomeo 3 | Copyright (c) 2012 Shane Girish 4 | Copyright (c) 2014 Daniel Wirtz 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 | /** 28 | * @license bcrypt.js (c) 2013 Daniel Wirtz 29 | * Released under the Apache License, Version 2.0 30 | * see: https://github.com/dcodeIO/bcrypt.js for details 31 | */ 32 | (function(global, factory) { 33 | 34 | /* AMD */ if (typeof define === 'function' && define["amd"]) 35 | define([], factory); 36 | /* CommonJS */ else if (typeof require === 'function' && typeof module === "object" && module && module["exports"]) 37 | module["exports"] = factory(); 38 | /* Global */ else 39 | (global["dcodeIO"] = global["dcodeIO"] || {})["bcrypt"] = factory(); 40 | 41 | }(this, function() { 42 | "use strict"; 43 | 44 | /** 45 | * bcrypt namespace. 46 | * @type {Object.} 47 | */ 48 | var bcrypt = {}; 49 | 50 | /** 51 | * Generates cryptographically secure random bytes. 52 | * @function 53 | * @param {number} len Bytes length 54 | * @returns {!Array.} Random bytes 55 | * @throws {Error} If no random implementation is available 56 | * @inner 57 | */ 58 | var random = require('./random').randomBytes; 59 | 60 | /** 61 | * Synchronously generates a salt. 62 | * @param {number=} rounds Number of rounds to use, defaults to 10 if omitted 63 | * @param {number=} seed_length Not supported. 64 | * @returns {string} Resulting salt 65 | * @throws {Error} If a random fallback is required but not set 66 | * @expose 67 | */ 68 | bcrypt.genSaltSync = function(rounds, seed_length) { 69 | rounds = rounds || GENSALT_DEFAULT_LOG2_ROUNDS; 70 | if (typeof rounds !== 'number') 71 | throw Error("Illegal arguments: "+(typeof rounds)+", "+(typeof seed_length)); 72 | if (rounds < 4) 73 | rounds = 4; 74 | else if (rounds > 31) 75 | rounds = 31; 76 | var salt = []; 77 | salt.push("$2a$"); 78 | if (rounds < 10) 79 | salt.push("0"); 80 | salt.push(rounds.toString()); 81 | salt.push('$'); 82 | salt.push(base64_encode(random(BCRYPT_SALT_LEN), BCRYPT_SALT_LEN)); // May throw 83 | return salt.join(''); 84 | }; 85 | 86 | /** 87 | * Asynchronously generates a salt. 88 | * @param {(number|function(Error, string=))=} rounds Number of rounds to use, defaults to 10 if omitted 89 | * @param {(number|function(Error, string=))=} seed_length Not supported. 90 | * @param {function(Error, string=)=} callback Callback receiving the error, if any, and the resulting salt 91 | * @expose 92 | */ 93 | bcrypt.genSalt = function(rounds, seed_length, callback) { 94 | if (typeof seed_length === 'function') 95 | callback = seed_length, 96 | seed_length = undefined; // Not supported. 97 | if (typeof rounds === 'function') 98 | callback = rounds, 99 | rounds = GENSALT_DEFAULT_LOG2_ROUNDS; 100 | if (typeof callback !== 'function') 101 | throw Error("Illegal callback: "+typeof(callback)); 102 | if (typeof rounds !== 'number') { 103 | nextTick(callback.bind(this, Error("Illegal arguments: "+(typeof rounds)))); 104 | return; 105 | } 106 | nextTick(function() { // Pretty thin, but salting is fast enough 107 | try { 108 | callback(null, bcrypt.genSaltSync(rounds)); 109 | } catch (err) { 110 | callback(err); 111 | } 112 | }); 113 | }; 114 | 115 | /** 116 | * Synchronously generates a hash for the given string. 117 | * @param {string} s String to hash 118 | * @param {(number|string)=} salt Salt length to generate or salt to use, default to 10 119 | * @returns {string} Resulting hash 120 | * @expose 121 | */ 122 | bcrypt.hashSync = function(s, salt) { 123 | if (typeof salt === 'undefined') 124 | salt = GENSALT_DEFAULT_LOG2_ROUNDS; 125 | if (typeof salt === 'number') 126 | salt = bcrypt.genSaltSync(salt); 127 | if (typeof s !== 'string' || typeof salt !== 'string') 128 | throw Error("Illegal arguments: "+(typeof s)+', '+(typeof salt)); 129 | return _hash(s, salt); 130 | }; 131 | 132 | /** 133 | * Asynchronously generates a hash for the given string. 134 | * @param {string} s String to hash 135 | * @param {number|string} salt Salt length to generate or salt to use 136 | * @param {function(Error, string=)} callback Callback receiving the error, if any, and the resulting hash 137 | * @param {function(number)=} progressCallback Callback successively called with the percentage of rounds completed 138 | * (0.0 - 1.0), maximally once per `MAX_EXECUTION_TIME = 100` ms. 139 | * @expose 140 | */ 141 | bcrypt.hash = function(s, salt, callback, progressCallback) { 142 | if (typeof callback !== 'function') 143 | throw Error("Illegal callback: "+typeof(callback)); 144 | if (typeof s === 'string' && typeof salt === 'number') 145 | bcrypt.genSalt(salt, function(err, salt) { 146 | _hash(s, salt, callback, progressCallback); 147 | }); 148 | else if (typeof s === 'string' && typeof salt === 'string') 149 | _hash(s, salt, callback, progressCallback); 150 | else 151 | nextTick(callback.bind(this, Error("Illegal arguments: "+(typeof s)+', '+(typeof salt)))); 152 | }; 153 | 154 | /** 155 | * Compares two strings of the same length in constant time. 156 | * @param {string} known Must be of the correct length 157 | * @param {string} unknown Must be the same length as `known` 158 | * @returns {boolean} 159 | * @inner 160 | */ 161 | function safeStringCompare(known, unknown) { 162 | var right = 0, 163 | wrong = 0; 164 | for (var i=0, k=known.length; i} UTF8 bytes 263 | * @inner 264 | */ 265 | function stringToBytes(str) { 266 | var out = [], 267 | i = 0; 268 | utfx.encodeUTF16toUTF8(function() { 269 | if (i >= str.length) return null; 270 | return str.charCodeAt(i++); 271 | }, function(b) { 272 | out.push(b); 273 | }); 274 | return out; 275 | } 276 | 277 | // A base64 implementation for the bcrypt algorithm. This is partly non-standard. 278 | 279 | /** 280 | * bcrypt's own non-standard base64 dictionary. 281 | * @type {!Array.} 282 | * @const 283 | * @inner 284 | **/ 285 | var BASE64_CODE = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".split(''); 286 | 287 | /** 288 | * @type {!Array.} 289 | * @const 290 | * @inner 291 | **/ 292 | var BASE64_INDEX = [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 293 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 294 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 295 | 1, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, -1, -1, -1, -1, -1, -1, 296 | -1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 297 | 20, 21, 22, 23, 24, 25, 26, 27, -1, -1, -1, -1, -1, -1, 28, 29, 30, 298 | 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 299 | 48, 49, 50, 51, 52, 53, -1, -1, -1, -1, -1]; 300 | 301 | /** 302 | * @type {!function(...number):string} 303 | * @inner 304 | */ 305 | var stringFromCharCode = String.fromCharCode; 306 | 307 | /** 308 | * Encodes a byte array to base64 with up to len bytes of input. 309 | * @param {!Array.} b Byte array 310 | * @param {number} len Maximum input length 311 | * @returns {string} 312 | * @inner 313 | */ 314 | function base64_encode(b, len) { 315 | var off = 0, 316 | rs = [], 317 | c1, c2; 318 | if (len <= 0 || len > b.length) 319 | throw Error("Illegal len: "+len); 320 | while (off < len) { 321 | c1 = b[off++] & 0xff; 322 | rs.push(BASE64_CODE[(c1 >> 2) & 0x3f]); 323 | c1 = (c1 & 0x03) << 4; 324 | if (off >= len) { 325 | rs.push(BASE64_CODE[c1 & 0x3f]); 326 | break; 327 | } 328 | c2 = b[off++] & 0xff; 329 | c1 |= (c2 >> 4) & 0x0f; 330 | rs.push(BASE64_CODE[c1 & 0x3f]); 331 | c1 = (c2 & 0x0f) << 2; 332 | if (off >= len) { 333 | rs.push(BASE64_CODE[c1 & 0x3f]); 334 | break; 335 | } 336 | c2 = b[off++] & 0xff; 337 | c1 |= (c2 >> 6) & 0x03; 338 | rs.push(BASE64_CODE[c1 & 0x3f]); 339 | rs.push(BASE64_CODE[c2 & 0x3f]); 340 | } 341 | return rs.join(''); 342 | } 343 | 344 | /** 345 | * Decodes a base64 encoded string to up to len bytes of output. 346 | * @param {string} s String to decode 347 | * @param {number} len Maximum output length 348 | * @returns {!Array.} 349 | * @inner 350 | */ 351 | function base64_decode(s, len) { 352 | var off = 0, 353 | slen = s.length, 354 | olen = 0, 355 | rs = [], 356 | c1, c2, c3, c4, o, code; 357 | if (len <= 0) 358 | throw Error("Illegal len: "+len); 359 | while (off < slen - 1 && olen < len) { 360 | code = s.charCodeAt(off++); 361 | c1 = code < BASE64_INDEX.length ? BASE64_INDEX[code] : -1; 362 | code = s.charCodeAt(off++); 363 | c2 = code < BASE64_INDEX.length ? BASE64_INDEX[code] : -1; 364 | if (c1 == -1 || c2 == -1) 365 | break; 366 | o = (c1 << 2) >>> 0; 367 | o |= (c2 & 0x30) >> 4; 368 | rs.push(stringFromCharCode(o)); 369 | if (++olen >= len || off >= slen) 370 | break; 371 | code = s.charCodeAt(off++); 372 | c3 = code < BASE64_INDEX.length ? BASE64_INDEX[code] : -1; 373 | if (c3 == -1) 374 | break; 375 | o = ((c2 & 0x0f) << 4) >>> 0; 376 | o |= (c3 & 0x3c) >> 2; 377 | rs.push(stringFromCharCode(o)); 378 | if (++olen >= len || off >= slen) 379 | break; 380 | code = s.charCodeAt(off++); 381 | c4 = code < BASE64_INDEX.length ? BASE64_INDEX[code] : -1; 382 | o = ((c3 & 0x03) << 6) >>> 0; 383 | o |= c4; 384 | rs.push(stringFromCharCode(o)); 385 | ++olen; 386 | } 387 | var res = []; 388 | for (off = 0; off 395 | * Released under the Apache License, Version 2.0 396 | * see: https://github.com/dcodeIO/utfx for details 397 | */ 398 | var utfx = function() { 399 | "use strict"; 400 | 401 | /** 402 | * utfx namespace. 403 | * @inner 404 | * @type {!Object.} 405 | */ 406 | var utfx = {}; 407 | 408 | /** 409 | * Maximum valid code point. 410 | * @type {number} 411 | * @const 412 | */ 413 | utfx.MAX_CODEPOINT = 0x10FFFF; 414 | 415 | /** 416 | * Encodes UTF8 code points to UTF8 bytes. 417 | * @param {(!function():number|null) | number} src Code points source, either as a function returning the next code point 418 | * respectively `null` if there are no more code points left or a single numeric code point. 419 | * @param {!function(number)} dst Bytes destination as a function successively called with the next byte 420 | */ 421 | utfx.encodeUTF8 = function(src, dst) { 422 | var cp = null; 423 | if (typeof src === 'number') 424 | cp = src, 425 | src = function() { return null; }; 426 | while (cp !== null || (cp = src()) !== null) { 427 | if (cp < 0x80) 428 | dst(cp&0x7F); 429 | else if (cp < 0x800) 430 | dst(((cp>>6)&0x1F)|0xC0), 431 | dst((cp&0x3F)|0x80); 432 | else if (cp < 0x10000) 433 | dst(((cp>>12)&0x0F)|0xE0), 434 | dst(((cp>>6)&0x3F)|0x80), 435 | dst((cp&0x3F)|0x80); 436 | else 437 | dst(((cp>>18)&0x07)|0xF0), 438 | dst(((cp>>12)&0x3F)|0x80), 439 | dst(((cp>>6)&0x3F)|0x80), 440 | dst((cp&0x3F)|0x80); 441 | cp = null; 442 | } 443 | }; 444 | 445 | /** 446 | * Decodes UTF8 bytes to UTF8 code points. 447 | * @param {!function():number|null} src Bytes source as a function returning the next byte respectively `null` if there 448 | * are no more bytes left. 449 | * @param {!function(number)} dst Code points destination as a function successively called with each decoded code point. 450 | * @throws {RangeError} If a starting byte is invalid in UTF8 451 | * @throws {Error} If the last sequence is truncated. Has an array property `bytes` holding the 452 | * remaining bytes. 453 | */ 454 | utfx.decodeUTF8 = function(src, dst) { 455 | var a, b, c, d, fail = function(b) { 456 | b = b.slice(0, b.indexOf(null)); 457 | var err = Error(b.toString()); 458 | err.name = "TruncatedError"; 459 | err['bytes'] = b; 460 | throw err; 461 | }; 462 | while ((a = src()) !== null) { 463 | if ((a&0x80) === 0) 464 | dst(a); 465 | else if ((a&0xE0) === 0xC0) 466 | ((b = src()) === null) && fail([a, b]), 467 | dst(((a&0x1F)<<6) | (b&0x3F)); 468 | else if ((a&0xF0) === 0xE0) 469 | ((b=src()) === null || (c=src()) === null) && fail([a, b, c]), 470 | dst(((a&0x0F)<<12) | ((b&0x3F)<<6) | (c&0x3F)); 471 | else if ((a&0xF8) === 0xF0) 472 | ((b=src()) === null || (c=src()) === null || (d=src()) === null) && fail([a, b, c ,d]), 473 | dst(((a&0x07)<<18) | ((b&0x3F)<<12) | ((c&0x3F)<<6) | (d&0x3F)); 474 | else throw RangeError("Illegal starting byte: "+a); 475 | } 476 | }; 477 | 478 | /** 479 | * Converts UTF16 characters to UTF8 code points. 480 | * @param {!function():number|null} src Characters source as a function returning the next char code respectively 481 | * `null` if there are no more characters left. 482 | * @param {!function(number)} dst Code points destination as a function successively called with each converted code 483 | * point. 484 | */ 485 | utfx.UTF16toUTF8 = function(src, dst) { 486 | var c1, c2 = null; 487 | while (true) { 488 | if ((c1 = c2 !== null ? c2 : src()) === null) 489 | break; 490 | if (c1 >= 0xD800 && c1 <= 0xDFFF) { 491 | if ((c2 = src()) !== null) { 492 | if (c2 >= 0xDC00 && c2 <= 0xDFFF) { 493 | dst((c1-0xD800)*0x400+c2-0xDC00+0x10000); 494 | c2 = null; continue; 495 | } 496 | } 497 | } 498 | dst(c1); 499 | } 500 | if (c2 !== null) dst(c2); 501 | }; 502 | 503 | /** 504 | * Converts UTF8 code points to UTF16 characters. 505 | * @param {(!function():number|null) | number} src Code points source, either as a function returning the next code point 506 | * respectively `null` if there are no more code points left or a single numeric code point. 507 | * @param {!function(number)} dst Characters destination as a function successively called with each converted char code. 508 | * @throws {RangeError} If a code point is out of range 509 | */ 510 | utfx.UTF8toUTF16 = function(src, dst) { 511 | var cp = null; 512 | if (typeof src === 'number') 513 | cp = src, src = function() { return null; }; 514 | while (cp !== null || (cp = src()) !== null) { 515 | if (cp <= 0xFFFF) 516 | dst(cp); 517 | else 518 | cp -= 0x10000, 519 | dst((cp>>10)+0xD800), 520 | dst((cp%0x400)+0xDC00); 521 | cp = null; 522 | } 523 | }; 524 | 525 | /** 526 | * Converts and encodes UTF16 characters to UTF8 bytes. 527 | * @param {!function():number|null} src Characters source as a function returning the next char code respectively `null` 528 | * if there are no more characters left. 529 | * @param {!function(number)} dst Bytes destination as a function successively called with the next byte. 530 | */ 531 | utfx.encodeUTF16toUTF8 = function(src, dst) { 532 | utfx.UTF16toUTF8(src, function(cp) { 533 | utfx.encodeUTF8(cp, dst); 534 | }); 535 | }; 536 | 537 | /** 538 | * Decodes and converts UTF8 bytes to UTF16 characters. 539 | * @param {!function():number|null} src Bytes source as a function returning the next byte respectively `null` if there 540 | * are no more bytes left. 541 | * @param {!function(number)} dst Characters destination as a function successively called with each converted char code. 542 | * @throws {RangeError} If a starting byte is invalid in UTF8 543 | * @throws {Error} If the last sequence is truncated. Has an array property `bytes` holding the remaining bytes. 544 | */ 545 | utfx.decodeUTF8toUTF16 = function(src, dst) { 546 | utfx.decodeUTF8(src, function(cp) { 547 | utfx.UTF8toUTF16(cp, dst); 548 | }); 549 | }; 550 | 551 | /** 552 | * Calculates the byte length of an UTF8 code point. 553 | * @param {number} cp UTF8 code point 554 | * @returns {number} Byte length 555 | */ 556 | utfx.calculateCodePoint = function(cp) { 557 | return (cp < 0x80) ? 1 : (cp < 0x800) ? 2 : (cp < 0x10000) ? 3 : 4; 558 | }; 559 | 560 | /** 561 | * Calculates the number of UTF8 bytes required to store UTF8 code points. 562 | * @param {(!function():number|null)} src Code points source as a function returning the next code point respectively 563 | * `null` if there are no more code points left. 564 | * @returns {number} The number of UTF8 bytes required 565 | */ 566 | utfx.calculateUTF8 = function(src) { 567 | var cp, l=0; 568 | while ((cp = src()) !== null) 569 | l += utfx.calculateCodePoint(cp); 570 | return l; 571 | }; 572 | 573 | /** 574 | * Calculates the number of UTF8 code points respectively UTF8 bytes required to store UTF16 char codes. 575 | * @param {(!function():number|null)} src Characters source as a function returning the next char code respectively 576 | * `null` if there are no more characters left. 577 | * @returns {!Array.} The number of UTF8 code points at index 0 and the number of UTF8 bytes required at index 1. 578 | */ 579 | utfx.calculateUTF16asUTF8 = function(src) { 580 | var n=0, l=0; 581 | utfx.UTF16toUTF8(src, function(cp) { 582 | ++n; l += utfx.calculateCodePoint(cp); 583 | }); 584 | return [n,l]; 585 | }; 586 | 587 | return utfx; 588 | }(); 589 | 590 | Date.now = Date.now || function() { return +new Date; }; 591 | 592 | /** 593 | * @type {number} 594 | * @const 595 | * @inner 596 | */ 597 | var BCRYPT_SALT_LEN = 16; 598 | 599 | /** 600 | * @type {number} 601 | * @const 602 | * @inner 603 | */ 604 | var GENSALT_DEFAULT_LOG2_ROUNDS = 10; 605 | 606 | /** 607 | * @type {number} 608 | * @const 609 | * @inner 610 | */ 611 | var BLOWFISH_NUM_ROUNDS = 16; 612 | 613 | /** 614 | * @type {number} 615 | * @const 616 | * @inner 617 | */ 618 | var MAX_EXECUTION_TIME = 100; 619 | 620 | /** 621 | * @type {Array.} 622 | * @const 623 | * @inner 624 | */ 625 | var P_ORIG = [ 626 | 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 627 | 0x299f31d0, 0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 628 | 0xbe5466cf, 0x34e90c6c, 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 629 | 0xb5470917, 0x9216d5d9, 0x8979fb1b 630 | ]; 631 | 632 | /** 633 | * @type {Array.} 634 | * @const 635 | * @inner 636 | */ 637 | var S_ORIG = [ 638 | 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 639 | 0x6a267e96, 0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 640 | 0x0801f2e2, 0x858efc16, 0x636920d8, 0x71574e69, 0xa458fea3, 641 | 0xf4933d7e, 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, 642 | 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, 0xc5d1b023, 643 | 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e, 644 | 0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, 645 | 0x55605c60, 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 646 | 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, 0xa15486af, 647 | 0x7c72e993, 0xb3ee1411, 0x636fbc2a, 0x2ba9c55d, 0x741831f6, 648 | 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 649 | 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, 650 | 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 651 | 0xe98575b1, 0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 652 | 0x0f6d6ff3, 0x83f44239, 0x2e0b4482, 0xa4842004, 0x69c8f04a, 653 | 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0, 654 | 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, 0x6eef0b6c, 655 | 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176, 656 | 0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 657 | 0x3b8b5ebe, 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 658 | 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, 0x37d0d724, 659 | 0xd00a1248, 0xdb0fead3, 0x49f1c09b, 0x075372c9, 0x80991b7b, 660 | 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 661 | 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, 662 | 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 663 | 0x9b30952c, 0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 664 | 0x660f2807, 0x192e4bb3, 0xc0cba857, 0x45c8740f, 0xd20b5f39, 665 | 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, 666 | 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, 0x3c7516df, 667 | 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760, 668 | 0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 669 | 0xdf1769db, 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 670 | 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 671 | 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, 0x9a53e479, 0xb6f84565, 672 | 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 673 | 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, 674 | 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 675 | 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 676 | 0x8888b812, 0x900df01c, 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 677 | 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1, 678 | 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, 0xb4a84fe0, 679 | 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705, 680 | 0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 681 | 0xfb9d35cf, 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 682 | 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af, 0x2464369b, 683 | 0xf009b91e, 0x5563911d, 0x59dfa6aa, 0x78c14389, 0xd95a537f, 684 | 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9, 0x11c81968, 685 | 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, 686 | 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 687 | 0x571be91f, 0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 688 | 0xff34052e, 0xc5855664, 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 689 | 0x6e85076a, 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 690 | 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266, 0xecaa8c71, 691 | 0x699a17ff, 0x5664526c, 0xc2b19ee1, 0x193602a5, 0x75094c29, 692 | 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 693 | 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, 694 | 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 695 | 0x3ebaefc9, 0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 696 | 0xb79c5305, 0xaa500737, 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 697 | 0x5716f2b8, 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, 698 | 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, 0xd19113f9, 699 | 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc, 700 | 0xc8b57634, 0x9af3dda7, 0xa9446146, 0x0fd0030e, 0xecc8c73e, 701 | 0xa4751e41, 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 702 | 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, 0x2cb81290, 703 | 0x24977c79, 0x5679b072, 0xbcaf89af, 0xde9a771f, 0xd9930810, 704 | 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124, 0x501adde6, 705 | 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, 706 | 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 707 | 0x3215d908, 0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 708 | 0x50940002, 0x133ae4dd, 0x71dff89e, 0x10314e55, 0x81ac77d6, 709 | 0x5f11199b, 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509, 710 | 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, 0x86e34570, 711 | 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa, 712 | 0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 713 | 0x9c10b36a, 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 714 | 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960, 0x5223a708, 715 | 0xf71312b6, 0xebadfe6e, 0xeac31f66, 0xe3bc4595, 0xa67bc883, 716 | 0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5, 0x65582185, 717 | 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, 718 | 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 719 | 0xeb61bd96, 0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, 720 | 0xd59e9e0b, 0xcbaade14, 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 721 | 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, 722 | 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, 0x9b540b19, 723 | 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77, 724 | 0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 725 | 0x7858ba99, 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 726 | 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 727 | 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, 0x5d4a14d9, 0xe864b7e3, 728 | 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 729 | 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, 730 | 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, 731 | 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 732 | 0x47848a0b, 0x5692b285, 0x095bbf00, 0xad19489d, 0x1462b174, 733 | 0x23820e00, 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061, 734 | 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, 0x7cde3759, 735 | 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e, 736 | 0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 737 | 0x800bcadc, 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 738 | 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340, 0xc5c43465, 739 | 0x713e38d8, 0x3d28f89e, 0xf16dff20, 0x153e21e7, 0x8fb03d4a, 740 | 0xe6e39f2b, 0xdb83adf7, 0xe93d5a68, 0x948140f7, 0xf64c261c, 741 | 0x94692934, 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068, 742 | 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, 0x1e39f62e, 743 | 0x97244546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af, 744 | 0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 745 | 0x31cb8504, 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 746 | 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb, 0x68dc1462, 747 | 0xd7486900, 0x680ec0a4, 0x27a18dee, 0x4f3ffea2, 0xe887ad8c, 748 | 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec, 0xce78a399, 749 | 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, 750 | 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 751 | 0xdd5b4332, 0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397, 752 | 0x454056ac, 0xba489527, 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 753 | 0xd096954b, 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, 754 | 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, 0xfdf8e802, 755 | 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22, 756 | 0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f, 0x404779a4, 757 | 0x5d886e17, 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 758 | 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 759 | 0x02e1329e, 0xaf664fd1, 0xcad18115, 0x6b2395e0, 0x333e92e1, 760 | 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 761 | 0x2da2f728, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, 762 | 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x0a476341, 763 | 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 764 | 0x991be14c, 0xdb6e6b0d, 0xc67b5510, 0x6d672c37, 0x2765d43b, 765 | 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b, 766 | 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, 0xbb132f88, 767 | 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979, 768 | 0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 769 | 0x782ef11c, 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 770 | 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9, 0x44421659, 771 | 0x0a121386, 0xd90cec6e, 0xd5abea2a, 0x64af674e, 0xda86a85f, 772 | 0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 773 | 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, 774 | 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 775 | 0xbde8ae24, 0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2, 776 | 0xf474ef38, 0x8789bdc2, 0x5366f9c3, 0xc8b38e74, 0xb475f255, 777 | 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, 778 | 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, 0xb90bace1, 779 | 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09, 780 | 0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 781 | 0x1d6efe10, 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, 782 | 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 783 | 0xa70683fa, 0xa002b5c4, 0x0de6d027, 0x9af88c27, 0x773f8641, 784 | 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0, 0x006058aa, 785 | 0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, 786 | 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0x6f05e409, 787 | 0x4b7c0188, 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 788 | 0x1ac15bb4, 0xd39eb8fc, 0xed545578, 0x08fca5b5, 0xd83d7cd3, 789 | 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c, 790 | 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, 0xd79a3234, 791 | 0x92638212, 0x670efa8e, 0x406000e0, 0x3a39ce37, 0xd3faf5cf, 792 | 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742, 0xd3822740, 793 | 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, 794 | 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 795 | 0xbc946e79, 0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 796 | 0xd5730a1d, 0x4cd04dc6, 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 797 | 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22, 798 | 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, 0x83c061ba, 799 | 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1, 800 | 0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 801 | 0x77fa0a59, 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 802 | 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, 803 | 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, 0x1f9f25cf, 0xadf2b89b, 804 | 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 805 | 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, 806 | 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 807 | 0x88f46dba, 0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, 808 | 0x97271aec, 0xa93a072a, 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 809 | 0x26dcf319, 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, 810 | 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, 0x4de81751, 811 | 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce, 812 | 0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 813 | 0x6413e680, 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 814 | 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 815 | 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, 0xdda26a7e, 0x3a59ff45, 816 | 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 817 | 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, 818 | 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 819 | 0x4eb4e2cc, 0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 820 | 0x06b89fb4, 0xce6ea048, 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 821 | 0x277227f8, 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd, 822 | 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, 0xe01cc87e, 823 | 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a, 824 | 0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 825 | 0xe0b12b4f, 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 826 | 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525, 0xfae59361, 827 | 0xceb69ceb, 0xc2a86459, 0x12baa8d1, 0xb6c1075e, 0xe3056a0c, 828 | 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 829 | 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, 830 | 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 831 | 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891, 832 | 0xce6279cf, 0xcd3e7e6f, 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 833 | 0xf6fb2299, 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, 834 | 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, 0xde966292, 835 | 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a, 836 | 0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 837 | 0x35bdd2f6, 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 838 | 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, 0xba38209c, 839 | 0xf746ce76, 0x77afa1c5, 0x20756060, 0x85cbfe4e, 0x8ae88dd8, 840 | 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 841 | 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, 842 | 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6 843 | ]; 844 | 845 | /** 846 | * @type {Array.} 847 | * @const 848 | * @inner 849 | */ 850 | var C_ORIG = [ 851 | 0x4f727068, 0x65616e42, 0x65686f6c, 0x64657253, 0x63727944, 852 | 0x6f756274 853 | ]; 854 | 855 | /** 856 | * @param {Array.} lr 857 | * @param {number} off 858 | * @param {Array.} P 859 | * @param {Array.} S 860 | * @returns {Array.} 861 | * @inner 862 | */ 863 | function _encipher(lr, off, P, S) { // This is our bottleneck: 1714/1905 ticks / 90% - see profile.txt 864 | var n, 865 | l = lr[off], 866 | r = lr[off + 1]; 867 | 868 | l ^= P[0]; 869 | for (var i=0, k=BLOWFISH_NUM_ROUNDS-2; i<=k;) 870 | // Feistel substitution on left word 871 | n = S[(l >> 24) & 0xff], 872 | n += S[0x100 | ((l >> 16) & 0xff)], 873 | n ^= S[0x200 | ((l >> 8) & 0xff)], 874 | n += S[0x300 | (l & 0xff)], 875 | r ^= n ^ P[++i], 876 | // Feistel substitution on right word 877 | n = S[(r >> 24) & 0xff], 878 | n += S[0x100 | ((r >> 16) & 0xff)], 879 | n ^= S[0x200 | ((r >> 8) & 0xff)], 880 | n += S[0x300 | (r & 0xff)], 881 | l ^= n ^ P[++i]; 882 | lr[off] = r ^ P[BLOWFISH_NUM_ROUNDS + 1]; 883 | lr[off + 1] = l; 884 | return lr; 885 | } 886 | 887 | /** 888 | * @param {Array.} data 889 | * @param {number} offp 890 | * @returns {{key: number, offp: number}} 891 | * @inner 892 | */ 893 | function _streamtoword(data, offp) { 894 | for (var i = 0, word = 0; i < 4; ++i) 895 | word = (word << 8) | (data[offp] & 0xff), 896 | offp = (offp + 1) % data.length; 897 | return { key: word, offp: offp }; 898 | } 899 | 900 | /** 901 | * @param {Array.} key 902 | * @param {Array.} P 903 | * @param {Array.} S 904 | * @inner 905 | */ 906 | function _key(key, P, S) { 907 | var offset = 0, 908 | lr = [0, 0], 909 | plen = P.length, 910 | slen = S.length, 911 | sw; 912 | for (var i = 0; i < plen; i++) 913 | sw = _streamtoword(key, offset), 914 | offset = sw.offp, 915 | P[i] = P[i] ^ sw.key; 916 | for (i = 0; i < plen; i += 2) 917 | lr = _encipher(lr, 0, P, S), 918 | P[i] = lr[0], 919 | P[i + 1] = lr[1]; 920 | for (i = 0; i < slen; i += 2) 921 | lr = _encipher(lr, 0, P, S), 922 | S[i] = lr[0], 923 | S[i + 1] = lr[1]; 924 | } 925 | 926 | /** 927 | * Expensive key schedule Blowfish. 928 | * @param {Array.} data 929 | * @param {Array.} key 930 | * @param {Array.} P 931 | * @param {Array.} S 932 | * @inner 933 | */ 934 | function _ekskey(data, key, P, S) { 935 | var offp = 0, 936 | lr = [0, 0], 937 | plen = P.length, 938 | slen = S.length, 939 | sw; 940 | for (var i = 0; i < plen; i++) 941 | sw = _streamtoword(key, offp), 942 | offp = sw.offp, 943 | P[i] = P[i] ^ sw.key; 944 | offp = 0; 945 | for (i = 0; i < plen; i += 2) 946 | sw = _streamtoword(data, offp), 947 | offp = sw.offp, 948 | lr[0] ^= sw.key, 949 | sw = _streamtoword(data, offp), 950 | offp = sw.offp, 951 | lr[1] ^= sw.key, 952 | lr = _encipher(lr, 0, P, S), 953 | P[i] = lr[0], 954 | P[i + 1] = lr[1]; 955 | for (i = 0; i < slen; i += 2) 956 | sw = _streamtoword(data, offp), 957 | offp = sw.offp, 958 | lr[0] ^= sw.key, 959 | sw = _streamtoword(data, offp), 960 | offp = sw.offp, 961 | lr[1] ^= sw.key, 962 | lr = _encipher(lr, 0, P, S), 963 | S[i] = lr[0], 964 | S[i + 1] = lr[1]; 965 | } 966 | 967 | /** 968 | * Internaly crypts a string. 969 | * @param {Array.} b Bytes to crypt 970 | * @param {Array.} salt Salt bytes to use 971 | * @param {number} rounds Number of rounds 972 | * @param {function(Error, Array.=)=} callback Callback receiving the error, if any, and the resulting bytes. If 973 | * omitted, the operation will be performed synchronously. 974 | * @param {function(number)=} progressCallback Callback called with the current progress 975 | * @returns {!Array.|undefined} Resulting bytes if callback has been omitted, otherwise `undefined` 976 | * @inner 977 | */ 978 | function _crypt(b, salt, rounds, callback, progressCallback) { 979 | var cdata = C_ORIG.slice(), 980 | clen = cdata.length, 981 | err; 982 | 983 | // Validate 984 | if (rounds < 4 || rounds > 31) { 985 | err = Error("Illegal number of rounds (4-31): "+rounds); 986 | if (callback) { 987 | nextTick(callback.bind(this, err)); 988 | return; 989 | } else 990 | throw err; 991 | } 992 | if (salt.length !== BCRYPT_SALT_LEN) { 993 | err =Error("Illegal salt length: "+salt.length+" != "+BCRYPT_SALT_LEN); 994 | if (callback) { 995 | nextTick(callback.bind(this, err)); 996 | return; 997 | } else 998 | throw err; 999 | } 1000 | rounds = (1 << rounds) >>> 0; 1001 | var P = P_ORIG.slice(), 1002 | S = S_ORIG.slice(), 1003 | i = 0, j; 1004 | _ekskey(salt, b, P, S); 1005 | 1006 | /** 1007 | * Calcualtes the next round. 1008 | * @returns {Array.|undefined} Resulting array if callback has been omitted, otherwise `undefined` 1009 | * @inner 1010 | */ 1011 | function next() { 1012 | if (progressCallback) 1013 | progressCallback(i / rounds); 1014 | if (i < rounds) { 1015 | var start = Date.now(); 1016 | for (; i < rounds;) { 1017 | i = i + 1; 1018 | _key(b, P, S); 1019 | _key(salt, P, S); 1020 | if (Date.now() - start > MAX_EXECUTION_TIME) 1021 | break; 1022 | } 1023 | } else { 1024 | for (i = 0; i < 64; i++) 1025 | for (j = 0; j < (clen >> 1); j++) 1026 | _encipher(cdata, j << 1, P, S); 1027 | var ret = []; 1028 | for (i = 0; i < clen; i++) 1029 | ret.push(((cdata[i] >> 24) & 0xff) >>> 0), 1030 | ret.push(((cdata[i] >> 16) & 0xff) >>> 0), 1031 | ret.push(((cdata[i] >> 8) & 0xff) >>> 0), 1032 | ret.push((cdata[i] & 0xff) >>> 0); 1033 | if (callback) { 1034 | callback(null, ret); 1035 | return; 1036 | } else 1037 | return ret; 1038 | } 1039 | if (callback) 1040 | nextTick(next); 1041 | } 1042 | 1043 | // Async 1044 | if (typeof callback !== 'undefined') { 1045 | next(); 1046 | 1047 | // Sync 1048 | } else { 1049 | var res; 1050 | while (true) 1051 | if (typeof(res = next()) !== 'undefined') 1052 | return res || []; 1053 | } 1054 | } 1055 | 1056 | /** 1057 | * Internally hashes a string. 1058 | * @param {string} s String to hash 1059 | * @param {?string} salt Salt to use, actually never null 1060 | * @param {function(Error, string=)=} callback Callback receiving the error, if any, and the resulting hash. If omitted, 1061 | * hashing is perormed synchronously. 1062 | * @param {function(number)=} progressCallback Callback called with the current progress 1063 | * @returns {string|undefined} Resulting hash if callback has been omitted, otherwise `undefined` 1064 | * @inner 1065 | */ 1066 | function _hash(s, salt, callback, progressCallback) { 1067 | var err; 1068 | if (typeof s !== 'string' || typeof salt !== 'string') { 1069 | err = Error("Invalid string / salt: Not a string"); 1070 | if (callback) { 1071 | nextTick(callback.bind(this, err)); 1072 | return; 1073 | } 1074 | else 1075 | throw err; 1076 | } 1077 | 1078 | // Validate the salt 1079 | var minor, offset; 1080 | if (salt.charAt(0) !== '$' || salt.charAt(1) !== '2') { 1081 | err = Error("Invalid salt version: "+salt.substring(0,2)); 1082 | if (callback) { 1083 | nextTick(callback.bind(this, err)); 1084 | return; 1085 | } 1086 | else 1087 | throw err; 1088 | } 1089 | if (salt.charAt(2) === '$') 1090 | minor = String.fromCharCode(0), 1091 | offset = 3; 1092 | else { 1093 | minor = salt.charAt(2); 1094 | if ((minor !== 'a' && minor !== 'b' && minor !== 'y') || salt.charAt(3) !== '$') { 1095 | err = Error("Invalid salt revision: "+salt.substring(2,4)); 1096 | if (callback) { 1097 | nextTick(callback.bind(this, err)); 1098 | return; 1099 | } else 1100 | throw err; 1101 | } 1102 | offset = 4; 1103 | } 1104 | 1105 | // Extract number of rounds 1106 | if (salt.charAt(offset + 2) > '$') { 1107 | err = Error("Missing salt rounds"); 1108 | if (callback) { 1109 | nextTick(callback.bind(this, err)); 1110 | return; 1111 | } else 1112 | throw err; 1113 | } 1114 | var r1 = parseInt(salt.substring(offset, offset + 1), 10) * 10, 1115 | r2 = parseInt(salt.substring(offset + 1, offset + 2), 10), 1116 | rounds = r1 + r2, 1117 | real_salt = salt.substring(offset + 3, offset + 25); 1118 | s += minor >= 'a' ? "\x00" : ""; 1119 | 1120 | var passwordb = stringToBytes(s), 1121 | saltb = base64_decode(real_salt, BCRYPT_SALT_LEN); 1122 | 1123 | /** 1124 | * Finishes hashing. 1125 | * @param {Array.} bytes Byte array 1126 | * @returns {string} 1127 | * @inner 1128 | */ 1129 | function finish(bytes) { 1130 | var res = []; 1131 | res.push("$2"); 1132 | if (minor >= 'a') 1133 | res.push(minor); 1134 | res.push("$"); 1135 | if (rounds < 10) 1136 | res.push("0"); 1137 | res.push(rounds.toString()); 1138 | res.push("$"); 1139 | res.push(base64_encode(saltb, saltb.length)); 1140 | res.push(base64_encode(bytes, C_ORIG.length * 4 - 1)); 1141 | return res.join(''); 1142 | } 1143 | 1144 | // Sync 1145 | if (typeof callback == 'undefined') 1146 | return finish(_crypt(passwordb, saltb, rounds)); 1147 | 1148 | // Async 1149 | else { 1150 | _crypt(passwordb, saltb, rounds, function(err, bytes) { 1151 | if (err) 1152 | callback(err, null); 1153 | else 1154 | callback(null, finish(bytes)); 1155 | }, progressCallback); 1156 | } 1157 | } 1158 | 1159 | /** 1160 | * Encodes a byte array to base64 with up to len bytes of input, using the custom bcrypt alphabet. 1161 | * @function 1162 | * @param {!Array.} b Byte array 1163 | * @param {number} len Maximum input length 1164 | * @returns {string} 1165 | * @expose 1166 | */ 1167 | bcrypt.encodeBase64 = base64_encode; 1168 | 1169 | /** 1170 | * Decodes a base64 encoded string to up to len bytes of output, using the custom bcrypt alphabet. 1171 | * @function 1172 | * @param {string} s String to decode 1173 | * @param {number} len Maximum output length 1174 | * @returns {!Array.} 1175 | * @expose 1176 | */ 1177 | bcrypt.decodeBase64 = base64_decode; 1178 | 1179 | return bcrypt; 1180 | })); --------------------------------------------------------------------------------