The pbkdf2
function has the JavaScript implementation but it actually delegates all the work to be done to the C++ side.
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>);
resource: https://github.com/nodejs/node/blob/master/src/node_crypto.cc
The Libuv module has another responsibility that is relevant for some very particular functions in the standard library.
For some standard library function calls, the Node C++ side and Libuv decide to do expensive calculations outside of the event loop entirely.
Instead they make use of something called a thread pool, the thread pool is a series of four threads that can be used for running computationally expensive tasks such as the pbkdf2
function.
By default Libuv creates 4 threads in this thread pool.
In addition to the threads used in the event loop there are four other threads that can be used to offload expensive calculations that need to occur inside our application.
Many of the functions included in the Node standard library automatically make use of this thread pool. The pbkdf2
function being one of them.
The presence of this thread pool is very significant.
So Node is not truly single threaded, because there are other threads that Node uses for doing some computationally expensive tasks.
If the event pool was responsible for doing the computationally expensive task, then our Node application could do nothing else.
Our CPU runs all the instructions inside a thread one by one.
By using the thread pool we can do other things inside an event loop while calculations are occurring.