private void ComputeHashWorker(string plainText, SupportedHashAlgorithm algorithm, int complexityThrottle = 1,
                                       byte[] saltBytes = null)
        {
            if (saltBytes == null)
            {
                saltBytes = _saltProvider.GetNonZeroBytes(SALT_BYTE_LENGTH);
            }

            var plainTextBytes = Encoding.UTF8.GetBytes(plainText);
            var algoBytes      = Encoding.UTF8.GetBytes(GetAlgoIdentifier(algorithm));

            byte[] hashBytes;
            var    hasComplexityThrottle = false;

            _complexityThrottle = complexityThrottle;

            switch (algorithm)
            {
            case SupportedHashAlgorithm.SHA1:
                hashBytes = CryptoHashAlgorithmComputeBytes(plainTextBytes, saltBytes, new SHA1Managed());
                break;

            case SupportedHashAlgorithm.SHA256:
                hashBytes = CryptoHashAlgorithmComputeBytes(plainTextBytes, saltBytes, new SHA256Managed());
                break;

            case SupportedHashAlgorithm.SHA384:
                hashBytes = CryptoHashAlgorithmComputeBytes(plainTextBytes, saltBytes, new SHA384Managed());
                break;

            case SupportedHashAlgorithm.SHA512:
                hashBytes = CryptoHashAlgorithmComputeBytes(plainTextBytes, saltBytes, new SHA512Managed());
                break;

            case SupportedHashAlgorithm.PBKDF2:
                complexityThrottle = complexityThrottle * 1000;

                hashBytes             = new Rfc2898DeriveBytes(plainTextBytes, saltBytes, complexityThrottle).GetBytes(24);
                hasComplexityThrottle = true;
                break;

            default:
                hashBytes = CryptoHashAlgorithmComputeBytes(plainTextBytes, saltBytes,
                                                            new MD5CryptoServiceProvider());
                break;
            }

            _saltBytes = saltBytes;

            if (hasComplexityThrottle)
            {
                saltBytes = saltBytes.Concat(BitConverter.GetBytes(_complexityThrottle)).ToArray();
            }

            saltBytes = saltBytes.Concat(algoBytes).ToArray();

            // append the salt bytes to the end of the hash
            IEnumerable <byte> hashWithSaltBytes = hashBytes.Concat(saltBytes);

            HashString = Convert.ToBase64String(hashWithSaltBytes.ToArray());

            _inited = true;
        }