  static NAN_METHOD(New) {
    MarkPopErrorOnReturn mark_pop_error_on_return;

    if (!info[0]->IsString())
      return Nan::ThrowTypeError("Missing/Invalid cipher name");

    if (!Buffer::HasInstance(info[1]))
      return Nan::ThrowTypeError("Missing/Invalid cipher key");

    if (!Buffer::HasInstance(info[2]))
      return Nan::ThrowTypeError("Missing/Invalid cipher IV");

    if (!info[3]->IsString())
      return Nan::ThrowTypeError("Missing/Invalid HMAC name");

    if (!Buffer::HasInstance(info[4]))
      return Nan::ThrowTypeError("Missing/Invalid HMAC key");

    if (!info[5]->IsBoolean())
      return Nan::ThrowTypeError("Missing/Invalid HMAC ETM flag");

    const Nan::Utf8String cipher_name(info[0]);
    const Nan::Utf8String mac_name(info[3]);
    int is_etm = (Nan::To<bool>(info[5]).FromJust() ? 1 : 0);

    GenericCipher* obj = new GenericCipher();
    ErrorType r = obj->init(
      *cipher_name,
      reinterpret_cast<unsigned char*>(Buffer::Data(info[1])),
      Buffer::Length(info[1]),
      reinterpret_cast<unsigned char*>(Buffer::Data(info[2])),
      Buffer::Length(info[2]),
      *mac_name,
      reinterpret_cast<unsigned char*>(Buffer::Data(info[4])),
      Buffer::Length(info[4]),
      is_etm
    );
    if (r != kErrNone) {
      delete obj;
      switch (r) {
        case kErrBadKeyLen:
          return Nan::ThrowError("Invalid keys length");
        case kErrBadIVLen:
          return Nan::ThrowError("Invalid IV length");
        case kErrBadCipherName:
          return Nan::ThrowError("Invalid cipher name");
        case kErrBadHMACName:
          return Nan::ThrowError("Invalid MAC name");
        case kErrBadInit:
          return Nan::ThrowError("Failed to properly initialize cipher");
        case kErrOpenSSL: {
          char msg_buf[128] = {0};
          ERR_error_string_n(ERR_get_error(), msg_buf, sizeof(msg_buf));
          return Nan::ThrowError(msg_buf);
        }
        default:
          return Nan::ThrowError("Unknown init failure");
      }
    }

    obj->Wrap(info.This());
    info.GetReturnValue().Set(info.This());
  }
  static NAN_METHOD(New) {
    MarkPopErrorOnReturn mark_pop_error_on_return;

    if (!info[0]->IsString())
      return Nan::ThrowTypeError("Missing/Invalid cipher name");

    if (!Buffer::HasInstance(info[1]))
      return Nan::ThrowTypeError("Missing/Invalid cipher key");

    if (!Buffer::HasInstance(info[2]))
      return Nan::ThrowTypeError("Missing/Invalid cipher IV");

    if (!info[3]->IsString())
      return Nan::ThrowTypeError("Missing/Invalid HMAC name");

    if (!Buffer::HasInstance(info[4]))
      return Nan::ThrowTypeError("Missing/Invalid HMAC key");

    if (!info[5]->IsBoolean())
      return Nan::ThrowTypeError("Missing/Invalid HMAC ETM flag");

    const Nan::Utf8String cipher_name(info[0]);
    const Nan::Utf8String mac_name(info[3]);
    int is_etm = (Nan::To<bool>(info[5]).FromJust() ? 1 : 0);

    GenericCipher* obj = new GenericCipher();
    ErrorType r = obj->init(
      *cipher_name,
      reinterpret_cast<unsigned char*>(Buffer::Data(info[1])),
      Buffer::Length(info[1]),
      reinterpret_cast<unsigned char*>(Buffer::Data(info[2])),
      Buffer::Length(info[2]),
      *mac_name,
      reinterpret_cast<unsigned char*>(Buffer::Data(info[4])),
      Buffer::Length(info[4]),
      is_etm
    );
    if (r != kErrNone) {
      delete obj;
      switch (r) {
        case kErrBadKeyLen:
          return Nan::ThrowError("Invalid keys length");
        case kErrBadIVLen:
          return Nan::ThrowError("Invalid IV length");
        case kErrBadCipherName:
          return Nan::ThrowError("Invalid cipher name");
        case kErrBadHMACName:
          return Nan::ThrowError("Invalid MAC name");
        case kErrBadInit:
          return Nan::ThrowError("Failed to properly initialize cipher");
        case kErrOpenSSL: {
          char msg_buf[128] = {0};
          ERR_error_string_n(ERR_get_error(), msg_buf, sizeof(msg_buf));
          return Nan::ThrowError(msg_buf);
        }
        default:
          return Nan::ThrowError("Unknown init failure");
      }
    }

    obj->Wrap(info.This());
    info.GetReturnValue().Set(info.This());
  }