convert this c++ openssl to nodejs javascript
inline bool weakDecrypt2(QByteArray& data)
{
    if (data.isEmpty())
        return false;
    const int possibleSizes[] = { 9, 12, 15 };
    for (int prependSize = 4; prependSize <= 10; ++prependSize)
    {
        for (int passwordSize : possibleSizes)
        {
            for (int saltSize : possibleSizes)
            {
                if (data.size() < prependSize + passwordSize + saltSize)
                    continue;
                std::vector<unsigned char> password(passwordSize);
                std::vector<unsigned char> salt(saltSize);
                std::memcpy(password.data(), data.data() + prependSize, passwordSize);
                std::memcpy(salt.data(), data.data() + prependSize + passwordSize, saltSize);
                // Base64 encode the salt
                int b64SaltSize = 4 * ((saltSize + 2) / 3);
                std::vector<unsigned char> b64Salt(b64SaltSize + 1);
                EVP_EncodeBlock(b64Salt.data(), salt.data(), saltSize);
                // SHA256 the password and salt
                unsigned char keyHash[SHA256_DIGEST_LENGTH];
                unsigned char ivHash[SHA256_DIGEST_LENGTH];
                SHA256(password.data(), passwordSize, keyHash);
                SHA256(b64Salt.data(),  b64SaltSize,  ivHash);
                unsigned char hashedKey[16];
                unsigned char hashedIv[16];
                std::memcpy(hashedKey, keyHash, 16);
                std::memcpy(hashedIv, ivHash, 16);
                OPENSSL_cleanse(keyHash, sizeof(keyHash));
                OPENSSL_cleanse(ivHash, sizeof(ivHash));
                // Attempt decryption
                const EVP_CIPHER* cipherType = EVP_aes_128_cbc();
                EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
                if (!ctx)
                    continue;
                if (EVP_DecryptInit_ex(ctx, cipherType, NULL, hashedKey, hashedIv) != 1)
                {
                    EVP_CIPHER_CTX_free(ctx);
                    continue;
                }
                int cipherTextSize = data.size() - prependSize - passwordSize - saltSize;
                std::vector<unsigned char> decryptedData(cipherTextSize + EVP_MAX_BLOCK_LENGTH);
                int outLen1 = 0;
                if (EVP_DecryptUpdate(ctx, decryptedData.data(), &outLen1,
                    reinterpret_cast<const unsigned char>(data.data()) + prependSize + passwordSize + saltSize,
                    cipherTextSize) != 1)
                {
                    EVP_CIPHER_CTX_free(ctx);
                    continue;
                }
                int outLen2 = 0;
                if (EVP_DecryptFinal_ex(ctx, decryptedData.data() + outLen1, &outLen2) != 1)
                {
                    EVP_CIPHER_CTX_free(ctx);
                    continue;
                }
                EVP_CIPHER_CTX_free(ctx);
                // Decryption successful
                int totalDecryptedSize = outLen1 + outLen2;
                decryptedData.resize(outLen1 + outLen2);
                OPENSSL_cleanse(data.data(), data.size());
                data = QByteArray(reinterpret_cast<char>(decryptedData.data()), totalDecryptedSize);
                OPENSSL_cleanse(decryptedData.data(), decryptedData.size());
                return true;
            }
        }
    }
    // Decryption failed
    return false;
}