bcrypt-ruby 2.1.3-x86-mingw32

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of bcrypt-ruby might be problematic. Click here for more details.

data/ext/mri/bcrypt.c ADDED
@@ -0,0 +1,297 @@
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 2009-09-16:
5
+ *
6
+ * - Standardized on stdint.h's numerical types and removed some debug cruft.
7
+ *
8
+ * Modified by <hongli@phusion.nl> on 2009-08-05:
9
+ *
10
+ * - Got rid of the global variables; they're not thread-safe.
11
+ * Modified the functions to accept local buffers instead.
12
+ *
13
+ * Modified by <coda.hale@gmail.com> on 2007-02-27:
14
+ *
15
+ * - Changed bcrypt_gensalt to accept a random seed as a parameter,
16
+ * to remove the code's dependency on arc4random(), which isn't
17
+ * available on Linux.
18
+ */
19
+
20
+ /*
21
+ * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>
22
+ * All rights reserved.
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. All advertising materials mentioning features or use of this software
33
+ * must display the following acknowledgement:
34
+ * This product includes software developed by Niels Provos.
35
+ * 4. The name of the author may not be used to endorse or promote products
36
+ * derived from this software without specific prior written permission.
37
+ *
38
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
39
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
40
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
41
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
42
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
43
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
44
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
45
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
46
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
47
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
48
+ */
49
+
50
+ /* This password hashing algorithm was designed by David Mazieres
51
+ * <dm@lcs.mit.edu> and works as follows:
52
+ *
53
+ * 1. state := InitState ()
54
+ * 2. state := ExpandKey (state, salt, password) 3.
55
+ * REPEAT rounds:
56
+ * state := ExpandKey (state, 0, salt)
57
+ * state := ExpandKey(state, 0, password)
58
+ * 4. ctext := "OrpheanBeholderScryDoubt"
59
+ * 5. REPEAT 64:
60
+ * ctext := Encrypt_ECB (state, ctext);
61
+ * 6. RETURN Concatenate (salt, ctext);
62
+ *
63
+ */
64
+
65
+ #include <stdio.h>
66
+ #include <stdlib.h>
67
+ #include <string.h>
68
+ #include "blf.h"
69
+ #include "bcrypt.h"
70
+
71
+ /* This implementation is adaptable to current computing power.
72
+ * You can have up to 2^31 rounds which should be enough for some
73
+ * time to come.
74
+ */
75
+
76
+ static void encode_salt(char *, uint8_t *, uint16_t, uint8_t);
77
+ static void encode_base64(uint8_t *, uint8_t *, uint16_t);
78
+ static void decode_base64(uint8_t *, uint16_t, uint8_t *);
79
+
80
+ static const uint8_t Base64Code[] =
81
+ "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
82
+
83
+ static const uint8_t index_64[128] = {
84
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
85
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
86
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
87
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
88
+ 255, 255, 255, 255, 255, 255, 0, 1, 54, 55,
89
+ 56, 57, 58, 59, 60, 61, 62, 63, 255, 255,
90
+ 255, 255, 255, 255, 255, 2, 3, 4, 5, 6,
91
+ 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
92
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
93
+ 255, 255, 255, 255, 255, 255, 28, 29, 30,
94
+ 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
95
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
96
+ 51, 52, 53, 255, 255, 255, 255, 255
97
+ };
98
+ #define CHAR64(c) ( (c) > 127 ? 255 : index_64[(c)])
99
+
100
+ static void
101
+ decode_base64(uint8_t *buffer, uint16_t len, uint8_t *data)
102
+ {
103
+ uint8_t *bp = buffer;
104
+ uint8_t *p = data;
105
+ uint8_t c1, c2, c3, c4;
106
+ while (bp < buffer + len) {
107
+ c1 = CHAR64(*p);
108
+ c2 = CHAR64(*(p + 1));
109
+
110
+ /* Invalid data */
111
+ if (c1 == 255 || c2 == 255)
112
+ break;
113
+
114
+ *bp++ = (c1 << 2) | ((c2 & 0x30) >> 4);
115
+ if (bp >= buffer + len)
116
+ break;
117
+
118
+ c3 = CHAR64(*(p + 2));
119
+ if (c3 == 255)
120
+ break;
121
+
122
+ *bp++ = ((c2 & 0x0f) << 4) | ((c3 & 0x3c) >> 2);
123
+ if (bp >= buffer + len)
124
+ break;
125
+
126
+ c4 = CHAR64(*(p + 3));
127
+ if (c4 == 255)
128
+ break;
129
+ *bp++ = ((c3 & 0x03) << 6) | c4;
130
+
131
+ p += 4;
132
+ }
133
+ }
134
+
135
+ static void
136
+ encode_salt(char *salt, uint8_t *csalt, uint16_t clen, uint8_t logr)
137
+ {
138
+ salt[0] = '$';
139
+ salt[1] = BCRYPT_VERSION;
140
+ salt[2] = 'a';
141
+ salt[3] = '$';
142
+
143
+ snprintf(salt + 4, 4, "%2.2u$", logr);
144
+
145
+ encode_base64((uint8_t *) salt + 7, csalt, clen);
146
+ }
147
+ /* Generates a salt for this version of crypt.
148
+ Since versions may change. Keeping this here
149
+ seems sensible.
150
+ */
151
+
152
+ char *
153
+ ruby_bcrypt_gensalt(char *output, uint8_t log_rounds, uint8_t *rseed)
154
+ {
155
+ if (log_rounds < 4)
156
+ log_rounds = 4;
157
+ else if (log_rounds > 31)
158
+ log_rounds = 31;
159
+
160
+ encode_salt(output, rseed, BCRYPT_MAXSALT, log_rounds);
161
+ return output;
162
+ }
163
+ /* We handle $Vers$log2(NumRounds)$salt+passwd$
164
+ i.e. $2$04$iwouldntknowwhattosayetKdJ6iFtacBqJdKe6aW7ou */
165
+
166
+ char *
167
+ ruby_bcrypt(char *output, const char *key, const char *salt)
168
+ {
169
+ blf_ctx state;
170
+ uint32_t rounds, i, k;
171
+ uint16_t j;
172
+ uint8_t key_len, salt_len, logr, minor;
173
+ uint8_t ciphertext[4 * BCRYPT_BLOCKS] = "OrpheanBeholderScryDoubt";
174
+ uint8_t csalt[BCRYPT_MAXSALT];
175
+ uint32_t cdata[BCRYPT_BLOCKS];
176
+ int n;
177
+
178
+ /* Discard "$" identifier */
179
+ salt++;
180
+
181
+ if (*salt > BCRYPT_VERSION) {
182
+ return NULL;
183
+ }
184
+
185
+ /* Check for minor versions */
186
+ if (salt[1] != '$') {
187
+ switch (salt[1]) {
188
+ case 'a':
189
+ /* 'ab' should not yield the same as 'abab' */
190
+ minor = salt[1];
191
+ salt++;
192
+ break;
193
+ default:
194
+ return NULL;
195
+ }
196
+ } else
197
+ minor = 0;
198
+
199
+ /* Discard version + "$" identifier */
200
+ salt += 2;
201
+
202
+ if (salt[2] != '$')
203
+ /* Out of sync with passwd entry */
204
+ return NULL;
205
+
206
+ /* Computer power doesn't increase linear, 2^x should be fine */
207
+ n = atoi(salt);
208
+ if (n > 31 || n < 0)
209
+ return NULL;
210
+ logr = (uint8_t)n;
211
+ if ((rounds = (uint32_t) 1 << logr) < BCRYPT_MINROUNDS)
212
+ return NULL;
213
+
214
+ /* Discard num rounds + "$" identifier */
215
+ salt += 3;
216
+
217
+ if (strlen(salt) * 3 / 4 < BCRYPT_MAXSALT)
218
+ return NULL;
219
+
220
+ /* We dont want the base64 salt but the raw data */
221
+ decode_base64(csalt, BCRYPT_MAXSALT, (uint8_t *) salt);
222
+ salt_len = BCRYPT_MAXSALT;
223
+ key_len = strlen(key) + (minor >= 'a' ? 1 : 0);
224
+
225
+ /* Setting up S-Boxes and Subkeys */
226
+ Blowfish_initstate(&state);
227
+ Blowfish_expandstate(&state, csalt, salt_len,
228
+ (uint8_t *) key, key_len);
229
+ for (k = 0; k < rounds; k++) {
230
+ Blowfish_expand0state(&state, (uint8_t *) key, key_len);
231
+ Blowfish_expand0state(&state, csalt, salt_len);
232
+ }
233
+
234
+ /* This can be precomputed later */
235
+ j = 0;
236
+ for (i = 0; i < BCRYPT_BLOCKS; i++)
237
+ cdata[i] = Blowfish_stream2word(ciphertext, 4 * BCRYPT_BLOCKS, &j);
238
+
239
+ /* Now do the encryption */
240
+ for (k = 0; k < 64; k++)
241
+ blf_enc(&state, cdata, BCRYPT_BLOCKS / 2);
242
+
243
+ for (i = 0; i < BCRYPT_BLOCKS; i++) {
244
+ ciphertext[4 * i + 3] = cdata[i] & 0xff;
245
+ cdata[i] = cdata[i] >> 8;
246
+ ciphertext[4 * i + 2] = cdata[i] & 0xff;
247
+ cdata[i] = cdata[i] >> 8;
248
+ ciphertext[4 * i + 1] = cdata[i] & 0xff;
249
+ cdata[i] = cdata[i] >> 8;
250
+ ciphertext[4 * i + 0] = cdata[i] & 0xff;
251
+ }
252
+
253
+
254
+ i = 0;
255
+ output[i++] = '$';
256
+ output[i++] = BCRYPT_VERSION;
257
+ if (minor)
258
+ output[i++] = minor;
259
+ output[i++] = '$';
260
+
261
+ snprintf(output + i, 4, "%2.2u$", logr);
262
+
263
+ encode_base64((uint8_t *) output + i + 3, csalt, BCRYPT_MAXSALT);
264
+ encode_base64((uint8_t *) output + strlen(output), ciphertext,
265
+ 4 * BCRYPT_BLOCKS - 1);
266
+ return output;
267
+ }
268
+
269
+ static void
270
+ encode_base64(uint8_t *buffer, uint8_t *data, uint16_t len)
271
+ {
272
+ uint8_t *bp = buffer;
273
+ uint8_t *p = data;
274
+ uint8_t c1, c2;
275
+ while (p < data + len) {
276
+ c1 = *p++;
277
+ *bp++ = Base64Code[(c1 >> 2)];
278
+ c1 = (c1 & 0x03) << 4;
279
+ if (p >= data + len) {
280
+ *bp++ = Base64Code[c1];
281
+ break;
282
+ }
283
+ c2 = *p++;
284
+ c1 |= (c2 >> 4) & 0x0f;
285
+ *bp++ = Base64Code[c1];
286
+ c1 = (c2 & 0x0f) << 2;
287
+ if (p >= data + len) {
288
+ *bp++ = Base64Code[c1];
289
+ break;
290
+ }
291
+ c2 = *p++;
292
+ c1 |= (c2 >> 6) & 0x03;
293
+ *bp++ = Base64Code[c1];
294
+ *bp++ = Base64Code[c2 & 0x3f];
295
+ }
296
+ *bp = '\0';
297
+ }
data/ext/mri/bcrypt.h ADDED
@@ -0,0 +1,67 @@
1
+ /*
2
+ * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>
3
+ * All rights reserved.
4
+ *
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. All advertising materials mentioning features or use of this software
14
+ * must display the following acknowledgement:
15
+ * This product includes software developed by Niels Provos.
16
+ * 4. The name of the author may not be used to endorse or promote products
17
+ * derived from this software without specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ */
30
+
31
+ #ifndef _BCRYPT_H_
32
+ #define _BCRYPT_H_
33
+
34
+ #include <stdint.h>
35
+
36
+ #define BCRYPT_VERSION '2'
37
+ #define BCRYPT_MAXSALT 16 /* Precomputation is just so nice */
38
+ #define BCRYPT_BLOCKS 6 /* Ciphertext blocks */
39
+ #define BCRYPT_MINROUNDS 16 /* we have log2(rounds) in salt */
40
+ #define BCRYPT_SALT_OUTPUT_SIZE (7 + (BCRYPT_MAXSALT * 4 + 2) / 3 + 1)
41
+ #define BCRYPT_OUTPUT_SIZE 128
42
+
43
+ /*
44
+ * Given a logarithmic cost parameter, generates a salt for use with bcrypt().
45
+ *
46
+ * output: the computed salt will be stored here. This buffer must be
47
+ * at least BCRYPT_SALT_OUTPUT_SIZE bytes. The result will be
48
+ * null-terminated.
49
+ * log_rounds: the logarithmic cost.
50
+ * rseed: a seed of BCRYPT_MAXSALT bytes. Should be obtained from a
51
+ * cryptographically secure random source.
52
+ * Returns: output
53
+ */
54
+ char *ruby_bcrypt_gensalt(char *output, uint8_t log_rounds, uint8_t *rseed);
55
+
56
+ /*
57
+ * Given a secret and a salt, generates a salted hash (which you can then store safely).
58
+ *
59
+ * output: the computed salted hash will be stored here. This buffer must
60
+ * be at least BCRYPT_OUTPUT_SIZE bytes, and will become null-terminated.
61
+ * key: A null-terminated secret.
62
+ * salt: The salt, as generated by bcrypt_gensalt().
63
+ * Returns: output on success, NULL on error.
64
+ */
65
+ char *ruby_bcrypt(char *output, const char *key, const char *salt);
66
+
67
+ #endif /* _BCRYPT_H_ */
@@ -0,0 +1,87 @@
1
+ #include "ruby.h"
2
+ #include "bcrypt.h"
3
+
4
+ static VALUE mBCrypt;
5
+ static VALUE cBCryptEngine;
6
+
7
+ /* Define RSTRING_PTR for Ruby 1.8.5, ruby-core's idea of a point release is
8
+ insane. */
9
+ #ifndef RSTRING_PTR
10
+ # define RSTRING_PTR(s) (RSTRING(s)->ptr)
11
+ #endif
12
+
13
+ #ifdef RUBY_VM
14
+ # define RUBY_1_9
15
+ #endif
16
+
17
+ #ifdef RUBY_1_9
18
+
19
+ /* When on Ruby 1.9+, we will want to unlock the GIL while performing
20
+ * expensive calculations, for greater concurrency. Do not do this for
21
+ * cheap calculations because locking/unlocking the GIL incurs some overhead as well.
22
+ */
23
+ #define GIL_UNLOCK_COST_THRESHOLD 9
24
+
25
+ typedef struct {
26
+ char *output;
27
+ const char *key;
28
+ const char *salt;
29
+ } BCryptArguments;
30
+
31
+ static VALUE bcrypt_wrapper(void *_args) {
32
+ BCryptArguments *args = (BCryptArguments *)_args;
33
+ return (VALUE)ruby_bcrypt(args->output, args->key, args->salt);
34
+ }
35
+
36
+ #endif /* RUBY_1_9 */
37
+
38
+ /* Given a logarithmic cost parameter, generates a salt for use with +bc_crypt+.
39
+ */
40
+ static VALUE bc_salt(VALUE self, VALUE cost, VALUE seed) {
41
+ int icost = NUM2INT(cost);
42
+ char salt[BCRYPT_SALT_OUTPUT_SIZE];
43
+
44
+ ruby_bcrypt_gensalt(salt, icost, (uint8_t *)RSTRING_PTR(seed));
45
+ return rb_str_new2(salt);
46
+ }
47
+
48
+ /* Given a secret and a salt, generates a salted hash (which you can then store safely).
49
+ */
50
+ static VALUE bc_crypt(VALUE self, VALUE key, VALUE salt, VALUE cost) {
51
+ const char * safeguarded = RSTRING_PTR(key) ? RSTRING_PTR(key) : "";
52
+ char output[BCRYPT_OUTPUT_SIZE];
53
+
54
+ #ifdef RUBY_1_9
55
+ int icost = NUM2INT(cost);
56
+ if (icost >= GIL_UNLOCK_COST_THRESHOLD) {
57
+ BCryptArguments args;
58
+ VALUE ret;
59
+
60
+ args.output = output;
61
+ args.key = safeguarded;
62
+ args.salt = RSTRING_PTR(salt);
63
+ ret = rb_thread_blocking_region(bcrypt_wrapper, &args, RUBY_UBF_IO, 0);
64
+ if (ret != (VALUE) 0) {
65
+ return rb_str_new2(output);
66
+ } else {
67
+ return Qnil;
68
+ }
69
+ }
70
+ /* otherwise, fallback to the non-GIL-unlocking code, just like on Ruby 1.8 */
71
+ #endif
72
+
73
+ if (ruby_bcrypt(output, safeguarded, (char *)RSTRING_PTR(salt)) != NULL) {
74
+ return rb_str_new2(output);
75
+ } else {
76
+ return Qnil;
77
+ }
78
+ }
79
+
80
+ /* Create the BCrypt and BCrypt::Engine modules, and populate them with methods. */
81
+ void Init_bcrypt_ext(){
82
+ mBCrypt = rb_define_module("BCrypt");
83
+ cBCryptEngine = rb_define_class_under(mBCrypt, "Engine", rb_cObject);
84
+
85
+ rb_define_singleton_method(cBCryptEngine, "__bc_salt", bc_salt, 2);
86
+ rb_define_singleton_method(cBCryptEngine, "__bc_crypt", bc_crypt, 3);
87
+ }