|
I believe that if the RepeatCharacters bool is set to false (do not allow repeat chars) and the password length is greater than the length of available chars, then the generate code enters an infinite loop.
A quick fix would be to ignore the RepeatCharacters value and continue reusing those characters after that point, as in the code below: (or just return the results thus far)
if ( false == this.RepeatCharacters )
{
string temp = pwdBuffer.ToString();
int duplicateIndex = temp.IndexOf(nextCharacter);
int upperBound = pwdCharArray.GetUpperBound(0);
if ( true == this.ExcludeSymbols )
{
upperBound = PasswordGenerator.UBoundDigit;
}
if (pwdLength <= upperBound)
{
while ( -1 != duplicateIndex )
{
nextCharacter = GetRandomCharacter();
duplicateIndex = temp.IndexOf(nextCharacter);
}
}
}
Although this takes into account the upperBound of the available chars, it does not include the count of the excluded chars list.
.frihani
|
|
|
|
|
Here's my alternative, shorter version:
public class AlphaNumericPasswordGenerator
{
public string Generate()
{
return MD5Hash(this.secondsSinceEpoch().ToString());
}
private int secondsSinceEpoch()
{
TimeSpan timeSpan = (DateTime.UtcNow - new DateTime(1970, 1, 1));
return (int) timeSpan.TotalSeconds;
}
private string MD5Hash(string Data)
{
MD5 md5 = new MD5CryptoServiceProvider();
byte[] hash = md5.ComputeHash( Encoding.ASCII.GetBytes(Data) );
StringBuilder stringBuilder = new StringBuilder();
foreach( byte b in hash )
{
stringBuilder.AppendFormat("{0:x2}", b);
}
return stringBuilder.ToString();
}
}
www.sloppycode.net
|
|
|
|
|
Nice! Thanks for sharing your approach.
Kevin
"Semicolons in a programming language are like mother's milk."
|
|
|
|
|
Worth noting that mine doesn't work unless you Thread.Sleep(100) and use the random number generator, if you're generating inside a loop!
|
|
|
|
|
Thread.Sleep() for the same amount of time each time will make this predictable after enough generations. If you want to use md5 to get alphanumerics, use input data like so:
rndBytes = new byte[arraySize];<br />
rng = new RNGCryptoServiceProvider();<br />
md5 = new MD5CryptoServiceProvider();<br />
<br />
rng.GetBytes(rndBytes);
byte[] outArray = md5.ComputeHash(rndBytes);<br />
StringBuilder stringBuilder = new StringBuilder();<br />
foreach( byte b in outArray ) {<br />
stringBuilder.AppendFormat("{0:x2}", b);<br />
}<br />
return stringBuilder.ToString();
|
|
|
|
|
public bool Validate(string password)
{
int iCount = 0;
if (password.Length < minSize || password.Length > maxSize)
return(false);
if (!hasConsecutive)
{
for (iCount = 0; iCount < password.Length-1; iCount++)
{
if (password[iCount] == password[iCount+1])
return(false);
}
}
if (!hasRepeating)
{
for (iCount = 0; iCount < password.Length; iCount++)
{
int index = password.IndexOf(password[iCount]);
while (index != -1)
{
if (index != iCount)
return(false);
index = password.IndexOf(password[iCount]);
}
}
}
if (Exclusions != null)
{
for (iCount = 0; iCount < password.Length; iCount++)
{
if (Exclusions.IndexOf(password[iCount]) != -1)
return(false);
}
}
if (ExcludeSymbols)
{
for (iCount = UBoundDigit; iCount < pwdCharArray.GetUpperBound(0); iCount++)
{
if (password.IndexOf(pwdCharArray[iCount]) != -1)
return(false);
}
}
return(true);
}
|
|
|
|
|
Thanks, Dirk! I should've implemented validation in the original code, but I'm a slacker. However, I have been considering a new version where you can specify a regular expression as a way to generate the password. Then, you could use the same input regex to validate the output. I'll post it once I get around to writing it!
Kevin
"Semicolons in a programming language are like mother's milk."
|
|
|
|
|
Is it my imagination...or does GetCryptographicRandomNumber not seem to return an integer between the lbound and ubound!
|
|
|
|
|
nope...it was my imagination after all!
|
|
|
|
|
Hello. I am very new in C programing. i have to do a class project and would really love to include a password requester in it. Where, when someone presses a set of keys, another screen will pop out and request for a password to shut the program down. With out the right pass the pop out will close and return to the original page.
A few things you might want to know.
1)The user cannot use the mouse to shut the program down.
2)I was wondering if i could include the if and else commands on the pop out for the password page.
like
if(password is right)
{
Allow shut down.
}
else
{
pop up closes
}
But was thinking, it won't be case sensitive.
So, i really need all of your expertise. Please... I need it badly. PLease help. I might get lost on this new found site. So if possible, you can reply to me via e-mail at goddime@yahoo.ca
Or else, i would try to find this forum again. thanks alot for your kind help.
Oh yah.. since i am so new, i really hope you can include the command from starting to end. Which includes #include <stdio.h> and ends with
system("pause");
return 0
}
Cos i keep getting confused with the codes on this site. Finally, I need the code in C program. Not other compilers. Teacher's rule. I hope you can include lots of details. So i know why and how the code is working, and created. thanks alot.
|
|
|
|
|
private char[] pwdCharArray = {<br />
'a','b','c','d','e','f','g','h','i','j','k','l','m',<br />
'n','o','p','q','r','s','t','u','v','w','x','y','z',<br />
'A','B','C','D','E','F','G','H','I','J','K','L','M',<br />
'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',<br />
'0','1','2','3','4','5','6','7','8','9','`','~','!',<br />
'@','#','$','%','^','&','*','(',')','-','_','=','+',<br />
'[',']','{','}','\\','|',';',':','\'','"',',','<',<br />
'.','>','/','?'<br />
}
can be simplified (for ease of typing, and perhaps also reading) using the string's ToCharArray() method, to:
<br />
private char[] pwdCharArray = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789`~!@#$%^&*()-_=+[]{}\\|;:'\",<.>/?".ToCharArray();<br />
|
|
|
|
|
Good suggestion! Might make it into my next update. Thanks!
Kevin
"Semicolons in a programming language are like mother's milk."
|
|
|
|
|
Interesting article, but there is a not so small gotcha.
A rather large bias is introduced in this line in GetCryptographicRandomNumber()
int number = ( Int32.Parse(rndnum[0].ToString()) % uBound )
The problem is that the modulo operator "%" will produce an uneven distribution, especially where the operand is only a byte (0-255). The bias is variable depending on the value of upperBound and can significantly skew the distributions of characters. If you increase the random number range to 32 bits it won't eliminate the bias but it becomes trivial.
Also this section has a significant bias to return lBound whenever lBound is >0.
if ( lBound > number )
{
number = lBound;
}
-Marty
|
|
|
|
|
Here's a possible hack:
protected int GetCryptographicRandomNumber(int lBound, int uBound)
{
byte[] rndnum = new Byte[4];
rng.GetBytes(rndnum);
uint urndnum = System.BitConverter.ToUInt32(rndnum,0);
return (int)(urndnum % (uBound-lBound)) + lBound;
}
-Marty
|
|
|
|
|
You made a couple of very good points, Marty.
Alternatively, you can simply reject values outside the requested range. This removes any bias that is not in the random number generator itself, including the 0.00001% that's left in your solution.
protected int GetCryptographicRandomNumber(int lBound, int uBound)
{
byte[] rndnum = new Byte[1];
int number;
do
{
rng.GetBytes(rndnum);
number = Convert.ToInt32(rndnum[0]) & 0x7F;
} while (number < lBound || number > uBound);
return number;
} Note that the "& 0x7F " should be removed if uBound can be larger than 127.
If you're concerned about performance, you can work with a buffer of random bytes to minimize calls to GetBytes and/or reduce your random byte to the smallest range 0 to 2^n-1 that fits lBound and uBound. However, since we're not generating millions of passwords here, I don't think that's much of a concern.
Jeffrey
Everything should be as simple as possible, but not simpler. -- Albert Einstein
http://www.extremeoptimization.com/
|
|
|
|
|
I was wondering how long it would take for someone to grab that residual bias "bait" Chuckle.
It does show how subtle flaws can be in these sorts of things. I also concur about the linear congruential generator being flawed. The rand() in clib is so badly biased that Monte Carlo simulations of a craps game materially diverges (p <.001) from it's estimate after 10^10 passes. I went to a crypto level rnd gen as a result. It's amazing what can be done with "microprocessors" these days.
-Marty
|
|
|
|
|
Now I see what happens when you sleep through probability and statistics.
You both make excellent points and I will incorporate one of your proposed solutions in the next update, which will probably be today or tomorrow since it looks like the article posting got messed up a bit. Thanks for the feedback!
Kevin
"Semicolons in a programming language are like mother's milk."
|
|
|
|
|
Kevin,
Here's a hack that incorporates Jeffrey's exclusion and eliminates likely very long while() loops that can occur when lBound is close to uBound.
protected int GetCryptographicRandomNumber(int lBound, int uBound)
{
uint urndnum;
byte[] rndnum = new Byte[4];
if (lBound == uBound-1)
return lBound;
uint xcludeRndBase = (uint.MaxValue - (uint.MaxValue%(uint)(uBound-lBound)));
do {
rng.GetBytes(rndnum);
urndnum = System.BitConverter.ToUInt32(rndnum,0);
} while (urndnum >= xcludeRndBase);
return (int)(urndnum % (uBound-lBound)) + lBound;
}
-Marty
|
|
|
|
|
Nice hack. Passed my unit tests, so it's in the code now. I'll be sending out the update later this evening. Thanks!
Kevin
"Semicolons in a programming language are like mother's milk."
|
|
|
|
|
I see talk of a version that has some of the improvements discussed.
(checkboxes, crypto random, exclusion fixed for .NET 1.1, performance, ASP. NET..)
am I missing something or is that version not posted yet - (not trying to rush you - but when it is done, this is where it will be posted, right ? )
|
|
|
|
|
I sent the update in to be posted, but it looks like both the article and the downloads got a little screwed up. I'll try and get it fixed today.
Kevin
"Semicolons in a programming language are like mother's milk."
|
|
|
|
|
You may want to replace the Random class with RNGCryptoServiceProvider .
From the MSDN documentation[^]:
"To generate a cryptographically secure random number suitable for creating a random password, for example, use a class derived from System.Security.Cryptography.RandomNumberGenerator such as System.Security.Cryptography.RNGCryptoServiceProvider."
The reason is, apparently, that the System.Random class uses a linear algorithm which has some not-quite-perfect randomness properties that a password cracker might be able to exploit. The cryptographic generator uses a nonlinear algorithm which doesn't suffer from this deficiency.
Jeffrey
Everything should be as simple as possible, but not simpler. -- Albert Einstein
http://www.extremeoptimization.com/
|
|
|
|
|
OK, OK...you got me. I was being lazy. So, of course, I will change the implementation. Man, my to-do list for this code just keeps getting longer...
Kevin
"Semicolons in a programming language are like mother's milk."
|
|
|
|
|
1) Congratulations
2)On NET FRAMEWORK 1.1, the exclusions option doesn't run.
The ToString() method on a char array returns System.Char[] ...
Here the modification :
if ( ( null != this.Exclusions )&& (true == hasExclusions) )
{
foreach(char item in this.Exclusions)
{
if(item.Equals(nextCharacter))
{
nextCharacter = GetRandomCharacter(charFlag);
break;
}
}
}
Best Regards
|
|
|
|
|
Thanks! I just got Visual Studio.NET 2003 and will be making a few modifications to the code with it and test it using .NET 1.1. I should have a new posting in a few days.
Kevin
"Semicolons in a programming language are like mother's milk."
|
|
|
|
|