Skip to content

Commit

Permalink
With some help from the node-png project I got gen_salt being async. …
Browse files Browse the repository at this point in the history
…No formal tests yet, but it works in a local test.

Signed-off-by: Nick Campbell <nicholas.j.campbell@gmail.com>
  • Loading branch information
ncb000gt committed Mar 27, 2011
1 parent 150255d commit 2d54786
Show file tree
Hide file tree
Showing 2 changed files with 124 additions and 4 deletions.
112 changes: 111 additions & 1 deletion src/bcrypt_node.cc
Expand Up @@ -52,7 +52,7 @@ void BCrypt::Initialize (Handle<Object> 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);

Expand Down Expand Up @@ -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<Value> 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<Value> BCrypt::GenerateSalt(const Arguments &args) {
BCrypt *bcrypt_obj = ObjectWrap::Unwrap<BCrypt>(args.This());
HandleScope scope;

Local<Function> 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<Function>::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<Function>::Cast(args[1]);
} else if (args.Length() > 2 && args[1]->IsNumber()) {
rand_len = args[1]->Int32Value();

if (args[2]->IsFunction()) {
callback = Local<Function>::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<Function>::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<Value> BCrypt::GenerateSaltSync(const Arguments& args) {
BCrypt *bcrypt_obj = ObjectWrap::Unwrap<BCrypt>(args.This());
HandleScope scope;
Expand Down
16 changes: 13 additions & 3 deletions src/bcrypt_node.h
Expand Up @@ -10,7 +10,17 @@ class BCrypt : public node::ObjectWrap {
static v8::Handle<v8::Value> GenerateSaltSync(const v8::Arguments& args);
static v8::Handle<v8::Value> HashPWSync(const v8::Arguments& args);
static v8::Handle<v8::Value> CompareSync(const v8::Arguments& args);
/*static v8::Handle<v8::Value> GenerateSalt(const v8::Arguments& args);
static v8::Handle<v8::Value> HashPW(const v8::Arguments& args);
static v8::Handle<v8::Value> Compare(const v8::Arguments& args);*/
static v8::Handle<v8::Value> GenerateSalt(const v8::Arguments& args);
//static v8::Handle<v8::Value> HashPW(const v8::Arguments& args);
//static v8::Handle<v8::Value> Compare(const v8::Arguments& args);
};

struct salt_request {
v8::Persistent<v8::Function> callback;
void *bcrypt_obj;
char *salt;
int salt_len;
int rand_len;
ssize_t rounds;
char *error;
};

0 comments on commit 2d54786

Please sign in to comment.