2015-11-05 6 views
6

Ich brauche node.js eingebautes Modul 'crypto' aus meinem C++ Addon. Ich habe versucht, Beispiele für C++ - Addons zu finden, die eingebaute Module verwenden, aber fehlgeschlagen sind. Ich schaute in node_crypto.h/.cc und es hat so verschiedene Funktionssignaturen im Vergleich mit node.js Cryptodokumentation, geschützten Konstruktoren, etc. node_crypto.h enthält InitCrypto() -Deklaration mit einem Parameter, aber node_crypto.cc hat keine Definition von solche Funktion. Es gibt nur InitCrypto mit vier Parametern. Ich habe trotzdem versucht, InitCrypto mit einem Parameter zu benutzen und bekam "Symbol Lookup Error".Wie verwendet man node.js eingebaute Module aus C++ - Addons

Ich könnte Ergebnis von require ('crypto') zu meinem Addon übergeben und dann mit diesem Objekt arbeiten, aber das ist so unsicher. Unser JS-Code funktioniert auf dem Client-Server.

Für jetzt denke ich, dass es für C++ - Addon einfacher ist, smth wie openssl lib anstelle des eingebauten Knotenmoduls 'crypto' zu verwenden.

Also brauche ich ein funktionierendes Beispiel mit C++ - Addon, das 'Crypto' Modul verwendet oder einen Artikel verlinkt.

Jedes Beispiel, das ein eingebautes Modul aus C++ - Addon verwendet, wäre hilfreich.

Antwort

6

Ich habe den gleichen Weg verwendet, wenn Daten in einem Nodejs Addon verschlüsselt/entschlüsselt werden mussten.

Wie ich verstehe, Klassen von node_crypto.h werden verwendet, um native Bindungen in Nodejs, ich konnte sie nicht in meinem Addon verwenden.

Dann habe ich versucht, OpenSSL von Nodejs zu verwenden, konnte es aber nicht, da OpenSSL statisch in die ausführbare Nodejs-Datei eingebunden ist.

Danach habe ich versucht, einen JavaScript-Code von C++ zu nennen und bekam schließlich die folgende Lösung - NodeJS Funktionen von C++ Code aufzurufen:

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 
} 

Wie Sie sehen können, C++ Code mit V8-API ist ziemlich ausführliche . Im realen Projekt nutzte ich die Funktionen meiner v8pp-Bibliothek, um Objekteigenschaften und Aufruffunktionen mit Datenkonvertierung in V8-Handles zu erhalten.

+0

Vielen Dank! Diese Lösung ist sicherer und übergibt das Ergebnis von require ('crypto') an addon. Wenn niemand bis Ende November pure C++ Lösung posten wird, werde ich dies als Antwort markieren. Verstehe ich richtig, dass jemand eingebaute Module in node_src_root/lib/* .js Dateien korrigieren kann und diese korrigierten * .js Dateien vom Addon benutzt werden? Hast du irgendwelche Leistungstests durchgeführt? Angenommen, Sie versuchen, einige Funktionen in globalen Objekten zwischenzuspeichern und mit Crypto-Bibliotheken von Drittanbietern zu vergleichen. – Dzenly

+1

Ich benutzte dies als einen schnellen und schmutzigen Weg, um eine externe Krypto-Bibliothek-Abhängigkeit in meinem Addon zu vermeiden, weil das Erstellen solcher Sachen wie OpenSSL Kopfschmerzen bereiten würde. Ja, Sie haben Recht, diese Lösung verwendet 'lib \ * .js' aus Knotenquellen. Wenn jemand die Quellen geändert hat und diese modifizierten Nodejs ausführen würde, könnte es unsicher sein. Ich musste einen Datenblock nur einmal beim Start der Anwendung verschlüsseln/entschlüsseln. Daher habe ich für diese Lösung keine Leistungstests durchgeführt. – pmed

+0

Große Lösung! – Icebob

Verwandte Themen