This suggests that repurposing a Guid is a great way to craft a random password of strictly alphanumeric characters. Well, I tested the theory today and am pleased with what came to be. The code in black below could have just been left out, but I kept it for readability.
using System;
using System.Collections.Generic;
using System.Linq;
namespace EQL.Members
{
public static class PasswordGenerator
{
public static string Generate(int lengthOfPassword)
{
Guid guid = Guid.NewGuid();
string secret = guid.ToString().Replace("-", "");
if (lengthOfPassword > 1 && lengthOfPassword < 32) secret = secret.Substring(0,
lengthOfPassword);
return RandomizeTheCaseOnLetters(secret);
}
private static string RandomizeTheCaseOnLetters(string secret)
{
char[] characterArray = secret.ToCharArray();
char[] arrayForRandomizing = Guid.NewGuid().ToString().Replace("-",
"").ToCharArray();
List<bool> listForRandomizing = arrayForRandomizing.Select(c => ((int) c%2 == 0)
? true : false).ToList();
int counter = 0;
bool containsNumber = false;
bool containsLetter = false;
while (counter < characterArray.Length)
{
char character = characterArray[counter];
int characterEncoding = (int)character;
if (characterEncoding > 49)
{
containsLetter = true;
string stringifiedCharacter = character.ToString();
if (listForRandomizing[counter])
{
stringifiedCharacter = stringifiedCharacter.ToUpper();
} else {
stringifiedCharacter = stringifiedCharacter.ToLower();
}
characterArray[counter] = stringifiedCharacter.ToCharArray()[0];
} else {
containsNumber = true;
}
counter++;
}
characterArray = EnsurePresenceOfBothOneDigitAndOneLetter(characterArray,
containsNumber, containsLetter);
return characterArray.Aggregate("", (current, c) => current + c.ToString());
}
private static char[] EnsurePresenceOfBothOneDigitAndOneLetter(char[]
characterArray, bool containsNumber, bool containsLetter)
{
if (!containsNumber)
{
characterArray[0] = '0';
}
if (!containsLetter)
{
characterArray[0] = 'a';
}
return characterArray;
}
}
}
My tests:
using System.Text.RegularExpressions;
using EQL.Members;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace EQL.Tests
{
[TestClass]
public class PasswordGeneratorTests
{
[TestMethod]
public void GuidToAlphanumericPasswordConversionBehavesAsExpected()
{
string password = PasswordGenerator.Generate(31);
Assert.AreEqual(password.Length, 31);
Assert.IsTrue(Regex.IsMatch(password, @"^[A-Za-z0-9]+$"));
}
[TestMethod]
public void PasswordsAlwaysHaveAtLeastOneNumberAndAtLeastOneLetter()
{
string password = PasswordGenerator.Generate(2);
char[] characterArray = password.ToCharArray();
int counter = 0;
bool containsNumber = false;
bool containsLetter = false;
while (counter < characterArray.Length)
{
char character = characterArray[counter];
int characterEncoding = (int)character;
if (characterEncoding > 49)
{
containsLetter = true;
} else {
containsNumber = true;
}
counter++;
}
Assert.IsTrue(containsNumber);
Assert.IsTrue(containsLetter);
}
}
}
No comments:
Post a Comment