public static SaltWithParameters GenerateSalt(ScryptParameters parameters)
        {
            if (parameters == null) throw new ArgumentNullException("parameters");

            var salt = SaltGenerator.GenerateRandomSalt(parameters.SaltLengthBytes);
            return new SaltWithParameters(salt, parameters);
        }
        private static SaltParseException InternalTryParseSalt(string hashedPasswordString, out SaltWithParameters saltWithParameters,
            out string hashedPassword)
        {
            saltWithParameters = null;
            hashedPassword = null;

            ulong n;
            uint r, p, hashLengthBytes;

            var components = hashedPasswordString.Split('$');
            if (components.Length != 8)
                return new SaltParseException("Expected 8 dollar-sign ($) delimited salt components");
            if (components[0] != "" || components[1] != "scrypt")
                return new SaltParseException("Expected $scrypt$");
            if (!ulong.TryParse(components[2], out n))
                return new SaltParseException("Failed to parse N parameter");
            if (!uint.TryParse(components[3], out r))
                return new SaltParseException("Failed to parse r parameter");
            if (!uint.TryParse(components[4], out p))
                return new SaltParseException("Failed to parse p parameter");
            if (!uint.TryParse(components[5], out hashLengthBytes))
                return new SaltParseException("Failed to parse hashLengthBytes parameter");

            var saltBytes = Convert.FromBase64String(components[6]);
            var parameters = new ScryptParameters(n, r, p, hashLengthBytes, (uint)saltBytes.Length);
            saltWithParameters = new SaltWithParameters(saltBytes, parameters);

            hashedPassword = components[7];

            return null;
        }
        public SaltWithParameters(byte[] salt, ScryptParameters parameters)
        {
            if (salt == null) throw new ArgumentNullException("salt");
            if (parameters == null) throw new ArgumentNullException("parameters");

            if (parameters.SaltLengthBytes != salt.Length)
            {
                throw new ArgumentException(
                    string.Format("Expected {0} bytes of salt but got {1}", parameters.SaltLengthBytes, salt.Length),
                    "salt");
            }

            this.salt = salt;
            this.parameters = parameters;
        }