2015-11-05 14 views
6

Ho bisogno di utilizzare node.js integrato nel modulo "crypto" dal mio addon C++. Ho provato a trovare esempi di addon C++ che utilizzano moduli incorporati, ma non sono riusciti. Ho cercato in node_crypto.h/.cc e ha firme di funzioni così diverse confrontate con la documentazione crittografica node.js, i costruttori protetti, ecc. Node_crypto.h contiene la dichiarazione InitCrypto() con un parametro, ma node_crypto.cc non ha definizione di tale funzione. C'è solo InitCrypto con quattro parametri. Ho provato comunque a utilizzare InitCrypto con un parametro e ho ottenuto "errore di ricerca dei simboli".Come utilizzare node.js integrato nei moduli dagli addon C++

Potrei passare il risultato di require ('crypto') al mio addon e quindi lavorare con questo oggetto, ma questo non è sicuro. Il nostro codice JS funziona sul server del cliente.

Per ora penso che sia più semplice per l'addon C++ usare smth come openssl lib invece del modulo nodo incorporato 'crypto'.

Quindi ho bisogno di qualche esempio funzionante con addon C++ che usi il modulo 'crypto' o il link ad alcuni articoli su questo.

Qualsiasi esempio di utilizzo di qualsiasi modulo integrato da addon C++ sarebbe utile.

risposta

6

Ho usato la stessa procedura quando ho avuto bisogno di crittografare/decodificare i dati in un addon Nodejs.

Come ho capito, le classi da node_crypto.h vengono utilizzate per creare collegamenti nativi in ​​Nodejs, non potrei utilizzarli nel mio addon.

Quindi ho provato a utilizzare OpenSSL da Nodejs ma non ho potuto farlo perché OpenSSL è collegato staticamente all'eseguibile Nodejs.

Dopo che ho provato a chiamare un codice JavaScript da C++ e, infine, ha ottenuto la seguente soluzione - per richiamare le funzioni Nodejs da codice C++:

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 
} 

Come si può vedere, codice C++ con V8 API è abbastanza prolisso . Nel progetto reale ho utilizzato le funzioni di utilità dalla mia libreria v8pp per ottenere proprietà dell'oggetto e funzioni di chiamata con conversione dei dati in handle V8.

+0

Grazie mille! Questa soluzione è più sicura quindi passa il risultato di require ('crypto') ad addon. Se nessuno pubblicherà una soluzione C++ pura fino alla fine di novembre, contrassegnerò questa come risposta. Comprendo correttamente che qualcuno possa correggere i moduli incorporati nei file node_src_root/lib/*. Js e questi file * .js corretti verranno utilizzati dall'addon? Hai qualche test delle prestazioni? Di ', prova a mettere in cache alcune funzioni negli oggetti globali e il confronto con le librerie crittografiche di terze parti? – Dzenly

+1

L'ho usato come un modo veloce e sporco per evitare una dipendenza da una libreria crittografica esterna nel mio addon, perché costruire cose come OpenSSL sarebbe un mal di testa. Sì, hai ragione questa soluzione utilizzata 'lib \ *. Js' dalle origini del nodo. Se qualcuno ha cambiato i sorgenti e ha eseguito questo Nodejs modificato, potrebbe non essere sicuro. Avevo bisogno di criptare/decodificare un blocco di dati solo una volta all'avvio dell'applicazione. Quindi non ho fatto alcun test delle prestazioni per questa soluzione. – pmed

+0

Ottima soluzione! – Icebob

Problemi correlati