- cfpassphrase/src/mindrot/jbcrypt/BCrypt.java
- v0.1
- 27 KB
- 751
1package mindrot.jbcrypt;
2
3// Copyright (c) 2006 Damien Miller <djm@mindrot.org>
4//
5// Permission to use, copy, modify, and distribute this software for any
6// purpose with or without fee is hereby granted, provided that the above
7// copyright notice and this permission notice appear in all copies.
8//
9// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
17import java.io.UnsupportedEncodingException;
18
19import java.security.SecureRandom;
20
21/**
22 * BCrypt implements OpenBSD-style Blowfish password hashing using
23 * the scheme described in "A Future-Adaptable Password Scheme" by
24 * Niels Provos and David Mazieres.
25 * <p>
26 * This password hashing system tries to thwart off-line password
27 * cracking using a computationally-intensive hashing algorithm,
28 * based on Bruce Schneier's Blowfish cipher. The work factor of
29 * the algorithm is parameterised, so it can be increased as
30 * computers get faster.
31 * <p>
32 * Usage is really simple. To hash a password for the first time,
33 * call the hashpw method with a random salt, like this:
34 * <p>
35 * <code>
36 * String pw_hash = BCrypt.hashpw(plain_password, BCrypt.gensalt()); <br />
37 * </code>
38 * <p>
39 * To check whether a plaintext password matches one that has been
40 * hashed previously, use the checkpw method:
41 * <p>
42 * <code>
43 * if (BCrypt.checkpw(candidate_password, stored_hash))<br />
44 * System.out.println("It matches");<br />
45 * else<br />
46 * System.out.println("It does not match");<br />
47 * </code>
48 * <p>
49 * The gensalt() method takes an optional parameter (log_rounds)
50 * that determines the computational complexity of the hashing:
51 * <p>
52 * <code>
53 * String strong_salt = BCrypt.gensalt(10)<br />
54 * String stronger_salt = BCrypt.gensalt(12)<br />
55 * </code>
56 * <p>
57 * The amount of work increases exponentially (2**log_rounds), so
58 * each increment is twice as much work. The default log_rounds is
59 * 10, and the valid range is 4 to 31.
60 *
61 * @author Damien Miller
62 * @version 0.2
63 */
64public class BCrypt {
65 // BCrypt parameters
66 private static final int GENSALT_DEFAULT_LOG2_ROUNDS = 16;
67 private static final int BCRYPT_SALT_LEN = 16;
68
69 // Blowfish parameters
70 private static final int BLOWFISH_NUM_ROUNDS = 16;
71
72 // Initial contents of key schedule
73 private static final int P_orig[] = {
74 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,
75 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,
76 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
77 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,
78 0x9216d5d9, 0x8979fb1b
79 };
80 private static final int S_orig[] = {
81 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7,
82 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
83 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
84 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
85 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee,
86 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
87 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef,
88 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
89 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
90 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
91 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce,
92 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
93 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e,
94 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
95 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
96 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
97 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88,
98 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
99 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e,
100 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
101 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
102 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
103 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88,
104 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
105 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6,
106 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,
107 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
108 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
109 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba,
110 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
111 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f,
112 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
113 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
114 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
115 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279,
116 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
117 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab,
118 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,
119 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
120 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
121 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0,
122 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
123 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790,
124 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,
125 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
126 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
127 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7,
128 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
129 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad,
130 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
131 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
132 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
133 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477,
134 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
135 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49,
136 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
137 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
138 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
139 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41,
140 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
141 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400,
142 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
143 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
144 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a,
145 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623,
146 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
147 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
148 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
149 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6,
150 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
151 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e,
152 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
153 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
154 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
155 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff,
156 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
157 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701,
158 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
159 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
160 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
161 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf,
162 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
163 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e,
164 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
165 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
166 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,
167 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16,
168 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
169 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b,
170 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
171 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
172 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,
173 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f,
174 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
175 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4,
176 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
177 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
178 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
179 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802,
180 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
181 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510,
182 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
183 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
184 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,
185 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50,
186 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
187 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8,
188 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
189 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
190 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
191 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128,
192 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
193 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0,
194 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
195 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
196 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
197 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3,
198 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
199 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00,
200 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
201 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
202 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
203 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735,
204 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
205 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9,
206 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
207 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
208 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7,
209 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934,
210 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
211 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
212 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
213 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45,
214 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
215 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a,
216 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
217 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
218 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
219 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42,
220 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
221 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2,
222 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
223 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
224 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
225 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33,
226 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
227 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3,
228 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
229 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
230 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
231 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b,
232 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
233 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922,
234 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
235 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
236 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
237 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37,
238 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
239 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804,
240 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
241 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
242 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
243 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d,
244 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
245 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350,
246 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
247 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
248 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
249 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d,
250 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
251 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f,
252 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
253 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
254 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
255 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2,
256 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
257 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e,
258 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,
259 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
260 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
261 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52,
262 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
263 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5,
264 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
265 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
266 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
267 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24,
268 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
269 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4,
270 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
271 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
272 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0,
273 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b,
274 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
275 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
276 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
277 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8,
278 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
279 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304,
280 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
281 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
282 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,
283 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9,
284 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
285 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593,
286 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
287 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
288 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,
289 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b,
290 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
291 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c,
292 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,
293 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
294 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
295 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb,
296 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
297 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991,
298 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,
299 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
300 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
301 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae,
302 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
303 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5,
304 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
305 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
306 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,
307 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84,
308 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
309 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8,
310 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
311 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
312 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,
313 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38,
314 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
315 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c,
316 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,
317 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
318 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
319 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964,
320 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
321 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8,
322 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
323 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
324 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,
325 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02,
326 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
327 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614,
328 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,
329 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
330 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
331 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0,
332 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
333 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e,
334 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
335 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
336 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6
337 };
338
339 // bcrypt IV: "OrpheanBeholderScryDoubt"
340 static private final int bf_crypt_ciphertext[] = {
341 0x4f727068, 0x65616e42, 0x65686f6c,
342 0x64657253, 0x63727944, 0x6f756274
343 };
344
345 // Table for Base64 encoding
346 static private final char base64_code[] = {
347 '.', '/', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
348 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
349 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
350 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
351 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5',
352 '6', '7', '8', '9'
353 };
354
355 // Table for Base64 decoding
356 static private final byte index_64[] = {
357 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
358 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
359 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
360 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
361 -1, -1, -1, -1, -1, -1, 0, 1, 54, 55,
362 56, 57, 58, 59, 60, 61, 62, 63, -1, -1,
363 -1, -1, -1, -1, -1, 2, 3, 4, 5, 6,
364 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
365 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
366 -1, -1, -1, -1, -1, -1, 28, 29, 30,
367 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
368 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
369 51, 52, 53, -1, -1, -1, -1, -1
370 };
371
372 // Expanded Blowfish key
373 private int P[];
374 private int S[];
375
376 /**
377 * Encode a byte array using bcrypt's slightly-modified base64
378 * encoding scheme. Note that this is *not* compatible with
379 * the standard MIME-base64 encoding.
380 *
381 * @param d the byte array to encode
382 * @param len the number of bytes to encode
383 * @return base64-encoded string
384 * @exception IllegalArgumentException if the length is invalid
385 */
386 private static String encode_base64(byte d[], int len)
387 throws IllegalArgumentException {
388 int off = 0;
389 StringBuffer rs = new StringBuffer();
390 int c1, c2;
391
392 if (len <= 0 || len > d.length)
393 throw new IllegalArgumentException ("Invalid len");
394
395 while (off < len) {
396 c1 = d[off++] & 0xff;
397 rs.append(base64_code[(c1 >> 2) & 0x3f]);
398 c1 = (c1 & 0x03) << 4;
399 if (off >= len) {
400 rs.append(base64_code[c1 & 0x3f]);
401 break;
402 }
403 c2 = d[off++] & 0xff;
404 c1 |= (c2 >> 4) & 0x0f;
405 rs.append(base64_code[c1 & 0x3f]);
406 c1 = (c2 & 0x0f) << 2;
407 if (off >= len) {
408 rs.append(base64_code[c1 & 0x3f]);
409 break;
410 }
411 c2 = d[off++] & 0xff;
412 c1 |= (c2 >> 6) & 0x03;
413 rs.append(base64_code[c1 & 0x3f]);
414 rs.append(base64_code[c2 & 0x3f]);
415 }
416 return rs.toString();
417 }
418
419 /**
420 * Look up the 3 bits base64-encoded by the specified character,
421 * range-checking againt conversion table
422 * @param x the base64-encoded value
423 * @return the decoded value of x
424 */
425 private static byte char64(char x) {
426 if ((int)x < 0 || (int)x > index_64.length)
427 return -1;
428 return index_64[(int)x];
429 }
430
431 /**
432 * Decode a string encoded using bcrypt's base64 scheme to a
433 * byte array. Note that this is *not* compatible with
434 * the standard MIME-base64 encoding.
435 * @param s the string to decode
436 * @param maxolen the maximum number of bytes to decode
437 * @return an array containing the decoded bytes
438 * @throws IllegalArgumentException if maxolen is invalid
439 */
440 private static byte[] decode_base64(String s, int maxolen)
441 throws IllegalArgumentException {
442 StringBuffer rs = new StringBuffer();
443 int off = 0, slen = s.length(), olen = 0;
444 byte ret[];
445 byte c1, c2, c3, c4, o;
446
447 if (maxolen <= 0)
448 throw new IllegalArgumentException ("Invalid maxolen");
449
450 while (off < slen - 1 && olen < maxolen) {
451 c1 = char64(s.charAt(off++));
452 c2 = char64(s.charAt(off++));
453 if (c1 == -1 || c2 == -1)
454 break;
455 o = (byte)(c1 << 2);
456 o |= (c2 & 0x30) >> 4;
457 rs.append((char)o);
458 if (++olen >= maxolen || off >= slen)
459 break;
460 c3 = char64(s.charAt(off++));
461 if (c3 == -1)
462 break;
463 o = (byte)((c2 & 0x0f) << 4);
464 o |= (c3 & 0x3c) >> 2;
465 rs.append((char)o);
466 if (++olen >= maxolen || off >= slen)
467 break;
468 c4 = char64(s.charAt(off++));
469 o = (byte)((c3 & 0x03) << 6);
470 o |= c4;
471 rs.append((char)o);
472 ++olen;
473 }
474
475 ret = new byte[olen];
476 for (off = 0; off < olen; off++)
477 ret[off] = (byte)rs.charAt(off);
478 return ret;
479 }
480
481 /**
482 * Blowfish encipher a single 64-bit block encoded as
483 * two 32-bit halves
484 * @param lr an array containing the two 32-bit half blocks
485 * @param off the position in the array of the blocks
486 */
487 private final void encipher(int lr[], int off) {
488 int i, n, l = lr[off], r = lr[off + 1];
489
490 l ^= P[0];
491 for (i = 0; i <= BLOWFISH_NUM_ROUNDS - 2;) {
492 // Feistel substitution on left word
493 n = S[(l >> 24) & 0xff];
494 n += S[0x100 | ((l >> 16) & 0xff)];
495 n ^= S[0x200 | ((l >> 8) & 0xff)];
496 n += S[0x300 | (l & 0xff)];
497 r ^= n ^ P[++i];
498
499 // Feistel substitution on right word
500 n = S[(r >> 24) & 0xff];
501 n += S[0x100 | ((r >> 16) & 0xff)];
502 n ^= S[0x200 | ((r >> 8) & 0xff)];
503 n += S[0x300 | (r & 0xff)];
504 l ^= n ^ P[++i];
505 }
506 lr[off] = r ^ P[BLOWFISH_NUM_ROUNDS + 1];
507 lr[off + 1] = l;
508 }
509
510 /**
511 * Cycically extract a word of key material
512 * @param data the string to extract the data from
513 * @param offp a "pointer" (as a one-entry array) to the
514 * current offset into data
515 * @return the next word of material from data
516 */
517 private static int streamtoword(byte data[], int offp[]) {
518 int i;
519 int word = 0;
520 int off = offp[0];
521
522 for (i = 0; i < 4; i++) {
523 word = (word << 8) | (data[off] & 0xff);
524 off = (off + 1) % data.length;
525 }
526
527 offp[0] = off;
528 return word;
529 }
530
531 /**
532 * Initialise the Blowfish key schedule
533 */
534 private void init_key() {
535 P = (int[])P_orig.clone();
536 S = (int[])S_orig.clone();
537 }
538
539 /**
540 * Key the Blowfish cipher
541 * @param key an array containing the key
542 */
543 private void key(byte key[]) {
544 int i;
545 int koffp[] = { 0 };
546 int lr[] = { 0, 0 };
547 int plen = P.length, slen = S.length;
548
549 for (i = 0; i < plen; i++)
550 P[i] = P[i] ^ streamtoword(key, koffp);
551
552 for (i = 0; i < plen; i += 2) {
553 encipher(lr, 0);
554 P[i] = lr[0];
555 P[i + 1] = lr[1];
556 }
557
558 for (i = 0; i < slen; i += 2) {
559 encipher(lr, 0);
560 S[i] = lr[0];
561 S[i + 1] = lr[1];
562 }
563 }
564
565 /**
566 * Perform the "enhanced key schedule" step described by
567 * Provos and Mazieres in "A Future-Adaptable Password Scheme"
568 * http://www.openbsd.org/papers/bcrypt-paper.ps
569 * @param data salt information
570 * @param key password information
571 */
572 private void ekskey(byte data[], byte key[]) {
573 int i;
574 int koffp[] = { 0 }, doffp[] = { 0 };
575 int lr[] = { 0, 0 };
576 int plen = P.length, slen = S.length;
577
578 for (i = 0; i < plen; i++)
579 P[i] = P[i] ^ streamtoword(key, koffp);
580
581 for (i = 0; i < plen; i += 2) {
582 lr[0] ^= streamtoword(data, doffp);
583 lr[1] ^= streamtoword(data, doffp);
584 encipher(lr, 0);
585 P[i] = lr[0];
586 P[i + 1] = lr[1];
587 }
588
589 for (i = 0; i < slen; i += 2) {
590 lr[0] ^= streamtoword(data, doffp);
591 lr[1] ^= streamtoword(data, doffp);
592 encipher(lr, 0);
593 S[i] = lr[0];
594 S[i + 1] = lr[1];
595 }
596 }
597
598 /**
599 * Perform the central password hashing step in the
600 * bcrypt scheme
601 * @param password the password to hash
602 * @param salt the binary salt to hash with the password
603 * @param log_rounds the binary logarithm of the number
604 * of rounds of hashing to apply
605 * @return an array containing the binary hashed password
606 */
607 private byte[] crypt_raw(byte password[], byte salt[], int log_rounds) {
608 int rounds, i, j;
609 int cdata[] = (int[])bf_crypt_ciphertext.clone();
610 int clen = cdata.length;
611 byte ret[];
612
613 if (log_rounds < 4 || log_rounds > 31)
614 throw new IllegalArgumentException ("Bad number of rounds");
615 rounds = 1 << log_rounds;
616 if (salt.length != BCRYPT_SALT_LEN)
617 throw new IllegalArgumentException ("Bad salt length");
618
619 init_key();
620 ekskey(salt, password);
621 for (i = 0; i < rounds; i++) {
622 key(password);
623 key(salt);
624 }
625
626 for (i = 0; i < 64; i++) {
627 for (j = 0; j < (clen >> 1); j++)
628 encipher(cdata, j << 1);
629 }
630
631 ret = new byte[clen * 4];
632 for (i = 0, j = 0; i < clen; i++) {
633 ret[j++] = (byte)((cdata[i] >> 24) & 0xff);
634 ret[j++] = (byte)((cdata[i] >> 16) & 0xff);
635 ret[j++] = (byte)((cdata[i] >> 8) & 0xff);
636 ret[j++] = (byte)(cdata[i] & 0xff);
637 }
638 return ret;
639 }
640
641 /**
642 * Hash a password using the OpenBSD bcrypt scheme
643 * @param password the password to hash
644 * @param salt the salt to hash with (perhaps generated
645 * using BCrypt.gensalt)
646 * @return the hashed password
647 */
648 public static String hashpw(String password, String salt) {
649 BCrypt B;
650 String real_salt;
651 byte passwordb[], saltb[], hashed[];
652 char minor = (char)0;
653 int rounds, off = 0;
654 StringBuffer rs = new StringBuffer();
655
656 if (salt.charAt(0) != '$' || salt.charAt(1) != '2')
657 throw new IllegalArgumentException ("Invalid salt version");
658 if (salt.charAt(2) == '$')
659 off = 3;
660 else {
661 minor = salt.charAt(2);
662 if (minor != 'a' || salt.charAt(3) != '$')
663 throw new IllegalArgumentException ("Invalid salt revision");
664 off = 4;
665 }
666
667 // Extract number of rounds
668 if (salt.charAt(off + 2) > '$')
669 throw new IllegalArgumentException ("Missing salt rounds");
670 rounds = Integer.parseInt(salt.substring(off, off + 2));
671
672 real_salt = salt.substring(off + 3, off + 25);
673 try {
674 passwordb = (password + (minor >= 'a' ? "\000" : "")).getBytes("UTF-8");
675 } catch (UnsupportedEncodingException uee) {
676 throw new AssertionError("UTF-8 is not supported");
677 }
678
679 saltb = decode_base64(real_salt, BCRYPT_SALT_LEN);
680
681 B = new BCrypt();
682 hashed = B.crypt_raw(passwordb, saltb, rounds);
683
684 rs.append("$2");
685 if (minor >= 'a')
686 rs.append(minor);
687 rs.append("$");
688 if (rounds < 10)
689 rs.append("0");
690 rs.append(Integer.toString(rounds));
691 rs.append("$");
692 rs.append(encode_base64(saltb, saltb.length));
693 rs.append(encode_base64(hashed,
694 bf_crypt_ciphertext.length * 4 - 1));
695 return rs.toString();
696 }
697
698 /**
699 * Generate a salt for use with the BCrypt.hashpw() method
700 * @param log_rounds the log2 of the number of rounds of
701 * hashing to apply - the work factor therefore increases as
702 * 2**log_rounds.
703 * @param random an instance of SecureRandom to use
704 * @return an encoded salt value
705 */
706 public static String gensalt(int log_rounds, SecureRandom random) {
707 StringBuffer rs = new StringBuffer();
708 byte rnd[] = new byte[BCRYPT_SALT_LEN];
709
710 random.nextBytes(rnd);
711
712 rs.append("$2a$");
713 if (log_rounds < 10)
714 rs.append("0");
715 rs.append(Integer.toString(log_rounds));
716 rs.append("$");
717 rs.append(encode_base64(rnd, rnd.length));
718 return rs.toString();
719 }
720
721 /**
722 * Generate a salt for use with the BCrypt.hashpw() method
723 * @param log_rounds the log2 of the number of rounds of
724 * hashing to apply - the work factor therefore increases as
725 * 2**log_rounds.
726 * @return an encoded salt value
727 */
728 public static String gensalt(int log_rounds) {
729 return gensalt(log_rounds, new SecureRandom());
730 }
731
732 /**
733 * Generate a salt for use with the BCrypt.hashpw() method,
734 * selecting a reasonable default for the number of hashing
735 * rounds to apply
736 * @return an encoded salt value
737 */
738 public static String gensalt() {
739 return gensalt(GENSALT_DEFAULT_LOG2_ROUNDS);
740 }
741
742 /**
743 * Check that a plaintext password matches a previously hashed
744 * one
745 * @param plaintext the plaintext password to verify
746 * @param hashed the previously-hashed password
747 * @return true if the passwords match, false otherwise
748 */
749 public static boolean checkpw(String plaintext, String hashed) {
750 return (hashed.compareTo(hashpw(plaintext, hashed)) == 0);
751 }
752}