8

C++ アドオンからモジュール 'crypto' に組み込まれた node.js を使用する必要があります。組み込みモジュールを使用する C++ アドオンの例を見つけようとしましたが、失敗しました。node_crypto.h/.cc を調べたところ、node.js 暗号ドキュメント、保護されたコンストラクターなどと比較して非常に異なる関数シグネチャがあります。node_crypto.h には 1 つのパラメーターを持つ InitCrypto() 宣言が含まれていますが、node_crypto.cc にはそのような定義がありません関数。4 つのパラメーターを持つ InitCrypto のみがあります。とにかく1つのパラメーターでInitCryptoを使用しようとしたところ、「シンボルルックアップエラー」が発生しました。

require('crypto') の結果をアドオンに渡してから、このオブジェクトを操作できますが、これは非常に安全ではありません。私たちの JS コードはクライアントのサーバー上で動作します。

今のところ、C++ アドオンは、組み込みのノード モジュール 'crypto' ではなく、openssl lib のような smth を使用する方が簡単だと思います。

したがって、「crypto」モジュールを使用している C++ アドオンを使用した実際の例、またはこれに関する記事へのリンクが必要です。

C++アドオンの組み込みモジュールを使用した例は役に立ちます。

4

1 に答える 1

9

Nodejsアドオンでデータを暗号化/復号化する必要がある場合、同じ方法を使用しました.

私が理解しているように、からのクラスnode_crypto.hは Nodejs でネイティブ バインディングを作成するために使用されますが、アドオンでは使用できませんでした。

次に、Nodejs から OpenSSL を使用しようとしましたが、OpenSSL が Nodejs 実行可能ファイルに静的にリンクされているため、使用できませんでした。

その後、C++ から JavaScript コードを呼び出そうとしましたが、最終的に次の解決策を得ました - C++ コードから Nodejs 関数を呼び出す:

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
}

ご覧のとおり、V8 API を使用した C++ コードは非常に冗長です。実際のプロジェクトでは、v8pp ライブラリのユーティリティ関数を使用してオブジェクト プロパティを取得し、V8 ハンドルへのデータ変換を伴う関数を呼び出しました。

于 2015-11-06T07:10:05.577 に答える