• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1'use strict';
2
3var crypto_hash_sha512 = require('tweetnacl').lowlevel.crypto_hash;
4
5/*
6 * This file is a 1:1 port from the OpenBSD blowfish.c and bcrypt_pbkdf.c. As a
7 * result, it retains the original copyright and license. The two files are
8 * under slightly different (but compatible) licenses, and are here combined in
9 * one file.
10 *
11 * Credit for the actual porting work goes to:
12 *  Devi Mandiri <me@devi.web.id>
13 */
14
15/*
16 * The Blowfish portions are under the following license:
17 *
18 * Blowfish block cipher for OpenBSD
19 * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>
20 * All rights reserved.
21 *
22 * Implementation advice by David Mazieres <dm@lcs.mit.edu>.
23 *
24 * Redistribution and use in source and binary forms, with or without
25 * modification, are permitted provided that the following conditions
26 * are met:
27 * 1. Redistributions of source code must retain the above copyright
28 *    notice, this list of conditions and the following disclaimer.
29 * 2. Redistributions in binary form must reproduce the above copyright
30 *    notice, this list of conditions and the following disclaimer in the
31 *    documentation and/or other materials provided with the distribution.
32 * 3. The name of the author may not be used to endorse or promote products
33 *    derived from this software without specific prior written permission.
34 *
35 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
36 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
37 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
38 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
39 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
40 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
41 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
42 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
43 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
44 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
45 */
46
47/*
48 * The bcrypt_pbkdf portions are under the following license:
49 *
50 * Copyright (c) 2013 Ted Unangst <tedu@openbsd.org>
51 *
52 * Permission to use, copy, modify, and distribute this software for any
53 * purpose with or without fee is hereby granted, provided that the above
54 * copyright notice and this permission notice appear in all copies.
55 *
56 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
57 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
58 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
59 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
60 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
61 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
62 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
63 */
64
65/*
66 * Performance improvements (Javascript-specific):
67 *
68 * Copyright 2016, Joyent Inc
69 * Author: Alex Wilson <alex.wilson@joyent.com>
70 *
71 * Permission to use, copy, modify, and distribute this software for any
72 * purpose with or without fee is hereby granted, provided that the above
73 * copyright notice and this permission notice appear in all copies.
74 *
75 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
76 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
77 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
78 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
79 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
80 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
81 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
82 */
83
84// Ported from OpenBSD bcrypt_pbkdf.c v1.9
85
86var BLF_J = 0;
87
88var Blowfish = function() {
89  this.S = [
90    new Uint32Array([
91      0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7,
92      0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
93      0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
94      0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
95      0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee,
96      0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
97      0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef,
98      0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
99      0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
100      0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
101      0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce,
102      0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
103      0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e,
104      0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
105      0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
106      0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
107      0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88,
108      0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
109      0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e,
110      0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
111      0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
112      0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
113      0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88,
114      0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
115      0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6,
116      0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,
117      0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
118      0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
119      0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba,
120      0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
121      0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f,
122      0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
123      0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
124      0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
125      0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279,
126      0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
127      0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab,
128      0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,
129      0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
130      0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
131      0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0,
132      0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
133      0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790,
134      0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,
135      0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
136      0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
137      0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7,
138      0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
139      0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad,
140      0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
141      0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
142      0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
143      0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477,
144      0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
145      0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49,
146      0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
147      0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
148      0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
149      0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41,
150      0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
151      0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400,
152      0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
153      0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
154      0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a]),
155    new Uint32Array([
156      0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623,
157      0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
158      0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
159      0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
160      0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6,
161      0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
162      0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e,
163      0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
164      0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
165      0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
166      0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff,
167      0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
168      0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701,
169      0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
170      0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
171      0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
172      0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf,
173      0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
174      0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e,
175      0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
176      0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
177      0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,
178      0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16,
179      0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
180      0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b,
181      0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
182      0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
183      0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,
184      0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f,
185      0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
186      0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4,
187      0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
188      0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
189      0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
190      0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802,
191      0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
192      0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510,
193      0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
194      0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
195      0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,
196      0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50,
197      0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
198      0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8,
199      0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
200      0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
201      0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
202      0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128,
203      0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
204      0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0,
205      0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
206      0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
207      0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
208      0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3,
209      0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
210      0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00,
211      0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
212      0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
213      0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
214      0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735,
215      0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
216      0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9,
217      0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
218      0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
219      0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7]),
220    new Uint32Array([
221      0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934,
222      0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
223      0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
224      0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
225      0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45,
226      0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
227      0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a,
228      0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
229      0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
230      0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
231      0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42,
232      0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
233      0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2,
234      0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
235      0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
236      0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
237      0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33,
238      0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
239      0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3,
240      0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
241      0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
242      0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
243      0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b,
244      0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
245      0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922,
246      0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
247      0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
248      0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
249      0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37,
250      0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
251      0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804,
252      0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
253      0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
254      0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
255      0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d,
256      0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
257      0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350,
258      0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
259      0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
260      0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
261      0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d,
262      0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
263      0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f,
264      0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
265      0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
266      0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
267      0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2,
268      0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
269      0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e,
270      0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,
271      0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
272      0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
273      0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52,
274      0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
275      0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5,
276      0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
277      0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
278      0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
279      0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24,
280      0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
281      0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4,
282      0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
283      0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
284      0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0]),
285    new Uint32Array([
286      0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b,
287      0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
288      0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
289      0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
290      0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8,
291      0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
292      0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304,
293      0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
294      0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
295      0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,
296      0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9,
297      0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
298      0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593,
299      0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
300      0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
301      0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,
302      0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b,
303      0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
304      0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c,
305      0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,
306      0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
307      0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
308      0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb,
309      0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
310      0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991,
311      0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,
312      0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
313      0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
314      0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae,
315      0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
316      0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5,
317      0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
318      0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
319      0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,
320      0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84,
321      0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
322      0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8,
323      0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
324      0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
325      0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,
326      0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38,
327      0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
328      0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c,
329      0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,
330      0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
331      0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
332      0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964,
333      0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
334      0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8,
335      0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
336      0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
337      0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,
338      0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02,
339      0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
340      0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614,
341      0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,
342      0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
343      0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
344      0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0,
345      0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
346      0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e,
347      0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
348      0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
349      0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6])
350    ];
351  this.P = new Uint32Array([
352    0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,
353    0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,
354    0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
355    0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,
356    0x9216d5d9, 0x8979fb1b]);
357};
358
359function F(S, x8, i) {
360  return (((S[0][x8[i+3]] +
361            S[1][x8[i+2]]) ^
362            S[2][x8[i+1]]) +
363            S[3][x8[i]]);
364};
365
366Blowfish.prototype.encipher = function(x, x8) {
367  if (x8 === undefined) {
368    x8 = new Uint8Array(x.buffer);
369    if (x.byteOffset !== 0)
370      x8 = x8.subarray(x.byteOffset);
371  }
372  x[0] ^= this.P[0];
373  for (var i = 1; i < 16; i += 2) {
374    x[1] ^= F(this.S, x8, 0) ^ this.P[i];
375    x[0] ^= F(this.S, x8, 4) ^ this.P[i+1];
376  }
377  var t = x[0];
378  x[0] = x[1] ^ this.P[17];
379  x[1] = t;
380};
381
382Blowfish.prototype.decipher = function(x) {
383  var x8 = new Uint8Array(x.buffer);
384  if (x.byteOffset !== 0)
385    x8 = x8.subarray(x.byteOffset);
386  x[0] ^= this.P[17];
387  for (var i = 16; i > 0; i -= 2) {
388    x[1] ^= F(this.S, x8, 0) ^ this.P[i];
389    x[0] ^= F(this.S, x8, 4) ^ this.P[i-1];
390  }
391  var t = x[0];
392  x[0] = x[1] ^ this.P[0];
393  x[1] = t;
394};
395
396function stream2word(data, databytes){
397  var i, temp = 0;
398  for (i = 0; i < 4; i++, BLF_J++) {
399    if (BLF_J >= databytes) BLF_J = 0;
400    temp = (temp << 8) | data[BLF_J];
401  }
402  return temp;
403};
404
405Blowfish.prototype.expand0state = function(key, keybytes) {
406  var d = new Uint32Array(2), i, k;
407  var d8 = new Uint8Array(d.buffer);
408
409  for (i = 0, BLF_J = 0; i < 18; i++) {
410    this.P[i] ^= stream2word(key, keybytes);
411  }
412  BLF_J = 0;
413
414  for (i = 0; i < 18; i += 2) {
415    this.encipher(d, d8);
416    this.P[i]   = d[0];
417    this.P[i+1] = d[1];
418  }
419
420  for (i = 0; i < 4; i++) {
421    for (k = 0; k < 256; k += 2) {
422      this.encipher(d, d8);
423      this.S[i][k]   = d[0];
424      this.S[i][k+1] = d[1];
425    }
426  }
427};
428
429Blowfish.prototype.expandstate = function(data, databytes, key, keybytes) {
430  var d = new Uint32Array(2), i, k;
431
432  for (i = 0, BLF_J = 0; i < 18; i++) {
433    this.P[i] ^= stream2word(key, keybytes);
434  }
435
436  for (i = 0, BLF_J = 0; i < 18; i += 2) {
437    d[0] ^= stream2word(data, databytes);
438    d[1] ^= stream2word(data, databytes);
439    this.encipher(d);
440    this.P[i]   = d[0];
441    this.P[i+1] = d[1];
442  }
443
444  for (i = 0; i < 4; i++) {
445    for (k = 0; k < 256; k += 2) {
446      d[0] ^= stream2word(data, databytes);
447      d[1] ^= stream2word(data, databytes);
448      this.encipher(d);
449      this.S[i][k]   = d[0];
450      this.S[i][k+1] = d[1];
451    }
452  }
453  BLF_J = 0;
454};
455
456Blowfish.prototype.enc = function(data, blocks) {
457  for (var i = 0; i < blocks; i++) {
458    this.encipher(data.subarray(i*2));
459  }
460};
461
462Blowfish.prototype.dec = function(data, blocks) {
463  for (var i = 0; i < blocks; i++) {
464    this.decipher(data.subarray(i*2));
465  }
466};
467
468var BCRYPT_BLOCKS = 8,
469    BCRYPT_HASHSIZE = 32;
470
471function bcrypt_hash(sha2pass, sha2salt, out) {
472  var state = new Blowfish(),
473      cdata = new Uint32Array(BCRYPT_BLOCKS), i,
474      ciphertext = new Uint8Array([79,120,121,99,104,114,111,109,97,116,105,
475            99,66,108,111,119,102,105,115,104,83,119,97,116,68,121,110,97,109,
476            105,116,101]); //"OxychromaticBlowfishSwatDynamite"
477
478  state.expandstate(sha2salt, 64, sha2pass, 64);
479  for (i = 0; i < 64; i++) {
480    state.expand0state(sha2salt, 64);
481    state.expand0state(sha2pass, 64);
482  }
483
484  for (i = 0; i < BCRYPT_BLOCKS; i++)
485    cdata[i] = stream2word(ciphertext, ciphertext.byteLength);
486  for (i = 0; i < 64; i++)
487    state.enc(cdata, cdata.byteLength / 8);
488
489  for (i = 0; i < BCRYPT_BLOCKS; i++) {
490    out[4*i+3] = cdata[i] >>> 24;
491    out[4*i+2] = cdata[i] >>> 16;
492    out[4*i+1] = cdata[i] >>> 8;
493    out[4*i+0] = cdata[i];
494  }
495};
496
497function bcrypt_pbkdf(pass, passlen, salt, saltlen, key, keylen, rounds) {
498  var sha2pass = new Uint8Array(64),
499      sha2salt = new Uint8Array(64),
500      out = new Uint8Array(BCRYPT_HASHSIZE),
501      tmpout = new Uint8Array(BCRYPT_HASHSIZE),
502      countsalt = new Uint8Array(saltlen+4),
503      i, j, amt, stride, dest, count,
504      origkeylen = keylen;
505
506  if (rounds < 1)
507    return -1;
508  if (passlen === 0 || saltlen === 0 || keylen === 0 ||
509      keylen > (out.byteLength * out.byteLength) || saltlen > (1<<20))
510    return -1;
511
512  stride = Math.floor((keylen + out.byteLength - 1) / out.byteLength);
513  amt = Math.floor((keylen + stride - 1) / stride);
514
515  for (i = 0; i < saltlen; i++)
516    countsalt[i] = salt[i];
517
518  crypto_hash_sha512(sha2pass, pass, passlen);
519
520  for (count = 1; keylen > 0; count++) {
521    countsalt[saltlen+0] = count >>> 24;
522    countsalt[saltlen+1] = count >>> 16;
523    countsalt[saltlen+2] = count >>>  8;
524    countsalt[saltlen+3] = count;
525
526    crypto_hash_sha512(sha2salt, countsalt, saltlen + 4);
527    bcrypt_hash(sha2pass, sha2salt, tmpout);
528    for (i = out.byteLength; i--;)
529      out[i] = tmpout[i];
530
531    for (i = 1; i < rounds; i++) {
532      crypto_hash_sha512(sha2salt, tmpout, tmpout.byteLength);
533      bcrypt_hash(sha2pass, sha2salt, tmpout);
534      for (j = 0; j < out.byteLength; j++)
535        out[j] ^= tmpout[j];
536    }
537
538    amt = Math.min(amt, keylen);
539    for (i = 0; i < amt; i++) {
540      dest = i * stride + (count - 1);
541      if (dest >= origkeylen)
542        break;
543      key[dest] = out[i];
544    }
545    keylen -= i;
546  }
547
548  return 0;
549};
550
551module.exports = {
552      BLOCKS: BCRYPT_BLOCKS,
553      HASHSIZE: BCRYPT_HASHSIZE,
554      hash: bcrypt_hash,
555      pbkdf: bcrypt_pbkdf
556};
557