79074306

Date: 2024-10-10 12:06:35
Score: 0.5
Natty:
Report link

Unfortunately (or perhaps by design) both solutions in this thread still generate passwords with symbols even though the numberOfNonAlphanumericCharacters is set to 0. Also the number of symbols generated will very likely be higher than numberOfNonAlphanumericCharacters.

So I adjusted @ReneLombard's answer and made adjustments to make sure that the output is consistent with the input variables.

public class Password
{
    private readonly char[] symbols = "!@#$%^&*()_-+[{]}:>|/?".ToCharArray();

    public string Generate(int length = 64, int maximumNumberOfSymbolsInPassword = 0)
    {
        ArgumentOutOfRangeException.ThrowIfLessThan(length, 1);
        ArgumentOutOfRangeException.ThrowIfGreaterThan(length, 128);
        ArgumentOutOfRangeException.ThrowIfLessThan(maximumNumberOfSymbolsInPassword, 0);
        ArgumentOutOfRangeException.ThrowIfGreaterThan(maximumNumberOfSymbolsInPassword, length);

        using var rng = RandomNumberGenerator.Create();
        var characterBuffer = new char[length];
        var byteBuffer = new byte[length];
        rng.GetBytes(byteBuffer);

        for (var i = 0; i < length; i++)
        {
            var idx = byteBuffer[i] % 62;
            switch (idx)
            {
                case < 10:
                    characterBuffer[i] = (char)('0' + idx);
                    break;
                case < 36:
                    characterBuffer[i] = (char)('A' + idx - 10);
                    break;
                default:
                    characterBuffer[i] = (char)('a' + idx - 36);
                    break;
            }
        }

        // Replace characters in the buffer with symbols, note that this might generate
        // fewer passwords than is specified in maximumNumberOfSymbolsInPassword if
        // the same k index value is chosen more than once
        for (var i = 0; i < maximumNumberOfSymbolsInPassword; i++)
        {
            int k;
            do
            {
                k = GetRandomInt(rng, length);
            }
            while (!char.IsLetterOrDigit(characterBuffer[k]));
            characterBuffer[k] = symbols[GetRandomInt(rng, symbols.Length)];
        }

        return new string(characterBuffer);
    }

    private static int GetRandomInt(RandomNumberGenerator randomGenerator, int maxInput)
    {
        var buffer = new byte[4];
        randomGenerator.GetBytes(buffer);
        return Math.Abs(BitConverter.ToInt32(buffer) % maxInput);
    }
}
Reasons:
  • Long answer (-1):
  • Has code block (-0.5):
  • User mentioned (1): @ReneLombard's
  • Low reputation (1):
Posted by: sverrirs-landlaeknir