  static NAN_METHOD(Decrypt) {
    MarkPopErrorOnReturn mark_pop_error_on_return;

    AESGCMDecipher* obj = ObjectWrap::Unwrap<AESGCMDecipher>(info.Holder());

    if (!Buffer::HasInstance(info[0]))
      return Nan::ThrowTypeError("Missing/Invalid packet");

    if (!info[1]->IsUint32())
      return Nan::ThrowTypeError("Missing/Invalid length");

    if (!Buffer::HasInstance(info[2]) || Buffer::Length(info[2]) != 16)
      return Nan::ThrowTypeError("Missing/Invalid tag");

    uint32_t length = Nan::To<uint32_t>(info[1]).FromJust();
    unsigned char length_bytes[4];
    length_bytes[0] = (length >> 24) & 0xFF;
    length_bytes[1] = (length >> 16) & 0xFF;
    length_bytes[2] = (length >> 8) & 0xFF;
    length_bytes[3] = length & 0xFF;

    ErrorType r = obj->decrypt(
      reinterpret_cast<unsigned char*>(Buffer::Data(info[0])),
      Buffer::Length(info[0]),
      length_bytes,
      reinterpret_cast<unsigned char*>(Buffer::Data(info[2]))
    );
    switch (r) {
      case kErrNone:
        return;
      case kErrAADFailure:
        return Nan::ThrowError("Error setting AAD");
      case kErrPartialDecrypt:
        return Nan::ThrowError("Failed to completely decrypt packet");
      case kErrTagFailure:
        return Nan::ThrowError("Error generating authentication tag");
      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 decrypt failure");
    }
  }
  static NAN_METHOD(Decrypt) {
    MarkPopErrorOnReturn mark_pop_error_on_return;

    AESGCMDecipher* obj = ObjectWrap::Unwrap<AESGCMDecipher>(info.Holder());

    if (!Buffer::HasInstance(info[0]))
      return Nan::ThrowTypeError("Missing/Invalid packet");

    if (!info[1]->IsUint32())
      return Nan::ThrowTypeError("Missing/Invalid length");

    if (!Buffer::HasInstance(info[2]) || Buffer::Length(info[2]) != 16)
      return Nan::ThrowTypeError("Missing/Invalid tag");

    uint32_t length = Nan::To<uint32_t>(info[1]).FromJust();
    unsigned char length_bytes[4];
    length_bytes[0] = (length >> 24) & 0xFF;
    length_bytes[1] = (length >> 16) & 0xFF;
    length_bytes[2] = (length >> 8) & 0xFF;
    length_bytes[3] = length & 0xFF;

    ErrorType r = obj->decrypt(
      reinterpret_cast<unsigned char*>(Buffer::Data(info[0])),
      Buffer::Length(info[0]),
      length_bytes,
      reinterpret_cast<unsigned char*>(Buffer::Data(info[2]))
    );
    switch (r) {
      case kErrNone:
        return;
      case kErrAADFailure:
        return Nan::ThrowError("Error setting AAD");
      case kErrPartialDecrypt:
        return Nan::ThrowError("Failed to completely decrypt packet");
      case kErrTagFailure:
        return Nan::ThrowError("Error generating authentication tag");
      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 decrypt failure");
    }
  }