I need to use node.js built in module 'crypto' from my C++ addon. I tried to find examples of C++ addons which use built in modules, but failed. I looked in node_crypto.h/.cc and it has so different function signatures comparing with node.js crypto documentation, protected constructors, etc. node_crypto.h contains InitCrypto() declaration with one parameter, but node_crypto.cc has not definition of such function. There is only InitCrypto with four parameters. I tried anyway use InitCrypto with one parameter and got "symbol lookup error".
I could pass result of require('crypto') to my addon and then work with this object, but this is so unsecure. Our JS code works on client's server.
For now I think that it is simpler for C++ addon to use smth like openssl lib instead of built in node module 'crypto'.
So I need some working example with C++ addon which is using 'crypto' module or link to some article about this.
Any example using any built in module from C++ addon would be helpful.
js Built-in Modules. Node. js has a set of built-in modules which you can use without any further installation.
It gives the opportunity to make intensive, parallel, and high-accuracy calculations. It also gives the opportunity to use C++ libraries in NodeJS. We can integrate a third-party library written in C/C++ and use it directly in NodeJS.
I used the same way when had a need to encrypt/decrypt data in a Nodejs addon.
As I understand, classes from node_crypto.h
are used to make native bindings in Nodejs, I couldn't use them in my addon.
Then I tried to use OpenSSL from Nodejs but couldn't do it because OpenSSL is linked statically into the Nodejs executable.
After that I tried to call a JavaScript code from C++ and finally got the following solution - to invoke Nodejs functions from C++ code:
using namespace v8;
// persistent handle for the crypto module
static Persistent<Object> node_crypto;
// Addon startup procedure
void Init(Local<Object> exports, Local<Object> module)
{
Isolate* isolate = Isolate::GetCurrent();
HandleScope scope(isolate);
// get `require` function
Local<Function> require = module->Get(String::NewFromUtf8(isolate, "require")).As<Function>();
// call require('crypto')
Local<Value> args[] = { String::NewFromUtf8(isolate, "crypto") };
Local<Object> crypto = require->Call(module, 1, args).As<Object>();
// store crypto module in persistent handle for further use
node_crypto.Reset(isolate, crypto);
}
NODE_MODULE(addon, Init);
// must be invoked in then Node main thread since the function uses V8 API
std::string encrypt(std::string const& key, std::string const& text)
{
Isolate* isolate = Isolate::GetCurrent();
HandleScope scope(isolate);
// get local handle from persistent
Local<Object> crypto = Local<Object>::New(isolate, node_crypto);
// get `createCipher` function from the crypto module
Local<Function> createCipher = crypto->Get(String::NewFromUtf8(isolate, "createCipher")).As<Function>();
// call crypto.createCipher("aes256", key)
Local<Value> create_args[] =
{
String::NewFromUtf8(isolate, "aes256"),
String::NewFromUtf8(isolate, key.c_str())
};
Local<Object> cipher = createCipher->Call(crypto, 2, create_args).As<Object>();
// get update and final functions from the crypto module
Local<Function> update = cipher->Get(String::NewFromUtf8(isolate, "update")).As<Function>();
Local<Function> final = cipher->Get(String::NewFromUtf8(isolate, "final")).As<Function>();
// buf1 = cipher.update(text), buf2 = cipher.final()
Local<Value> update_args[] = { node::Buffer::New(isolate, text.data(), text.size()) };
Local<Value> buf1 = update->Call(cipher, 1, update_args);
Local<Value> buf2 = final->Call(cipher, 0, nullptr);
// concatenate update and final buffers into result string
char const* const data1 = node::Buffer::Data(buf1);
char const* const data2 = node::Buffer::Data(buf2);
size_t const size1 = node::Buffer::Length(buf1);
size_t const size2 = node::Buffer::Lenght(buf2);
std::string result;
result.reserve(size1 + size2);
result.append(data1, size1);
result.append(data2, size2);
return result;
}
std::string decrypt(std::string const& key, std::string const& text)
{
// similar as in encrypt, use createDecipher instead
}
As you can see, C++ code with V8 API is quite verbose. In the real project I used utility functions from my v8pp library to get object properties and call functions with data conversion to V8 handles.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With