I am new to C# and develop a configurable PasswordService
class. As the code works the next step is to improve the code.
Right now there are the following options:
- Set alpha characters and the number of alpha characters that has to be in the password.
- Set numeric and the number of numeric characters that has to be in the password.
- Set non alphanumeric and the number of non alphanumeric characters that has to be in the password.
My questions:
Is the structure fine as it is?
Are the thrown Exceptions and it's message well chosen?
What do you think about the generate function yet?
Would you add or adjust the options?
Are the comments c#/xml valid?
How can I improve the password algorithm?
Did I miss something else?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PasswordGenerator
{
namespace Utility
{
namespace Service
{
/// <summary>
/// This is a configurable password generator.
/// </summary>
class PasswordService
{
string sAlphaCharacters;
string sNumericCharacters;
string sNonAlphanumericCharacters;
uint uiNumberOfAlphaCharacters;
uint uiNumberOfNumericCharacters;
uint uiNumberOfNonAlphanumericCharacters;
/// <summary>
/// Initializes class with common configuration.
/// </summary>
public PasswordService()
{
this.SAlphaCharacters = "abcdefghijklmnopqrstuwvxyABCDEFGHIJKLMNOPQRSTUWVXYYZ";
this.SNumericCharacters = "0123456789";
this.SNonAlphanumericCharacters = "!$%&()[]{}=?#";
this.UiNumberOfAlphaCharacters = 6;
this.UiNumberOfNumericCharacters = 6;
this.UiNumberOfNonAlphanumericCharacters = 3;
}
// Accessor & modifier
public string SAlphaCharacters
{
get
{
return sAlphaCharacters;
}
set
{
System.Text.RegularExpressions.Regex oRegex = new System.Text.RegularExpressions.Regex("[^a-zA-Z]{1,}");
if (oRegex.IsMatch(value))
{
throw new ArgumentException("Value must not contain anything but alpha characters.", "SAlphaCharacters.set");
}
sAlphaCharacters = value;
}
}
public string SNumericCharacters
{
get
{
return sNumericCharacters;
}
set
{
System.Text.RegularExpressions.Regex oRegex = new System.Text.RegularExpressions.Regex("[^0-9]{1,}");
if (oRegex.IsMatch(value))
{
throw new ArgumentException("Value must not contain anything but numeric characters.", "SNumericCharacters.set");
}
sNumericCharacters = value;
}
}
public string SNonAlphanumericCharacters
{
get
{
return sNonAlphanumericCharacters;
}
set
{
System.Text.RegularExpressions.Regex oRegex = new System.Text.RegularExpressions.Regex("[a-zA-Z0-9]{1,}");
if (oRegex.IsMatch(value))
{
throw new ArgumentException("Value must not contain alphanumeric characters.", "SNonAlphanumericCharacters.set");
}
sNonAlphanumericCharacters = value;
}
}
public uint UiNumberOfAlphaCharacters
{
get
{
return uiNumberOfAlphaCharacters;
}
set
{
uiNumberOfAlphaCharacters = value;
}
}
public uint UiNumberOfNumericCharacters
{
get
{
return uiNumberOfNumericCharacters;
}
set
{
uiNumberOfNumericCharacters = value;
}
}
public uint UiNumberOfNonAlphanumericCharacters
{
get
{
return uiNumberOfNonAlphanumericCharacters;
}
set
{
uiNumberOfNonAlphanumericCharacters = value;
}
}
/// <summary>
/// Chooses randomly characters of given group and returns them.
/// </summary>
/// <param name="sCharacterGroup">From this character group the chararacters will be choosen.</param>
/// <param name="uiNumberOfThisGroup">The amount of characters to choose randomly.</param>
/// <returns>One random character of the character group</returns>
public string getRandomSubstrOfCharacterGroup(string sCharacterGroup, uint uiNumberOfThisGroup)
{
Random rnd = new Random();
int iPosition = 0;
string sCharacters = "";
for (uint ui = 0; ui < uiNumberOfThisGroup; ui++)
{
iPosition = iPosition = rnd.Next(0, sCharacterGroup.Length);
sCharacters += sCharacterGroup.ToCharArray()[iPosition].ToString();
}
return sCharacters;
}
/// <summary>
/// Based upon the config a password will be generated and returned.
/// </summary>
/// <exception cref="InvalidOperationException">
/// Thrown when the number of each character group is 0.
/// </exception>
/// <returns>
/// Returns generated password.
/// </returns>
public string generate()
{
if (this.UiNumberOfAlphaCharacters == 0 && this.UiNumberOfNumericCharacters == 0 && this.UiNumberOfNonAlphanumericCharacters == 0)
{
throw new InvalidOperationException("The number of each character group is 0.");
}
Random oRand = new Random();
string sPassword = "";
sPassword += this.getRandomSubstrOfCharacterGroup(this.SAlphaCharacters, this.uiNumberOfAlphaCharacters);
sPassword += this.getRandomSubstrOfCharacterGroup(this.SNumericCharacters, this.UiNumberOfNumericCharacters);
sPassword += this.getRandomSubstrOfCharacterGroup(this.SNonAlphanumericCharacters, this.UiNumberOfNonAlphanumericCharacters);
sPassword = new string(sPassword.ToCharArray().OrderBy(s => (oRand.Next(2) % 2) == 0).ToArray());
return sPassword;
}
}
}
}
}