git ssb

0+

dangerousbeans / %aPBe2k3ugtjBr4rrsU1…



Tree: 7e4f6e0afadfe4fcafb532df1846f9f05c340463

Files: 7e4f6e0afadfe4fcafb532df1846f9f05c340463 / ext / mri / bcrypt_ext.c

2426 bytesRaw
1#include "ruby.h"
2#include "bcrypt.h"
3
4static VALUE mBCrypt;
5static 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)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 */
40static VALUE bc_salt(VALUE self, VALUE cost, VALUE seed) {
41 int icost = NUM2INT(cost);
42 char salt[BCRYPT_SALT_OUTPUT_SIZE];
43
44 bcrypt_gensalt(salt, icost, (u_int8_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 */
50static 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 (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. */
81void 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}
88

Built with git-ssb-web