git ssb

0+

dangerousbeans / %aPBe2k3ugtjBr4rrsU1…



Tree: 62fc1729c7b2f9ad485afb1f4b948b89dad341b6

Files: 62fc1729c7b2f9ad485afb1f4b948b89dad341b6 / ext / bcrypt.c

9056 bytesRaw
1/* $OpenBSD: bcrypt.c,v 1.22 2007/02/20 01:44:16 ray Exp $ */
2
3/*
4 * Modified by <coda.hale@gmail.com> on 2007-02-27:
5 *
6 * - Changed bcrypt_gensalt to accept a random seed as a parameter,
7 * to remove the code's dependency on arc4random(), which isn't
8 * available on Linux.
9 */
10
11/*
12 * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>
13 * All rights reserved.
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
17 * are met:
18 * 1. Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 * 2. Redistributions in binary form must reproduce the above copyright
21 * notice, this list of conditions and the following disclaimer in the
22 * documentation and/or other materials provided with the distribution.
23 * 3. All advertising materials mentioning features or use of this software
24 * must display the following acknowledgement:
25 * This product includes software developed by Niels Provos.
26 * 4. The name of the author may not be used to endorse or promote products
27 * derived from this software without specific prior written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
30 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
31 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
32 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
33 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
34 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
38 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 */
40
41/* This password hashing algorithm was designed by David Mazieres
42 * <dm@lcs.mit.edu> and works as follows:
43 *
44 * 1. state := InitState ()
45 * 2. state := ExpandKey (state, salt, password) 3.
46 * REPEAT rounds:
47 * state := ExpandKey (state, 0, salt)
48 * state := ExpandKey(state, 0, password)
49 * 4. ctext := "OrpheanBeholderScryDoubt"
50 * 5. REPEAT 64:
51 * ctext := Encrypt_ECB (state, ctext);
52 * 6. RETURN Concatenate (salt, ctext);
53 *
54 */
55
56#if 0
57#include <stdio.h>
58#endif
59
60#include <stdio.h>
61#include <stdlib.h>
62#include <sys/types.h>
63#include <string.h>
64#include "blf.h"
65
66/* This implementation is adaptable to current computing power.
67 * You can have up to 2^31 rounds which should be enough for some
68 * time to come.
69 */
70
71#define BCRYPT_VERSION '2'
72#define BCRYPT_MAXSALT 16 /* Precomputation is just so nice */
73#define BCRYPT_BLOCKS 6 /* Ciphertext blocks */
74#define BCRYPT_MINROUNDS 16 /* we have log2(rounds) in salt */
75
76char *bcrypt_gensalt(u_int8_t, u_int8_t *);
77
78static void encode_salt(char *, u_int8_t *, u_int16_t, u_int8_t);
79static void encode_base64(u_int8_t *, u_int8_t *, u_int16_t);
80static void decode_base64(u_int8_t *, u_int16_t, u_int8_t *);
81
82static char encrypted[_PASSWORD_LEN];
83static char gsalt[7 + (BCRYPT_MAXSALT * 4 + 2) / 3 + 1];
84static char error[] = ":";
85
86const static u_int8_t Base64Code[] =
87"./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
88
89const static u_int8_t index_64[128] = {
90 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
91 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
92 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
93 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
94 255, 255, 255, 255, 255, 255, 0, 1, 54, 55,
95 56, 57, 58, 59, 60, 61, 62, 63, 255, 255,
96 255, 255, 255, 255, 255, 2, 3, 4, 5, 6,
97 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
98 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
99 255, 255, 255, 255, 255, 255, 28, 29, 30,
100 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
101 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
102 51, 52, 53, 255, 255, 255, 255, 255
103};
104#define CHAR64(c) ( (c) > 127 ? 255 : index_64[(c)])
105
106static void
107decode_base64(u_int8_t *buffer, u_int16_t len, u_int8_t *data)
108{
109 u_int8_t *bp = buffer;
110 u_int8_t *p = data;
111 u_int8_t c1, c2, c3, c4;
112 while (bp < buffer + len) {
113 c1 = CHAR64(*p);
114 c2 = CHAR64(*(p + 1));
115
116 /* Invalid data */
117 if (c1 == 255 || c2 == 255)
118 break;
119
120 *bp++ = (c1 << 2) | ((c2 & 0x30) >> 4);
121 if (bp >= buffer + len)
122 break;
123
124 c3 = CHAR64(*(p + 2));
125 if (c3 == 255)
126 break;
127
128 *bp++ = ((c2 & 0x0f) << 4) | ((c3 & 0x3c) >> 2);
129 if (bp >= buffer + len)
130 break;
131
132 c4 = CHAR64(*(p + 3));
133 if (c4 == 255)
134 break;
135 *bp++ = ((c3 & 0x03) << 6) | c4;
136
137 p += 4;
138 }
139}
140
141static void
142encode_salt(char *salt, u_int8_t *csalt, u_int16_t clen, u_int8_t logr)
143{
144 salt[0] = '$';
145 salt[1] = BCRYPT_VERSION;
146 salt[2] = 'a';
147 salt[3] = '$';
148
149 snprintf(salt + 4, 4, "%2.2u$", logr);
150
151 encode_base64((u_int8_t *) salt + 7, csalt, clen);
152}
153/* Generates a salt for this version of crypt.
154 Since versions may change. Keeping this here
155 seems sensible.
156 */
157
158char *
159bcrypt_gensalt(u_int8_t log_rounds, u_int8_t *rseed)
160{
161 if (log_rounds < 4)
162 log_rounds = 4;
163 else if (log_rounds > 31)
164 log_rounds = 31;
165
166 encode_salt(gsalt, rseed, BCRYPT_MAXSALT, log_rounds);
167 return gsalt;
168}
169/* We handle $Vers$log2(NumRounds)$salt+passwd$
170 i.e. $2$04$iwouldntknowwhattosayetKdJ6iFtacBqJdKe6aW7ou */
171
172char *
173bcrypt(const char *key, const char *salt)
174{
175 blf_ctx state;
176 u_int32_t rounds, i, k;
177 u_int16_t j;
178 u_int8_t key_len, salt_len, logr, minor;
179 u_int8_t ciphertext[4 * BCRYPT_BLOCKS] = "OrpheanBeholderScryDoubt";
180 u_int8_t csalt[BCRYPT_MAXSALT];
181 u_int32_t cdata[BCRYPT_BLOCKS];
182 int n;
183
184 /* Discard "$" identifier */
185 salt++;
186
187 if (*salt > BCRYPT_VERSION) {
188 /* How do I handle errors ? Return ':' */
189 return error;
190 }
191
192 /* Check for minor versions */
193 if (salt[1] != '$') {
194 switch (salt[1]) {
195 case 'a':
196 /* 'ab' should not yield the same as 'abab' */
197 minor = salt[1];
198 salt++;
199 break;
200 default:
201 return error;
202 }
203 } else
204 minor = 0;
205
206 /* Discard version + "$" identifier */
207 salt += 2;
208
209 if (salt[2] != '$')
210 /* Out of sync with passwd entry */
211 return error;
212
213 /* Computer power doesn't increase linear, 2^x should be fine */
214 n = atoi(salt);
215 if (n > 31 || n < 0)
216 return error;
217 logr = (u_int8_t)n;
218 if ((rounds = (u_int32_t) 1 << logr) < BCRYPT_MINROUNDS)
219 return error;
220
221 /* Discard num rounds + "$" identifier */
222 salt += 3;
223
224 if (strlen(salt) * 3 / 4 < BCRYPT_MAXSALT)
225 return error;
226
227 /* We dont want the base64 salt but the raw data */
228 decode_base64(csalt, BCRYPT_MAXSALT, (u_int8_t *) salt);
229 salt_len = BCRYPT_MAXSALT;
230 key_len = strlen(key) + (minor >= 'a' ? 1 : 0);
231
232 /* Setting up S-Boxes and Subkeys */
233 Blowfish_initstate(&state);
234 Blowfish_expandstate(&state, csalt, salt_len,
235 (u_int8_t *) key, key_len);
236 for (k = 0; k < rounds; k++) {
237 Blowfish_expand0state(&state, (u_int8_t *) key, key_len);
238 Blowfish_expand0state(&state, csalt, salt_len);
239 }
240
241 /* This can be precomputed later */
242 j = 0;
243 for (i = 0; i < BCRYPT_BLOCKS; i++)
244 cdata[i] = Blowfish_stream2word(ciphertext, 4 * BCRYPT_BLOCKS, &j);
245
246 /* Now do the encryption */
247 for (k = 0; k < 64; k++)
248 blf_enc(&state, cdata, BCRYPT_BLOCKS / 2);
249
250 for (i = 0; i < BCRYPT_BLOCKS; i++) {
251 ciphertext[4 * i + 3] = cdata[i] & 0xff;
252 cdata[i] = cdata[i] >> 8;
253 ciphertext[4 * i + 2] = cdata[i] & 0xff;
254 cdata[i] = cdata[i] >> 8;
255 ciphertext[4 * i + 1] = cdata[i] & 0xff;
256 cdata[i] = cdata[i] >> 8;
257 ciphertext[4 * i + 0] = cdata[i] & 0xff;
258 }
259
260
261 i = 0;
262 encrypted[i++] = '$';
263 encrypted[i++] = BCRYPT_VERSION;
264 if (minor)
265 encrypted[i++] = minor;
266 encrypted[i++] = '$';
267
268 snprintf(encrypted + i, 4, "%2.2u$", logr);
269
270 encode_base64((u_int8_t *) encrypted + i + 3, csalt, BCRYPT_MAXSALT);
271 encode_base64((u_int8_t *) encrypted + strlen(encrypted), ciphertext,
272 4 * BCRYPT_BLOCKS - 1);
273 return encrypted;
274}
275
276static void
277encode_base64(u_int8_t *buffer, u_int8_t *data, u_int16_t len)
278{
279 u_int8_t *bp = buffer;
280 u_int8_t *p = data;
281 u_int8_t c1, c2;
282 while (p < data + len) {
283 c1 = *p++;
284 *bp++ = Base64Code[(c1 >> 2)];
285 c1 = (c1 & 0x03) << 4;
286 if (p >= data + len) {
287 *bp++ = Base64Code[c1];
288 break;
289 }
290 c2 = *p++;
291 c1 |= (c2 >> 4) & 0x0f;
292 *bp++ = Base64Code[c1];
293 c1 = (c2 & 0x0f) << 2;
294 if (p >= data + len) {
295 *bp++ = Base64Code[c1];
296 break;
297 }
298 c2 = *p++;
299 c1 |= (c2 >> 6) & 0x03;
300 *bp++ = Base64Code[c1];
301 *bp++ = Base64Code[c2 & 0x3f];
302 }
303 *bp = '\0';
304}
305#if 0
306void
307main()
308{
309 char blubber[73];
310 char salt[100];
311 char *p;
312 salt[0] = '$';
313 salt[1] = BCRYPT_VERSION;
314 salt[2] = '$';
315
316 snprintf(salt + 3, 4, "%2.2u$", 5);
317
318 printf("24 bytes of salt: ");
319 fgets(salt + 6, sizeof(salt) - 6, stdin);
320 salt[99] = 0;
321 printf("72 bytes of password: ");
322 fpurge(stdin);
323 fgets(blubber, sizeof(blubber), stdin);
324 blubber[72] = 0;
325
326 p = crypt(blubber, salt);
327 printf("Passwd entry: %s\n\n", p);
328
329 p = bcrypt_gensalt(5);
330 printf("Generated salt: %s\n", p);
331 p = crypt(blubber, p);
332 printf("Passwd entry: %s\n", p);
333}
334#endif
335

Built with git-ssb-web