From 2d54786fd6a6f780d75dfd30039f7b6f0cfe0fce Mon Sep 17 00:00:00 2001 From: Nick Campbell Date: Sun, 27 Mar 2011 02:41:04 -0400 Subject: [PATCH] With some help from the node-png project I got gen_salt being async. No formal tests yet, but it works in a local test. Signed-off-by: Nick Campbell --- src/bcrypt_node.cc | 112 ++++++++++++++++++++++++++++++++++++++++++++- src/bcrypt_node.h | 16 +++++-- 2 files changed, 124 insertions(+), 4 deletions(-) diff --git a/src/bcrypt_node.cc b/src/bcrypt_node.cc index 95e1f00a..e0daa3c5 100644 --- a/src/bcrypt_node.cc +++ b/src/bcrypt_node.cc @@ -52,7 +52,7 @@ void BCrypt::Initialize (Handle target) { NODE_SET_PROTOTYPE_METHOD(t, "gen_salt_sync", BCrypt::GenerateSaltSync); NODE_SET_PROTOTYPE_METHOD(t, "hashpw_sync", BCrypt::HashPWSync); NODE_SET_PROTOTYPE_METHOD(t, "compare_sync", BCrypt::CompareSync); - //NODE_SET_PROTOTYPE_METHOD(t, "gen_salt", BCrypt::GenerateSalt); + NODE_SET_PROTOTYPE_METHOD(t, "gen_salt", BCrypt::GenerateSalt); //NODE_SET_PROTOTYPE_METHOD(t, "hashpw", BCrypt::HashPW); //NODE_SET_PROTOTYPE_METHOD(t, "compare", BCrypt::Compare); @@ -86,6 +86,116 @@ int BCrypt::GetSeed(u_int8_t *seed, int size) { } } +int BCrypt::EIO_GenSalt(eio_req *req) { + salt_request *s_req = (salt_request *)req->data; + BCrypt *bcrypt_obj = (BCrypt *)s_req->bcrypt_obj; + + try { + u_int8_t *_seed = (u_int8_t *)malloc(s_req->rand_len * sizeof(u_int8_t)); + switch(BCrypt::GetSeed(_seed, s_req->rand_len)) { + case -1: + s_req->error = strdup("Rand operation not supported."); + case 0: + s_req->error = strdup("Rand operation did not generate a cryptographically sound seed."); + } + char* salt = bcrypt_gensalt(s_req->rounds, _seed); + s_req->salt_len = strlen(salt); + //memcpy(s_req->salt, (const char *)salt, s_req->salt_len); + s_req->salt = strdup(salt); + free(_seed); + } catch (const char *err) { + s_req->error = strdup(err); + } + + return 0; +} + +int BCrypt::EIO_GenSaltAfter(eio_req *req) +{ + HandleScope scope; + + ev_unref(EV_DEFAULT_UC); + salt_request *s_req = (salt_request *)req->data; + + Handle argv[2]; + + if (s_req->error) { + argv[0] = Exception::Error(String::New(s_req->error)); + argv[1] = Undefined(); + } + else { + argv[0] = Undefined(); + argv[1] = Encode(s_req->salt, s_req->salt_len, BINARY); + } + + TryCatch try_catch; // don't quite see the necessity of this + + s_req->callback->Call(Context::GetCurrent()->Global(), 2, argv); + + if (try_catch.HasCaught()) + FatalException(try_catch); + + s_req->callback.Dispose(); + free(s_req->salt); + free(s_req->error); + + ((BCrypt *)s_req->bcrypt_obj)->Unref(); + free(s_req); + + return 0; +} + +Handle BCrypt::GenerateSalt(const Arguments &args) { + BCrypt *bcrypt_obj = ObjectWrap::Unwrap(args.This()); + HandleScope scope; + + Local callback; + int rand_len = 20; + ssize_t rounds = 10; + if (args.Length() < 1) { + return ThrowException(Exception::Error(String::New("Must provide at least a callback."))); + } else if (args[0]->IsFunction()) { + callback = Local::Cast(args[0]); + } else if (args.Length() == 1) { + return ThrowException(Exception::Error(String::New("Must provide at least a callback."))); + } + if (args.Length() > 1) { + if (args[1]->IsFunction()) { + rounds = args[0]->Int32Value(); + callback = Local::Cast(args[1]); + } else if (args.Length() > 2 && args[1]->IsNumber()) { + rand_len = args[1]->Int32Value(); + + if (args[2]->IsFunction()) { + callback = Local::Cast(args[2]); + } else { + return ThrowException(Exception::Error(String::New("No callback supplied."))); + } + } else { + return ThrowException(Exception::Error(String::New("No callback supplied."))); + } + } else { + return ThrowException(Exception::Error(String::New("No callback supplied."))); + } + + salt_request *s_req = (salt_request *)malloc(sizeof(*s_req)); + if (!s_req) + return ThrowException(Exception::Error(String::New("malloc in BCrypt::GenerateSalt failed."))); + + s_req->callback = Persistent::New(callback); + s_req->bcrypt_obj = bcrypt_obj; + s_req->rand_len = rand_len; + s_req->rounds = rounds; + s_req->error = NULL; + + eio_custom(EIO_GenSalt, EIO_PRI_DEFAULT, EIO_GenSaltAfter, s_req); + + ev_ref(EV_DEFAULT_UC); + bcrypt_obj->Ref(); + + return Undefined(); +} + Handle BCrypt::GenerateSaltSync(const Arguments& args) { BCrypt *bcrypt_obj = ObjectWrap::Unwrap(args.This()); HandleScope scope; diff --git a/src/bcrypt_node.h b/src/bcrypt_node.h index dad0b273..d347222b 100644 --- a/src/bcrypt_node.h +++ b/src/bcrypt_node.h @@ -10,7 +10,17 @@ class BCrypt : public node::ObjectWrap { static v8::Handle GenerateSaltSync(const v8::Arguments& args); static v8::Handle HashPWSync(const v8::Arguments& args); static v8::Handle CompareSync(const v8::Arguments& args); - /*static v8::Handle GenerateSalt(const v8::Arguments& args); - static v8::Handle HashPW(const v8::Arguments& args); - static v8::Handle Compare(const v8::Arguments& args);*/ + static v8::Handle GenerateSalt(const v8::Arguments& args); + //static v8::Handle HashPW(const v8::Arguments& args); + //static v8::Handle Compare(const v8::Arguments& args); +}; + +struct salt_request { + v8::Persistent callback; + void *bcrypt_obj; + char *salt; + int salt_len; + int rand_len; + ssize_t rounds; + char *error; };