Skip to content

Instantly share code, notes, and snippets.

@Rephistorch
Last active November 24, 2015 11:35
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Rephistorch/9e7bd09ca2c1b536dfc1 to your computer and use it in GitHub Desktop.
Save Rephistorch/9e7bd09ca2c1b536dfc1 to your computer and use it in GitHub Desktop.
C# Console Password Generator
using System;
using System.Text;
/*
* Code by: Christopher Ardelean
* Version 1.0
* 2015-01-29
*
* I had far too much fun with this one...
*/
namespace Password_Generation
{
class Program
{
static char[] ALPHA = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray();
static char[] alpha = "abcdefghijklmnopqrstuvwxyz".ToCharArray();
static char[] numeric = "0123456789".ToCharArray();
static char[] symbol = "!@#$%^&*()[]{};:'\",.<>/?\\|_+-=`~".ToCharArray();
static string keyboard = "`1234567890-=qwertyuiop[]\\asdfghjkl;'zxcvbnm,./";
static string KEYBOARD = "~!@#$%^&*()_+QWERTYUIOP{}|ASDFGHJKL:\"ZXCVBNM<>?";
static string[] units = { "Seconds", "Minutes", "Hours", "Days", "Weeks", "Years", "Decades", "Centuries", "Millenia" };
static double[] unitValues = { 1, 60, 60, 24, 7, (365.242196 / 7), 10, 10, 10 }; // 365.242196 is a reasonable estimate for leap years
static void Main(string[] args)
{
int length = 0;
int numberOfPass = 1;
bool uppercase = false;
bool lowercase = false;
bool num = false;
bool sym = false;
bool ASCII = false;
bool again = true;
while (again)
{
Console.Clear();
Console.WriteLine("Welcome to the password generator.\n");
Console.WriteLine("Your current character sets are as follows:");
Console.WriteLine("-------------------------------------------");
ShowArray("Uppercase", ALPHA);
ShowArray("Lowercase", alpha);
ShowArray("Numerics", numeric);
ShowArray("Symbols", symbol);
AskInt("How long would you like your password to be", ref length, 1, 32);
AskInt("How many passwords would you like to generate", ref numberOfPass, 1, 20);
AskBool("the full ASCII page", ref ASCII);
if (!ASCII)
{
Console.WriteLine();
AskBool("uppercase", ref uppercase);
AskBool("lowercase", ref lowercase);
AskBool("numerics", ref num);
AskBool("symbols", ref sym);
}
generatePassword(ASCII, uppercase, lowercase, num, sym, length, numberOfPass);
AskBool("this tool again", ref again);
}
Console.WriteLine("Goodbye!");
}
static void ShowArray(string name, char[] array)
{
StringBuilder sb = new StringBuilder(80);
sb.Append(name);
sb.Append(":\t");
for (int i = 0; i < array.Length; i++)
sb.Append(array[i]);
Console.WriteLine(sb.ToString());
}
static void AskBool(string subject, ref bool test)
{
Console.Write("Would you like to use {0}? (y|n): ", subject);
ConsoleKeyInfo key = Console.ReadKey(true);
while (key.Key != ConsoleKey.Y && key.Key != ConsoleKey.N)
key = Console.ReadKey(true);
Console.WriteLine(key.Key);
test = key.Key == ConsoleKey.Y;
}
static void AskInt(string question, ref int response, int lower, int upper)
{
if (upper > lower) // Make sure a coder hooking into this library doesn't accidently create an infinite loop. Defensive coding!
{
Console.WriteLine("\n{0}? (Valid Range: {1}-{2})", question, lower, upper);
while (!Int32.TryParse(Console.ReadLine(), out response) || response > upper || response < lower)
{
Console.WriteLine("That input didn't make sense. Please type a numeric value between {0} and {1}.", lower, upper);
}
}
else
throw new Exception("AskInt requires that your upper bound be higher than your lower bound.");
}
static void generatePassword(bool ASCII, bool upper, bool lower, bool num, bool sym, int length, int numOfPass)
{
StringBuilder sb = new StringBuilder();
Random r = new Random();
int RandomLength = 0;
char[] charset;
if (length > 0 && length < 33 && (ASCII || upper || lower || num || sym)) // Length should never be either of these values, but this is good defensive coding. You never know when someone else might mess up your main method.
{
for (int j = 0; j < numOfPass; j++)
{
if (ASCII)
{
RandomLength = 255;
for (int i = 0; i < length; i++)
{
sb.Append((char)(r.Next(RandomLength)+1)); // 0 is NULL terminator, and not alt-able. 255 total values, 1-255.
}
}
else
{
RandomLength = 0;
RandomLength += upper ? ALPHA.Length : 0;
RandomLength += lower ? alpha.Length : 0;
RandomLength += num ? numeric.Length : 0;
RandomLength += sym ? symbol.Length : 0;
charset = new char[RandomLength];
int curLength = 0;
BuildCharset(upper, ref curLength, ref charset, ref ALPHA);
BuildCharset(lower, ref curLength, ref charset, ref alpha);
BuildCharset(num, ref curLength, ref charset, ref numeric);
BuildCharset(sym, ref curLength, ref charset, ref symbol);
for (int i = 0; i < length; i++)
{
int pos = r.Next(RandomLength);
sb.Append(charset[pos]);
}
}
Console.WriteLine("\nYour generated password is: {0}", ASCII ? KeyCombo(sb.ToString()) : sb.ToString());
if (!ASCII)
Console.WriteLine(KeyCombo(sb.ToString()));
sb.Clear();
}
double stats = Math.Pow((double)RandomLength, (double)length);
double result1 = Math.Ceiling(stats / 1000);
double result2 = Math.Ceiling(stats / 10000000);
double result3 = Math.Ceiling(stats / 100000000000);
string unit1 = "";
string unit2 = "";
string unit3 = "";
FriendlyUnits(ref result1, ref unit1);
FriendlyUnits(ref result2, ref unit2);
FriendlyUnits(ref result3, ref unit3);
Console.WriteLine("\nPassword Statistics:");
Console.WriteLine("---------------------");
if (stats < Int64.MaxValue)
Console.WriteLine("\nYour password's uniqueness is 1 in {0:N0}", stats);
else
Console.WriteLine("\nYour password's uniqueness is 1 in {0}", stats);
if (result1 < 100)
Console.WriteLine("At 1,000 guesses per second it would take\t{0:N1}\t{1} to guess.", result1, unit1);
else
Console.WriteLine("At 1,000 guesses per second it would take:\n{0:F1} {1} to guess.", result1, unit1);
if (result2 < 100)
Console.WriteLine("At 10,000,000 guesses per second it would take\t{0:N1}\t{1} to guess.", result2, unit2);
else
Console.WriteLine("At 10,000,000 guesses per second it would take:\n{0:F1} {1} to guess.", result2, unit2);
if (result3 < 100)
Console.WriteLine("At 100 Billion guesses per second it would take\t{0:N1}\t{1} to guess.\n", result3, unit3);
else
Console.WriteLine("At 100 Billion guesses per second it would take:\n{0:F1} {1} to guess.\n", result3, unit3);
}
else
{
Console.WriteLine("\nNo valid passwords could be generated. Check your criteria, and try again.\n");
}
}
static string KeyCombo (string password)
{
StringBuilder sb = new StringBuilder(80);
for (int i = 0; i < password.Length; i++ )
{
char c = password.Substring(i, 1).ToCharArray()[0];
int k = keyboard.IndexOf(c);
int K = KEYBOARD.IndexOf(c);
if (k > 0)
sb.Append(string.Format("{0} ", keyboard.Substring(k, 1).ToUpper()));
else if (K > 0)
sb.Append(string.Format("Shift+{0} ", keyboard.Substring(K, 1).ToUpper()));
else if (c == ' ')
sb.Append("Spacebar ");
else
sb.Append(string.Format("Alt+{0} ", (byte)c));
}
return sb.ToString();
}
static void FriendlyUnits (ref double d, ref string unit)
{
double result = d;
int i = 0;
// This code might never run if the result is already within range.
while (result >= 1 && i < units.Length - 1)
{
i++;
result = result / unitValues[i];
if (result >= 1) // only assign the result if it's in the right range
d = result;
else // This is the final run of the loop, because the result is too coarse. Reduce i so that the appropriate unit is selected.
i--;
}
unit = units[i];
}
static void BuildCharset (bool test, ref int curLength, ref char[] charset, ref char[] chars)
{
if (test)
{
chars.CopyTo(charset, curLength);
curLength += chars.Length;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment