Merge remote-tracking branch 'origin/v0.10'
authorBen Noordhuis <info@bnoordhuis.nl>
Mon, 29 Apr 2013 12:08:51 +0000 (14:08 +0200)
committerBen Noordhuis <info@bnoordhuis.nl>
Mon, 29 Apr 2013 12:08:51 +0000 (14:08 +0200)
Conflicts:
AUTHORS
ChangeLog
deps/uv/ChangeLog
deps/uv/src/version.c
lib/http.js
src/node_crypto.cc
src/node_os.cc
src/node_version.h
test/simple/helper-debugger-repl.js

1  2 
AUTHORS
ChangeLog
deps/openssl/asm/Makefile
doc/api/events.markdown
lib/crypto.js
src/node_crypto.cc
src/node_os.cc

diff --cc AUTHORS
+++ b/AUTHORS
@@@ -431,9 -431,6 +431,10 @@@ JeongHoon Byun <outsideris@gmail.com
  Iskren Ivov Chernev <iskren.chernev@gmail.com>
  Alexey Kupershtokh <alexey.kupershtokh@gmail.com>
  Benjamin Ruston <benjy.ruston@gmail.com>
 +Manav Rathi <manav.r@directi.com>
 +Marcin Kostrzewa <marcinkostrzewa@yahoo.com>
 +Suwon Chae <doortts@gmail.com>
++David Braun <NodeJS-box@snkmail.com>
  Mitar Milutinovic <mitar.git@tnode.com>
  Michael Hart <michael.hart.au@gmail.com>
  Andrew Hart <hartandrewr@gmail.com>
@@@ -444,3 -440,5 +444,6 @@@ Stanislav Ochotnicky <sochotnicky@redha
  Ryan Graham <r.m.graham@gmail.com>
  Kelly Gerber <kellygerber22@yahoo.com>
  Ryan Doenges <rhdoenges@gmail.com>
+ Sean Silva <chisophugis@gmail.com>
+ Miroslav Bajtoš <miro.bajtos@gmail.com>
++Olof Johansson <olof@ethup.se>
diff --cc ChangeLog
+++ b/ChangeLog
@@@ -1,66 -1,25 +1,52 @@@
- 2013.03.28, Version 0.11.0 (Unstable), bce38b3d74e64fcb7d04a2dd551151da6168cdc5
- * V8: update to 3.17.13
- * os: use %SystemRoot% or %windir% in os.tmpdir() (Suwon Chae)
- * util: fix util.inspect() line width calculation (Marcin Kostrzewa)
- * buffer: remove _charsWritten (Trevor Norris)
- * fs: uv_[fl]stat now reports subsecond resolution (Timothy J Fontaine)
- * fs: Throw if error raised and missing callback (bnoordhuis)
- * tls: expose SSL_CTX_set_timeout via tls.createServer (Manav Rathi)
- * tls: remove harmful unnecessary bounds checking (Marcel Laverdet)
- * buffer: write ascii strings using WriteOneByte (Trevor Norris)
- * dtrace: fix generation of v8 constants on freebsd (Fedor Indutny)
- * dtrace: x64 ustack helper (Fedor Indutny)
- * readline: handle wide characters properly (Nao Iizuka)
- * repl: Use a domain to catch async errors safely (isaacs)
- * repl: emit 'reset' event when context is reset (Sami Samhuri)
- * util: custom `inspect()` method may return an Object (Nathan Rajlich)
- * console: `console.dir()` bypasses inspect() methods (Nathan Rajlich)
- 2013.04.11, Version 0.10.4 (Stable)
+ 2013.04.23, Version 0.10.5 (Stable)
+ * uv: Upgrade to 0.10.5 (isaacs)
+ * build: added support for Visual Studio 2012 (Miroslav Bajtoš)
+ * http: Don't try to destroy nonexistent sockets (isaacs)
+ * crypto: LazyTransform on properties, not methods (isaacs)
+ * assert: put info in err.message, not err.name (Ryan Doenges)
+ * dgram: fix no address bind() (Ben Noordhuis)
+ * handle_wrap: fix NULL pointer dereference (Ben Noordhuis)
+ * os: fix unlikely buffer overflow in os.type() (Ben Noordhuis)
+ * stream: Fix unshift() race conditions (isaacs)
 +2013.04.19, Version 0.11.1 (Unstable)
 +
 +* V8: upgrade to 3.18.0
 +
 +* uv: Upgrade to v0.11.1
 +
 +* http: split into multiple separate modules (Timothy J Fontaine)
 +
 +* http: escape unsafe characters in request path (Ben Noordhuis)
 +
 +* url: Escape all unwise characters (isaacs)
 +
 +* build: depend on v8 postmortem-metadata if enabled (Paddy Byers)
 +
 +* etw: update prototypes to match dtrace provider (Timothy J Fontaine)
 +
 +* buffer: change output of Buffer.prototype.toJSON() (David Braun)
 +
 +* dtrace: actually use the _handle.fd value (Timothy J Fontaine)
 +
 +* dtrace: pass more arguments to probes (Dave Pacheco)
 +
 +* build: allow building with dtrace on osx (Dave Pacheco)
 +
 +* zlib: allow passing options to convenience methods (Kyle Robinson Young)
 +
 +
+ 2013.04.11, Version 0.10.4 (Stable), 9712aa9f76073c30850b20a188b1ed12ffb74d17
  
  * uv: Upgrade to 0.10.4
  
  * src: tie process.versions.uv to uv_version_string() (Ben Noordhuis)
  
  
 -2013.03.28, Version 0.10.2 (Stable)
++2013.03.28, Version 0.11.0 (Unstable), bce38b3d74e64fcb7d04a2dd551151da6168cdc5
++
++* V8: update to 3.17.13
++
++* os: use %SystemRoot% or %windir% in os.tmpdir() (Suwon Chae)
++
++* util: fix util.inspect() line width calculation (Marcin Kostrzewa)
++
++* buffer: remove _charsWritten (Trevor Norris)
++
++* fs: uv_[fl]stat now reports subsecond resolution (Timothy J Fontaine)
++
++* fs: Throw if error raised and missing callback (bnoordhuis)
++
++* tls: expose SSL_CTX_set_timeout via tls.createServer (Manav Rathi)
++
++* tls: remove harmful unnecessary bounds checking (Marcel Laverdet)
++
++* buffer: write ascii strings using WriteOneByte (Trevor Norris)
++
++* dtrace: fix generation of v8 constants on freebsd (Fedor Indutny)
++
++* dtrace: x64 ustack helper (Fedor Indutny)
++
++* readline: handle wide characters properly (Nao Iizuka)
++
++* repl: Use a domain to catch async errors safely (isaacs)
++
++* repl: emit 'reset' event when context is reset (Sami Samhuri)
++
++* util: custom `inspect()` method may return an Object (Nathan Rajlich)
++
++* console: `console.dir()` bypasses inspect() methods (Nathan Rajlich)
++
++
 +2013.03.28, Version 0.10.2 (Stable), 1e0de9c426e07a260bbec2d2196c2d2db8eb8886
  
  * npm: Upgrade to 1.2.15
  
Simple merge
Simple merge
diff --cc lib/crypto.js
Simple merge
@@@ -2048,1204 -2024,1654 +2048,1204 @@@ Handle<Value> Connection::SetSNICallbac
  #endif
  
  
 -class Cipher : public ObjectWrap {
 - public:
 -  static void Initialize (v8::Handle<v8::Object> target) {
 -    HandleScope scope;
 +void CipherBase::Initialize(Handle<Object> target) {
 +  HandleScope scope(node_isolate);
  
 -    Local<FunctionTemplate> t = FunctionTemplate::New(New);
 +  Local<FunctionTemplate> t = FunctionTemplate::New(New);
  
 -    t->InstanceTemplate()->SetInternalFieldCount(1);
 +  t->InstanceTemplate()->SetInternalFieldCount(1);
  
 -    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);
 +  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);
  
 -    target->Set(String::NewSymbol("Cipher"), t->GetFunction());
 -  }
 +  target->Set(String::NewSymbol("CipherBase"), t->GetFunction());
 +}
  
  
 -  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;
 -    }
 +Handle<Value> CipherBase::New(const Arguments& args) {
 +  HandleScope scope(node_isolate);
  
 -    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;
 -  }
 +  CipherBase* cipher = new CipherBase(args[0]->IsTrue() ? kCipher : kDecipher);
 +  cipher->Wrap(args.This());
 +  return args.This();
 +}
  
 -  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);
 -  }
  
 -  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")));
 -    }
 -
 -    ASSERT_IS_BUFFER(args[1]);
 -    ssize_t key_buf_len = Buffer::Length(args[1]);
 +  EVP_CipherInit_ex(&ctx_,
 +                    NULL,
 +                    NULL,
 +                    reinterpret_cast<unsigned char*>(key),
 +                    reinterpret_cast<unsigned char*>(iv),
 +                    kind_ == kCipher);
 +  initialised_ = true;
 +  return Null(node_isolate);
 +}
  
 -    if (key_buf_len < 0) {
 -      Local<Value> exception = Exception::TypeError(String::New("Bad argument"));
 -      return ThrowException(exception);
 -    }
  
 -    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);
 +Handle<Value> CipherBase::Init(const Arguments& args) {
 +  HandleScope scope(node_isolate);
  
 -    String::Utf8Value cipherType(args[0]);
 +  CipherBase* cipher = ObjectWrap::Unwrap<CipherBase>(args.This());
  
 -    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;
 -
 -
 -    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")));
 -    }
 +Handle<Value> CipherBase::InitIv(char* cipher_type,
 +                                 char* key,
 +                                 int key_len,
 +                                 char* iv,
 +                                 int iv_len) {
 +  HandleScope scope(node_isolate);
  
 -    ASSERT_IS_BUFFER(args[1]);
 -    ssize_t key_len = Buffer::Length(args[1]);
 +  cipher_ = EVP_get_cipherbyname(cipher_type);
 +  if (cipher_ == NULL) {
 +    return ThrowError("Unknown cipher");
 +  }
  
 -    if (key_len < 0) {
 -      Local<Value> exception = Exception::TypeError(String::New("Bad argument"));
 -      return ThrowException(exception);
 -    }
 +  /* 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");
 +  }
  
 -    ASSERT_IS_BUFFER(args[2]);
 -    ssize_t iv_len = Buffer::Length(args[2]);
 +  EVP_CipherInit_ex(&ctx_,
 +                    NULL,
 +                    NULL,
 +                    reinterpret_cast<unsigned char*>(key),
 +                    reinterpret_cast<unsigned char*>(iv),
 +                    kind_ == kCipher);
 +  initialised_ = true;
 +  return Null(node_isolate);
 +}
  
 -    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);
 +Handle<Value> CipherBase::InitIv(const Arguments& args) {
 +  HandleScope scope(node_isolate);
  
 -    char* iv_buf = new char[iv_len];
 -    ssize_t iv_written = DecodeWrite(iv_buf, iv_len, args[2], BINARY);
 -    assert(iv_written == iv_len);
 +  CipherBase* cipher = ObjectWrap::Unwrap<CipherBase>(args.This());
  
 -    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_BUFFER(args[0]);
  
 -    unsigned char* out=0;
 -    int out_len=0, r;
 -    char* buffer_data = Buffer::Data(args[0]);
 -    size_t buffer_length = Buffer::Length(args[0]);
 +Handle<Value> CipherBase::Update(const Arguments& args) {
 +  HandleScope scope(node_isolate);
  
 -    r = cipher->CipherUpdate(buffer_data, buffer_length, &out, &out_len);
 +  CipherBase* cipher = ObjectWrap::Unwrap<CipherBase>(args.This());
  
 -    if (r == 0) {
 -      delete [] out;
 -      return ThrowCryptoTypeError(ERR_get_error());
 -    }
 +  ASSERT_IS_BUFFER(args[0]);
  
 -    Local<Value> outString;
 -    outString = Encode(out, out_len, BUFFER);
 +  unsigned char* out = NULL;
 +  bool r;
 +  int out_len = 0;
 +  char* buffer_data = Buffer::Data(args[0]);
 +  size_t buffer_length = Buffer::Length(args[0]);
  
 -    if (out) delete [] out;
 +  r = cipher->Update(buffer_data, buffer_length, &out, &out_len);
  
 -    return scope.Close(outString);
 +  if (!r) {
 +    delete[] out;
 +    return ThrowCryptoTypeError(ERR_get_error());
    }
  
 -  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();
 -  }
 +  Buffer* buf = Buffer::New(reinterpret_cast<char*>(out), out_len);
  
 -  static Handle<Value> CipherFinal(const Arguments& args) {
 -    Cipher *cipher = ObjectWrap::Unwrap<Cipher>(args.This());
 +  return scope.Close(buf->handle_);
 +}
  
 -    HandleScope scope;
  
 -    unsigned char* out_value = NULL;
 -    int out_len = -1;
 -    Local<Value> outString ;
 +bool CipherBase::SetAutoPadding(bool auto_padding) {
 +  if (!initialised_) return false;
 +  return EVP_CIPHER_CTX_set_padding(&ctx_, auto_padding);
 +}
  
 -    int r = cipher->CipherFinal(&out_value, &out_len);
  
 -    if (out_len <= 0 || r == 0) {
 -      delete[] out_value;
 -      out_value = NULL;
 -      if (r == 0) return ThrowCryptoTypeError(ERR_get_error());
 -    }
 +Handle<Value> CipherBase::SetAutoPadding(const Arguments& args) {
 +  HandleScope scope(node_isolate);
  
 -    outString = Encode(out_value, out_len, BUFFER);
 +  CipherBase* cipher = ObjectWrap::Unwrap<CipherBase>(args.This());
  
 -    delete [] out_value;
 -    return scope.Close(outString);
 -  }
 +  cipher->SetAutoPadding(args.Length() < 1 || args[0]->BooleanValue());
  
 -  Cipher () : ObjectWrap ()
 -  {
 -    initialised_ = false;
 -  }
 +  return Undefined(node_isolate);
 +}
  
 -  ~Cipher () {
 -    if (initialised_) {
 -      EVP_CIPHER_CTX_cleanup(&ctx);
 -    }
 -  }
  
 - private:
 +bool CipherBase::Final(unsigned char** out, int *out_len) {
 +  if (!initialised_) return false;
  
 -  EVP_CIPHER_CTX ctx; /* coverity[member_decl] */
 -  const EVP_CIPHER *cipher; /* coverity[member_decl] */
 -  bool initialised_;
 -};
 +  *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;
  
 +  return r;
 +}
  
  
 -class Decipher : public ObjectWrap {
 - public:
 -  static void
 -  Initialize (v8::Handle<v8::Object> target)
 -  {
 -    HandleScope scope;
 +Handle<Value> CipherBase::Final(const Arguments& args) {
 +  HandleScope scope(node_isolate);
  
 -    Local<FunctionTemplate> t = FunctionTemplate::New(New);
 +  CipherBase* cipher = ObjectWrap::Unwrap<CipherBase>(args.This());
  
 -    t->InstanceTemplate()->SetInternalFieldCount(1);
 +  unsigned char* out_value = NULL;
 +  int out_len = -1;
 +  Local<Value> outString;
  
 -    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);
 +  bool r = cipher->Final(&out_value, &out_len);
  
 -    target->Set(String::NewSymbol("Decipher"), t->GetFunction());
 +  if (out_len <= 0 || !r) {
 +    delete[] out_value;
 +    out_value = NULL;
 +    out_len = 0;
 +    if (!r) return ThrowCryptoTypeError(ERR_get_error());
    }
  
 -  bool DecipherInit(char* cipherType, char* key_buf, int key_buf_len) {
 -    cipher_ = EVP_get_cipherbyname(cipherType);
 +  Buffer* buf = Buffer::New(reinterpret_cast<char*>(out_value), out_len);
  
 -    if(!cipher_) {
 -      fprintf(stderr, "node-crypto : Unknown cipher %s\n", cipherType);
 -      return false;
 -    }
 +  return scope.Close(buf->handle_);
 +}
  
 -    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;
 -    }
  
 -    *out_len=len+EVP_CIPHER_CTX_block_size(&ctx);
 -    *out= new unsigned char[*out_len];
 +void Hmac::Initialize(v8::Handle<v8::Object> target) {
 +  HandleScope scope(node_isolate);
  
 -    return EVP_CipherUpdate(&ctx, *out, out_len, (unsigned char*)data, len);
 -  }
 +  Local<FunctionTemplate> t = FunctionTemplate::New(New);
  
 -  int SetAutoPadding(bool auto_padding) {
 -    if (!initialised_) return 0;
 -    return EVP_CIPHER_CTX_set_padding(&ctx, auto_padding ? 1 : 0);
 -  }
 +  t->InstanceTemplate()->SetInternalFieldCount(1);
  
 -  // coverity[alloc_arg]
 -  int DecipherFinal(unsigned char** out, int *out_len) {
 -    int r;
 +  NODE_SET_PROTOTYPE_METHOD(t, "init", HmacInit);
 +  NODE_SET_PROTOTYPE_METHOD(t, "update", HmacUpdate);
 +  NODE_SET_PROTOTYPE_METHOD(t, "digest", HmacDigest);
  
 -    if (!initialised_) {
 -      *out_len = 0;
 -      *out = NULL;
 -      return 0;
 -    }
 +  target->Set(String::NewSymbol("Hmac"), t->GetFunction());
 +}
  
 -    *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;
 -  }
  
 +Handle<Value> Hmac::New(const Arguments& args) {
 +  HandleScope scope(node_isolate);
  
 - protected:
 +  Hmac* hmac = new Hmac();
 +  hmac->Wrap(args.This());
 +  return args.This();
 +}
  
 -  static Handle<Value> New (const Arguments& args) {
 -    HandleScope scope;
  
 -    Decipher *cipher = new Decipher();
 -    cipher->Wrap(args.This());
 -    return args.This();
 -  }
 +Handle<Value> Hmac::HmacInit(char* hashType, char* key, int key_len) {
 +  HandleScope scope(node_isolate);
  
 -  static Handle<Value> DecipherInit(const Arguments& args) {
 -    Decipher *cipher = ObjectWrap::Unwrap<Decipher>(args.This());
 +  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;
  
 -    HandleScope scope;
 +  return Null(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")));
 -    }
  
 -    ASSERT_IS_BUFFER(args[1]);
 -    ssize_t key_len = Buffer::Length(args[1]);
 +Handle<Value> Hmac::HmacInit(const Arguments& args) {
 +  HandleScope scope(node_isolate);
  
 -    if (key_len < 0) {
 -      Local<Value> exception = Exception::TypeError(String::New("Bad argument"));
 -      return ThrowException(exception);
 -    }
 +  Hmac* hmac = ObjectWrap::Unwrap<Hmac>(args.This());
  
 -    char* key_buf = new char[key_len];
 -    ssize_t key_written = DecodeWrite(key_buf, key_len, args[1], BINARY);
 -    assert(key_written == key_len);
 +  if (args.Length() < 2 || !args[0]->IsString()) {
 +    return ThrowError("Must give hashtype string, key as arguments");
 +  }
  
 -    String::Utf8Value cipherType(args[0]);
 +  ASSERT_IS_BUFFER(args[1]);
  
 -    bool r = cipher->DecipherInit(*cipherType, key_buf,key_len);
 +  String::Utf8Value hashType(args[0]);
  
 -    delete [] key_buf;
 +  char* buffer_data = Buffer::Data(args[1]);
 +  size_t buffer_length = Buffer::Length(args[1]);
  
 -    if (!r) {
 -      return ThrowException(Exception::Error(String::New("DecipherInit error")));
 -    }
 +  Handle<Value> ret = hmac->HmacInit(*hashType, buffer_data, buffer_length);
  
 +  if (ret->IsNull()) {
      return args.This();
 +  } else {
 +    // Exception
 +    return ret;
    }
 +}
  
 -  static Handle<Value> DecipherInitIv(const Arguments& args) {
 -    Decipher *cipher = ObjectWrap::Unwrap<Decipher>(args.This());
 -
 -    HandleScope scope;
 -
 -    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")));
 -    }
 -
 -    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);
 -    }
  
 -    ASSERT_IS_BUFFER(args[2]);
 -    ssize_t iv_len = Buffer::Length(args[2]);
 +bool Hmac::HmacUpdate(char* data, int len) {
 +  if (!initialised_) return false;
 +  HMAC_Update(&ctx_, reinterpret_cast<unsigned char*>(data), len);
 +  return true;
 +}
  
 -    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);
 +Handle<Value> Hmac::HmacUpdate(const Arguments& args) {
 +  HandleScope scope(node_isolate);
  
 -    char* iv_buf = new char[iv_len];
 -    ssize_t iv_written = DecodeWrite(iv_buf, iv_len, args[2], BINARY);
 -    assert(iv_written == iv_len);
 +  Hmac* hmac = ObjectWrap::Unwrap<Hmac>(args.This());
  
 -    String::Utf8Value cipherType(args[0]);
 +  ASSERT_IS_BUFFER(args[0]);
  
 -    bool r = cipher->DecipherInitIv(*cipherType, key_buf,key_len,iv_buf,iv_len);
 +  bool r;
  
 -    delete [] key_buf;
 -    delete [] iv_buf;
 +  char* buffer_data = Buffer::Data(args[0]);
 +  size_t buffer_length = Buffer::Length(args[0]);
  
 -    if (!r) {
 -      return ThrowException(Exception::Error(String::New("DecipherInitIv error")));
 -    }
 +  r = hmac->HmacUpdate(buffer_data, buffer_length);
  
 -    return args.This();
 +  if (!r) {
 +    return ThrowTypeError("HmacUpdate fail");
    }
  
 -  static Handle<Value> DecipherUpdate(const Arguments& args) {
 -    HandleScope scope;
 -
 -    Decipher *cipher = ObjectWrap::Unwrap<Decipher>(args.This());
 -
 -    ASSERT_IS_BUFFER(args[0]);
 +  return args.This();
 +}
  
 -    ssize_t len;
  
 -    char* buf;
 -    // if alloc_buf then buf must be deleted later
 -    bool alloc_buf = false;
 -    char* buffer_data = Buffer::Data(args[0]);
 -    size_t buffer_length = Buffer::Length(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;
 +}
  
 -    buf = buffer_data;
 -    len = buffer_length;
  
 -    unsigned char* out=0;
 -    int out_len=0;
 -    int r = cipher->DecipherUpdate(buf, len, &out, &out_len);
 +Handle<Value> Hmac::HmacDigest(const Arguments& args) {
 +  HandleScope scope(node_isolate);
  
 -    if (!r) {
 -      delete [] out;
 -      return ThrowCryptoTypeError(ERR_get_error());
 -    }
 +  Hmac* hmac = ObjectWrap::Unwrap<Hmac>(args.This());
  
 -    Local<Value> outString;
 -    outString = Encode(out, out_len, BUFFER);
 +  unsigned char* md_value = NULL;
 +  unsigned int md_len = 0;
 +  Local<Value> outString;
  
 -    if (out) delete [] out;
 +  bool r = hmac->HmacDigest(&md_value, &md_len);
 +  if (!r) {
 +    md_value = NULL;
 +    md_len = 0;
 +  }
  
 -    if (alloc_buf) delete [] buf;
 -    return scope.Close(outString);
 +  Buffer* buf = Buffer::New(reinterpret_cast<char*>(md_value), md_len);
  
 -  }
 +  return scope.Close(buf->handle_);
 +}
  
 -  static Handle<Value> SetAutoPadding(const Arguments& args) {
 -    HandleScope scope;
 -    Decipher *cipher = ObjectWrap::Unwrap<Decipher>(args.This());
  
 -    cipher->SetAutoPadding(args.Length() < 1 || args[0]->BooleanValue());
 +void Hash::Initialize(v8::Handle<v8::Object> target) {
 +  HandleScope scope(node_isolate);
  
 -    return Undefined();
 -  }
 +  Local<FunctionTemplate> t = FunctionTemplate::New(New);
  
 -  static Handle<Value> DecipherFinal(const Arguments& args) {
 -    HandleScope scope;
 +  t->InstanceTemplate()->SetInternalFieldCount(1);
  
 -    Decipher *cipher = ObjectWrap::Unwrap<Decipher>(args.This());
 +  NODE_SET_PROTOTYPE_METHOD(t, "update", HashUpdate);
 +  NODE_SET_PROTOTYPE_METHOD(t, "digest", HashDigest);
  
 -    unsigned char* out_value = NULL;
 -    int out_len = -1;
 -    Local<Value> outString;
 +  target->Set(String::NewSymbol("Hash"), t->GetFunction());
 +}
  
 -    int r = cipher->DecipherFinal(&out_value, &out_len);
  
 -    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());
 -    }
 +Handle<Value> Hash::New(const Arguments& args) {
 +  HandleScope scope(node_isolate);
  
 -    outString = Encode(out_value, out_len, BUFFER);
 -    delete [] out_value;
 -    return scope.Close(outString);
 +  if (args.Length() == 0 || !args[0]->IsString()) {
 +    return ThrowError("Must give hashtype string as argument");
    }
  
 -  Decipher () : ObjectWrap () {
 -    initialised_ = false;
 -  }
 +  String::Utf8Value hashType(args[0]);
  
 -  ~Decipher () {
 -    if (initialised_) {
 -      EVP_CIPHER_CTX_cleanup(&ctx);
 -    }
 +  Hash* hash = new Hash();
 +  if (!hash->HashInit(*hashType)) {
 +    delete hash;
 +    return ThrowError("Digest method not supported");
    }
  
 - private:
 +  hash->Wrap(args.This());
 +  return args.This();
 +}
  
 -  EVP_CIPHER_CTX ctx;
 -  const EVP_CIPHER *cipher_;
 -  bool initialised_;
 -};
  
 +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;
 +}
  
  
 +bool Hash::HashUpdate(char* data, int len) {
 +  if (!initialised_) return false;
 +  EVP_DigestUpdate(&mdctx_, data, len);
 +  return true;
 +}
  
 -class Hmac : public ObjectWrap {
 - public:
 -  static void Initialize (v8::Handle<v8::Object> target) {
 -    HandleScope scope;
  
 -    Local<FunctionTemplate> t = FunctionTemplate::New(New);
 +Handle<Value> Hash::HashUpdate(const Arguments& args) {
 +  HandleScope scope(node_isolate);
  
 -    t->InstanceTemplate()->SetInternalFieldCount(1);
 +  Hash* hash = ObjectWrap::Unwrap<Hash>(args.This());
  
 -    NODE_SET_PROTOTYPE_METHOD(t, "init", HmacInit);
 -    NODE_SET_PROTOTYPE_METHOD(t, "update", HmacUpdate);
 -    NODE_SET_PROTOTYPE_METHOD(t, "digest", HmacDigest);
 +  ASSERT_IS_BUFFER(args[0]);
  
 -    target->Set(String::NewSymbol("Hmac"), t->GetFunction());
 -  }
 +  bool r;
  
 -  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;
 -
 -  }
 +  char* buffer_data = Buffer::Data(args[0]);
 +  size_t buffer_length = Buffer::Length(args[0]);
 +  r = hash->HashUpdate(buffer_data, buffer_length);
  
 -  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());
 +  unsigned char md_value[EVP_MAX_MD_SIZE];
 +  unsigned int md_len;
  
 -    HandleScope scope;
 +  EVP_DigestFinal_ex(&hash->mdctx_, md_value, &md_len);
 +  EVP_MD_CTX_cleanup(&hash->mdctx_);
 +  hash->initialised_ = false;
  
 -    if (args.Length() == 0 || !args[0]->IsString()) {
 -      return ThrowException(Exception::Error(String::New(
 -        "Must give hashtype string as argument")));
 -    }
 -
 -    ASSERT_IS_BUFFER(args[1]);
 -    ssize_t len = Buffer::Length(args[1]);
 +  Buffer* buf = Buffer::New(reinterpret_cast<char*>(md_value), md_len);
  
 -    if (len < 0) {
 -      Local<Value> exception = Exception::TypeError(String::New("Bad argument"));
 -      return ThrowException(exception);
 -    }
 -
 -    String::Utf8Value hashType(args[0]);
 -
 -    bool r;
 +  return scope.Close(buf->handle_);
 +}
  
 -    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;
 -    }
 -
 -    if (!r) {
 -      return ThrowException(Exception::Error(String::New("hmac error")));
 -    }
 +  t->InstanceTemplate()->SetInternalFieldCount(1);
  
 -    return args.This();
 -  }
 +  NODE_SET_PROTOTYPE_METHOD(t, "init", SignInit);
 +  NODE_SET_PROTOTYPE_METHOD(t, "update", SignUpdate);
 +  NODE_SET_PROTOTYPE_METHOD(t, "sign", SignFinal);
  
 -  static Handle<Value> HmacUpdate(const Arguments& args) {
 -    Hmac *hmac = ObjectWrap::Unwrap<Hmac>(args.This());
 +  target->Set(String::NewSymbol("Sign"), t->GetFunction());
 +}
  
 -    HandleScope scope;
  
 -    ASSERT_IS_BUFFER(args[0]);
 +Handle<Value> Sign::New(const Arguments& args) {
 +  HandleScope scope(node_isolate);
  
 -    int r;
 +  Sign* sign = new Sign();
 +  sign->Wrap(args.This());
  
 -    char* buffer_data = Buffer::Data(args[0]);
 -    size_t buffer_length = Buffer::Length(args[0]);
 +  return args.This();
 +}
  
 -    r = hmac->HmacUpdate(buffer_data, buffer_length);
  
 -    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;
 -
 -    unsigned char* md_value = NULL;
 -    unsigned int md_len = 0;
 -    Local<Value> outString;
  
 -    int r = hmac->HmacDigest(&md_value, &md_len);
 -    if (r == 0) {
 -      md_value = NULL;
 -      md_len = 0;
 -    }
 +Handle<Value> Sign::SignInit(const Arguments& args) {
 +  HandleScope scope(node_isolate);
  
 -    outString = Encode(md_value, md_len, BUFFER);
 +  Sign* sign = ObjectWrap::Unwrap<Sign>(args.This());
  
 -    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);
 +
 +  if (ret->IsNull()) {
 +    return args.This();
 +  } else {
 +    // Exception
 +    return scope.Close(ret);
    }
 +}
  
 - private:
  
 -  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;
 +Handle<Value> Sign::SignUpdate(const Arguments& args) {
 +  HandleScope scope(node_isolate);
  
 -    Local<FunctionTemplate> t = FunctionTemplate::New(New);
 +  Sign* sign = ObjectWrap::Unwrap<Sign>(args.This());
  
 -    t->InstanceTemplate()->SetInternalFieldCount(1);
 +  ASSERT_IS_BUFFER(args[0]);
  
 -    NODE_SET_PROTOTYPE_METHOD(t, "update", HashUpdate);
 -    NODE_SET_PROTOTYPE_METHOD(t, "digest", HashDigest);
 +  bool r;
  
 -    target->Set(String::NewSymbol("Hash"), t->GetFunction());
 -  }
 +  char* buffer_data = Buffer::Data(args[0]);
 +  size_t buffer_length = Buffer::Length(args[0]);
  
 -  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;
 -  }
 +  r = sign->SignUpdate(buffer_data, buffer_length);
  
 -  int HashUpdate(char* data, int len) {
 -    if (!initialised_) return 0;
 -    EVP_DigestUpdate(&mdctx, data, len);
 -    return 1;
 +  if (!r) {
 +    return ThrowTypeError("SignUpdate fail");
    }
  
 +  return args.This();
 +}
  
 - protected:
 -
 -  static Handle<Value> New (const Arguments& args) {
 -    HandleScope scope;
  
 -    if (args.Length() == 0 || !args[0]->IsString()) {
 -      return ThrowException(Exception::Error(String::New(
 -        "Must give hashtype string as argument")));
 -    }
 +bool Sign::SignFinal(unsigned char** md_value,
 +                     unsigned int *md_len,
 +                     char* key_pem,
 +                     int key_pem_len) {
 +  if (!initialised_) return false;
  
 -    String::Utf8Value hashType(args[0]);
 +  BIO* bp = NULL;
 +  EVP_PKEY* pkey = NULL;
 +  bp = BIO_new(BIO_s_mem());
 +  if (!BIO_write(bp, key_pem, key_pem_len)) return false;
  
 -    Hash *hash = new Hash();
 -    if (!hash->HashInit(*hashType)) {
 -      delete hash;
 -      return ThrowException(Exception::Error(String::New(
 -        "Digest method not supported")));
 -    }
 +  pkey = PEM_read_bio_PrivateKey(bp, NULL, NULL, NULL);
 +  if (pkey == NULL) return 0;
  
 -    hash->Wrap(args.This());
 -    return args.This();
 -  }
 +  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;
 +}
  
 -  static Handle<Value> HashUpdate(const Arguments& args) {
 -    HandleScope scope;
  
 -    Hash *hash = ObjectWrap::Unwrap<Hash>(args.This());
 +Handle<Value> Sign::SignFinal(const Arguments& args) {
 +  HandleScope scope(node_isolate);
  
 -    ASSERT_IS_BUFFER(args[0]);
 +  Sign* sign = ObjectWrap::Unwrap<Sign>(args.This());
  
 -    int r;
 +  unsigned char* md_value;
 +  unsigned int md_len;
 +  Local<Value> outString;
  
-   md_len = 8192; // Maximum key size is 8192 bits
-   md_value = new unsigned char[md_len];
 -    char* buffer_data = Buffer::Data(args[0]);
 -    size_t buffer_length = Buffer::Length(args[0]);
 -    r = hash->HashUpdate(buffer_data, buffer_length);
 +  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;
 -
 -    Hash *hash = ObjectWrap::Unwrap<Hash>(args.This());
 +  Buffer* ret = Buffer::New(reinterpret_cast<char*>(md_value), md_len);
 +  delete[] md_value;
  
 -    if (!hash->initialised_) {
 -      return ThrowException(Exception::Error(String::New("Not initialized")));
 -    }
 +  return scope.Close(ret->handle_);
 +}
  
 -    unsigned char md_value[EVP_MAX_MD_SIZE];
 -    unsigned int md_len;
  
 -    EVP_DigestFinal_ex(&hash->mdctx, md_value, &md_len);
 -    EVP_MD_CTX_cleanup(&hash->mdctx);
 -    hash->initialised_ = false;
 +void Verify::Initialize(v8::Handle<v8::Object> target) {
 +  HandleScope scope(node_isolate);
  
 -    Local<Value> outString;
 +  Local<FunctionTemplate> t = FunctionTemplate::New(New);
  
 -    outString = Encode(md_value, md_len, BUFFER);
 +  t->InstanceTemplate()->SetInternalFieldCount(1);
  
 -    return scope.Close(outString);
 -  }
 +  NODE_SET_PROTOTYPE_METHOD(t, "init", VerifyInit);
 +  NODE_SET_PROTOTYPE_METHOD(t, "update", VerifyUpdate);
 +  NODE_SET_PROTOTYPE_METHOD(t, "verify", VerifyFinal);
  
 -  Hash () : ObjectWrap () {
 -    initialised_ = false;
 -  }
 -
 -  ~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());
 -
 -    if (args.Length() == 0 || !args[0]->IsString()) {
 -      return ThrowException(Exception::Error(String::New(
 -        "Must give signtype string as argument")));
 -    }
 -
 -    String::Utf8Value signType(args[0]);
 -
 -    bool r = sign->SignInit(*signType);
 -
 -    if (!r) {
 -      return ThrowException(Exception::Error(String::New("SignInit error")));
 -    }
  
 -    return args.This();
 -  }
 +bool Verify::VerifyUpdate(char* data, int len) {
 +  if (!initialised_) return false;
 +  EVP_VerifyUpdate(&mdctx_, data, len);
 +  return true;
 +}
  
 -  static Handle<Value> SignUpdate(const Arguments& args) {
 -    Sign *sign = ObjectWrap::Unwrap<Sign>(args.This());
  
 -    HandleScope scope;
 +Handle<Value> Verify::VerifyUpdate(const Arguments& args) {
 +  HandleScope scope(node_isolate);
  
 -    ASSERT_IS_BUFFER(args[0]);
 +  Verify* verify = ObjectWrap::Unwrap<Verify>(args.This());
  
 -    int r;
 +  ASSERT_IS_BUFFER(args[0]);
  
 -    char* buffer_data = Buffer::Data(args[0]);
 -    size_t buffer_length = Buffer::Length(args[0]);
 +  bool r;
  
 -    r = sign->SignUpdate(buffer_data, buffer_length);
 +  char* buffer_data = Buffer::Data(args[0]);
 +  size_t buffer_length = Buffer::Length(args[0]);
  
 -    if (!r) {
 -      Local<Value> exception = Exception::TypeError(String::New("SignUpdate fail"));
 -      return ThrowException(exception);
 -    }
 +  r = verify->VerifyUpdate(buffer_data, buffer_length);
  
 -    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;
 -
 -    ASSERT_IS_BUFFER(args[0]);
 -    ssize_t len = Buffer::Length(args[0]);
 -
 -    char* buf = new char[len];
 -    ssize_t written = DecodeWrite(buf, len, args[0], BUFFER);
 -    assert(written == len);
 -
 -    md_len = 8192; // Maximum key size is 8192 bits
 -    md_value = new unsigned char[md_len];
 -
 -    int r = sign->SignFinal(&md_value, &md_len, buf, len);
 -    if (r == 0) {
 -      md_value = NULL;
 -      md_len = r;
 -    }
 +  return args.This();
 +}
  
 -    delete [] buf;
  
 -    outString = Encode(md_value, md_len, BUFFER);
 +Handle<Value> Verify::VerifyFinal(char* key_pem,
 +                                  int key_pem_len,
 +                                  unsigned char* sig,
 +                                  int siglen) {
 +  HandleScope scope(node_isolate);
  
 -    delete [] md_value;
 -    return scope.Close(outString);
 +  if (!initialised_) {
 +    return ThrowError("Verify not initalised");
    }
  
 -  Sign () : ObjectWrap () {
 -    initialised_ = false;
 -  }
 +  EVP_PKEY* pkey = NULL;
 +  BIO* bp = NULL;
 +  X509* x509 = NULL;
 +  bool fatal = true;
 +  int r;
  
 -  ~Sign () {
 -    if (initialised_) {
 -      EVP_MD_CTX_cleanup(&mdctx);
 +  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);
      }
 -  }
 -
 - private:
 -
 -  EVP_MD_CTX mdctx; /* coverity[member_decl] */
 -  const EVP_MD *md; /* coverity[member_decl] */
 -  bool initialised_;
 -};
 -
 -class Verify : public ObjectWrap {
 - public:
 -  static void Initialize (v8::Handle<v8::Object> target) {
 -    HandleScope scope;
 -
 -    Local<FunctionTemplate> t = FunctionTemplate::New(New);
 -
 -    t->InstanceTemplate()->SetInternalFieldCount(1);
 -
 -    NODE_SET_PROTOTYPE_METHOD(t, "init", VerifyInit);
 -    NODE_SET_PROTOTYPE_METHOD(t, "update", VerifyUpdate);
 -    NODE_SET_PROTOTYPE_METHOD(t, "verify", VerifyFinal);
 +    if (pkey == NULL)
 +      goto exit;
 +  } else {
 +    // X.509 fallback
 +    x509 = PEM_read_bio_X509(bp, NULL, NULL, NULL);
 +    if (x509 == NULL)
 +      goto exit;
  
 -    target->Set(String::NewSymbol("Verify"), t->GetFunction());
 +    pkey = X509_get_pubkey(x509);
 +    if (pkey == NULL)
 +      goto exit;
    }
  
 +  fatal = false;
 +  r = EVP_VerifyFinal(&mdctx_, sig, siglen, pkey);
  
 -  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;
 -  }
 +exit:
 +  if (pkey != NULL)
 +    EVP_PKEY_free(pkey);
 +  if (bp != NULL)
 +    BIO_free_all(bp);
 +  if (x509 != NULL)
 +    X509_free(x509);
  
 +  EVP_MD_CTX_cleanup(&mdctx_);
 +  initialised_ = false;
  
 -  int VerifyUpdate(char* data, int len) {
 -    if (!initialised_) return 0;
 -    EVP_VerifyUpdate(&mdctx, data, len);
 -    return 1;
 +  if (fatal) {
 +    unsigned long err = ERR_get_error();
 +    return ThrowCryptoError(err);
    }
  
 +  return scope.Close(r ? True() : False(node_isolate));
 +}
  
 -  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;
 +Handle<Value> Verify::VerifyFinal(const Arguments& args) {
 +  HandleScope scope(node_isolate);
  
 -    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;
 -    }
 +  Verify* verify = ObjectWrap::Unwrap<Verify>(args.This());
  
 -    // 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;
 -      }
 -
 -      pkey = X509_get_pubkey(x509);
 -      if (pkey == NULL) {
 -        ERR_print_errors_fp(stderr);
 -        return 0;
 -      }
 -    }
 -
 -    r = EVP_VerifyFinal(&mdctx, sig, siglen, pkey);
 +  ASSERT_IS_BUFFER(args[0]);
 +  char* kbuf = Buffer::Data(args[0]);
 +  ssize_t klen = Buffer::Length(args[0]);
  
 -    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;
 +  ASSERT_IS_BUFFER(args[1]);
 +  unsigned char* hbuf = reinterpret_cast<unsigned char*>(Buffer::Data(args[1]));
 +  ssize_t hlen = Buffer::Length(args[1]);
  
 -    return r;
 -  }
 +  return scope.Close(verify->VerifyFinal(kbuf, klen, hbuf, hlen));
 +}
  
  
 - protected:
 +void DiffieHellman::Initialize(v8::Handle<v8::Object> target) {
 +  HandleScope scope(node_isolate);
  
 -  static Handle<Value> New (const Arguments& args) {
 -    HandleScope scope;
 +  Local<FunctionTemplate> t = FunctionTemplate::New(New);
  
 -    Verify *verify = new Verify();
 -    verify->Wrap(args.This());
 +  t->InstanceTemplate()->SetInternalFieldCount(1);
  
 -    return args.This();
 -  }
 +  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);
  
 +  target->Set(String::NewSymbol("DiffieHellman"), t->GetFunction());
  
 -  static Handle<Value> VerifyInit(const Arguments& args) {
 -    Verify *verify = ObjectWrap::Unwrap<Verify>(args.This());
 +  Local<FunctionTemplate> t2 = FunctionTemplate::New(DiffieHellmanGroup);
 +  t2->InstanceTemplate()->SetInternalFieldCount(1);
  
 -    HandleScope scope;
 +  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);
  
 -    if (args.Length() == 0 || !args[0]->IsString()) {
 -      return ThrowException(Exception::Error(String::New(
 -        "Must give verifytype string as argument")));
 -    }
 +  target->Set(String::NewSymbol("DiffieHellmanGroup"), t2->GetFunction());
 +}
  
 -    String::Utf8Value verifyType(args[0]);
  
 -    bool r = verify->VerifyInit(*verifyType);
 +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;
 +}
  
 -    if (!r) {
 -      return ThrowException(Exception::Error(String::New("VerifyInit error")));
 -    }
  
 -    return 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;
 +}
  
  
 -  static Handle<Value> VerifyUpdate(const Arguments& args) {
 -    HandleScope scope;
 +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;
 +}
  
 -    Verify *verify = ObjectWrap::Unwrap<Verify>(args.This());
  
 -    ASSERT_IS_BUFFER(args[0]);
 +Handle<Value> DiffieHellman::DiffieHellmanGroup(const Arguments& args) {
 +  HandleScope scope(node_isolate);
  
 -    int r;
 +  DiffieHellman* diffieHellman = new DiffieHellman();
  
 -    char* buffer_data = Buffer::Data(args[0]);
 -    size_t buffer_length = Buffer::Length(args[0]);
 +  if (args.Length() != 1 || !args[0]->IsString()) {
 +    return ThrowError("No group name given");
 +  }
  
 -    r = verify->VerifyUpdate(buffer_data, buffer_length);
 +  String::Utf8Value group_name(args[0]);
  
 -    if (!r) {
 -      Local<Value> exception = Exception::TypeError(String::New("VerifyUpdate fail"));
 -      return ThrowException(exception);
 -    }
 +  modp_group* it = modp_groups;
  
 -    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_BUFFER(args[1]);
 -    ssize_t hlen = Buffer::Length(args[1]);
 +  DiffieHellman* diffieHellman = new DiffieHellman();
 +  bool initialized = false;
  
 -    if (hlen < 0) {
 -      delete [] kbuf;
 -      Local<Value> exception = Exception::TypeError(String::New("Bad argument"));
 -      return ThrowException(exception);
 +  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]));
      }
 -
 -    unsigned char* hbuf = new unsigned char[hlen];
 -    ssize_t hwritten = DecodeWrite((char*)hbuf, hlen, args[1], BINARY);
 -    assert(hwritten == hlen);
 -
 -    int r;
 -
 -    r = verify->VerifyFinal(kbuf, klen, hbuf, hlen);
 -
 -    delete [] kbuf;
 -    delete [] hbuf;
 -
 -    return Boolean::New(r && r != -1);
    }
  
 -  Verify () : ObjectWrap () {
 -    initialised_ = false;
 +  if (!initialized) {
 +    return ThrowError("Initialization failed");
    }
  
 -  ~Verify () {
 -    if (initialised_) {
 -      EVP_MD_CTX_cleanup(&mdctx);
 -    }
 -  }
 +  diffieHellman->Wrap(args.This());
  
 - private:
 +  return args.This();
 +}
  
 -  EVP_MD_CTX mdctx; /* coverity[member_decl] */
 -  const EVP_MD *md; /* coverity[member_decl] */
 -  bool initialised_;
  
 -};
 +Handle<Value> DiffieHellman::GenerateKeys(const Arguments& args) {
 +  HandleScope scope(node_isolate);
  
 -class DiffieHellman : public ObjectWrap {
 - public:
 -  static void Initialize(v8::Handle<v8::Object> target) {
 -    HandleScope scope;
 +  DiffieHellman* diffieHellman =
 +      ObjectWrap::Unwrap<DiffieHellman>(args.This());
  
 -    Local<FunctionTemplate> t = FunctionTemplate::New(New);
 +  if (!diffieHellman->initialised_) {
 +    return ThrowError("Not initialized");
 +  }
  
 -    t->InstanceTemplate()->SetInternalFieldCount(1);
 +  if (!DH_generate_key(diffieHellman->dh)) {
 +    return ThrowError("Key generation failed");
 +  }
  
 -    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);
 +  Local<Value> outString;
  
 -    target->Set(String::NewSymbol("DiffieHellman"), t->GetFunction());
 +  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));
  
 -    Local<FunctionTemplate> t2 = FunctionTemplate::New(DiffieHellmanGroup);
 -    t2->InstanceTemplate()->SetInternalFieldCount(1);
 +  outString = Encode(data, dataSize, BUFFER);
 +  delete[] data;
  
 -    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);
 +  return scope.Close(outString);
 +}
  
 -    target->Set(String::NewSymbol("DiffieHellmanGroup"), t2->GetFunction());
 -  }
  
 -  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;
 -  }
 +Handle<Value> DiffieHellman::GetPrime(const Arguments& args) {
 +  HandleScope scope(node_isolate);
  
 -  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;
 -  }
 +  DiffieHellman* diffieHellman =
 +      ObjectWrap::Unwrap<DiffieHellman>(args.This());
  
 -  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;
 +  if (!diffieHellman->initialised_) {
 +    return ThrowError("Not initialized");
    }
  
 - protected:
 -  static Handle<Value> DiffieHellmanGroup(const Arguments& args) {
 -    HandleScope scope;
 +  int dataSize = BN_num_bytes(diffieHellman->dh->p);
 +  char* data = new char[dataSize];
 +  BN_bn2bin(diffieHellman->dh->p, reinterpret_cast<unsigned char*>(data));
  
 -    DiffieHellman* diffieHellman = new DiffieHellman();
 +  Local<Value> outString;
  
 -    if (args.Length() != 1 || !args[0]->IsString()) {
 -      return ThrowException(Exception::Error(
 -          String::New("No group name given")));
 -    }
 +  outString = Encode(data, dataSize, BUFFER);
  
 -    String::Utf8Value group_name(args[0]);
 +  delete[] data;
  
 -    modp_group* it = modp_groups;
 +  return scope.Close(outString);
 +}
  
 -    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 ThrowException(Exception::Error(
 -          String::New("Unknown group")));
 -    }
 +Handle<Value> DiffieHellman::GetGenerator(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> New(const Arguments& args) {
 -    HandleScope scope;
 -
 -    DiffieHellman* diffieHellman = new DiffieHellman();
 -    bool initialized = false;
 -
 -    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")));
 -    }
 +  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());
 -
 -    return args.This();
 -  }
 +  Local<Value> outString;
  
 -  static Handle<Value> GenerateKeys(const Arguments& args) {
 -    DiffieHellman* diffieHellman =
 -      ObjectWrap::Unwrap<DiffieHellman>(args.This());
 +  outString = Encode(data, dataSize, BUFFER);
  
 -    HandleScope scope;
 +  delete[] data;
  
 -    if (!diffieHellman->initialised_) {
 -      return ThrowException(Exception::Error(
 -            String::New("Not initialized")));
 -    }
 +  return scope.Close(outString);
 +}
  
 -    if (!DH_generate_key(diffieHellman->dh)) {
 -      return ThrowException(Exception::Error(
 -            String::New("Key generation failed")));
 -    }
  
 -    Local<Value> outString;
 +Handle<Value> DiffieHellman::GetPublicKey(const Arguments& args) {
 +  HandleScope scope(node_isolate);
  
 -    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));
 +  DiffieHellman* diffieHellman =
 +      ObjectWrap::Unwrap<DiffieHellman>(args.This());
  
 -    outString = Encode(data, dataSize, BUFFER);
 -    delete[] data;
 +  if (!diffieHellman->initialised_) {
 +    return ThrowError("Not initialized");
 +  }
  
 -    return scope.Close(outString);
 +  if (diffieHellman->dh->pub_key == NULL) {
 +    return ThrowError("No public key - did you forget to generate one?");
    }
  
 -  static Handle<Value> GetPrime(const Arguments& args) {
 -    DiffieHellman* diffieHellman =
 -      ObjectWrap::Unwrap<DiffieHellman>(args.This());
 +  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));
  
 -    HandleScope scope;
 +  Local<Value> outString;
  
 -    if (!diffieHellman->initialised_) {
 -      return ThrowException(Exception::Error(String::New("Not initialized")));
 -    }
 +  outString = Encode(data, dataSize, BUFFER);
 +
 +  delete[] data;
  
 -    int dataSize = BN_num_bytes(diffieHellman->dh->p);
 -    char* data = new char[dataSize];
 -    BN_bn2bin(diffieHellman->dh->p, reinterpret_cast<unsigned char*>(data));
 +  return scope.Close(outString);
 +}
  
 -    Local<Value> outString;
  
 -    outString = Encode(data, dataSize, BUFFER);
 +Handle<Value> DiffieHellman::GetPrivateKey(const Arguments& args) {
 +  HandleScope scope(node_isolate);
  
 -    delete[] data;
 +  DiffieHellman* diffieHellman =
 +      ObjectWrap::Unwrap<DiffieHellman>(args.This());
  
 -    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")));
 -    }
 +  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")));
 -    }
 -
 -    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 {
diff --cc src/node_os.cc
@@@ -87,8 -87,7 +87,7 @@@ static Handle<Value> GetOSType(const Ar
  }
  
  static Handle<Value> GetOSRelease(const Arguments& args) {
 -  HandleScope scope;
 +  HandleScope scope(node_isolate);
-   char release[256];
  
  #ifdef __POSIX__
    struct utsname info;