pbkdf2 函数具有 JavaScript 实现,但它实际上将所有要完成的工作委托给 C++ 端。
env->SetMethod(target, "pbkdf2", PBKDF2);
env->SetMethod(target, "generateKeyPairRSA", GenerateKeyPairRSA);
env->SetMethod(target, "generateKeyPairDSA", GenerateKeyPairDSA);
env->SetMethod(target, "generateKeyPairEC", GenerateKeyPairEC);
NODE_DEFINE_CONSTANT(target, OPENSSL_EC_NAMED_CURVE);
NODE_DEFINE_CONSTANT(target, OPENSSL_EC_EXPLICIT_CURVE);
NODE_DEFINE_CONSTANT(target, kKeyEncodingPKCS1);
NODE_DEFINE_CONSTANT(target, kKeyEncodingPKCS8);
NODE_DEFINE_CONSTANT(target, kKeyEncodingSPKI);
NODE_DEFINE_CONSTANT(target, kKeyEncodingSEC1);
NODE_DEFINE_CONSTANT(target, kKeyFormatDER);
NODE_DEFINE_CONSTANT(target, kKeyFormatPEM);
NODE_DEFINE_CONSTANT(target, kKeyTypeSecret);
NODE_DEFINE_CONSTANT(target, kKeyTypePublic);
NODE_DEFINE_CONSTANT(target, kKeyTypePrivate);
env->SetMethod(target, "randomBytes", RandomBytes);
env->SetMethodNoSideEffect(target, "timingSafeEqual", TimingSafeEqual);
env->SetMethodNoSideEffect(target, "getSSLCiphers", GetSSLCiphers);
env->SetMethodNoSideEffect(target, "getCiphers", GetCiphers);
env->SetMethodNoSideEffect(target, "getHashes", GetHashes);
env->SetMethodNoSideEffect(target, "getCurves", GetCurves);
env->SetMethod(target, "publicEncrypt",
PublicKeyCipher::Cipher<PublicKeyCipher::kPublic,
EVP_PKEY_encrypt_init,
EVP_PKEY_encrypt>);
env->SetMethod(target, "privateDecrypt",
PublicKeyCipher::Cipher<PublicKeyCipher::kPrivate,
EVP_PKEY_decrypt_init,
EVP_PKEY_decrypt>);
env->SetMethod(target, "privateEncrypt",
PublicKeyCipher::Cipher<PublicKeyCipher::kPrivate,
EVP_PKEY_sign_init,
EVP_PKEY_sign>);
env->SetMethod(target, "publicDecrypt",
PublicKeyCipher::Cipher<PublicKeyCipher::kPublic,
EVP_PKEY_verify_recover_init,
EVP_PKEY_verify_recover>);
资源:https://github.com/nodejs/node/blob/master/src/node_crypto.cc
Libuv 模块还有另一个与标准库中一些非常特殊的功能相关的职责。
对于一些标准库函数调用,Node C++ 端和 Libuv 决定完全在事件循环之外进行昂贵的计算。
他们使用称为线程池的东西,线程池是一系列四个线程,可用于运行计算量大的任务,例如 pbkdf2 函数。
默认情况下,Libuv 在这个线程池中创建 4 个线程。
除了事件循环中使用的线程之外,还有四个其他线程可用于卸载需要在我们的应用程序中进行的昂贵计算。
Node 标准库中包含的许多函数会自动使用此线程池。 pbkdf2 函数就是其中之一。
这个线程池的存在意义重大。
所以 Node 并不是真正的单线程,因为 Node 使用其他线程来执行一些计算量很大的任务。
如果事件池负责执行计算量大的任务,那么我们的 Node 应用程序将无能为力。
我们的 CPU 在一个线程中一一运行所有指令。
通过使用线程池,我们可以在计算发生时在事件循环中做其他事情。