1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.apache.directory.api.ldap.model.password;
16
17
18 import java.io.UnsupportedEncodingException;
19 import java.security.SecureRandom;
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65 public class BCrypt
66 {
67
68 private static final int GENSALT_DEFAULT_LOG2_ROUNDS = 10;
69 private static final int BCRYPT_SALT_LEN = 16;
70
71
72 private static final int BLOWFISH_NUM_ROUNDS = 16;
73
74
75 private static final int[] P_ORIG =
76 {
77 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,
78 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,
79 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
80 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,
81 0x9216d5d9, 0x8979fb1b
82 };
83
84 private static final int[] S_ORIG =
85 {
86 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7,
87 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
88 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
89 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
90 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee,
91 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
92 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef,
93 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
94 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
95 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
96 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce,
97 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
98 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e,
99 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
100 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
101 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
102 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88,
103 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
104 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e,
105 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
106 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
107 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
108 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88,
109 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
110 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6,
111 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,
112 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
113 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
114 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba,
115 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
116 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f,
117 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
118 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
119 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
120 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279,
121 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
122 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab,
123 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,
124 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
125 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
126 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0,
127 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
128 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790,
129 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,
130 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
131 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
132 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7,
133 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
134 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad,
135 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
136 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
137 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
138 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477,
139 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
140 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49,
141 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
142 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
143 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
144 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41,
145 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
146 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400,
147 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
148 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
149 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a,
150 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623,
151 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
152 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
153 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
154 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6,
155 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
156 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e,
157 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
158 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
159 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
160 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff,
161 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
162 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701,
163 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
164 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
165 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
166 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf,
167 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
168 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e,
169 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
170 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
171 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,
172 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16,
173 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
174 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b,
175 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
176 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
177 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,
178 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f,
179 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
180 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4,
181 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
182 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
183 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
184 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802,
185 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
186 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510,
187 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
188 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
189 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,
190 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50,
191 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
192 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8,
193 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
194 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
195 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
196 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128,
197 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
198 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0,
199 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
200 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
201 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
202 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3,
203 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
204 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00,
205 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
206 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
207 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
208 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735,
209 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
210 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9,
211 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
212 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
213 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7,
214 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934,
215 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
216 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
217 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
218 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45,
219 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
220 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a,
221 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
222 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
223 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
224 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42,
225 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
226 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2,
227 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
228 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
229 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
230 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33,
231 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
232 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3,
233 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
234 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
235 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
236 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b,
237 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
238 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922,
239 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
240 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
241 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
242 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37,
243 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
244 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804,
245 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
246 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
247 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
248 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d,
249 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
250 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350,
251 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
252 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
253 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
254 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d,
255 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
256 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f,
257 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
258 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
259 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
260 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2,
261 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
262 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e,
263 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,
264 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
265 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
266 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52,
267 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
268 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5,
269 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
270 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
271 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
272 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24,
273 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
274 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4,
275 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
276 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
277 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0,
278 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b,
279 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
280 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
281 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
282 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8,
283 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
284 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304,
285 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
286 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
287 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,
288 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9,
289 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
290 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593,
291 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
292 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
293 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,
294 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b,
295 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
296 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c,
297 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,
298 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
299 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
300 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb,
301 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
302 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991,
303 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,
304 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
305 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
306 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae,
307 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
308 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5,
309 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
310 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
311 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,
312 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84,
313 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
314 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8,
315 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
316 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
317 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,
318 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38,
319 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
320 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c,
321 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,
322 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
323 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
324 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964,
325 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
326 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8,
327 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
328 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
329 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,
330 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02,
331 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
332 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614,
333 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,
334 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
335 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
336 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0,
337 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
338 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e,
339 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
340 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
341 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6
342 };
343
344
345
346
347 private static final int[] BF_CRYPT_CIPHERTEXT =
348 {
349 0x4f727068,
350 0x65616e42,
351 0x65686f6c,
352 0x64657253,
353 0x63727944,
354 0x6f756274
355 };
356
357
358 private static final char[] BASE_64_CHAR =
359 {
360 '.', '/', 'A', 'B', 'C', 'D', 'E', 'F',
361 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
362 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
363 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
364 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
365 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
366 'u', 'v', 'w', 'x', 'y', 'z', '0', '1',
367 '2', '3', '4', '5', '6', '7', '8', '9'
368 };
369
370
371 private static final byte[] INDEX_64 =
372 {
373 -1, -1, -1, -1, -1, -1, -1, -1,
374 -1, -1, -1, -1, -1, -1, -1, -1,
375 -1, -1, -1, -1, -1, -1, -1, -1,
376 -1, -1, -1, -1, -1, -1, -1, -1,
377 -1, -1, -1, -1, -1, -1, -1, -1,
378 -1, -1, -1, -1, -1, -1, 0, 1,
379 54, 55, 56, 57, 58, 59, 60, 61,
380 62, 63, -1, -1, -1, -1, -1, -1,
381 -1, 2, 3, 4, 5, 6, 7, 8,
382 9, 10, 11, 12, 13, 14, 15, 16,
383 17, 18, 19, 20, 21, 22, 23, 24,
384 25, 26, 27, -1, -1, -1, -1, -1,
385 -1, 28, 29, 30, 31, 32, 33, 34,
386 35, 36, 37, 38, 39, 40, 41, 42,
387 43, 44, 45, 46, 47, 48, 49, 50,
388 51, 52, 53, -1, -1, -1, -1, -1
389 };
390
391
392 private int[] pKey;
393 private int[] sKey;
394
395
396
397
398
399
400
401
402
403
404
405
406 private static String encodeBase64( byte[] d, int len )
407 {
408 int off = 0;
409 StringBuilder rs = new StringBuilder();
410 int c1;
411 int c2;
412
413 if ( len <= 0 || len > d.length )
414 {
415 throw new IllegalArgumentException( "Invalid len" );
416 }
417
418 while ( off < len )
419 {
420 c1 = d[off++] & 0xff;
421 rs.append( BASE_64_CHAR[( c1 >> 2 ) & 0x3f] );
422 c1 = ( c1 & 0x03 ) << 4;
423
424 if ( off >= len )
425 {
426 rs.append( BASE_64_CHAR[c1 & 0x3f] );
427 break;
428 }
429
430 c2 = d[off++] & 0xff;
431 c1 |= ( c2 >> 4 ) & 0x0f;
432 rs.append( BASE_64_CHAR[c1 & 0x3f] );
433 c1 = ( c2 & 0x0f ) << 2;
434
435 if ( off >= len )
436 {
437 rs.append( BASE_64_CHAR[c1 & 0x3f] );
438 break;
439 }
440
441 c2 = d[off++] & 0xff;
442 c1 |= ( c2 >> 6 ) & 0x03;
443 rs.append( BASE_64_CHAR[c1 & 0x3f] );
444 rs.append( BASE_64_CHAR[c2 & 0x3f] );
445 }
446
447 return rs.toString();
448 }
449
450
451
452
453
454
455
456
457 private static byte char64( char x )
458 {
459 if ( ( int ) x < 0 || ( int ) x > INDEX_64.length )
460 {
461 return -1;
462 }
463
464 return INDEX_64[( int ) x];
465 }
466
467
468
469
470
471
472
473
474
475
476
477 private static byte[] decodeBase64( String s, int maxolen )
478 {
479 StringBuilder rs = new StringBuilder();
480 int off = 0;
481 int slen = s.length();
482 int olen = 0;
483 byte[] ret;
484 byte c1;
485 byte c2;
486 byte c3;
487 byte c4;
488 byte o;
489
490 if ( maxolen <= 0 )
491 {
492 throw new IllegalArgumentException( "Invalid maxolen" );
493 }
494
495 while ( off < slen - 1 && olen < maxolen )
496 {
497 c1 = char64( s.charAt( off++ ) );
498 c2 = char64( s.charAt( off++ ) );
499
500 if ( c1 == -1 || c2 == -1 )
501 {
502 break;
503 }
504
505 o = ( byte ) ( c1 << 2 );
506 o |= ( c2 & 0x30 ) >> 4;
507 rs.append( ( char ) o );
508
509 if ( ++olen >= maxolen || off >= slen )
510 {
511 break;
512 }
513
514 c3 = char64( s.charAt( off++ ) );
515
516 if ( c3 == -1 )
517 {
518 break;
519 }
520
521 o = ( byte ) ( ( c2 & 0x0f ) << 4 );
522 o |= ( c3 & 0x3c ) >> 2;
523 rs.append( ( char ) o );
524
525 if ( ++olen >= maxolen || off >= slen )
526 {
527 break;
528 }
529
530 c4 = char64( s.charAt( off++ ) );
531 o = ( byte ) ( ( c3 & 0x03 ) << 6 );
532 o |= c4;
533 rs.append( ( char ) o );
534 ++olen;
535 }
536
537 ret = new byte[olen];
538
539 for ( off = 0; off < olen; off++ )
540 {
541 ret[off] = ( byte ) rs.charAt( off );
542 }
543
544 return ret;
545 }
546
547
548
549
550
551
552
553
554 private void encipher( int[] lr, int off )
555 {
556 int i;
557 int n;
558 int l = lr[off];
559 int r = lr[off + 1];
560
561 l ^= pKey[0];
562
563 for ( i = 0; i <= BLOWFISH_NUM_ROUNDS - 2; )
564 {
565
566 n = sKey[( l >> 24 ) & 0xff];
567 n += sKey[0x100 | ( ( l >> 16 ) & 0xff )];
568 n ^= sKey[0x200 | ( ( l >> 8 ) & 0xff )];
569 n += sKey[0x300 | ( l & 0xff )];
570 r ^= n ^ pKey[++i];
571
572
573 n = sKey[( r >> 24 ) & 0xff];
574 n += sKey[0x100 | ( ( r >> 16 ) & 0xff )];
575 n ^= sKey[0x200 | ( ( r >> 8 ) & 0xff )];
576 n += sKey[0x300 | ( r & 0xff )];
577 l ^= n ^ pKey[++i];
578 }
579
580 lr[off] = r ^ pKey[BLOWFISH_NUM_ROUNDS + 1];
581 lr[off + 1] = l;
582 }
583
584
585
586
587
588
589
590
591
592 private static int streamToWord( byte[] data, int[] offp )
593 {
594 int i;
595 int word = 0;
596 int off = offp[0];
597
598 for ( i = 0; i < 4; i++ )
599 {
600 word = ( word << 8 ) | ( data[off] & 0xff );
601 off = ( off + 1 ) % data.length;
602 }
603
604 offp[0] = off;
605
606 return word;
607 }
608
609
610
611
612
613 private void initKey()
614 {
615 pKey = ( int[] ) P_ORIG.clone();
616 sKey = ( int[] ) S_ORIG.clone();
617 }
618
619
620
621
622
623
624 private void key( byte[] key )
625 {
626 int i;
627 int[] koffp = { 0 };
628 int[] lr = { 0, 0 };
629 int plen = pKey.length;
630 int slen = sKey.length;
631
632 for ( i = 0; i < plen; i++ )
633 {
634 pKey[i] = pKey[i] ^ streamToWord( key, koffp );
635 }
636
637 for ( i = 0; i < plen; i += 2 )
638 {
639 encipher( lr, 0 );
640 pKey[i] = lr[0];
641 pKey[i + 1] = lr[1];
642 }
643
644 for ( i = 0; i < slen; i += 2 )
645 {
646 encipher( lr, 0 );
647 sKey[i] = lr[0];
648 sKey[i + 1] = lr[1];
649 }
650 }
651
652
653
654
655
656
657
658
659
660 private void eksKey( byte[] data, byte[] key )
661 {
662 int i;
663 int[] koffp = { 0 };
664 int[] doffp = { 0 };
665 int[] lr = { 0, 0 };
666 int plen = pKey.length;
667 int slen = sKey.length;
668
669 for ( i = 0; i < plen; i++ )
670 {
671 pKey[i] = pKey[i] ^ streamToWord( key, koffp );
672 }
673
674 for ( i = 0; i < plen; i += 2 )
675 {
676 lr[0] ^= streamToWord( data, doffp );
677 lr[1] ^= streamToWord( data, doffp );
678 encipher( lr, 0 );
679 pKey[i] = lr[0];
680 pKey[i + 1] = lr[1];
681 }
682
683 for ( i = 0; i < slen; i += 2 )
684 {
685 lr[0] ^= streamToWord( data, doffp );
686 lr[1] ^= streamToWord( data, doffp );
687 encipher( lr, 0 );
688 sKey[i] = lr[0];
689 sKey[i + 1] = lr[1];
690 }
691 }
692
693
694
695
696
697
698
699
700
701
702
703
704 public byte[] cryptRaw( byte[] password, byte[] salt, int logRounds, int[] cdata )
705 {
706 int rounds;
707 int i;
708 int j;
709 int clen = cdata.length;
710 byte[] ret;
711
712 if ( logRounds < 4 || logRounds > 30 )
713 {
714 throw new IllegalArgumentException( "Bad number of rounds" );
715 }
716
717 rounds = 1 << logRounds;
718
719 if ( salt.length != BCRYPT_SALT_LEN )
720 {
721 throw new IllegalArgumentException( "Bad salt length" );
722 }
723
724 initKey();
725 eksKey( salt, password );
726
727 for ( i = 0; i != rounds; i++ )
728 {
729 key( password );
730 key( salt );
731 }
732
733 for ( i = 0; i < 64; i++ )
734 {
735 for ( j = 0; j < ( clen >> 1 ); j++ )
736 {
737 encipher( cdata, j << 1 );
738 }
739 }
740
741 ret = new byte[clen * 4];
742
743 for ( i = 0, j = 0; i < clen; i++ )
744 {
745 ret[j++] = ( byte ) ( ( cdata[i] >> 24 ) & 0xff );
746 ret[j++] = ( byte ) ( ( cdata[i] >> 16 ) & 0xff );
747 ret[j++] = ( byte ) ( ( cdata[i] >> 8 ) & 0xff );
748 ret[j++] = ( byte ) ( cdata[i] & 0xff );
749 }
750
751 return ret;
752 }
753
754
755
756
757
758
759
760
761
762 public static String hashPw( String password, String salt )
763 {
764 BCrypt bcrypt;
765 String realSalt;
766 byte[] passwordb;
767 byte[] saltb;
768 byte[] hashed;
769 char minor = ( char ) 0;
770 int rounds;
771 int off;
772 StringBuilder rs = new StringBuilder();
773
774 if ( salt.charAt( 0 ) != '$' || salt.charAt( 1 ) != '2' )
775 {
776 throw new IllegalArgumentException( "Invalid salt version" );
777 }
778
779 if ( salt.charAt( 2 ) == '$' )
780 {
781 off = 3;
782 }
783
784 else
785 {
786 minor = salt.charAt( 2 );
787
788 if ( minor != 'a' || salt.charAt( 3 ) != '$' )
789 {
790 throw new IllegalArgumentException( "Invalid salt revision" );
791 }
792
793 off = 4;
794 }
795
796
797 if ( salt.charAt( off + 2 ) > '$' )
798 {
799 throw new IllegalArgumentException( "Missing salt rounds" );
800 }
801
802 rounds = Integer.parseInt( salt.substring( off, off + 2 ) );
803
804 realSalt = salt.substring( off + 3, off + 25 );
805
806 try
807 {
808 passwordb = ( password + ( minor >= 'a' ? "\000" : "" ) ).getBytes( "UTF-8" );
809 }
810 catch ( UnsupportedEncodingException uee )
811 {
812 throw new AssertionError( "UTF-8 is not supported" );
813 }
814
815 saltb = decodeBase64( realSalt, BCRYPT_SALT_LEN );
816
817 bcrypt = new BCrypt();
818 hashed = bcrypt.cryptRaw( passwordb, saltb, rounds, ( int[] ) BF_CRYPT_CIPHERTEXT.clone() );
819
820 rs.append( "$2" );
821
822 if ( minor >= 'a' )
823 {
824 rs.append( minor );
825 }
826
827 rs.append( "$" );
828
829 if ( rounds < 10 )
830 {
831 rs.append( "0" );
832 }
833
834 if ( rounds > 30 )
835 {
836 throw new IllegalArgumentException( "rounds exceeds maximum (30)" );
837 }
838
839 rs.append( Integer.toString( rounds ) );
840 rs.append( "$" );
841 rs.append( encodeBase64( saltb, saltb.length ) );
842 rs.append( encodeBase64( hashed, BF_CRYPT_CIPHERTEXT.length * 4 - 1 ) );
843
844 return rs.toString();
845 }
846
847
848
849
850
851
852
853
854
855
856 public static String genSalt( int logRounds, SecureRandom random )
857 {
858 StringBuilder rs = new StringBuilder();
859 byte[] rnd = new byte[BCRYPT_SALT_LEN];
860
861 random.nextBytes( rnd );
862
863 rs.append( "$2a$" );
864
865 if ( logRounds < 10 )
866 {
867 rs.append( "0" );
868 }
869
870 if ( logRounds > 30 )
871 {
872 throw new IllegalArgumentException( "log_rounds exceeds maximum (30)" );
873 }
874 rs.append( Integer.toString( logRounds ) );
875 rs.append( "$" );
876 rs.append( encodeBase64( rnd, rnd.length ) );
877
878 return rs.toString();
879 }
880
881
882
883
884
885
886
887
888
889 public static String gensalt( int logRounds )
890 {
891 return genSalt( logRounds, new SecureRandom() );
892 }
893
894
895
896
897
898
899
900
901 public static String genSalt()
902 {
903 return gensalt( GENSALT_DEFAULT_LOG2_ROUNDS );
904 }
905
906
907
908
909
910
911
912
913
914 public static boolean checkPw( String plaintext, String hashed )
915 {
916 byte[] hashedBytes;
917 byte[] tryBytes;
918
919 try
920 {
921 String tryPw = hashPw( plaintext, hashed );
922 hashedBytes = hashed.getBytes( "UTF-8" );
923 tryBytes = tryPw.getBytes( "UTF-8" );
924 }
925 catch ( UnsupportedEncodingException uee )
926 {
927 return false;
928 }
929
930 if ( hashedBytes.length != tryBytes.length )
931 {
932 return false;
933 }
934
935 byte ret = 0;
936
937 for ( int i = 0; i < tryBytes.length; i++ )
938 {
939 ret |= hashedBytes[i] ^ tryBytes[i];
940 }
941
942 return ret == 0;
943 }
944 }