Search code examples
c++google-chrome-extensiongoogle-chrome-appgoogle-nativeclient

Send unsigned char string from native client module to browser


In a chrome NaCl extension that encrypts the data received from the browser and supposed to return the encrypted text via PostMessage() I am having trouble in sending the data type of unsigned char* for ciphertext. The pp::Var specification doesn't mentions anything about such form of data. I tried converting unsigned char to std::string but did not find a suitable way to do so. My code snippet is as follows:

if(action == "encryption")
    {
      pp::Var var_content = dict_message.Get("content");
      if (!var_action.is_string())
        return;
      std::string content = var_content.AsString();

      //encryption code starts here
      const char *password = "password";
      unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH];
      int len = content.length()+EVP_MAX_BLOCK_LENGTH;
      unsigned char *ciphertext = (unsigned char*)malloc(len*sizeof(unsigned char));

      aes_init(password, (int)strlen(password), key, iv);
      len = encrypt((unsigned char*)(content.c_str()), (int)strlen(content.c_str()), key, iv, ciphertext);

      pp::Var var_reply(ciphertext);
      PostMessage(var_reply);
      free(ciphertext);
    }

This returns a compile time error:

crest.cc:55:15: error: calling a private constructor of class 'pp::Var'
      pp::Var var_reply(ciphertext);
              ^
/home/kunal/Downloads/nacl_sdk/pepper_41/include/ppapi/cpp/var.h:318:3: note: declared private here
  Var(void* non_scriptable_object_pointer);
  ^
1 error generated.
make: *** [pnacl/Release/crest.o] Error 1

Solution

  • The constructor that is private is not the one you want. Try casting the ciphertext to a (const char*):

    pp::Var var_reply(static_cast<const char*>(ciphertext));
    

    Note that this expects a UTF8 string. If your encrypted data is not in this format (it likely isn't) this will not work properly. You probably want to send this as an ArrayBuffer instead, which allows an arbitrary byte sequence (untested, assuming len is the length of the encrypted ciphertext):

    pp::VarArrayBuffer buffer(len);
    void* buffer_ptr = buffer.Map();
    memcpy(buffer_ptr, ciphertext, len);
    buffer.Unmap();
    PostMessage(buffer);
    

    Then in JavaScript, the object you'll receive is an JavaScript ArrayBuffer.

    You can read the data from this by using a typed array object:

    function handleMessage(e) {
      var buffer = e.data;
      var view = new Uint8Array(buffer);
      ...
    }