If you need help building a random password, you should check out pctools.com random password generator. It’s great, it gives you a lot of options and you can have it generate a list of 50 passwords with their callsign spellings in seconds. I’ve found the callsign spelling to be very helpful for remembering and recognizing all the characters in a new password I generate. I liked this solution so much, I decided port this concept over to C# with a set of helpers. This can be used anywhere you want to generate a password, I am currently using it in a ASP.NET LOB app to suggest and show better passwords options.
Generating Random Passwords
using System;
using System.Collections.Generic;
using System.Linq;
public static class StringHelper
{
// Shared Static Random Generator
private static readonly Random CommonRandom = new Random();
public static string GenerateRandomPassword(int passwordLength, bool canRepeatCharacters = false)
{
char[] chars = "$%#@!*abcdefghijklmnopqrstuvwxyz1234567890?;:ABCDEFGHIJKLMNOPQRSTUVWXYZ^&".ToCharArray();
string randomPassword = string.Empty;
for (int l = 0; l < passwordLength; l++)
{
int x = CommonRandom.Next(1, chars.Length);
if (canRepeatCharacters || !randomPassword.ToCharArray().Any(ch => ch == chars[x]))
randomPassword += chars[x].ToString();
else
l--;
}
return randomPassword;
}
public static List<string> GenerateRandomPasswords(int quantity, int passwordLength = 8)
{
List<string> passwords = new List<string>();
for (int i = 0; i < quantity; i++)
{
passwords.Add(GenerateRandomPassword(passwordLength));
}
return passwords;
}
}
There are a few options on the generator, like not repeating a character and configuring the password length. In addition to the main method, I also have a helper that also returns a list of multiple passwords, to return in a list to give your users options.
Important note, Random() is not very random when your making quick consecutive calls. If you want to call Random() in a loop, you should move your instance of the Random() class to the outside to prevent duplicate seeds, which will result in duplicate passwords.
public static string GetCallsignSpelling(string password)
{
if (string.IsNullOrEmpty(password))
return string.Empty;
Dictionary<char, string> callsigns = new Dictionary<char, string>()
{
{'$',"Dollar Symbol"},
{'%',"Percent Symbol"},
{'#',"Number Symbol"},
{'@',"At Symbol"},
{'!',"Exclamation Symbol"},
{'*',"Asterisk Symbol"},
{'a',"alpha"},
{'b',"bravo"},
{'c',"charlie"},
{'d',"delta"},
{'e',"echo"},
{'f',"foxtrot"},
{'g',"golf"},
{'h',"hotel"},
{'i',"india"},
{'j',"juliet"},
{'k',"kilo"},
{'l',"lima"},
{'m',"mike"},
{'n',"november"},
{'o',"oscar"},
{'p',"papa"},
{'q',"quebec"},
{'r',"romeo"},
{'s',"sierra"},
{'t',"tango"},
{'u',"uniform"},
{'v',"victor"},
{'w',"whiskey"},
{'x',"xray"},
{'y',"yankee"},
{'z',"zulu"},
{'1',"One"},
{'2',"Two"},
{'3',"Three"},
{'4',"Four"},
{'5',"Five"},
{'6',"Six"},
{'7',"Seven"},
{'8',"Eight"},
{'9',"Nine"},
{'0',"Zero"},
{'?',"Question Symbol"},
{';',"SemiColon Symbol"},
{':',"Colon Symbol"},
{'A',"ALPHA"},
{'B',"BRAVO"},
{'C',"CHARLIE"},
{'D',"DELTA"},
{'E',"ECHO"},
{'F',"FOXTROT"},
{'G',"GOLF"},
{'H',"HOTEL"},
{'I',"INDIA"},
{'J',"JULIET"},
{'K',"KILO"},
{'L',"LIMA"},
{'M',"MIKE"},
{'N',"NOVEMBER"},
{'O',"OSCAR"},
{'P',"PAPA"},
{'Q',"QUEBEC"},
{'R',"ROMEO"},
{'S',"SIERRA"},
{'T',"TANGO"},
{'U',"UNIFORM"},
{'V',"VICTOR"},
{'W',"WHISKEY"},
{'X',"XRAY"},
{'Y',"YANKEE"},
{'Z',"ZULU"},
{'^',"Caret Symbol"},
{'&',"Ampersand Symbol"}
};
char[] wordCharacters = password.ToCharArray();
string callsignSpelling =
wordCharacters.Aggregate(string.Empty,
(current, passwordCharacter) =>
current + (callsigns[passwordCharacter] + " - ")).TrimEnd(' ', '-');
return callsignSpelling;
}
The spelling is done using a Key/Value dictionary, and iterating over each character of the password one-by-one.
The result of using these two helpers is below.