David Gatti David Gatti - 3 months ago 40
Node.js Question

C++ invalid conversion from ‘char*’ to ‘const unsigned char*’

I'm writing my project in NodeJS, but I'm forced to use a C shared library. Because of this I have to use Node.js Addons. Calling the C++ code works perfectly, I was also able to load the custom library, and call two C functions successfully: one gives me the version number of the library, the other method generated a key based on the data provided form JS.

The problem that I'm having is related to the generated Key. I have to use in the

encrypt
and
decrypt
methods.



This is the variable that I'm using to store the key:

unsigned char generated_key[256];


This is the function that generates the key:

extern "C"
{
#ifdef WIN32
VE_EXPORT int CALLBACK generate_key
#else
int generate_key
#endif
(char *variable_msg, /*!< variable seed */
char *shared_seed, /*!< shared seed */
unsigned char *generated_key, /*!< generated key */
unsigned int key_size); /*!< key size */
}


This is a function that uses the key:

extern "C"
{
#ifdef WIN32
VE_EXPORT int CALLBACK encrypt
#else
int encrypt
#endif
(const unsigned char * const plain_data, /*!< plain data */
const unsigned int plain_data_len, /*!< number bytes to be encrypted */
unsigned char *encrypted_data, /*!< encrypted data */
const unsigned int encrypted_data_size, /*!< size encrypted_data array */
unsigned int *encrypted_data_len, /*!< number of bytes encrypted */
const unsigned char * const key /*!< symmetric encryption key */
);
}


When I try to compile the code I get:

gyp info it worked if it ends with ok
gyp info using node-gyp@3.4.0
gyp info using node@6.2.0 | linux | x64
gyp info spawn /usr/bin/python2
gyp info spawn args [ '/usr/local/lib/node_modules/node-gyp/gyp/gyp_main.py',
gyp info spawn args 'binding.gyp',
gyp info spawn args '-f',
gyp info spawn args 'make',
gyp info spawn args '-I',
gyp info spawn args '/home/dgatti/sequr/sequr-experiments/CPP/Sequr/build/config.gypi',
gyp info spawn args '-I',
gyp info spawn args '/usr/local/lib/node_modules/node-gyp/addon.gypi',
gyp info spawn args '-I',
gyp info spawn args '/home/dgatti/.node-gyp/6.2.0/include/node/common.gypi',
gyp info spawn args '-Dlibrary=shared_library',
gyp info spawn args '-Dvisibility=default',
gyp info spawn args '-Dnode_root_dir=/home/dgatti/.node-gyp/6.2.0',
gyp info spawn args '-Dnode_gyp_dir=/usr/local/lib/node_modules/node-gyp',
gyp info spawn args '-Dnode_lib_file=node.lib',
gyp info spawn args '-Dmodule_root_dir=/home/dgatti/sequr/sequr-experiments/CPP/Sequr',
gyp info spawn args '--depth=.',
gyp info spawn args '--no-parallel',
gyp info spawn args '--generator-output',
gyp info spawn args 'build',
gyp info spawn args '-Goutput_dir=.' ]
make: Entering directory `/home/dgatti/sequr/sequr-experiments/CPP/Sequr/build'
gyp info spawn make
gyp info spawn args [ 'BUILDTYPE=Release', '-C', 'build' ]
CXX(target) Release/obj.target/vertx/main.o
../main.cpp: In function ‘void demo::VertxEncrypt(const v8::FunctionCallbackInfo<v8::Value>&)’:
../main.cpp:127:102: error: invalid conversion from ‘char*’ to ‘const unsigned char*’ [-fpermissive]
vertx_encrypt(cPayload, sizeof(cPayload), encMessage, sizeof(encMessage), &encLength, generated_key);
^
In file included from ../main.cpp:3:0:
../libvertx_encryption.h:79:7: error: initializing argument 1 of ‘int vertx_encrypt(const unsigned char*, unsigned int, unsigned char*, unsigned int, unsigned int*, const unsigned char*)’ [-fpermissive]
int vertx_encrypt
^
make: *** [Release/obj.target/vertx/main.o] Error 1
make: Leaving directory `/home/dgatti/sequr/sequr-experiments/CPP/Sequr/build'
gyp ERR! build error
gyp ERR! stack Error: `make` failed with exit code: 2
gyp ERR! stack at ChildProcess.onExit (/usr/local/lib/node_modules/node-gyp/lib/build.js:276:23)
gyp ERR! stack at emitTwo (events.js:106:13)
gyp ERR! stack at ChildProcess.emit (events.js:191:7)
gyp ERR! stack at Process.ChildProcess._handle.onexit (internal/child_process.js:204:12)
gyp ERR! System Linux 3.10.0-327.13.1.el7.x86_64
gyp ERR! command "/usr/local/bin/node" "/usr/local/bin/node-gyp" "rebuild"
gyp ERR! cwd /home/dgatti/sequr/sequr-experiments/CPP/Sequr
gyp ERR! node -v v6.2.0
gyp ERR! node-gyp -v v3.4.0
gyp ERR! not ok


This is how I call the function, right now I'm just passing the variable as is, but I tried many different way of converting, casting and changing.

encrypt(cPayload, sizeof(cPayload), encMessage, sizeof(encMessage), &encLength, generated_key);


I wrote an example in C and everything works fine, but when I try to use this C functions in C++, things brakes. I have experience in C but defiantly not in C++. I looked for days to find a solution but uncle Google and buddy Stack weren't able to com up with a solution.

What I'm looking for




  • a keyword that could help me in my search for an answer,

  • or the solution to my problem.



Tech spec




  • gcc version 4.8.5 20150623 (Red Hat 4.8.5-4) (GCC)



Complete code



This is the complete code in C++ that I'm calling from NodeJS to access C functions:

#include <node.h>
#include <iostream>
#include "lib_encryption.h"

using namespace std;

namespace demo {

using v8::Exception;
using v8::FunctionCallbackInfo;
using v8::Isolate;
using v8::Local;
using v8::Number;
using v8::Object;
using v8::String;
using v8::Value;

unsigned char generated_key[256];
unsigned int key_size = 32;
unsigned int encLength;
unsigned char encMessage[256] = {0};

//
// This is the implementation of the "add" method
// Input arguments are passed using the
// const FunctionCallbackInfo<Value>& args struct
//
void GenerateKey(const FunctionCallbackInfo<Value>& args)
{
v8::String::Utf8Value param1(args[0]->ToString());
std::string strMessage = std::string(*param1);

v8::String::Utf8Value param2(args[1]->ToString());
std::string strSecret = std::string(*param2);

char cMessage[4];
strcpy(cMessage, strMessage.c_str());

char cSecret[11];
strcpy(cSecret, strSecret.c_str());

//
// Creating the key
//
_generate_key(cMessage, cSecret, generated_key, key_size);

//
// 1. Create isolation storage
//
Isolate* isolate = args.GetIsolate();

//
// 2. Save the value in to a isolate storage
//
Local<Value> str = String::NewFromUtf8(isolate, "Key done");

//
// 3. Set the return value (using the passed in
// FunctionCallbackInfo<Value>&)
//
args.GetReturnValue().Set(str);
}

void Encrypt(const FunctionCallbackInfo<Value>& args)
{
Isolate* isolate = args.GetIsolate();

v8::String::Utf8Value param1(args[0]->ToString());
std::string payload = std::string(*param1);

char cPayload[4];
strcpy(cPayload, payload.c_str());

for (int i=0; i<256; i++)
{
printf("%.2X ", generated_key[i]);
}

printf("\n");

encrypt(cPayload, sizeof(cPayload), encMessage, sizeof(encMessage), &encLength, generated_key);

//
// 1. Create isolation storage
//

//
// 2. Save the value in to a isolate storage
//
Local<Value> str = String::NewFromUtf8(isolate, "Encrypt");

//
// 3. Set the return value (using the passed in
// FunctionCallbackInfo<Value>&)
//
args.GetReturnValue().Set(str);
}

//
// * Initialize the object and expose the functions that need exposure.
//
void Init(Local<Object> exports)
{
NODE_SET_METHOD(exports, "GenerateKey", GenerateKey);
NODE_SET_METHOD(exports, "Encrypt", Encrypt);

}

//
// There is no semi-colon after NODE_MODULE as it's not a function
//
NODE_MODULE(, Init)
}

Answer

The other answers mention the background but not the specific problem, or they cast doubt on generated_key instead, but that one is OK. [edit] I see molbdnilo's comment now; I thought someone had mentioned it, but I couldn't seem to find it! [/edit] So here it is:

cPayload is a char[]. Its name when passed decays to a char *. You are passing it to a function that expects an unsigned char * in that position. These are two distinct types. Hence the error.

Back to the background, since it's worth specifying. char must have the same range of values as either signed char or unsigned char, can be static_cast with possible truncation, and has the same aliasing powers - etc. - but, in any case, it is considered a distinct type. You can verify this by checking your implementation's typeid results for the three types.