Random Password Generator with optional combination of Lower, Upper, Special and Numeric characters

This is been quite some time since I have shared some useful stuff with community. As you all know priorities always keep changing. So here is another simple utility class to generate random password.

You can define the minimum numbers of characters in your password string as well. This can be very useful if you have strict requirements for password security. As many password policy restrict user to set a password with sufficient complexity so that no one can brute force it easily.

This class uses double randomization algorithm to ensure that passwords don't get repeated. First it randomly picks the characters into a buffer. Once done, it does random swapping of all elements on buffer to ensure randomness of password.
Here is how you can utilize this code:-
/*
    * Author: Zeeshan Muar
    * Version: 1.0
    * This program is free software: you can redistribute it and/or modify
    * it under the terms of the GNU General Public License as published by
    * the Free Software Foundation, either version 3 of the License, or
    * (at your option) any later version.
    * 
    * This program is distributed in the hope that it will be useful,
    * but WITHOUT ANY WARRANTY; without even the implied warranty of
    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    * GNU General Public License for more details.
    * 
    * You should have received a copy of the GNU General Public License
    * along with this program.  If not, see .
*/
public sealed class PasswordEngine
{
    private static PasswordEngine engine = new PasswordEngine();
 
    public static PasswordEngine Default
    {
        get
        {
            return engine;
        }
    }
        
    private readonly Random rnd = new Random();
    private string[] allowedCharacters = new string[]
    {
        "abcdefghijklmnopqrstuvwxyz",
        "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
        "1234567890",
        "!@#$%^&*()_"
    };
 
    public string Generate(int size)
    {
        return Generate(size, 0, 0, 0);
    }
 
    public string Generate(int size,  int minCapitalLetters, int minNumbers, int minSpecial)
    {
        //Parameter validation
        if (minCapitalLetters + minNumbers + minSpecial > size)
        {
            throw new Exception("Parameter size should be less than or equal to minCapitalLetters + minSmallLetters + minNumbers + minSpecial");
        }
 
 
        //Buffer for 
        char[] buffer = new char[size];
 
        int currentIndex = 0;
        //Fill Capital Letters
        currentIndex = FillBuffer(currentIndex, minCapitalLetters, 1, buffer);
        //Fill Numbers Characters
        currentIndex = FillBuffer(currentIndex, minNumbers, 2, buffer);
        //Fill Special Characters
        currentIndex = FillBuffer(currentIndex, minSpecial, 3, buffer);
 
        //Fill remaining buffer with small characters
        int minSmallLetters= size - (minCapitalLetters  + minNumbers + minSpecial);
        currentIndex = FillBuffer(currentIndex, minSmallLetters, 0, buffer);
 
        RandomizeBuffer(size, buffer);
 
        return new string(buffer);
    }
 
    private void RandomizeBuffer(int size, char[] buffer)
    {
        for (int i = 0; i < size; i++)
        {
            char source = buffer[i];
            int swapIndex = rnd.Next(size);
            buffer[i] = buffer[swapIndex];
            buffer[swapIndex] = source;
        }
    }
 
    private int FillBuffer(int startIndex, int count, int row, char[] buffer)
    {
        for (int i = 0; i < count; i++)
        {
            rnd.Next(3);
            int col = rnd.Next(allowedCharacters[row].Length);
 
            buffer[i+startIndex] = allowedCharacters[row][col];
        }
 
        return startIndex + count;
    }
}

Here is how you can call this class to generate random passwords:-
//This will generate a simple password
string password1 = PasswordEngine.Default.Generate(10);
 
//This will generate a password with 2 numbers, 2 special and 2 capital letters
string password2 = PasswordEngine.Default.Generate(10, 2, 2, 2);

Feel free to discuss, Happy Coding !!!