Returning a random value via char array - c#

I'm trying to create an a blackjack game for my C# class and I've been trying to figure out how to obtain a random suit/card value from reciprocating char arrays. The goal is to return these values to a console application to "test" the return values and see if they're correct/adequate.
I have already declared the fields, properties, and set up a constructor. I just can't figure out how to get the values to return them so that they can be tested. We've just started using these things in my class as well.
[Additional Information added from O.P.'s "answer" below]
Right now, we're just trying to obtain a single card that is translated into a console application and the setup of the arrays is what the teacher told us to use.
public class Card
{
//Declaration of fields
char[] suit = new char[] { 'D', 'H', 'S', 'C' }; //Backing Variables
char[] value = new char[]{'A', '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K'};
static Random random = new Random();
public Card(char s, char v) //Constructor
{
suit = s;
value = v;
}
public char Suit //Properties
{
int suitType = random.Next(0, suit.Length);
char s = suit[suitType];
get { return value; }
}
public char Value
{
get { return value; }
}
}

As we cannot change the structure of the program, I would do this:
public class Card
{
//Declaration of fields
private static char[] suits = new char[] { 'D', 'H', 'S', 'C' }; //Backing Variables
private static char[] values = new char[]{'A', '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K'};
private readonly char suit;
private readonly char value;
static Random random = new Random();
public Card() //Constructor
{
int suitIndex = random.Next(0, suits.Length);
suit = suits[suitIndex];
int valueIndex = random.Next(0, values.Length);
value = values[valueIndex];
}
public char Suit //Properties
{
get { return suit; }
}
public char Value
{
get { return value; }
}
}
The set up of the fields is done in the constructor, without having to pass in any parameters. The properties can then be used in your console app like so:
class Program
{
static void Main(string[] args)
{
Card aCard = new Card();
Console.WriteLine("Suit: {0}", aCard.Suit);
Console.WriteLine("Value: {0}", aCard.Value);
Console.Read();
}
}
A card will be created with a random suit and value. As others have stated the random class could not be used to reliably used to build a deck of cards.
To build a deck you could add another constructor to the Card class like:
public Card(char suit, char value)
{
this.suit = suit;
this.value = value;
}
Then add a simple Deck class like so (after this you could remove the constructor with no paramaeters and the suit and value arrays from the Card class) :
public class Deck
{
private static char[] suits = new char[] { 'D', 'H', 'S', 'C' };
private static char[] values = new char[] { 'A', '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K' };
private readonly List<Card> cards;
public Deck()
{
cards = new List<Card>();
foreach (char suit in suits)
{
foreach (char value in values)
{
Card card = new Card(suit, value);
cards.Add(card);
}
}
}
public List<Card> Cards { get { return cards; } }
}
Then to view in the console app:
Deck deck = new Deck();
foreach (Card card in deck.Cards)
{
Console.WriteLine("Suit: {0}", card.Suit);
Console.WriteLine("Value: {0}", card.Value);
}

Myself, I'd do something like this:
public enum CardSuit
{
Hearts = 1 ,
Spades = 2 ,
Diamonds = 3 ,
Clubs = 4 ,
}
public enum CardValue {
Ace = 1 ,
Two = 2 ,
Three = 3 ,
Four = 4 ,
Five = 5 ,
Six = 6 ,
Seven = 7 ,
Eight = 8 ,
Nine = 9 ,
Ten = 10 ,
Jack = 11 ,
Queen = 12 ,
King = 13 ,
}
public class Card : IEquatable<Card> , IComparable<Card>
{
public readonly CardSuit Suit ;
public readonly CardValue Value ;
public Card( CardSuit suit , CardValue value )
{
if ( ! Enum.IsDefined(typeof(CardSuit),suit) ) throw new ArgumentOutOfRangeException("suit") ;
if ( ! Enum.IsDefined(typeof(CardValue),value) ) throw new ArgumentOutOfRangeException("value") ;
this.Suit = suit ;
this.Value = value ;
return;
}
public override int GetHashCode()
{
int value = ((int)this.Suit << 16 )
| ((int)this.Value & 0x0000FFFF )
;
return value.GetHashCode() ;
}
public bool Equals( Card other )
{
return this.Suit == other.Suit && 0 == CompareTo(other) ;
}
public int CompareTo( Card other )
{
int cc = Math.Sign( (int)this.Value - (int) other.Value ) ;
return cc;
}
}
public class DeckOfCards
{
private static Random rng = new Random() ;
private readonly IList<Card> cards ;
public DeckOfCards()
{
this.cards = new List<Card>(52) ;
foreach( CardSuit suit in Enum.GetValues(typeof(CardSuit)) )
{
foreach( CardValue value in Enum.GetValues(typeof(CardValue)) )
{
cards.Add(new Card(suit,value));
}
}
}
public void Shuffle()
{
// Fisher-Yates (Durtensfeld) shuffle algorithm: http://en.wikipedia.org/wiki/Fisher-Yates_shuffle
for ( int i = 0 ; i < cards.Count ; ++i )
{
int j = rng.Next(i,cards.Count) ;
Card t = cards[j] ;
cards[j] = cards[i] ;
cards[i] = t ;
}
return;
}
}
Proper implementation of operators comparison operators (==, !=, <, <=, >, >=) is left up to you.

Related

String of hex into a byte array? [duplicate]

This question already has answers here:
How can I convert a hex string to a byte array? [duplicate]
(4 answers)
Closed 5 years ago.
string hash = "4A|DA|6C|A9|C2|D5|71|EF|6E|2A|8C|C3|C9|4D|36|B9"
splitRHash2 = splitRHash.Split('|');
foreach (string i in splitRHash2)
{
//BYTEARRAY += Convert.ToByte(Convert.ToInt32(i, 16))???
}
I have no idea of going about this. I simply wanted this string of hex:
4ADA6CA9C2D571EF6E2A8CC3C94D36B9
Into a byte array with 16 bytes. This will greatly help me to call these values from the 'hash' and use it add round keys later on for a project. The problem is, I have no knowledge in getting the string at increments of 2 without using the .split method.
Any ideas? Thanks!!
Simply use LINQ to convert the splitted strings to bytes and to an array afterwards. Here is the code:
string hash = "4A|DA|6C|A9|C2|D5|71|EF|6E|2A|8C|C3|C9|4D|36|B9";
string[] splittedHash = hash.Split('|');
byte[] byteHash = splittedHash.Select(b => Convert.ToByte(b, 16)).ToArray();
You talking about something like this?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApp
{
class Program
{
static void Main (string[] args)
{
var str = "4ADA6CA9C2D571EF6E2A8CC3C94D36B9";
var result = Partition (str, 2).ToArray ();
}
public static IEnumerable<string> Partition (string str, int partSize)
{
if (str == null) throw new ArgumentNullException ();
if (partSize < 1) throw new ArgumentOutOfRangeException ();
var sb = new StringBuilder (partSize);
for (int i = 0; i < str.Length; i++)
{
sb.Append (str[i]);
bool isLastChar = i == str.Length - 1;
if (sb.Length == partSize || isLastChar)
{
yield return sb.ToString ();
sb.Clear ();
}
}
}
}
}
You could make the solution with only basic data structures and O(n) time like this.
string hash = "4A|DA|6C|A9|C2|D5|71|EF|6E|2A|8C|C3|C9|4D|36|B9";
byte[] result = new byte[16];
int i = 0;
int j = 0;
while(i < hash.Length)
{
byte value = (byte)(HexCharToByte(hash[i]) * 16 + HexCharToByte(hash[i + 1]));
result[j] = value;
i += 3;
j++;
}
For HexCharToByte(), you could make up something like this:
static byte HexCharToByte(char c)
{
HashSet<char> NumSet = new HashSet<char>( new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'} );
HashSet<char> CharSet = new HashSet<char>( new char[] { 'A', 'B', 'C', 'D', 'E', 'F' } );
if (NumSet.Contains(c))
{
return (byte)(c - '0');
}
else if (CharSet.Contains(c))
{
return (byte)(c - 'A' + 10);
}
throw new InvalidArgumentException("c");
}

How to call a method that takes a char array as a parameter

I have a reshuffle method that is of string type and it takes a char array as an argument it must randomize the characters inside the array each time the Encrypt method is used .. when I tried to call it in another method it gives me the syntax error "Method has some invalid arguments" This is the code
char[] p = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' };
string reshuffle(char[] alpas)
{
Random random=new Random();
for (int t = 0; t < alpas.Length; t++)
{
char tmp = alpas[t];
int r = random.Next(t, alpas.Length);
alpas[t] = alpas[r];
alpas[r] = tmp;
}
return new string (alpas);
}
public string Encrypt(string pt)
{
reshuffledChars=reshuffle(p[25]);
char[] ch = reshuffledChars.ToCharArray();
char[] buffer = new char[(pt.Length)];
for(int i=0;i<pt.Length;i++)
{
for(int j=0;j<26;j++)
{
if (char.ToUpper(p[j]) == pt[i])
{
buffer[i] = char.ToUpper(ch[j]);
break;
}
else if(char.ToLower(p[j])==pt[i])
{
buffer[i] = char.ToLower(ch[j]);
break;
}
else if(pt[i]==' ')
{
buffer[i] = ' ';
}
}
}
return new string(buffer);
}
Instead of passing reshuffle(p[25]), which is a single char, you should pass the entire array, like so: reshuffle(p).
In this line:
"reshuffledChars=reshuffle(p[25]);"
p[25] returns a char
This line in Encrypt():
reshuffle(p[25]);
should (I'm assuming) be:
reshuffle(p);
You're passing a char not a char[] to reshuffle() -- p[25] is the last char in the array p.
BTW if p should remain unchanged you'll need to copy it before passing to reshuffle.
You are passing wrong parameters instead of reshuffle(p[25]) use reshuffle(p) to send entire array.
If you are looking for a random string generator, this link will help. I have provided a working example in dotnet fiddle.
using System;
using System.Linq;
namespace Rextester
{
public class Program
{
private static Random random = new Random();
public static string RandomString(int length)
{
const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!##$%&";
return new string(Enumerable.Repeat(chars, length)
.Select(s => s[random.Next(s.Length)]).ToArray());
}
public static void Main(string[] args)
{
//Your code goes here
Console.WriteLine(RandomString(8));
}
}
}

Losing non printable ascii character (group separator) when deserializing with JsonConvert.DeserializeObject (Newtonsoft.Json)

I have a frustrating problem that I'm unable to solve. I am using Newtonsoft.Json to deserialize some .json data. I can plainly see in the raw json string that there are character sequences
{ '\\', 'u', '0', '0', '1', 'd' }
This represents "group separator" (ascii 29 or 0x1D). However, when I deserialize using JsonConvert.DeserializeObject<> these character sequences are not put correctly into their objects. What is put in instead is simply 1D. That is if you look at the character array you see:
29 '\u001d'
The 6 separate characters have been replaced by 1.
Does anyone know why this might happen? I have included a test program below. Unfortunately, it behaves exactly how I would expect. That is, the 6 characters show up in the objects field "Description". Clearly, I've missed something and not captured that actual problem and I realize one is supposed to try as hard as possible to come up with a small program that duplicates the problem in the large body of code. Unfortunately, I'm coming up blank. So, I'm asking for advice on what to look for and how this could possibly happen. What would do this replacement on a deserialization? The actual objects are more complicated than my Tanks example, but there is the ideas of IEnumerable in Tanks.
class Program
{
static void Main(string[] args)
{
JsonSerializerSettings settings = new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Ignore };
Tank tank1 = new Tank();
char[] array1 = new char[] { '1', '2', '\\', 'u', '0', '0', '1', 'd', '3', '4' };
tank1.Description = new string(array1);
tank1.Id = 1;
Console.WriteLine("Original string (showing hidden characters");
for (int i = 0; i < tank1.Description.ToArray().Length; i++)
{
Console.Write(tank1.Description.ToArray()[i] + " ");
}
Console.WriteLine();
string conversion1 = JsonConvert.SerializeObject(tank1);
Tank deserializedTank1 = JsonConvert.DeserializeObject<Tank>(conversion1, settings);
Console.WriteLine("Deserialized string (showing hidden characters");
for (int i = 0; i < deserializedTank1.Description.ToArray().Length; i++)
{
Console.Write(deserializedTank1.Description.ToArray()[i] + " ");
}
Console.WriteLine();
Tank tank2 = new Tank() { Id = 2 };
tank2.Description = new string(array1);
Tank tank3 = new Tank() { Id = 3 };
tank3.Description = new string(array1);
Tanks tanks = new Tanks();
tanks.Group = new [] { tank1, tank2, tank3};
string tanksSerializedString = JsonConvert.SerializeObject(tanks,Formatting.Indented,settings);
Tanks deserializedTanks = JsonConvert.DeserializeObject<Tanks>(tanksSerializedString, settings);
Console.WriteLine("Deserialized Tanks");
foreach (Tank tank in deserializedTanks.Group)
{
Console.WriteLine("Deserialized string (showing hidden characters");
for (int i = 0; i < tank.Description.ToArray().Length; i++)
{
Console.Write(tank.Description.ToArray()[i] + " ");
}
Console.WriteLine();
}
}
}
interface ITank
{
int Id { get; set; }
string Description { get; set; }
}
public class Tank : ITank
{
public Tank() { }
public string Description { get; set; }
public int Id { get; set; }
}
public class Tanks
{
public Tanks() { }
public IEnumerable<Tank> Group { get; set; }
}
The serializer is behaving as expected. According to the JSON Standard, a sequence of characters in the pattern \u four-hex-digits represent a single (utf16) Unicode character literal, the group separator character for \u001d:
If you don't want that, the \ character has to be escaped in the string: "\\u001d",

Regex - Improve search and add third group

This is kind of improvement of my previous question: c# generate random string based on pattern
I have code as below:
class Generator
{
private static readonly Random R = new Random();
private static readonly char[] L = { 'a', 'b', 'c', 'd', 'e' };
private static readonly char[] U = { 'A', 'B', 'C', 'D', 'E' };
private static readonly char[] S = { '!', '#', '#', '$', '%' };
public static string FromPattern(string pattern)
{
return Regex.Replace(pattern, #"\[([Ccds])(?::([\d]+))?\]", ReplaceSingleMatch);
}
private static string ReplaceSingleMatch(Match m)
{
int length;
if (!int.TryParse(m.Groups[2].Value, out length))
length = 1;
var output = new StringBuilder();
while (output.Length != length)
{
switch (m.Groups[1].Value)
{
case "d"://digits
output.Append(R.Next(0, 9));
break;
case "c"://lowercase char
output.Append(L[R.Next(L.Length)]);
break;
case "C"://uppercase char
output.Append(U[R.Next(U.Length)]);
break;
case "s"://special char
output.Append(S[R.Next(S.Length)]);
break;
}
}
return output.ToString();
}
}
Using above I can write:
Generator.FromPattern("ID: [d:3][c:2]#[C][s:2]")
And I will get sample output like : ID: 263ac#D$!
So when I enter [d] I get single digit, if I enter [d:5] I get 5 digits.
What I would like to add is range, so when I enter [d:2-5] I would get randomly from 2 to 5 random digits.
My biggest problem is regex, rest is easy :)
I need my regex to search below groups:
[d],
[d:3] (it must be number after colon),
[d:2-5] (two numbers separated by dash)
Any suggestion about improvements are welcome!
Awesome tool for regular expressions : http://www.ultrapico.com/Expresso.htm
Here's the expression I came up with (with named capture groups) :
\[(?<type>[Ccds])(:(?<a>[\d]+)(-(?<b>[\d]+))?)?\]

Generating a strong password in C#?

I was wondering how I can generate a strong and secure password in C#.
I googled a little bit and saw this formula in Wikipedia, where L is the length of the password and N is the number of possible symbols:
Also, I've found this question, but for some reason the method Membership.GeneratePassword just returns a random number with 1 digit, which absolutely no password. All the rest solutions, were very slow (>= 0.5 secs).
I need help implementing this formula (I don't know where to start). You may also suggest another solution or explain why the GeneratePassword isn't working.
I just tried the following in linqpad:
System.Web.Security.Membership.GeneratePassword(25, 10)
This is the password I got:
[XTJ_67g.i/ag1rL)6_Yv>*+%
Or, if that's not secure enough, try this:
System.Web.Security.Membership.GeneratePassword(128, 100)
which got me the following when running it three times:
|c^.:?m)#q+(]V;}[Z(})/?-;$]+#!|^/8*_9.$&.&!(?=^!Wx?[#%+&-#b;)>N;&+*w[>$2+_$%l;+h+#zhs^{e?&=*(}X_%|:}]]}*X[+)Er%J/-=;Q0{:+=%c7:^$
/:_)hxF+*){2|;(>:*N^+!_&|}B.$})?[V=[+v({-:-#9-Z$j?.[-}(#MHx+}(}Mz_S(7#4}{..>#G|!+++{+C=|_}=+r^#&$0;L*|kz-;$++/N3$=}?;%&]]*/^#^!+
:*{]-x^$g{|?*))_=B#^.#%L;g|+)#[nq}?y(_(m;]S^I$*q=l-[_/?}&-!k^(+[_{Z|&:^%!_)!=p%=)=wYd-#.UP$%s1{*l%+[%?!c+7=#=.;{+M)!^}&d/]{];(&}
this took way less than a second, btw. The framework is your friend.
See http://msdn.microsoft.com/en-us/library/system.web.security.membership.generatepassword.aspx
Not sure where I found this but here's a class to generate high entropy, truly random strings that can be used as passwords.
using System.Security.Cryptography;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
public class PasswordGenerator
{
public int MinimumLengthPassword { get; private set; }
public int MaximumLengthPassword { get; private set; }
public int MinimumLowerCaseChars { get; private set; }
public int MinimumUpperCaseChars { get; private set; }
public int MinimumNumericChars { get; private set; }
public int MinimumSpecialChars { get; private set; }
public static string AllLowerCaseChars { get; private set; }
public static string AllUpperCaseChars { get; private set; }
public static string AllNumericChars { get; private set; }
public static string AllSpecialChars { get; private set; }
private readonly string _allAvailableChars;
private readonly RandomSecureVersion _randomSecure = new RandomSecureVersion();
private int _minimumNumberOfChars;
static PasswordGenerator()
{
// Define characters that are valid and reject ambiguous characters such as ilo, IO and 1 or 0
AllLowerCaseChars = GetCharRange('a', 'z', exclusiveChars: "ilo");
AllUpperCaseChars = GetCharRange('A', 'Z', exclusiveChars: "IO");
AllNumericChars = GetCharRange('2', '9');
AllSpecialChars = "!##%*()$?+-=";
}
public PasswordGenerator(
int minimumLengthPassword = 15,
int maximumLengthPassword = 20,
int minimumLowerCaseChars = 2,
int minimumUpperCaseChars = 2,
int minimumNumericChars = 2,
int minimumSpecialChars = 2)
{
if (minimumLengthPassword < 15)
{
throw new ArgumentException("The minimumlength is smaller than 15.",
"minimumLengthPassword");
}
if (minimumLengthPassword > maximumLengthPassword)
{
throw new ArgumentException("The minimumLength is bigger than the maximum length.",
"minimumLengthPassword");
}
if (minimumLowerCaseChars < 2)
{
throw new ArgumentException("The minimumLowerCase is smaller than 2.",
"minimumLowerCaseChars");
}
if (minimumUpperCaseChars < 2)
{
throw new ArgumentException("The minimumUpperCase is smaller than 2.",
"minimumUpperCaseChars");
}
if (minimumNumericChars < 2)
{
throw new ArgumentException("The minimumNumeric is smaller than 2.",
"minimumNumericChars");
}
if (minimumSpecialChars < 2)
{
throw new ArgumentException("The minimumSpecial is smaller than 2.",
"minimumSpecialChars");
}
_minimumNumberOfChars = minimumLowerCaseChars + minimumUpperCaseChars +
minimumNumericChars + minimumSpecialChars;
if (minimumLengthPassword < _minimumNumberOfChars)
{
throw new ArgumentException(
"The minimum length of the password is smaller than the sum " +
"of the minimum characters of all catagories.",
"maximumLengthPassword");
}
MinimumLengthPassword = minimumLengthPassword;
MaximumLengthPassword = maximumLengthPassword;
MinimumLowerCaseChars = minimumLowerCaseChars;
MinimumUpperCaseChars = minimumUpperCaseChars;
MinimumNumericChars = minimumNumericChars;
MinimumSpecialChars = minimumSpecialChars;
_allAvailableChars =
OnlyIfOneCharIsRequired(minimumLowerCaseChars, AllLowerCaseChars) +
OnlyIfOneCharIsRequired(minimumUpperCaseChars, AllUpperCaseChars) +
OnlyIfOneCharIsRequired(minimumNumericChars, AllNumericChars) +
OnlyIfOneCharIsRequired(minimumSpecialChars, AllSpecialChars);
}
private string OnlyIfOneCharIsRequired(int minimum, string allChars)
{
return minimum > 0 || _minimumNumberOfChars == 0 ? allChars : string.Empty;
}
public string Generate()
{
var lengthOfPassword = _randomSecure.Next(MinimumLengthPassword, MaximumLengthPassword);
// Get the required number of characters of each catagory and
// add random charactes of all catagories
var minimumChars = GetRandomString(AllLowerCaseChars, MinimumLowerCaseChars) +
GetRandomString(AllUpperCaseChars, MinimumUpperCaseChars) +
GetRandomString(AllNumericChars, MinimumNumericChars) +
GetRandomString(AllSpecialChars, MinimumSpecialChars);
var rest = GetRandomString(_allAvailableChars, lengthOfPassword - minimumChars.Length);
var unshuffeledResult = minimumChars + rest;
// Shuffle the result so the order of the characters are unpredictable
var result = unshuffeledResult.ShuffleTextSecure();
return result;
}
private string GetRandomString(string possibleChars, int lenght)
{
var result = string.Empty;
for (var position = 0; position < lenght; position++)
{
var index = _randomSecure.Next(possibleChars.Length);
result += possibleChars[index];
}
return result;
}
private static string GetCharRange(char minimum, char maximum, string exclusiveChars = "")
{
var result = string.Empty;
for (char value = minimum; value <= maximum; value++)
{
result += value;
}
if (!string.IsNullOrEmpty(exclusiveChars))
{
var inclusiveChars = result.Except(exclusiveChars).ToArray();
result = new string(inclusiveChars);
}
return result;
}
}
internal static class Extensions
{
private static readonly Lazy<RandomSecureVersion> RandomSecure =
new Lazy<RandomSecureVersion>(() => new RandomSecureVersion());
public static IEnumerable<T> ShuffleSecure<T>(this IEnumerable<T> source)
{
var sourceArray = source.ToArray();
for (int counter = 0; counter < sourceArray.Length; counter++)
{
int randomIndex = RandomSecure.Value.Next(counter, sourceArray.Length);
yield return sourceArray[randomIndex];
sourceArray[randomIndex] = sourceArray[counter];
}
}
public static string ShuffleTextSecure(this string source)
{
var shuffeldChars = source.ShuffleSecure().ToArray();
return new string(shuffeldChars);
}
}
internal class RandomSecureVersion
{
//Never ever ever never use Random() in the generation of anything that requires true security/randomness
//and high entropy or I will hunt you down with a pitchfork!! Only RNGCryptoServiceProvider() is safe.
private readonly RNGCryptoServiceProvider _rngProvider = new RNGCryptoServiceProvider();
public int Next()
{
var randomBuffer = new byte[4];
_rngProvider.GetBytes(randomBuffer);
var result = BitConverter.ToInt32(randomBuffer, 0);
return result;
}
public int Next(int maximumValue)
{
// Do not use Next() % maximumValue because the distribution is not OK
return Next(0, maximumValue);
}
public int Next(int minimumValue, int maximumValue)
{
var seed = Next();
// Generate uniformly distributed random integers within a given range.
return new Random(seed).Next(minimumValue, maximumValue);
}
}
Consume in your code thusly:
var generator = new PasswordGenerator();
string password = generator.Generate();
Console.WriteLine(password);
To address your question about that formula:
The formula is saying that a password of length L drawn from an alphabet of N symbols is equivalent to a password of length H drawn from an alphabet of two symbols. So if you have, say, 64 symbols (say abc...xyzABC...XYZ01...89_!) and the password is 10 characters long, then that gives you equivalent security to a password 10 log2 64 = 60 characters long drawn from the alphabet "ab".
A "log" is the inverse operation of exponentiation. Two to the sixth power gives you sixty-four, therefore the "log two" of sixty-four gives you six.
I don't know if this will help you, but this is what I use when I want to generate a random password which is also strong. It's quick and simple to implement/understand and isn't as much of an overkill as the one through the membership provider above...
private string Token(byte Length) {
char[] Chars = new char[] {
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
};
string String = string.Empty;
Random Random = new Random();
for (byte a = 0; a < Length; a++) {
String += Chars[Random.Next(0, 61)];
};
return (String);
}
Why not just fill an array with some characters and pick on random a number of them. You can divide them in groups to be sure that are include letters numbers and special characters.
You will also have to pick a proper length and how much of every group of characters to include and that's it. I don't think you need some sophisticated formulas.
For systems that don't allow user-generated passwords it's very easy, actually: Any password is as secure as it's long. Not counting, of course, people who tack post-its to monitors, etc.
You probably want to maximize the set of characters from which the password is generated. But restricting the generated passwords greatly reduces the search space and therefore makes the password less secure. Again, this only holds if the user can't choose their own password.
If you deal with both generated and user-created passwords, then all bets are off, obviously. You then probably want to generate the passwords in a way that it uses as many characters from different classes as possible, resembling a strong user-chosen password. Ideally it should conform to the same constraints that the user-created password has to pass as well (if any).
I used random string from characters like below
public static string RandomString(int length)
{
const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789&?%$#";
return new string(Enumerable.Repeat(chars, length)
.Select(s => s[Random.Next(s.Length)]).ToArray());
}

Categories

Resources