#endif
-class Cipher : public ObjectWrap {
- public:
- static void Initialize (v8::Handle<v8::Object> target) {
- HandleScope scope;
-
- Local<FunctionTemplate> t = FunctionTemplate::New(New);
+void CipherBase::Initialize(Handle<Object> target) {
+ HandleScope scope(node_isolate);
- t->InstanceTemplate()->SetInternalFieldCount(1);
+ Local<FunctionTemplate> t = FunctionTemplate::New(New);
- NODE_SET_PROTOTYPE_METHOD(t, "init", CipherInit);
- NODE_SET_PROTOTYPE_METHOD(t, "initiv", CipherInitIv);
- NODE_SET_PROTOTYPE_METHOD(t, "update", CipherUpdate);
- NODE_SET_PROTOTYPE_METHOD(t, "setAutoPadding", SetAutoPadding);
- NODE_SET_PROTOTYPE_METHOD(t, "final", CipherFinal);
-
- target->Set(String::NewSymbol("Cipher"), t->GetFunction());
- }
+ t->InstanceTemplate()->SetInternalFieldCount(1);
+ NODE_SET_PROTOTYPE_METHOD(t, "init", Init);
+ NODE_SET_PROTOTYPE_METHOD(t, "initiv", InitIv);
+ NODE_SET_PROTOTYPE_METHOD(t, "update", Update);
+ NODE_SET_PROTOTYPE_METHOD(t, "final", Final);
+ NODE_SET_PROTOTYPE_METHOD(t, "setAutoPadding", SetAutoPadding);
- bool CipherInit(char* cipherType, char* key_buf, int key_buf_len) {
- cipher = EVP_get_cipherbyname(cipherType);
- if(!cipher) {
- fprintf(stderr, "node-crypto : Unknown cipher %s\n", cipherType);
- return false;
- }
+ target->Set(String::NewSymbol("CipherBase"), t->GetFunction());
+}
- unsigned char key[EVP_MAX_KEY_LENGTH],iv[EVP_MAX_IV_LENGTH];
- int key_len = EVP_BytesToKey(cipher, EVP_md5(), NULL,
- (unsigned char*) key_buf, key_buf_len, 1, key, iv);
- EVP_CIPHER_CTX_init(&ctx);
- EVP_CipherInit_ex(&ctx, cipher, NULL, NULL, NULL, true);
- if (!EVP_CIPHER_CTX_set_key_length(&ctx, key_len)) {
- fprintf(stderr, "node-crypto : Invalid key length %d\n", key_len);
- EVP_CIPHER_CTX_cleanup(&ctx);
- return false;
- }
- EVP_CipherInit_ex(&ctx, NULL, NULL,
- (unsigned char*)key,
- (unsigned char*)iv, true);
- initialised_ = true;
- return true;
- }
-
-
- bool CipherInitIv(char* cipherType,
- char* key,
- int key_len,
- char* iv,
- int iv_len) {
- cipher = EVP_get_cipherbyname(cipherType);
- if(!cipher) {
- fprintf(stderr, "node-crypto : Unknown cipher %s\n", cipherType);
- return false;
- }
- /* OpenSSL versions up to 0.9.8l failed to return the correct
- iv_length (0) for ECB ciphers */
- if (EVP_CIPHER_iv_length(cipher) != iv_len &&
- !(EVP_CIPHER_mode(cipher) == EVP_CIPH_ECB_MODE && iv_len == 0)) {
- fprintf(stderr, "node-crypto : Invalid IV length %d\n", iv_len);
- return false;
- }
- EVP_CIPHER_CTX_init(&ctx);
- EVP_CipherInit_ex(&ctx, cipher, NULL, NULL, NULL, true);
- if (!EVP_CIPHER_CTX_set_key_length(&ctx, key_len)) {
- fprintf(stderr, "node-crypto : Invalid key length %d\n", key_len);
- EVP_CIPHER_CTX_cleanup(&ctx);
- return false;
- }
- EVP_CipherInit_ex(&ctx, NULL, NULL,
- (unsigned char*)key,
- (unsigned char*)iv, true);
- initialised_ = true;
- return true;
- }
+Handle<Value> CipherBase::New(const Arguments& args) {
+ HandleScope scope(node_isolate);
- int CipherUpdate(char* data, int len, unsigned char** out, int* out_len) {
- if (!initialised_) return 0;
- *out_len = len+EVP_CIPHER_CTX_block_size(&ctx);
- *out = new unsigned char[*out_len];
- return EVP_CipherUpdate(&ctx, *out, out_len, (unsigned char*)data, len);
- }
+ CipherBase* cipher = new CipherBase(args[0]->IsTrue() ? kCipher : kDecipher);
+ cipher->Wrap(args.This());
+ return args.This();
+}
- int SetAutoPadding(bool auto_padding) {
- if (!initialised_) return 0;
- return EVP_CIPHER_CTX_set_padding(&ctx, auto_padding ? 1 : 0);
- }
+Handle<Value> CipherBase::Init(char* cipher_type,
+ char* key_buf,
+ int key_buf_len) {
+ HandleScope scope(node_isolate);
- int CipherFinal(unsigned char** out, int *out_len) {
- if (!initialised_) return 0;
- *out = new unsigned char[EVP_CIPHER_CTX_block_size(&ctx)];
- int r = EVP_CipherFinal_ex(&ctx,*out, out_len);
- EVP_CIPHER_CTX_cleanup(&ctx);
- initialised_ = false;
- return r;
+ assert(cipher_ == NULL);
+ cipher_ = EVP_get_cipherbyname(cipher_type);
+ if (cipher_ == NULL) {
+ return ThrowError("Unknown cipher");
}
+ unsigned char key[EVP_MAX_KEY_LENGTH];
+ unsigned char iv[EVP_MAX_IV_LENGTH];
- protected:
-
- static Handle<Value> New(const Arguments& args) {
- HandleScope scope;
+ int key_len = EVP_BytesToKey(cipher_,
+ EVP_md5(),
+ NULL,
+ reinterpret_cast<unsigned char*>(key_buf),
+ key_buf_len,
+ 1,
+ key,
+ iv);
- Cipher *cipher = new Cipher();
- cipher->Wrap(args.This());
- return args.This();
+ EVP_CIPHER_CTX_init(&ctx_);
+ EVP_CipherInit_ex(&ctx_, cipher_, NULL, NULL, NULL, kind_ == kCipher);
+ if (!EVP_CIPHER_CTX_set_key_length(&ctx_, key_len)) {
+ EVP_CIPHER_CTX_cleanup(&ctx_);
+ return ThrowError("Invalid key length");
}
- static Handle<Value> CipherInit(const Arguments& args) {
- HandleScope scope;
-
- Cipher *cipher = ObjectWrap::Unwrap<Cipher>(args.This());
-
- if (args.Length() <= 1
- || !args[0]->IsString()
- || !(args[1]->IsString() || Buffer::HasInstance(args[1])))
- {
- return ThrowException(Exception::Error(String::New(
- "Must give cipher-type, key")));
- }
+ EVP_CipherInit_ex(&ctx_,
+ NULL,
+ NULL,
+ reinterpret_cast<unsigned char*>(key),
+ reinterpret_cast<unsigned char*>(iv),
+ kind_ == kCipher);
+ initialised_ = true;
+ return Null(node_isolate);
+}
- ASSERT_IS_BUFFER(args[1]);
- ssize_t key_buf_len = Buffer::Length(args[1]);
- if (key_buf_len < 0) {
- Local<Value> exception = Exception::TypeError(String::New("Bad argument"));
- return ThrowException(exception);
- }
+Handle<Value> CipherBase::Init(const Arguments& args) {
+ HandleScope scope(node_isolate);
- char* key_buf = new char[key_buf_len];
- ssize_t key_written = DecodeWrite(key_buf, key_buf_len, args[1], BINARY);
- assert(key_written == key_buf_len);
+ CipherBase* cipher = ObjectWrap::Unwrap<CipherBase>(args.This());
- String::Utf8Value cipherType(args[0]);
-
- bool r = cipher->CipherInit(*cipherType, key_buf, key_buf_len);
+ if (args.Length() < 2 ||
+ !(args[0]->IsString() && Buffer::HasInstance(args[1]))) {
+ return ThrowError("Must give cipher-type, key");
+ }
- delete [] key_buf;
+ String::Utf8Value cipher_type(args[0]);
+ char* key_buf = Buffer::Data(args[1]);
+ ssize_t key_buf_len = Buffer::Length(args[1]);
- if (!r) return ThrowCryptoError(ERR_get_error());
+ Handle<Value> ret = cipher->Init(*cipher_type, key_buf, key_buf_len);
+ if (ret->IsNull()) {
return args.This();
+ } else {
+ // Exception
+ return scope.Close(ret);
}
+}
- static Handle<Value> CipherInitIv(const Arguments& args) {
- Cipher *cipher = ObjectWrap::Unwrap<Cipher>(args.This());
-
- HandleScope scope;
-
+Handle<Value> CipherBase::InitIv(char* cipher_type,
+ char* key,
+ int key_len,
+ char* iv,
+ int iv_len) {
+ HandleScope scope(node_isolate);
- if (args.Length() <= 2
- || !args[0]->IsString()
- || !(args[1]->IsString() || Buffer::HasInstance(args[1]))
- || !(args[2]->IsString() || Buffer::HasInstance(args[2])))
- {
- return ThrowException(Exception::Error(String::New(
- "Must give cipher-type, key, and iv as argument")));
- }
+ cipher_ = EVP_get_cipherbyname(cipher_type);
+ if (cipher_ == NULL) {
+ return ThrowError("Unknown cipher");
+ }
- ASSERT_IS_BUFFER(args[1]);
- ssize_t key_len = Buffer::Length(args[1]);
+ /* OpenSSL versions up to 0.9.8l failed to return the correct
+ iv_length (0) for ECB ciphers */
+ if (EVP_CIPHER_iv_length(cipher_) != iv_len &&
+ !(EVP_CIPHER_mode(cipher_) == EVP_CIPH_ECB_MODE && iv_len == 0)) {
+ return ThrowError("Invalid IV length");
+ }
+ EVP_CIPHER_CTX_init(&ctx_);
+ EVP_CipherInit_ex(&ctx_, cipher_, NULL, NULL, NULL, kind_ == kCipher);
+ if (!EVP_CIPHER_CTX_set_key_length(&ctx_, key_len)) {
+ EVP_CIPHER_CTX_cleanup(&ctx_);
+ return ThrowError("Invalid key length");
+ }
- if (key_len < 0) {
- Local<Value> exception = Exception::TypeError(String::New("Bad argument"));
- return ThrowException(exception);
- }
+ EVP_CipherInit_ex(&ctx_,
+ NULL,
+ NULL,
+ reinterpret_cast<unsigned char*>(key),
+ reinterpret_cast<unsigned char*>(iv),
+ kind_ == kCipher);
+ initialised_ = true;
+ return Null(node_isolate);
+}
- ASSERT_IS_BUFFER(args[2]);
- ssize_t iv_len = Buffer::Length(args[2]);
- if (iv_len < 0) {
- Local<Value> exception = Exception::TypeError(String::New("Bad argument"));
- return ThrowException(exception);
- }
+Handle<Value> CipherBase::InitIv(const Arguments& args) {
+ HandleScope scope(node_isolate);
- char* key_buf = new char[key_len];
- ssize_t key_written = DecodeWrite(key_buf, key_len, args[1], BINARY);
- assert(key_written == key_len);
+ CipherBase* cipher = ObjectWrap::Unwrap<CipherBase>(args.This());
- char* iv_buf = new char[iv_len];
- ssize_t iv_written = DecodeWrite(iv_buf, iv_len, args[2], BINARY);
- assert(iv_written == iv_len);
-
- String::Utf8Value cipherType(args[0]);
+ if (args.Length() < 3 || !args[0]->IsString()) {
+ return ThrowError("Must give cipher-type, key, and iv as argument");
+ }
- bool r = cipher->CipherInitIv(*cipherType, key_buf,key_len,iv_buf,iv_len);
+ ASSERT_IS_BUFFER(args[1]);
+ ASSERT_IS_BUFFER(args[2]);
- delete [] key_buf;
- delete [] iv_buf;
+ String::Utf8Value cipher_type(args[0]);
+ ssize_t key_len = Buffer::Length(args[1]);
+ char* key_buf = Buffer::Data(args[1]);
+ ssize_t iv_len = Buffer::Length(args[2]);
+ char* iv_buf = Buffer::Data(args[2]);
- if (!r) return ThrowCryptoError(ERR_get_error());
+ Handle<Value> ret = cipher->InitIv(*cipher_type,
+ key_buf,
+ key_len,
+ iv_buf,
+ iv_len);
+ if (ret->IsNull()) {
return args.This();
+ } else {
+ // Exception
+ return scope.Close(ret);
}
+}
- static Handle<Value> CipherUpdate(const Arguments& args) {
- Cipher *cipher = ObjectWrap::Unwrap<Cipher>(args.This());
- HandleScope scope;
+bool CipherBase::Update(char* data,
+ int len,
+ unsigned char** out,
+ int* out_len) {
+ if (!initialised_) return 0;
+ *out_len = len + EVP_CIPHER_CTX_block_size(&ctx_);
+ *out = new unsigned char[*out_len];
+ return EVP_CipherUpdate(&ctx_,
+ *out,
+ out_len,
+ reinterpret_cast<unsigned char*>(data),
+ len);
+}
- ASSERT_IS_STRING_OR_BUFFER(args[0]);
- // Only copy the data if we have to, because it's a string
- unsigned char* out = 0;
- int out_len = 0, r;
- if (args[0]->IsString()) {
- enum encoding encoding = ParseEncoding(args[1], BINARY);
- size_t buflen = StringBytes::StorageSize(args[0], encoding);
- char* buf = new char[buflen];
- size_t written = StringBytes::Write(buf, buflen, args[0], encoding);
- r = cipher->CipherUpdate(buf, written, &out, &out_len);
- delete[] buf;
- } else {
- char* buf = Buffer::Data(args[0]);
- size_t buflen = Buffer::Length(args[0]);
- r = cipher->CipherUpdate(buf, buflen, &out, &out_len);
- }
+Handle<Value> CipherBase::Update(const Arguments& args) {
+ HandleScope scope(node_isolate);
- if (r == 0) {
- delete[] out;
- return ThrowCryptoTypeError(ERR_get_error());
- }
+ CipherBase* cipher = ObjectWrap::Unwrap<CipherBase>(args.This());
- Local<Value> outString;
- outString = Encode(out, out_len, BUFFER);
+ ASSERT_IS_STRING_OR_BUFFER(args[0]);
- if (out) delete[] out;
+ unsigned char* out = NULL;
+ bool r;
+ int out_len = 0;
- return scope.Close(outString);
+ // Only copy the data if we have to, because it's a string
+ if (args[0]->IsString()) {
+ enum encoding encoding = ParseEncoding(args[1], BINARY);
+ size_t buflen = StringBytes::StorageSize(args[0], encoding);
+ char* buf = new char[buflen];
+ size_t written = StringBytes::Write(buf, buflen, args[0], encoding);
+ r = cipher->Update(buf, written, &out, &out_len);
+ delete[] buf;
+ } else {
+ char* buf = Buffer::Data(args[0]);
+ size_t buflen = Buffer::Length(args[0]);
+ r = cipher->Update(buf, buflen, &out, &out_len);
}
- static Handle<Value> SetAutoPadding(const Arguments& args) {
- HandleScope scope;
- Cipher *cipher = ObjectWrap::Unwrap<Cipher>(args.This());
-
- cipher->SetAutoPadding(args.Length() < 1 || args[0]->BooleanValue());
-
- return Undefined();
+ if (!r) {
+ delete[] out;
+ return ThrowCryptoTypeError(ERR_get_error());
}
- static Handle<Value> CipherFinal(const Arguments& args) {
- Cipher *cipher = ObjectWrap::Unwrap<Cipher>(args.This());
-
- HandleScope scope;
+ Buffer* buf = Buffer::New(reinterpret_cast<char*>(out), out_len);
- unsigned char* out_value = NULL;
- int out_len = -1;
- Local<Value> outString ;
+ if (out) delete[] out;
- int r = cipher->CipherFinal(&out_value, &out_len);
+ return scope.Close(buf->handle_);
+}
- if (out_len <= 0 || r == 0) {
- delete[] out_value;
- out_value = NULL;
- if (r == 0) return ThrowCryptoTypeError(ERR_get_error());
- }
- outString = Encode(out_value, out_len, BUFFER);
+bool CipherBase::SetAutoPadding(bool auto_padding) {
+ if (!initialised_) return false;
+ return EVP_CIPHER_CTX_set_padding(&ctx_, auto_padding);
+}
- delete [] out_value;
- return scope.Close(outString);
- }
- Cipher () : ObjectWrap ()
- {
- initialised_ = false;
- }
+Handle<Value> CipherBase::SetAutoPadding(const Arguments& args) {
+ HandleScope scope(node_isolate);
- ~Cipher () {
- if (initialised_) {
- EVP_CIPHER_CTX_cleanup(&ctx);
- }
- }
+ CipherBase* cipher = ObjectWrap::Unwrap<CipherBase>(args.This());
- private:
-
- EVP_CIPHER_CTX ctx; /* coverity[member_decl] */
- const EVP_CIPHER *cipher; /* coverity[member_decl] */
- bool initialised_;
-};
+ cipher->SetAutoPadding(args.Length() < 1 || args[0]->BooleanValue());
+ return Undefined(node_isolate);
+}
-class Decipher : public ObjectWrap {
- public:
- static void
- Initialize (v8::Handle<v8::Object> target)
- {
- HandleScope scope;
+bool CipherBase::Final(unsigned char** out, int *out_len) {
+ if (!initialised_) return false;
- Local<FunctionTemplate> t = FunctionTemplate::New(New);
+ *out = new unsigned char[EVP_CIPHER_CTX_block_size(&ctx_)];
+ bool r = EVP_CipherFinal_ex(&ctx_, *out, out_len);
+ EVP_CIPHER_CTX_cleanup(&ctx_);
+ initialised_ = false;
- t->InstanceTemplate()->SetInternalFieldCount(1);
-
- NODE_SET_PROTOTYPE_METHOD(t, "init", DecipherInit);
- NODE_SET_PROTOTYPE_METHOD(t, "initiv", DecipherInitIv);
- NODE_SET_PROTOTYPE_METHOD(t, "update", DecipherUpdate);
- NODE_SET_PROTOTYPE_METHOD(t, "final", DecipherFinal);
- NODE_SET_PROTOTYPE_METHOD(t, "finaltol", DecipherFinal); // remove someday
- NODE_SET_PROTOTYPE_METHOD(t, "setAutoPadding", SetAutoPadding);
+ return r;
+}
- target->Set(String::NewSymbol("Decipher"), t->GetFunction());
- }
- bool DecipherInit(char* cipherType, char* key_buf, int key_buf_len) {
- cipher_ = EVP_get_cipherbyname(cipherType);
+Handle<Value> CipherBase::Final(const Arguments& args) {
+ HandleScope scope(node_isolate);
- if(!cipher_) {
- fprintf(stderr, "node-crypto : Unknown cipher %s\n", cipherType);
- return false;
- }
+ CipherBase* cipher = ObjectWrap::Unwrap<CipherBase>(args.This());
- unsigned char key[EVP_MAX_KEY_LENGTH],iv[EVP_MAX_IV_LENGTH];
- int key_len = EVP_BytesToKey(cipher_,
- EVP_md5(),
- NULL,
- (unsigned char*)(key_buf),
- key_buf_len,
- 1,
- key,
- iv);
-
- EVP_CIPHER_CTX_init(&ctx);
- EVP_CipherInit_ex(&ctx, cipher_, NULL, NULL, NULL, false);
- if (!EVP_CIPHER_CTX_set_key_length(&ctx, key_len)) {
- fprintf(stderr, "node-crypto : Invalid key length %d\n", key_len);
- EVP_CIPHER_CTX_cleanup(&ctx);
- return false;
- }
- EVP_CipherInit_ex(&ctx, NULL, NULL,
- (unsigned char*)key,
- (unsigned char*)iv, false);
- initialised_ = true;
- return true;
- }
-
-
- bool DecipherInitIv(char* cipherType,
- char* key,
- int key_len,
- char* iv,
- int iv_len) {
- cipher_ = EVP_get_cipherbyname(cipherType);
- if(!cipher_) {
- fprintf(stderr, "node-crypto : Unknown cipher %s\n", cipherType);
- return false;
- }
- /* OpenSSL versions up to 0.9.8l failed to return the correct
- iv_length (0) for ECB ciphers */
- if (EVP_CIPHER_iv_length(cipher_) != iv_len &&
- !(EVP_CIPHER_mode(cipher_) == EVP_CIPH_ECB_MODE && iv_len == 0)) {
- fprintf(stderr, "node-crypto : Invalid IV length %d\n", iv_len);
- return false;
- }
- EVP_CIPHER_CTX_init(&ctx);
- EVP_CipherInit_ex(&ctx, cipher_, NULL, NULL, NULL, false);
- if (!EVP_CIPHER_CTX_set_key_length(&ctx, key_len)) {
- fprintf(stderr, "node-crypto : Invalid key length %d\n", key_len);
- EVP_CIPHER_CTX_cleanup(&ctx);
- return false;
- }
- EVP_CipherInit_ex(&ctx, NULL, NULL,
- (unsigned char*)key,
- (unsigned char*)iv, false);
- initialised_ = true;
- return true;
- }
-
- int DecipherUpdate(char* data, int len, unsigned char** out, int* out_len) {
- if (!initialised_) {
- *out_len = 0;
- *out = NULL;
- return 0;
- }
+ unsigned char* out_value = NULL;
+ int out_len = -1;
+ Local<Value> outString;
- *out_len = len+EVP_CIPHER_CTX_block_size(&ctx);
- *out = new unsigned char[*out_len];
+ bool r = cipher->Final(&out_value, &out_len);
- return EVP_CipherUpdate(&ctx, *out, out_len, (unsigned char*)data, len);
+ if (out_len <= 0 || !r) {
+ delete[] out_value;
+ out_value = NULL;
+ out_len = 0;
+ if (!r) return ThrowCryptoTypeError(ERR_get_error());
}
- int SetAutoPadding(bool auto_padding) {
- if (!initialised_) return 0;
- return EVP_CIPHER_CTX_set_padding(&ctx, auto_padding ? 1 : 0);
- }
+ Buffer* buf = Buffer::New(reinterpret_cast<char*>(out_value), out_len);
- // coverity[alloc_arg]
- int DecipherFinal(unsigned char** out, int *out_len) {
- int r;
+ return scope.Close(buf->handle_);
+}
- if (!initialised_) {
- *out_len = 0;
- *out = NULL;
- return 0;
- }
- *out = new unsigned char[EVP_CIPHER_CTX_block_size(&ctx)];
- r = EVP_CipherFinal_ex(&ctx,*out,out_len);
- EVP_CIPHER_CTX_cleanup(&ctx);
- initialised_ = false;
- return r;
- }
+void Hmac::Initialize(v8::Handle<v8::Object> target) {
+ HandleScope scope(node_isolate);
+ Local<FunctionTemplate> t = FunctionTemplate::New(New);
- protected:
+ t->InstanceTemplate()->SetInternalFieldCount(1);
- static Handle<Value> New (const Arguments& args) {
- HandleScope scope;
+ NODE_SET_PROTOTYPE_METHOD(t, "init", HmacInit);
+ NODE_SET_PROTOTYPE_METHOD(t, "update", HmacUpdate);
+ NODE_SET_PROTOTYPE_METHOD(t, "digest", HmacDigest);
- Decipher *cipher = new Decipher();
- cipher->Wrap(args.This());
- return args.This();
- }
+ target->Set(String::NewSymbol("Hmac"), t->GetFunction());
+}
- static Handle<Value> DecipherInit(const Arguments& args) {
- Decipher *cipher = ObjectWrap::Unwrap<Decipher>(args.This());
- HandleScope scope;
+Handle<Value> Hmac::New(const Arguments& args) {
+ HandleScope scope(node_isolate);
- if (args.Length() <= 1
- || !args[0]->IsString()
- || !(args[1]->IsString() || Buffer::HasInstance(args[1])))
- {
- return ThrowException(Exception::Error(String::New(
- "Must give cipher-type, key as argument")));
- }
+ Hmac* hmac = new Hmac();
+ hmac->Wrap(args.This());
+ return args.This();
+}
- ASSERT_IS_BUFFER(args[1]);
- ssize_t key_len = Buffer::Length(args[1]);
- if (key_len < 0) {
- Local<Value> exception = Exception::TypeError(String::New("Bad argument"));
- return ThrowException(exception);
- }
+Handle<Value> Hmac::HmacInit(char* hashType, char* key, int key_len) {
+ HandleScope scope(node_isolate);
- char* key_buf = new char[key_len];
- ssize_t key_written = DecodeWrite(key_buf, key_len, args[1], BINARY);
- assert(key_written == key_len);
+ assert(md_ == NULL);
+ md_ = EVP_get_digestbyname(hashType);
+ if (md_ == NULL) {
+ return ThrowError("Unknown message digest");
+ }
+ HMAC_CTX_init(&ctx_);
+ if (key_len == 0) {
+ HMAC_Init(&ctx_, "", 0, md_);
+ } else {
+ HMAC_Init(&ctx_, key, key_len, md_);
+ }
+ initialised_ = true;
- String::Utf8Value cipherType(args[0]);
+ return Null(node_isolate);
+}
- bool r = cipher->DecipherInit(*cipherType, key_buf,key_len);
- delete [] key_buf;
+Handle<Value> Hmac::HmacInit(const Arguments& args) {
+ HandleScope scope(node_isolate);
- if (!r) {
- return ThrowException(Exception::Error(String::New("DecipherInit error")));
- }
+ Hmac* hmac = ObjectWrap::Unwrap<Hmac>(args.This());
- return args.This();
+ if (args.Length() < 2 || !args[0]->IsString()) {
+ return ThrowError("Must give hashtype string, key as arguments");
}
- static Handle<Value> DecipherInitIv(const Arguments& args) {
- Decipher *cipher = ObjectWrap::Unwrap<Decipher>(args.This());
- HandleScope scope;
+ ASSERT_IS_BUFFER(args[1]);
- if (args.Length() <= 2
- || !args[0]->IsString()
- || !(args[1]->IsString() || Buffer::HasInstance(args[1]))
- || !(args[2]->IsString() || Buffer::HasInstance(args[2])))
- {
- return ThrowException(Exception::Error(String::New(
- "Must give cipher-type, key, and iv as argument")));
- }
+ String::Utf8Value hashType(args[0]);
- ASSERT_IS_BUFFER(args[1]);
- ssize_t key_len = Buffer::Length(args[1]);
+ char* buffer_data = Buffer::Data(args[1]);
+ size_t buffer_length = Buffer::Length(args[1]);
- if (key_len < 0) {
- Local<Value> exception = Exception::TypeError(String::New("Bad argument"));
- return ThrowException(exception);
- }
+ Handle<Value> ret = hmac->HmacInit(*hashType, buffer_data, buffer_length);
- ASSERT_IS_BUFFER(args[2]);
- ssize_t iv_len = Buffer::Length(args[2]);
+ if (ret->IsNull()) {
+ return args.This();
+ } else {
+ // Exception
+ return ret;
+ }
+}
- if (iv_len < 0) {
- Local<Value> exception = Exception::TypeError(String::New("Bad argument"));
- return ThrowException(exception);
- }
- char* key_buf = new char[key_len];
- ssize_t key_written = DecodeWrite(key_buf, key_len, args[1], BINARY);
- assert(key_written == key_len);
+bool Hmac::HmacUpdate(char* data, int len) {
+ if (!initialised_) return false;
+ HMAC_Update(&ctx_, reinterpret_cast<unsigned char*>(data), len);
+ return true;
+}
- char* iv_buf = new char[iv_len];
- ssize_t iv_written = DecodeWrite(iv_buf, iv_len, args[2], BINARY);
- assert(iv_written == iv_len);
- String::Utf8Value cipherType(args[0]);
+Handle<Value> Hmac::HmacUpdate(const Arguments& args) {
+ HandleScope scope(node_isolate);
- bool r = cipher->DecipherInitIv(*cipherType, key_buf,key_len,iv_buf,iv_len);
+ Hmac* hmac = ObjectWrap::Unwrap<Hmac>(args.This());
- delete [] key_buf;
- delete [] iv_buf;
+ ASSERT_IS_STRING_OR_BUFFER(args[0]);
- if (!r) {
- return ThrowException(Exception::Error(String::New("DecipherInitIv error")));
- }
+ // Only copy the data if we have to, because it's a string
+ bool r;
+ if (args[0]->IsString()) {
+ enum encoding encoding = ParseEncoding(args[1], BINARY);
+ size_t buflen = StringBytes::StorageSize(args[0], encoding);
+ char* buf = new char[buflen];
+ size_t written = StringBytes::Write(buf, buflen, args[0], encoding);
+ r = hmac->HmacUpdate(buf, written);
+ delete[] buf;
+ } else {
+ char* buf = Buffer::Data(args[0]);
+ size_t buflen = Buffer::Length(args[0]);
+ r = hmac->HmacUpdate(buf, buflen);
+ }
- return args.This();
+ if (!r) {
+ return ThrowTypeError("HmacUpdate fail");
}
- static Handle<Value> DecipherUpdate(const Arguments& args) {
- HandleScope scope;
+ return args.This();
+}
- Decipher *cipher = ObjectWrap::Unwrap<Decipher>(args.This());
- ASSERT_IS_STRING_OR_BUFFER(args[0]);
+bool Hmac::HmacDigest(unsigned char** md_value, unsigned int* md_len) {
+ if (!initialised_) return false;
+ *md_value = new unsigned char[EVP_MAX_MD_SIZE];
+ HMAC_Final(&ctx_, *md_value, md_len);
+ HMAC_CTX_cleanup(&ctx_);
+ initialised_ = false;
+ return true;
+}
- // Only copy the data if we have to, because it's a string
- unsigned char* out = 0;
- int out_len = 0, r;
- if (args[0]->IsString()) {
- enum encoding encoding = ParseEncoding(args[1], BINARY);
- size_t buflen = StringBytes::StorageSize(args[0], encoding);
- char* buf = new char[buflen];
- size_t written = StringBytes::Write(buf, buflen, args[0], encoding);
- r = cipher->DecipherUpdate(buf, written, &out, &out_len);
- delete[] buf;
- } else {
- char* buf = Buffer::Data(args[0]);
- size_t buflen = Buffer::Length(args[0]);
- r = cipher->DecipherUpdate(buf, buflen, &out, &out_len);
- }
- if (r == 0) {
- delete[] out;
- return ThrowCryptoTypeError(ERR_get_error());
- }
+Handle<Value> Hmac::HmacDigest(const Arguments& args) {
+ HandleScope scope(node_isolate);
- Local<Value> outString;
- outString = Encode(out, out_len, BUFFER);
+ Hmac* hmac = ObjectWrap::Unwrap<Hmac>(args.This());
- if (out) delete [] out;
+ enum encoding encoding = BUFFER;
+ if (args.Length() >= 1) {
+ encoding = ParseEncoding(args[0]->ToString(), BUFFER);
+ }
+
+ unsigned char* md_value = NULL;
+ unsigned int md_len = 0;
+ Local<Value> outString;
- return scope.Close(outString);
+ bool r = hmac->HmacDigest(&md_value, &md_len);
+ if (!r) {
+ md_value = NULL;
+ md_len = 0;
}
- static Handle<Value> SetAutoPadding(const Arguments& args) {
- HandleScope scope;
- Decipher *cipher = ObjectWrap::Unwrap<Decipher>(args.This());
+ outString = StringBytes::Encode(
+ reinterpret_cast<const char*>(md_value), md_len, encoding);
- cipher->SetAutoPadding(args.Length() < 1 || args[0]->BooleanValue());
+ delete[] md_value;
+ return scope.Close(outString);
+}
- return Undefined();
- }
- static Handle<Value> DecipherFinal(const Arguments& args) {
- HandleScope scope;
+void Hash::Initialize(v8::Handle<v8::Object> target) {
+ HandleScope scope(node_isolate);
- Decipher *cipher = ObjectWrap::Unwrap<Decipher>(args.This());
+ Local<FunctionTemplate> t = FunctionTemplate::New(New);
- unsigned char* out_value = NULL;
- int out_len = -1;
- Local<Value> outString;
+ t->InstanceTemplate()->SetInternalFieldCount(1);
- int r = cipher->DecipherFinal(&out_value, &out_len);
+ NODE_SET_PROTOTYPE_METHOD(t, "update", HashUpdate);
+ NODE_SET_PROTOTYPE_METHOD(t, "digest", HashDigest);
- if (out_len <= 0 || r == 0) {
- delete [] out_value; // allocated even if out_len == 0
- out_value = NULL;
- if (r == 0) return ThrowCryptoTypeError(ERR_get_error());
- }
+ target->Set(String::NewSymbol("Hash"), t->GetFunction());
+}
- outString = Encode(out_value, out_len, BUFFER);
- delete [] out_value;
- return scope.Close(outString);
- }
- Decipher () : ObjectWrap () {
- initialised_ = false;
- }
+Handle<Value> Hash::New(const Arguments& args) {
+ HandleScope scope(node_isolate);
- ~Decipher () {
- if (initialised_) {
- EVP_CIPHER_CTX_cleanup(&ctx);
- }
+ if (args.Length() == 0 || !args[0]->IsString()) {
+ return ThrowError("Must give hashtype string as argument");
}
- private:
+ String::Utf8Value hashType(args[0]);
- EVP_CIPHER_CTX ctx;
- const EVP_CIPHER *cipher_;
- bool initialised_;
-};
+ Hash* hash = new Hash();
+ if (!hash->HashInit(*hashType)) {
+ delete hash;
+ return ThrowError("Digest method not supported");
+ }
+ hash->Wrap(args.This());
+ return args.This();
+}
+bool Hash::HashInit(const char* hashType) {
+ assert(md_ == NULL);
+ md_ = EVP_get_digestbyname(hashType);
+ if (md_ == NULL) return false;
+ EVP_MD_CTX_init(&mdctx_);
+ EVP_DigestInit_ex(&mdctx_, md_, NULL);
+ initialised_ = true;
+ return true;
+}
-class Hmac : public ObjectWrap {
- public:
- static void Initialize (v8::Handle<v8::Object> target) {
- HandleScope scope;
- Local<FunctionTemplate> t = FunctionTemplate::New(New);
+bool Hash::HashUpdate(char* data, int len) {
+ if (!initialised_) return false;
+ EVP_DigestUpdate(&mdctx_, data, len);
+ return true;
+}
- t->InstanceTemplate()->SetInternalFieldCount(1);
- NODE_SET_PROTOTYPE_METHOD(t, "init", HmacInit);
- NODE_SET_PROTOTYPE_METHOD(t, "update", HmacUpdate);
- NODE_SET_PROTOTYPE_METHOD(t, "digest", HmacDigest);
+Handle<Value> Hash::HashUpdate(const Arguments& args) {
+ HandleScope scope(node_isolate);
- target->Set(String::NewSymbol("Hmac"), t->GetFunction());
- }
+ Hash* hash = ObjectWrap::Unwrap<Hash>(args.This());
- bool HmacInit(char* hashType, char* key, int key_len) {
- md = EVP_get_digestbyname(hashType);
- if(!md) {
- fprintf(stderr, "node-crypto : Unknown message digest %s\n", hashType);
- return false;
- }
- HMAC_CTX_init(&ctx);
- if (key_len == 0) {
- HMAC_Init(&ctx, "", 0, md);
- } else {
- HMAC_Init(&ctx, key, key_len, md);
- }
- initialised_ = true;
- return true;
+ ASSERT_IS_STRING_OR_BUFFER(args[0]);
+ // Only copy the data if we have to, because it's a string
+ bool r;
+ if (args[0]->IsString()) {
+ enum encoding encoding = ParseEncoding(args[1], BINARY);
+ size_t buflen = StringBytes::StorageSize(args[0], encoding);
+ char* buf = new char[buflen];
+ size_t written = StringBytes::Write(buf, buflen, args[0], encoding);
+ r = hash->HashUpdate(buf, written);
+ delete[] buf;
+ } else {
+ char* buf = Buffer::Data(args[0]);
+ size_t buflen = Buffer::Length(args[0]);
+ r = hash->HashUpdate(buf, buflen);
}
- int HmacUpdate(char* data, int len) {
- if (!initialised_) return 0;
- HMAC_Update(&ctx, (unsigned char*)data, len);
- return 1;
+ if (!r) {
+ return ThrowTypeError("HashUpdate fail");
}
- int HmacDigest(unsigned char** md_value, unsigned int *md_len) {
- if (!initialised_) return 0;
- *md_value = new unsigned char[EVP_MAX_MD_SIZE];
- HMAC_Final(&ctx, *md_value, md_len);
- HMAC_CTX_cleanup(&ctx);
- initialised_ = false;
- return 1;
- }
+ return args.This();
+}
- protected:
+Handle<Value> Hash::HashDigest(const Arguments& args) {
+ HandleScope scope(node_isolate);
- static Handle<Value> New (const Arguments& args) {
- HandleScope scope;
+ Hash* hash = ObjectWrap::Unwrap<Hash>(args.This());
- Hmac *hmac = new Hmac();
- hmac->Wrap(args.This());
- return args.This();
+ if (!hash->initialised_) {
+ return ThrowError("Not initialized");
}
- static Handle<Value> HmacInit(const Arguments& args) {
- Hmac *hmac = ObjectWrap::Unwrap<Hmac>(args.This());
-
- HandleScope scope;
-
- if (args.Length() == 0 || !args[0]->IsString()) {
- return ThrowException(Exception::Error(String::New(
- "Must give hashtype string as argument")));
- }
+ enum encoding encoding = BUFFER;
+ if (args.Length() >= 1) {
+ encoding = ParseEncoding(args[0]->ToString(), BUFFER);
+ }
- ASSERT_IS_BUFFER(args[1]);
- ssize_t len = Buffer::Length(args[1]);
+ unsigned char md_value[EVP_MAX_MD_SIZE];
+ unsigned int md_len;
- if (len < 0) {
- Local<Value> exception = Exception::TypeError(String::New("Bad argument"));
- return ThrowException(exception);
- }
+ EVP_DigestFinal_ex(&hash->mdctx_, md_value, &md_len);
+ EVP_MD_CTX_cleanup(&hash->mdctx_);
+ hash->initialised_ = false;
- String::Utf8Value hashType(args[0]);
-
- bool r;
+ return scope.Close(StringBytes::Encode(
+ reinterpret_cast<const char*>(md_value), md_len, encoding));
+}
- if( Buffer::HasInstance(args[1])) {
- char* buffer_data = Buffer::Data(args[1]);
- size_t buffer_length = Buffer::Length(args[1]);
- r = hmac->HmacInit(*hashType, buffer_data, buffer_length);
- } else {
- char* buf = new char[len];
- ssize_t written = DecodeWrite(buf, len, args[1], BINARY);
- assert(written == len);
+void Sign::Initialize(v8::Handle<v8::Object> target) {
+ HandleScope scope(node_isolate);
- r = hmac->HmacInit(*hashType, buf, len);
+ Local<FunctionTemplate> t = FunctionTemplate::New(New);
- delete [] buf;
- }
+ t->InstanceTemplate()->SetInternalFieldCount(1);
- if (!r) {
- return ThrowException(Exception::Error(String::New("hmac error")));
- }
+ NODE_SET_PROTOTYPE_METHOD(t, "init", SignInit);
+ NODE_SET_PROTOTYPE_METHOD(t, "update", SignUpdate);
+ NODE_SET_PROTOTYPE_METHOD(t, "sign", SignFinal);
- return args.This();
- }
+ target->Set(String::NewSymbol("Sign"), t->GetFunction());
+}
- static Handle<Value> HmacUpdate(const Arguments& args) {
- Hmac *hmac = ObjectWrap::Unwrap<Hmac>(args.This());
- HandleScope scope;
+Handle<Value> Sign::New(const Arguments& args) {
+ HandleScope scope(node_isolate);
- ASSERT_IS_STRING_OR_BUFFER(args[0]);
+ Sign* sign = new Sign();
+ sign->Wrap(args.This());
- // Only copy the data if we have to, because it's a string
- int r;
- if (args[0]->IsString()) {
- enum encoding encoding = ParseEncoding(args[1], BINARY);
- size_t buflen = StringBytes::StorageSize(args[0], encoding);
- char* buf = new char[buflen];
- size_t written = StringBytes::Write(buf, buflen, args[0], encoding);
- r = hmac->HmacUpdate(buf, written);
- delete[] buf;
- } else {
- char* buf = Buffer::Data(args[0]);
- size_t buflen = Buffer::Length(args[0]);
- r = hmac->HmacUpdate(buf, buflen);
- }
+ return args.This();
+}
- if (!r) {
- Local<Value> exception = Exception::TypeError(String::New("HmacUpdate fail"));
- return ThrowException(exception);
- }
+Handle<Value> Sign::SignInit(const char* sign_type) {
+ HandleScope scope(node_isolate);
- return args.This();
+ assert(md_ == NULL);
+ md_ = EVP_get_digestbyname(sign_type);
+ if (!md_) {
+ return ThrowError("Uknown message digest");
}
+ EVP_MD_CTX_init(&mdctx_);
+ EVP_SignInit_ex(&mdctx_, md_, NULL);
+ initialised_ = true;
+ return Null(node_isolate);
+}
- static Handle<Value> HmacDigest(const Arguments& args) {
- Hmac *hmac = ObjectWrap::Unwrap<Hmac>(args.This());
-
- HandleScope scope;
-
- enum encoding encoding = BUFFER;
- if (args.Length() >= 1) {
- encoding = ParseEncoding(args[0]->ToString(), BUFFER);
- }
- unsigned char* md_value = NULL;
- unsigned int md_len = 0;
- Local<Value> outString;
+Handle<Value> Sign::SignInit(const Arguments& args) {
+ HandleScope scope(node_isolate);
- int r = hmac->HmacDigest(&md_value, &md_len);
- if (r == 0) {
- md_value = NULL;
- md_len = 0;
- }
+ Sign* sign = ObjectWrap::Unwrap<Sign>(args.This());
- outString = StringBytes::Encode(
- reinterpret_cast<const char*>(md_value), md_len, encoding);
-
- delete[] md_value;
- return scope.Close(outString);
+ if (args.Length() == 0 || !args[0]->IsString()) {
+ return ThrowError("Must give signtype string as argument");
}
- Hmac () : ObjectWrap () {
- initialised_ = false;
- }
+ String::Utf8Value sign_type(args[0]);
- ~Hmac () {
- if (initialised_) {
- HMAC_CTX_cleanup(&ctx);
- }
- }
+ Handle<Value> ret = sign->SignInit(*sign_type);
- private:
+ if (ret->IsNull()) {
+ return args.This();
+ } else {
+ // Exception
+ return scope.Close(ret);
+ }
+}
- HMAC_CTX ctx; /* coverity[member_decl] */
- const EVP_MD *md; /* coverity[member_decl] */
- bool initialised_;
-};
+bool Sign::SignUpdate(char* data, int len) {
+ if (!initialised_) return false;
+ EVP_SignUpdate(&mdctx_, data, len);
+ return true;
+}
-class Hash : public ObjectWrap {
- public:
- static void Initialize (v8::Handle<v8::Object> target) {
- HandleScope scope;
- Local<FunctionTemplate> t = FunctionTemplate::New(New);
+Handle<Value> Sign::SignUpdate(const Arguments& args) {
+ HandleScope scope(node_isolate);
- t->InstanceTemplate()->SetInternalFieldCount(1);
+ Sign* sign = ObjectWrap::Unwrap<Sign>(args.This());
- NODE_SET_PROTOTYPE_METHOD(t, "update", HashUpdate);
- NODE_SET_PROTOTYPE_METHOD(t, "digest", HashDigest);
+ ASSERT_IS_STRING_OR_BUFFER(args[0]);
- target->Set(String::NewSymbol("Hash"), t->GetFunction());
+ // Only copy the data if we have to, because it's a string
+ int r;
+ if (args[0]->IsString()) {
+ enum encoding encoding = ParseEncoding(args[1], BINARY);
+ size_t buflen = StringBytes::StorageSize(args[0], encoding);
+ char* buf = new char[buflen];
+ size_t written = StringBytes::Write(buf, buflen, args[0], encoding);
+ r = sign->SignUpdate(buf, written);
+ delete[] buf;
+ } else {
+ char* buf = Buffer::Data(args[0]);
+ size_t buflen = Buffer::Length(args[0]);
+ r = sign->SignUpdate(buf, buflen);
}
- bool HashInit (const char* hashType) {
- md = EVP_get_digestbyname(hashType);
- if(!md) return false;
- EVP_MD_CTX_init(&mdctx);
- EVP_DigestInit_ex(&mdctx, md, NULL);
- initialised_ = true;
- return true;
+ if (!r) {
+ return ThrowTypeError("SignUpdate fail");
}
- int HashUpdate(char* data, int len) {
- if (!initialised_) return 0;
- EVP_DigestUpdate(&mdctx, data, len);
- return 1;
- }
+ return args.This();
+}
- protected:
+bool Sign::SignFinal(unsigned char** md_value,
+ unsigned int *md_len,
+ char* key_pem,
+ int key_pem_len) {
+ if (!initialised_) return false;
- static Handle<Value> New (const Arguments& args) {
- HandleScope scope;
+ BIO* bp = NULL;
+ EVP_PKEY* pkey = NULL;
+ bp = BIO_new(BIO_s_mem());
+ if (!BIO_write(bp, key_pem, key_pem_len)) return false;
- if (args.Length() == 0 || !args[0]->IsString()) {
- return ThrowException(Exception::Error(String::New(
- "Must give hashtype string as argument")));
- }
+ pkey = PEM_read_bio_PrivateKey(bp, NULL, NULL, NULL);
+ if (pkey == NULL) return 0;
- String::Utf8Value hashType(args[0]);
+ EVP_SignFinal(&mdctx_, *md_value, md_len, pkey);
+ EVP_MD_CTX_cleanup(&mdctx_);
+ initialised_ = false;
+ EVP_PKEY_free(pkey);
+ BIO_free_all(bp);
+ return true;
+}
- Hash *hash = new Hash();
- if (!hash->HashInit(*hashType)) {
- delete hash;
- return ThrowException(Exception::Error(String::New(
- "Digest method not supported")));
- }
- hash->Wrap(args.This());
- return args.This();
- }
+Handle<Value> Sign::SignFinal(const Arguments& args) {
+ HandleScope scope(node_isolate);
- static Handle<Value> HashUpdate(const Arguments& args) {
- HandleScope scope;
+ Sign* sign = ObjectWrap::Unwrap<Sign>(args.This());
- Hash *hash = ObjectWrap::Unwrap<Hash>(args.This());
+ unsigned char* md_value;
+ unsigned int md_len;
+ Local<Value> outString;
- ASSERT_IS_STRING_OR_BUFFER(args[0]);
+ enum encoding encoding = BUFFER;
+ if (args.Length() >= 2) {
+ encoding = ParseEncoding(args[1]->ToString(), BUFFER);
+ }
- // Only copy the data if we have to, because it's a string
- int r;
- if (args[0]->IsString()) {
- enum encoding encoding = ParseEncoding(args[1], BINARY);
- size_t buflen = StringBytes::StorageSize(args[0], encoding);
- char* buf = new char[buflen];
- size_t written = StringBytes::Write(buf, buflen, args[0], encoding);
- r = hash->HashUpdate(buf, written);
- delete[] buf;
- } else {
- char* buf = Buffer::Data(args[0]);
- size_t buflen = Buffer::Length(args[0]);
- r = hash->HashUpdate(buf, buflen);
- }
+ ASSERT_IS_BUFFER(args[0]);
+ ssize_t len = Buffer::Length(args[0]);
+ char* buf = Buffer::Data(args[0]);
- if (!r) {
- Local<Value> exception = Exception::TypeError(String::New("HashUpdate fail"));
- return ThrowException(exception);
- }
+ md_len = 8192; // Maximum key size is 8192 bits
+ md_value = new unsigned char[md_len];
- return args.This();
+ bool r = sign->SignFinal(&md_value, &md_len, buf, len);
+ if (!r) {
+ delete[] md_value;
+ md_value = NULL;
+ md_len = 0;
}
- static Handle<Value> HashDigest(const Arguments& args) {
- HandleScope scope;
+ outString = StringBytes::Encode(
+ reinterpret_cast<const char*>(md_value), md_len, encoding);
- Hash *hash = ObjectWrap::Unwrap<Hash>(args.This());
-
- if (!hash->initialised_) {
- return ThrowException(Exception::Error(String::New("Not initialized")));
- }
+ delete[] md_value;
+ return scope.Close(outString);
+}
- enum encoding encoding = BUFFER;
- if (args.Length() >= 1) {
- encoding = ParseEncoding(args[0]->ToString(), BUFFER);
- }
- unsigned char md_value[EVP_MAX_MD_SIZE];
- unsigned int md_len;
+void Verify::Initialize(v8::Handle<v8::Object> target) {
+ HandleScope scope(node_isolate);
- EVP_DigestFinal_ex(&hash->mdctx, md_value, &md_len);
- EVP_MD_CTX_cleanup(&hash->mdctx);
- hash->initialised_ = false;
+ Local<FunctionTemplate> t = FunctionTemplate::New(New);
- return scope.Close(StringBytes::Encode(
- reinterpret_cast<const char*>(md_value), md_len, encoding));
- }
+ t->InstanceTemplate()->SetInternalFieldCount(1);
- Hash () : ObjectWrap () {
- initialised_ = false;
- }
+ NODE_SET_PROTOTYPE_METHOD(t, "init", VerifyInit);
+ NODE_SET_PROTOTYPE_METHOD(t, "update", VerifyUpdate);
+ NODE_SET_PROTOTYPE_METHOD(t, "verify", VerifyFinal);
- ~Hash () {
- if (initialised_) {
- EVP_MD_CTX_cleanup(&mdctx);
- }
- }
+ target->Set(String::NewSymbol("Verify"), t->GetFunction());
+}
- private:
- EVP_MD_CTX mdctx; /* coverity[member_decl] */
- const EVP_MD *md; /* coverity[member_decl] */
- bool initialised_;
-};
+Handle<Value> Verify::New(const Arguments& args) {
+ HandleScope scope(node_isolate);
-class Sign : public ObjectWrap {
- public:
- static void
- Initialize (v8::Handle<v8::Object> target) {
- HandleScope scope;
+ Verify* verify = new Verify();
+ verify->Wrap(args.This());
- Local<FunctionTemplate> t = FunctionTemplate::New(New);
+ return args.This();
+}
- t->InstanceTemplate()->SetInternalFieldCount(1);
- NODE_SET_PROTOTYPE_METHOD(t, "init", SignInit);
- NODE_SET_PROTOTYPE_METHOD(t, "update", SignUpdate);
- NODE_SET_PROTOTYPE_METHOD(t, "sign", SignFinal);
+Handle<Value> Verify::VerifyInit(const char* verify_type) {
+ HandleScope scope(node_isolate);
- target->Set(String::NewSymbol("Sign"), t->GetFunction());
+ assert(md_ == NULL);
+ md_ = EVP_get_digestbyname(verify_type);
+ if (md_ == NULL) {
+ return ThrowError("Unknown message digest");
}
- bool SignInit (const char* signType) {
- md = EVP_get_digestbyname(signType);
- if(!md) {
- printf("Unknown message digest %s\n", signType);
- return false;
- }
- EVP_MD_CTX_init(&mdctx);
- EVP_SignInit_ex(&mdctx, md, NULL);
- initialised_ = true;
- return true;
+ EVP_MD_CTX_init(&mdctx_);
+ EVP_VerifyInit_ex(&mdctx_, md_, NULL);
+ initialised_ = true;
- }
-
- int SignUpdate(char* data, int len) {
- if (!initialised_) return 0;
- EVP_SignUpdate(&mdctx, data, len);
- return 1;
- }
+ return Null(node_isolate);
+}
- int SignFinal(unsigned char** md_value,
- unsigned int *md_len,
- char* key_pem,
- int key_pemLen) {
- if (!initialised_) return 0;
- BIO *bp = NULL;
- EVP_PKEY* pkey;
- bp = BIO_new(BIO_s_mem());
- if(!BIO_write(bp, key_pem, key_pemLen)) return 0;
+Handle<Value> Verify::VerifyInit(const Arguments& args) {
+ HandleScope scope(node_isolate);
- pkey = PEM_read_bio_PrivateKey( bp, NULL, NULL, NULL );
- if (pkey == NULL) return 0;
+ Verify* verify = ObjectWrap::Unwrap<Verify>(args.This());
- EVP_SignFinal(&mdctx, *md_value, md_len, pkey);
- EVP_MD_CTX_cleanup(&mdctx);
- initialised_ = false;
- EVP_PKEY_free(pkey);
- BIO_free(bp);
- return 1;
+ if (args.Length() == 0 || !args[0]->IsString()) {
+ return ThrowError("Must give verifytype string as argument");
}
+ String::Utf8Value verify_type(args[0]);
- protected:
-
- static Handle<Value> New (const Arguments& args) {
- HandleScope scope;
-
- Sign *sign = new Sign();
- sign->Wrap(args.This());
+ Handle<Value> ret = verify->VerifyInit(*verify_type);
+ if (ret->IsNull()) {
return args.This();
+ } else {
+ // Exception
+ return scope.Close(ret);
}
+}
- static Handle<Value> SignInit(const Arguments& args) {
- HandleScope scope;
- Sign *sign = ObjectWrap::Unwrap<Sign>(args.This());
+bool Verify::VerifyUpdate(char* data, int len) {
+ if (!initialised_) return false;
+ EVP_VerifyUpdate(&mdctx_, data, len);
+ return true;
+}
- if (args.Length() == 0 || !args[0]->IsString()) {
- return ThrowException(Exception::Error(String::New(
- "Must give signtype string as argument")));
- }
- String::Utf8Value signType(args[0]);
+Handle<Value> Verify::VerifyUpdate(const Arguments& args) {
+ HandleScope scope(node_isolate);
- bool r = sign->SignInit(*signType);
+ Verify* verify = ObjectWrap::Unwrap<Verify>(args.This());
- if (!r) {
- return ThrowException(Exception::Error(String::New("SignInit error")));
- }
+ ASSERT_IS_STRING_OR_BUFFER(args[0]);
- return args.This();
+ // Only copy the data if we have to, because it's a string
+ bool r;
+ if (args[0]->IsString()) {
+ enum encoding encoding = ParseEncoding(args[1], BINARY);
+ size_t buflen = StringBytes::StorageSize(args[0], encoding);
+ char* buf = new char[buflen];
+ size_t written = StringBytes::Write(buf, buflen, args[0], encoding);
+ r = verify->VerifyUpdate(buf, written);
+ delete[] buf;
+ } else {
+ char* buf = Buffer::Data(args[0]);
+ size_t buflen = Buffer::Length(args[0]);
+ r = verify->VerifyUpdate(buf, buflen);
}
- static Handle<Value> SignUpdate(const Arguments& args) {
- Sign *sign = ObjectWrap::Unwrap<Sign>(args.This());
-
- HandleScope scope;
-
- ASSERT_IS_STRING_OR_BUFFER(args[0]);
-
- // Only copy the data if we have to, because it's a string
- int r;
- if (args[0]->IsString()) {
- enum encoding encoding = ParseEncoding(args[1], BINARY);
- size_t buflen = StringBytes::StorageSize(args[0], encoding);
- char* buf = new char[buflen];
- size_t written = StringBytes::Write(buf, buflen, args[0], encoding);
- r = sign->SignUpdate(buf, written);
- delete[] buf;
- } else {
- char* buf = Buffer::Data(args[0]);
- size_t buflen = Buffer::Length(args[0]);
- r = sign->SignUpdate(buf, buflen);
- }
-
- if (!r) {
- Local<Value> exception = Exception::TypeError(String::New("SignUpdate fail"));
- return ThrowException(exception);
- }
-
- return args.This();
+ if (!r) {
+ return ThrowTypeError("VerifyUpdate fail");
}
- static Handle<Value> SignFinal(const Arguments& args) {
- Sign *sign = ObjectWrap::Unwrap<Sign>(args.This());
-
- HandleScope scope;
-
- unsigned char* md_value;
- unsigned int md_len;
- Local<Value> outString;
+ return args.This();
+}
- ASSERT_IS_BUFFER(args[0]);
- ssize_t len = Buffer::Length(args[0]);
- enum encoding encoding = BUFFER;
- if (args.Length() >= 2) {
- encoding = ParseEncoding(args[1]->ToString(), BUFFER);
- }
+Handle<Value> Verify::VerifyFinal(char* key_pem,
+ int key_pem_len,
+ unsigned char* sig,
+ int siglen) {
+ HandleScope scope(node_isolate);
- char* buf = new char[len];
- ssize_t written = DecodeWrite(buf, len, args[0], BUFFER);
- assert(written == len);
+ if (!initialised_) {
+ return ThrowError("Verify not initalised");
+ }
- md_len = 8192; // Maximum key size is 8192 bits
- md_value = new unsigned char[md_len];
+ EVP_PKEY* pkey = NULL;
+ BIO* bp = NULL;
+ X509* x509 = NULL;
+ bool fatal = true;
+ int r;
- int r = sign->SignFinal(&md_value, &md_len, buf, len);
- if (r == 0) {
- md_value = NULL;
- md_len = r;
+ bp = BIO_new(BIO_s_mem());
+ if (bp == NULL)
+ goto exit;
+
+ if (!BIO_write(bp, key_pem, key_pem_len))
+ goto exit;
+
+ // Check if this is a PKCS#8 or RSA public key before trying as X.509.
+ // Split this out into a separate function once we have more than one
+ // consumer of public keys.
+ if (strncmp(key_pem, PUBLIC_KEY_PFX, PUBLIC_KEY_PFX_LEN) == 0) {
+ pkey = PEM_read_bio_PUBKEY(bp, NULL, NULL, NULL);
+ if (pkey == NULL)
+ goto exit;
+ } else if (strncmp(key_pem, PUBRSA_KEY_PFX, PUBRSA_KEY_PFX_LEN) == 0) {
+ RSA* rsa = PEM_read_bio_RSAPublicKey(bp, NULL, NULL, NULL);
+ if (rsa) {
+ pkey = EVP_PKEY_new();
+ if (pkey) EVP_PKEY_set1_RSA(pkey, rsa);
+ RSA_free(rsa);
}
+ if (pkey == NULL)
+ goto exit;
+ } else {
+ // X.509 fallback
+ x509 = PEM_read_bio_X509(bp, NULL, NULL, NULL);
+ if (x509 == NULL)
+ goto exit;
- delete [] buf;
+ pkey = X509_get_pubkey(x509);
+ if (pkey == NULL)
+ goto exit;
+ }
- outString = StringBytes::Encode(
- reinterpret_cast<const char*>(md_value), md_len, encoding);
+ fatal = false;
+ r = EVP_VerifyFinal(&mdctx_, sig, siglen, pkey);
- delete [] md_value;
- return scope.Close(outString);
- }
+exit:
+ if (pkey != NULL)
+ EVP_PKEY_free(pkey);
+ if (bp != NULL)
+ BIO_free_all(bp);
+ if (x509 != NULL)
+ X509_free(x509);
- Sign () : ObjectWrap () {
- initialised_ = false;
- }
+ EVP_MD_CTX_cleanup(&mdctx_);
+ initialised_ = false;
- ~Sign () {
- if (initialised_) {
- EVP_MD_CTX_cleanup(&mdctx);
- }
+ if (fatal) {
+ unsigned long err = ERR_get_error();
+ return ThrowCryptoError(err);
}
- private:
-
- EVP_MD_CTX mdctx; /* coverity[member_decl] */
- const EVP_MD *md; /* coverity[member_decl] */
- bool initialised_;
-};
+ return scope.Close(r ? True(node_isolate) : False(node_isolate));
+}
-class Verify : public ObjectWrap {
- public:
- static void Initialize (v8::Handle<v8::Object> target) {
- HandleScope scope;
- Local<FunctionTemplate> t = FunctionTemplate::New(New);
+Handle<Value> Verify::VerifyFinal(const Arguments& args) {
+ HandleScope scope(node_isolate);
- t->InstanceTemplate()->SetInternalFieldCount(1);
+ Verify* verify = ObjectWrap::Unwrap<Verify>(args.This());
- NODE_SET_PROTOTYPE_METHOD(t, "init", VerifyInit);
- NODE_SET_PROTOTYPE_METHOD(t, "update", VerifyUpdate);
- NODE_SET_PROTOTYPE_METHOD(t, "verify", VerifyFinal);
+ ASSERT_IS_BUFFER(args[0]);
+ char* kbuf = Buffer::Data(args[0]);
+ ssize_t klen = Buffer::Length(args[0]);
- target->Set(String::NewSymbol("Verify"), t->GetFunction());
+ ASSERT_IS_STRING_OR_BUFFER(args[1]);
+ // BINARY works for both buffers and binary strings.
+ enum encoding encoding = BINARY;
+ if (args.Length() >= 3) {
+ encoding = ParseEncoding(args[2]->ToString(), BINARY);
}
-
- bool VerifyInit (const char* verifyType) {
- md = EVP_get_digestbyname(verifyType);
- if(!md) {
- fprintf(stderr, "node-crypto : Unknown message digest %s\n", verifyType);
- return false;
- }
- EVP_MD_CTX_init(&mdctx);
- EVP_VerifyInit_ex(&mdctx, md, NULL);
- initialised_ = true;
- return true;
- }
+ ssize_t hlen = StringBytes::Size(args[1], encoding);
- int VerifyUpdate(char* data, int len) {
- if (!initialised_) return 0;
- EVP_VerifyUpdate(&mdctx, data, len);
- return 1;
+
+ // only copy if we need to, because it's a string.
+ unsigned char* hbuf;
+ if (args[1]->IsString()) {
+ hbuf = new unsigned char[hlen];
+ ssize_t hwritten = StringBytes::Write(
+ reinterpret_cast<char*>(hbuf), hlen, args[1], encoding);
+ assert(hwritten == hlen);
+ } else {
+ hbuf = reinterpret_cast<unsigned char*>(Buffer::Data(args[1]));
}
+ Local<Value> retval = Local<Value>::New(verify->VerifyFinal(kbuf, klen, hbuf, hlen));
+ if (args[1]->IsString()) {
+ delete[] hbuf;
+ }
+ return scope.Close(retval);
+}
- int VerifyFinal(char* key_pem, int key_pemLen, unsigned char* sig, int siglen) {
- if (!initialised_) return 0;
-
- EVP_PKEY* pkey = NULL;
- BIO *bp = NULL;
- X509 *x509 = NULL;
- int r = 0;
- bp = BIO_new(BIO_s_mem());
- if (bp == NULL) {
- ERR_print_errors_fp(stderr);
- return 0;
- }
- if(!BIO_write(bp, key_pem, key_pemLen)) {
- ERR_print_errors_fp(stderr);
- return 0;
- }
-
- // Check if this is a PKCS#8 or RSA public key before trying as X.509.
- // Split this out into a separate function once we have more than one
- // consumer of public keys.
- if (strncmp(key_pem, PUBLIC_KEY_PFX, PUBLIC_KEY_PFX_LEN) == 0) {
- pkey = PEM_read_bio_PUBKEY(bp, NULL, NULL, NULL);
- if (pkey == NULL) {
- ERR_print_errors_fp(stderr);
- return 0;
- }
- } else if (strncmp(key_pem, PUBRSA_KEY_PFX, PUBRSA_KEY_PFX_LEN) == 0) {
- RSA* rsa = PEM_read_bio_RSAPublicKey(bp, NULL, NULL, NULL);
- if (rsa) {
- pkey = EVP_PKEY_new();
- if (pkey) EVP_PKEY_set1_RSA(pkey, rsa);
- RSA_free(rsa);
- }
- if (pkey == NULL) {
- ERR_print_errors_fp(stderr);
- return 0;
- }
- } else {
- // X.509 fallback
- x509 = PEM_read_bio_X509(bp, NULL, NULL, NULL);
- if (x509 == NULL) {
- ERR_print_errors_fp(stderr);
- return 0;
- }
+void DiffieHellman::Initialize(v8::Handle<v8::Object> target) {
+ HandleScope scope(node_isolate);
- pkey = X509_get_pubkey(x509);
- if (pkey == NULL) {
- ERR_print_errors_fp(stderr);
- return 0;
- }
- }
+ Local<FunctionTemplate> t = FunctionTemplate::New(New);
- r = EVP_VerifyFinal(&mdctx, sig, siglen, pkey);
+ t->InstanceTemplate()->SetInternalFieldCount(1);
- if(pkey != NULL)
- EVP_PKEY_free (pkey);
- if (x509 != NULL)
- X509_free(x509);
- if (bp != NULL)
- BIO_free(bp);
- EVP_MD_CTX_cleanup(&mdctx);
- initialised_ = false;
+ NODE_SET_PROTOTYPE_METHOD(t, "generateKeys", GenerateKeys);
+ NODE_SET_PROTOTYPE_METHOD(t, "computeSecret", ComputeSecret);
+ NODE_SET_PROTOTYPE_METHOD(t, "getPrime", GetPrime);
+ NODE_SET_PROTOTYPE_METHOD(t, "getGenerator", GetGenerator);
+ NODE_SET_PROTOTYPE_METHOD(t, "getPublicKey", GetPublicKey);
+ NODE_SET_PROTOTYPE_METHOD(t, "getPrivateKey", GetPrivateKey);
+ NODE_SET_PROTOTYPE_METHOD(t, "setPublicKey", SetPublicKey);
+ NODE_SET_PROTOTYPE_METHOD(t, "setPrivateKey", SetPrivateKey);
- return r;
- }
+ target->Set(String::NewSymbol("DiffieHellman"), t->GetFunction());
+ Local<FunctionTemplate> t2 = FunctionTemplate::New(DiffieHellmanGroup);
+ t2->InstanceTemplate()->SetInternalFieldCount(1);
- protected:
+ NODE_SET_PROTOTYPE_METHOD(t2, "generateKeys", GenerateKeys);
+ NODE_SET_PROTOTYPE_METHOD(t2, "computeSecret", ComputeSecret);
+ NODE_SET_PROTOTYPE_METHOD(t2, "getPrime", GetPrime);
+ NODE_SET_PROTOTYPE_METHOD(t2, "getGenerator", GetGenerator);
+ NODE_SET_PROTOTYPE_METHOD(t2, "getPublicKey", GetPublicKey);
+ NODE_SET_PROTOTYPE_METHOD(t2, "getPrivateKey", GetPrivateKey);
- static Handle<Value> New (const Arguments& args) {
- HandleScope scope;
+ target->Set(String::NewSymbol("DiffieHellmanGroup"), t2->GetFunction());
+}
- Verify *verify = new Verify();
- verify->Wrap(args.This());
- return args.This();
- }
+bool DiffieHellman::Init(int primeLength) {
+ dh = DH_new();
+ DH_generate_parameters_ex(dh, primeLength, DH_GENERATOR_2, 0);
+ bool result = VerifyContext();
+ if (!result) return false;
+ initialised_ = true;
+ return true;
+}
- static Handle<Value> VerifyInit(const Arguments& args) {
- Verify *verify = ObjectWrap::Unwrap<Verify>(args.This());
+bool DiffieHellman::Init(unsigned char* p, int p_len) {
+ dh = DH_new();
+ dh->p = BN_bin2bn(p, p_len, 0);
+ dh->g = BN_new();
+ if (!BN_set_word(dh->g, 2)) return false;
+ bool result = VerifyContext();
+ if (!result) return false;
+ initialised_ = true;
+ return true;
+}
- HandleScope scope;
- if (args.Length() == 0 || !args[0]->IsString()) {
- return ThrowException(Exception::Error(String::New(
- "Must give verifytype string as argument")));
- }
+bool DiffieHellman::Init(unsigned char* p,
+ int p_len,
+ unsigned char* g,
+ int g_len) {
+ dh = DH_new();
+ dh->p = BN_bin2bn(p, p_len, 0);
+ dh->g = BN_bin2bn(g, g_len, 0);
+ initialised_ = true;
+ return true;
+}
- String::Utf8Value verifyType(args[0]);
- bool r = verify->VerifyInit(*verifyType);
+Handle<Value> DiffieHellman::DiffieHellmanGroup(const Arguments& args) {
+ HandleScope scope(node_isolate);
- if (!r) {
- return ThrowException(Exception::Error(String::New("VerifyInit error")));
- }
+ DiffieHellman* diffieHellman = new DiffieHellman();
- return args.This();
+ if (args.Length() != 1 || !args[0]->IsString()) {
+ return ThrowError("No group name given");
}
+ String::Utf8Value group_name(args[0]);
- static Handle<Value> VerifyUpdate(const Arguments& args) {
- HandleScope scope;
-
- Verify *verify = ObjectWrap::Unwrap<Verify>(args.This());
-
- ASSERT_IS_STRING_OR_BUFFER(args[0]);
+ modp_group* it = modp_groups;
- // Only copy the data if we have to, because it's a string
- int r;
- if (args[0]->IsString()) {
- enum encoding encoding = ParseEncoding(args[1], BINARY);
- size_t buflen = StringBytes::StorageSize(args[0], encoding);
- char* buf = new char[buflen];
- size_t written = StringBytes::Write(buf, buflen, args[0], encoding);
- r = verify->VerifyUpdate(buf, written);
- delete[] buf;
- } else {
- char* buf = Buffer::Data(args[0]);
- size_t buflen = Buffer::Length(args[0]);
- r = verify->VerifyUpdate(buf, buflen);
- }
-
- if (!r) {
- Local<Value> exception = Exception::TypeError(String::New("VerifyUpdate fail"));
- return ThrowException(exception);
- }
-
- return args.This();
+ while(it->name != NULL) {
+ if (!strcasecmp(*group_name, it->name))
+ break;
+ it++;
}
+ if (it->name != NULL) {
+ diffieHellman->Init(it->prime,
+ it->prime_size,
+ it->gen,
+ it->gen_size);
+ } else {
+ return ThrowError("Unknown group");
+ }
- static Handle<Value> VerifyFinal(const Arguments& args) {
- HandleScope scope;
-
- Verify *verify = ObjectWrap::Unwrap<Verify>(args.This());
+ diffieHellman->Wrap(args.This());
- ASSERT_IS_BUFFER(args[0]);
- ssize_t klen = Buffer::Length(args[0]);
+ return args.This();
+}
- if (klen < 0) {
- Local<Value> exception = Exception::TypeError(String::New("Bad argument"));
- return ThrowException(exception);
- }
- char* kbuf = new char[klen];
- ssize_t kwritten = DecodeWrite(kbuf, klen, args[0], BINARY);
- assert(kwritten == klen);
+Handle<Value> DiffieHellman::New(const Arguments& args) {
+ HandleScope scope(node_isolate);
- ASSERT_IS_STRING_OR_BUFFER(args[1]);
+ DiffieHellman* diffieHellman = new DiffieHellman();
+ bool initialized = false;
- // BINARY works for both buffers and binary strings.
- enum encoding encoding = BINARY;
- if (args.Length() >= 3) {
- encoding = ParseEncoding(args[2]->ToString(), BINARY);
+ if (args.Length() > 0) {
+ if (args[0]->IsInt32()) {
+ initialized = diffieHellman->Init(args[0]->Int32Value());
+ } else {
+ initialized = diffieHellman->Init(
+ reinterpret_cast<unsigned char*>(Buffer::Data(args[0])),
+ Buffer::Length(args[0]));
}
+ }
- ssize_t hlen = StringBytes::Size(args[1], encoding);
+ if (!initialized) {
+ return ThrowError("Initialization failed");
+ }
- if (hlen < 0) {
- delete[] kbuf;
- Local<Value> exception = Exception::TypeError(String::New("Bad argument"));
- return ThrowException(exception);
- }
+ diffieHellman->Wrap(args.This());
- unsigned char* hbuf = new unsigned char[hlen];
- ssize_t hwritten = StringBytes::Write(
- reinterpret_cast<char*>(hbuf), hlen, args[1], encoding);
- assert(hwritten == hlen);
+ return args.This();
+}
- int r;
- r = verify->VerifyFinal(kbuf, klen, hbuf, hlen);
- delete[] kbuf;
- delete[] hbuf;
+Handle<Value> DiffieHellman::GenerateKeys(const Arguments& args) {
+ HandleScope scope(node_isolate);
- return Boolean::New(r && r != -1);
- }
+ DiffieHellman* diffieHellman =
+ ObjectWrap::Unwrap<DiffieHellman>(args.This());
- Verify () : ObjectWrap () {
- initialised_ = false;
+ if (!diffieHellman->initialised_) {
+ return ThrowError("Not initialized");
}
- ~Verify () {
- if (initialised_) {
- EVP_MD_CTX_cleanup(&mdctx);
- }
+ if (!DH_generate_key(diffieHellman->dh)) {
+ return ThrowError("Key generation failed");
}
- private:
+ Local<Value> outString;
- EVP_MD_CTX mdctx; /* coverity[member_decl] */
- const EVP_MD *md; /* coverity[member_decl] */
- bool initialised_;
+ int dataSize = BN_num_bytes(diffieHellman->dh->pub_key);
+ char* data = new char[dataSize];
+ BN_bn2bin(diffieHellman->dh->pub_key,
+ reinterpret_cast<unsigned char*>(data));
-};
-
-class DiffieHellman : public ObjectWrap {
- public:
- static void Initialize(v8::Handle<v8::Object> target) {
- HandleScope scope;
-
- Local<FunctionTemplate> t = FunctionTemplate::New(New);
-
- t->InstanceTemplate()->SetInternalFieldCount(1);
+ outString = Encode(data, dataSize, BUFFER);
+ delete[] data;
- NODE_SET_PROTOTYPE_METHOD(t, "generateKeys", GenerateKeys);
- NODE_SET_PROTOTYPE_METHOD(t, "computeSecret", ComputeSecret);
- NODE_SET_PROTOTYPE_METHOD(t, "getPrime", GetPrime);
- NODE_SET_PROTOTYPE_METHOD(t, "getGenerator", GetGenerator);
- NODE_SET_PROTOTYPE_METHOD(t, "getPublicKey", GetPublicKey);
- NODE_SET_PROTOTYPE_METHOD(t, "getPrivateKey", GetPrivateKey);
- NODE_SET_PROTOTYPE_METHOD(t, "setPublicKey", SetPublicKey);
- NODE_SET_PROTOTYPE_METHOD(t, "setPrivateKey", SetPrivateKey);
+ return scope.Close(outString);
+}
- target->Set(String::NewSymbol("DiffieHellman"), t->GetFunction());
- Local<FunctionTemplate> t2 = FunctionTemplate::New(DiffieHellmanGroup);
- t2->InstanceTemplate()->SetInternalFieldCount(1);
+Handle<Value> DiffieHellman::GetPrime(const Arguments& args) {
+ HandleScope scope(node_isolate);
- NODE_SET_PROTOTYPE_METHOD(t2, "generateKeys", GenerateKeys);
- NODE_SET_PROTOTYPE_METHOD(t2, "computeSecret", ComputeSecret);
- NODE_SET_PROTOTYPE_METHOD(t2, "getPrime", GetPrime);
- NODE_SET_PROTOTYPE_METHOD(t2, "getGenerator", GetGenerator);
- NODE_SET_PROTOTYPE_METHOD(t2, "getPublicKey", GetPublicKey);
- NODE_SET_PROTOTYPE_METHOD(t2, "getPrivateKey", GetPrivateKey);
+ DiffieHellman* diffieHellman =
+ ObjectWrap::Unwrap<DiffieHellman>(args.This());
- target->Set(String::NewSymbol("DiffieHellmanGroup"), t2->GetFunction());
+ if (!diffieHellman->initialised_) {
+ return ThrowError("Not initialized");
}
- bool Init(int primeLength) {
- dh = DH_new();
- DH_generate_parameters_ex(dh, primeLength, DH_GENERATOR_2, 0);
- bool result = VerifyContext();
- if (!result) return false;
- initialised_ = true;
- return true;
- }
+ int dataSize = BN_num_bytes(diffieHellman->dh->p);
+ char* data = new char[dataSize];
+ BN_bn2bin(diffieHellman->dh->p, reinterpret_cast<unsigned char*>(data));
- bool Init(unsigned char* p, int p_len) {
- dh = DH_new();
- dh->p = BN_bin2bn(p, p_len, 0);
- dh->g = BN_new();
- if (!BN_set_word(dh->g, 2)) return false;
- bool result = VerifyContext();
- if (!result) return false;
- initialised_ = true;
- return true;
- }
+ Local<Value> outString;
- bool Init(unsigned char* p, int p_len, unsigned char* g, int g_len) {
- dh = DH_new();
- dh->p = BN_bin2bn(p, p_len, 0);
- dh->g = BN_bin2bn(g, g_len, 0);
- initialised_ = true;
- return true;
- }
+ outString = Encode(data, dataSize, BUFFER);
- protected:
- static Handle<Value> DiffieHellmanGroup(const Arguments& args) {
- HandleScope scope;
+ delete[] data;
- DiffieHellman* diffieHellman = new DiffieHellman();
+ return scope.Close(outString);
+}
- if (args.Length() != 1 || !args[0]->IsString()) {
- return ThrowException(Exception::Error(
- String::New("No group name given")));
- }
- String::Utf8Value group_name(args[0]);
+Handle<Value> DiffieHellman::GetGenerator(const Arguments& args) {
+ HandleScope scope(node_isolate);
- modp_group* it = modp_groups;
+ DiffieHellman* diffieHellman =
+ ObjectWrap::Unwrap<DiffieHellman>(args.This());
- while(it->name != NULL) {
- if (!strcasecmp(*group_name, it->name))
- break;
- it++;
- }
+ if (!diffieHellman->initialised_) {
+ return ThrowError("Not initialized");
+ }
- if (it->name != NULL) {
- diffieHellman->Init(it->prime, it->prime_size,
- it->gen, it->gen_size);
- } else {
- return ThrowException(Exception::Error(
- String::New("Unknown group")));
- }
+ int dataSize = BN_num_bytes(diffieHellman->dh->g);
+ char* data = new char[dataSize];
+ BN_bn2bin(diffieHellman->dh->g, reinterpret_cast<unsigned char*>(data));
- diffieHellman->Wrap(args.This());
+ Local<Value> outString;
- return args.This();
- }
+ outString = Encode(data, dataSize, BUFFER);
- static Handle<Value> New(const Arguments& args) {
- HandleScope scope;
+ delete[] data;
- DiffieHellman* diffieHellman = new DiffieHellman();
- bool initialized = false;
+ return scope.Close(outString);
+}
- if (args.Length() > 0) {
- if (args[0]->IsInt32()) {
- initialized = diffieHellman->Init(args[0]->Int32Value());
- } else {
- initialized = diffieHellman->Init(
- reinterpret_cast<unsigned char*>(Buffer::Data(args[0])),
- Buffer::Length(args[0]));
- }
- }
- if (!initialized) {
- return ThrowException(Exception::Error(
- String::New("Initialization failed")));
- }
+Handle<Value> DiffieHellman::GetPublicKey(const Arguments& args) {
+ HandleScope scope(node_isolate);
- diffieHellman->Wrap(args.This());
+ DiffieHellman* diffieHellman =
+ ObjectWrap::Unwrap<DiffieHellman>(args.This());
- return args.This();
+ if (!diffieHellman->initialised_) {
+ return ThrowError("Not initialized");
}
- static Handle<Value> GenerateKeys(const Arguments& args) {
- DiffieHellman* diffieHellman =
- ObjectWrap::Unwrap<DiffieHellman>(args.This());
+ if (diffieHellman->dh->pub_key == NULL) {
+ return ThrowError("No public key - did you forget to generate one?");
+ }
- HandleScope scope;
+ int dataSize = BN_num_bytes(diffieHellman->dh->pub_key);
+ char* data = new char[dataSize];
+ BN_bn2bin(diffieHellman->dh->pub_key,
+ reinterpret_cast<unsigned char*>(data));
- if (!diffieHellman->initialised_) {
- return ThrowException(Exception::Error(
- String::New("Not initialized")));
- }
+ Local<Value> outString;
- if (!DH_generate_key(diffieHellman->dh)) {
- return ThrowException(Exception::Error(
- String::New("Key generation failed")));
- }
+ outString = Encode(data, dataSize, BUFFER);
- Local<Value> outString;
+ delete[] data;
- int dataSize = BN_num_bytes(diffieHellman->dh->pub_key);
- char* data = new char[dataSize];
- BN_bn2bin(diffieHellman->dh->pub_key,
- reinterpret_cast<unsigned char*>(data));
+ return scope.Close(outString);
+}
- outString = Encode(data, dataSize, BUFFER);
- delete[] data;
- return scope.Close(outString);
- }
+Handle<Value> DiffieHellman::GetPrivateKey(const Arguments& args) {
+ HandleScope scope(node_isolate);
- static Handle<Value> GetPrime(const Arguments& args) {
- DiffieHellman* diffieHellman =
+ DiffieHellman* diffieHellman =
ObjectWrap::Unwrap<DiffieHellman>(args.This());
- HandleScope scope;
-
- if (!diffieHellman->initialised_) {
- return ThrowException(Exception::Error(String::New("Not initialized")));
- }
-
- int dataSize = BN_num_bytes(diffieHellman->dh->p);
- char* data = new char[dataSize];
- BN_bn2bin(diffieHellman->dh->p, reinterpret_cast<unsigned char*>(data));
-
- Local<Value> outString;
-
- outString = Encode(data, dataSize, BUFFER);
-
- delete[] data;
-
- return scope.Close(outString);
+ if (!diffieHellman->initialised_) {
+ return ThrowError("Not initialized");
}
- static Handle<Value> GetGenerator(const Arguments& args) {
- DiffieHellman* diffieHellman =
- ObjectWrap::Unwrap<DiffieHellman>(args.This());
+ if (diffieHellman->dh->priv_key == NULL) {
+ return ThrowError("No private key - did you forget to generate one?");
+ }
- HandleScope scope;
+ int dataSize = BN_num_bytes(diffieHellman->dh->priv_key);
+ char* data = new char[dataSize];
+ BN_bn2bin(diffieHellman->dh->priv_key,
+ reinterpret_cast<unsigned char*>(data));
- if (!diffieHellman->initialised_) {
- return ThrowException(Exception::Error(String::New("Not initialized")));
- }
+ Local<Value> outString;
- int dataSize = BN_num_bytes(diffieHellman->dh->g);
- char* data = new char[dataSize];
- BN_bn2bin(diffieHellman->dh->g, reinterpret_cast<unsigned char*>(data));
+ outString = Encode(data, dataSize, BUFFER);
- Local<Value> outString;
+ delete[] data;
- outString = Encode(data, dataSize, BUFFER);
+ return scope.Close(outString);
+}
- delete[] data;
- return scope.Close(outString);
- }
+Handle<Value> DiffieHellman::ComputeSecret(const Arguments& args) {
+ HandleScope scope(node_isolate);
- static Handle<Value> GetPublicKey(const Arguments& args) {
- DiffieHellman* diffieHellman =
+ DiffieHellman* diffieHellman =
ObjectWrap::Unwrap<DiffieHellman>(args.This());
- HandleScope scope;
+ if (!diffieHellman->initialised_) {
+ return ThrowError("Not initialized");
+ }
- if (!diffieHellman->initialised_) {
- return ThrowException(Exception::Error(String::New("Not initialized")));
- }
++ ClearErrorOnReturn clear_error_on_return;
++ (void) &clear_error_on_return; // Silence compiler warning.
+ BIGNUM* key = NULL;
- if (diffieHellman->dh->pub_key == NULL) {
- return ThrowException(Exception::Error(
- String::New("No public key - did you forget to generate one?")));
- }
+ if (args.Length() == 0) {
+ return ThrowError("First argument must be other party's public key");
+ } else {
+ ASSERT_IS_BUFFER(args[0]);
+ key = BN_bin2bn(
+ reinterpret_cast<unsigned char*>(Buffer::Data(args[0])),
+ Buffer::Length(args[0]),
+ 0);
+ }
- int dataSize = BN_num_bytes(diffieHellman->dh->pub_key);
- char* data = new char[dataSize];
- BN_bn2bin(diffieHellman->dh->pub_key,
- reinterpret_cast<unsigned char*>(data));
+ int dataSize = DH_size(diffieHellman->dh);
+ char* data = new char[dataSize];
- Local<Value> outString;
+ int size = DH_compute_key(reinterpret_cast<unsigned char*>(data),
+ key,
+ diffieHellman->dh);
- outString = Encode(data, dataSize, BUFFER);
+ if (size == -1) {
+ int checkResult;
+ int checked;
+ checked = DH_check_pub_key(diffieHellman->dh, key, &checkResult);
+ BN_free(key);
delete[] data;
- return scope.Close(outString);
- }
-
- static Handle<Value> GetPrivateKey(const Arguments& args) {
- DiffieHellman* diffieHellman =
- ObjectWrap::Unwrap<DiffieHellman>(args.This());
-
- HandleScope scope;
-
- if (!diffieHellman->initialised_) {
- return ThrowException(Exception::Error(String::New("Not initialized")));
+ if (!checked) {
+ return ThrowError("Invalid key");
+ } else if (checkResult) {
+ if (checkResult & DH_CHECK_PUBKEY_TOO_SMALL) {
+ return ThrowError("Supplied key is too small");
+ } else if (checkResult & DH_CHECK_PUBKEY_TOO_LARGE) {
+ return ThrowError("Supplied key is too large");
+ } else {
+ return ThrowError("Invalid key");
+ }
+ } else {
+ return ThrowError("Invalid key");
}
+ }
- if (diffieHellman->dh->priv_key == NULL) {
- return ThrowException(Exception::Error(
- String::New("No private key - did you forget to generate one?")));
- }
+ BN_free(key);
+ assert(size >= 0);
- int dataSize = BN_num_bytes(diffieHellman->dh->priv_key);
- char* data = new char[dataSize];
- BN_bn2bin(diffieHellman->dh->priv_key,
- reinterpret_cast<unsigned char*>(data));
+ // DH_size returns number of bytes in a prime number
+ // DH_compute_key returns number of bytes in a remainder of exponent, which
+ // may have less bytes than a prime number. Therefore add 0-padding to the
+ // allocated buffer.
+ if (size != dataSize) {
+ assert(dataSize > size);
+ memmove(data + dataSize - size, data, size);
+ memset(data, 0, dataSize - size);
+ }
- Local<Value> outString;
+ Local<Value> outString;
- outString = Encode(data, dataSize, BUFFER);
+ outString = Encode(data, dataSize, BUFFER);
- delete[] data;
+ delete[] data;
+ return scope.Close(outString);
+}
- return scope.Close(outString);
- }
- static Handle<Value> ComputeSecret(const Arguments& args) {
- HandleScope scope;
+Handle<Value> DiffieHellman::SetPublicKey(const Arguments& args) {
+ HandleScope scope(node_isolate);
- DiffieHellman* diffieHellman =
+ DiffieHellman* diffieHellman =
ObjectWrap::Unwrap<DiffieHellman>(args.This());
- if (!diffieHellman->initialised_) {
- return ThrowException(Exception::Error(String::New("Not initialized")));
- }
-
- ClearErrorOnReturn clear_error_on_return;
- (void) &clear_error_on_return; // Silence compiler warning.
- BIGNUM* key = 0;
+ if (!diffieHellman->initialised_) {
+ return ThrowError("Not initialized");
+ }
- if (args.Length() == 0) {
- return ThrowException(Exception::Error(
- String::New("First argument must be other party's public key")));
- } else {
- ASSERT_IS_BUFFER(args[0]);
- key = BN_bin2bn(
+ if (args.Length() == 0) {
+ return ThrowError("First argument must be public key");
+ } else {
+ ASSERT_IS_BUFFER(args[0]);
+ diffieHellman->dh->pub_key = BN_bin2bn(
reinterpret_cast<unsigned char*>(Buffer::Data(args[0])),
Buffer::Length(args[0]), 0);
- }
-
- int dataSize = DH_size(diffieHellman->dh);
- char* data = new char[dataSize];
-
- int size = DH_compute_key(reinterpret_cast<unsigned char*>(data),
- key, diffieHellman->dh);
-
- if (size == -1) {
- int checkResult;
- int checked;
-
- checked = DH_check_pub_key(diffieHellman->dh, key, &checkResult);
- BN_free(key);
- delete[] data;
-
- if (!checked) {
- return ThrowException(Exception::Error(String::New("Invalid key")));
- } else if (checkResult) {
- if (checkResult & DH_CHECK_PUBKEY_TOO_SMALL) {
- return ThrowException(Exception::Error(
- String::New("Supplied key is too small")));
- } else if (checkResult & DH_CHECK_PUBKEY_TOO_LARGE) {
- return ThrowException(Exception::Error(
- String::New("Supplied key is too large")));
- } else {
- return ThrowException(Exception::Error(String::New("Invalid key")));
- }
- } else {
- return ThrowException(Exception::Error(String::New("Invalid key")));
- }
- }
-
- BN_free(key);
- assert(size >= 0);
-
- // DH_size returns number of bytes in a prime number
- // DH_compute_key returns number of bytes in a remainder of exponent, which
- // may have less bytes than a prime number. Therefore add 0-padding to the
- // allocated buffer.
- if (size != dataSize) {
- assert(dataSize > size);
- memmove(data + dataSize - size, data, size);
- memset(data, 0, dataSize - size);
- }
-
- Local<Value> outString;
-
- outString = Encode(data, dataSize, BUFFER);
-
- delete[] data;
- return scope.Close(outString);
}
- static Handle<Value> SetPublicKey(const Arguments& args) {
- HandleScope scope;
-
- DiffieHellman* diffieHellman =
- ObjectWrap::Unwrap<DiffieHellman>(args.This());
-
- if (!diffieHellman->initialised_) {
- return ThrowException(Exception::Error(String::New("Not initialized")));
- }
-
- if (args.Length() == 0) {
- return ThrowException(Exception::Error(
- String::New("First argument must be public key")));
- } else {
- ASSERT_IS_BUFFER(args[0]);
- diffieHellman->dh->pub_key =
- BN_bin2bn(
- reinterpret_cast<unsigned char*>(Buffer::Data(args[0])),
- Buffer::Length(args[0]), 0);
- }
+ return args.This();
+}
- return args.This();
- }
- static Handle<Value> SetPrivateKey(const Arguments& args) {
- HandleScope scope;
+Handle<Value> DiffieHellman::SetPrivateKey(const Arguments& args) {
+ HandleScope scope(node_isolate);
- DiffieHellman* diffieHellman =
+ DiffieHellman* diffieHellman =
ObjectWrap::Unwrap<DiffieHellman>(args.This());
- if (!diffieHellman->initialised_) {
- return ThrowException(Exception::Error(
- String::New("Not initialized")));
- }
-
- if (args.Length() == 0) {
- return ThrowException(Exception::Error(
- String::New("First argument must be private key")));
- } else {
- ASSERT_IS_BUFFER(args[0]);
- diffieHellman->dh->priv_key =
- BN_bin2bn(
- reinterpret_cast<unsigned char*>(Buffer::Data(args[0])),
- Buffer::Length(args[0]), 0);
- }
-
- return args.This();
+ if (!diffieHellman->initialised_) {
+ return ThrowError("Not initialized");
}
- DiffieHellman() : ObjectWrap() {
- initialised_ = false;
- dh = NULL;
+ if (args.Length() == 0) {
+ return ThrowError("First argument must be private key");
+ } else {
+ ASSERT_IS_BUFFER(args[0]);
+ diffieHellman->dh->priv_key = BN_bin2bn(
+ reinterpret_cast<unsigned char*>(Buffer::Data(args[0])),
+ Buffer::Length(args[0]),
+ 0);
}
- ~DiffieHellman() {
- if (dh != NULL) {
- DH_free(dh);
- }
- }
+ return args.This();
+}
- private:
- bool VerifyContext() {
- int codes;
- if (!DH_check(dh, &codes)) return false;
- if (codes & DH_CHECK_P_NOT_SAFE_PRIME) return false;
- if (codes & DH_CHECK_P_NOT_PRIME) return false;
- if (codes & DH_UNABLE_TO_CHECK_GENERATOR) return false;
- if (codes & DH_NOT_SUITABLE_GENERATOR) return false;
- return true;
- }
- bool initialised_;
- DH* dh;
-};
+bool DiffieHellman::VerifyContext() {
+ int codes;
+ if (!DH_check(dh, &codes)) return false;
+ if (codes & DH_CHECK_P_NOT_SAFE_PRIME) return false;
+ if (codes & DH_CHECK_P_NOT_PRIME) return false;
+ if (codes & DH_UNABLE_TO_CHECK_GENERATOR) return false;
+ if (codes & DH_NOT_SUITABLE_GENERATOR) return false;
+ return true;
+}
struct pbkdf2_req {