views:

134

answers:

5

Hello all,

I'm new to .NET and C# and I'm trying to figure out how this code works:

public static string CreateRandomPassword(int PasswordLength)
{
  String _allowedChars = "abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ23456789";
  Byte[] randomBytes = new Byte[PasswordLength];
  RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
  rng.GetBytes(randomBytes);
  char[] chars = new char[PasswordLength];
  int allowedCharCount = _allowedChars.Length;

  for(int i = 0;i<PasswordLength;i++)
  {
      ///
      /// I don't understand how this line works:
      ///
      chars[i] = _allowedChars[(int)randomBytes[i] % allowedCharCount];
  }

  return new string(chars);
}

I think I've got a pretty good handle on most of this. I haven't been able to understand the following line:

chars[i] = _allowedChars[(int)randomBytes[i] % allowedCharCount];

I understand that the code generates random binary numbers and uses those random numbers in the for loop to select a character from the _allowedChars string. What I don't get is why this code uses the modulous operator (%) to get the _allowedChars index value.

Thanks for any help

A: 

It uses the modulus operator because randomBytes[i] could hold a value larger than the length of the _allowedChars array.

By using % allowedCharCount it ensures that the index into _allowedChars is always within range. Otherwise the code would have the potential to raise an exception on that line.

ChrisF
A: 

You're working modulo allowedCharCount, this ensure that the number generated is between 0 and allowedCharCount so that no IndexOutOfRange exception is thrown.

Baddie
A: 

Using mod ensures that the number is between 0 and allowedCharCount - it prevents an index out of range exception. Without it, you'd have to restrict the range of the randomly generated numbers, which isn't possible with the crypto provider. It also means that you can change the list of allowed characters in the string without the code breaking.

Dan Puzey
+2  A: 

The value of randomBytes[i] can be any integer from 0 through 255. The length of the _allowedChars array is less than 255. The modules operator returns the remainder of dividing the first argument ((int)randomBytes[i]) by the second argument (allowedCharCount). This ensures that the value we index the _allowedChars array with (the result of the modulo operator) is always less than the allowedCharacterCount.

qstarin
Sweet... I get it.
quakkels
Cool .. I'm glad my explanation clicked for you.
qstarin
+2  A: 

This is only a side note, but that code is subtly broken. The modulus operator (%) used to select which character to pick is not uniform: it's going to prefer some characters (those nearer the front of the array) more than others, meaning the password is not truly random. An attacker can use that to try higher-probability passwords first, and significantly reduce the time it takes to complete a crack.

Joel Coehoorn
hmmmm... is there a simple solution?
quakkels
+1: I was about to post the same observation. It's possible that biased results aren't a problem for the OP, but if that's the case then why not just use (simpler, faster) `Random` rather than `RNGCryptoServiceProvider`?
LukeH
@quakkels - base64 encode the bytes
Joel Coehoorn
The reason I'm working on this code structure is because of the following article: http://www.aspheute.com/english/20040105.aspIs there any resource you guys can suggest?
quakkels
@Joel Coehoorn - base64 encode? I'm sorry for asking you to spell it out for me, but, what would change if I use base64?
quakkels
Don't forget, there's always this: http://msdn.microsoft.com/en-us/library/system.web.security.membership.generatepassword.aspx
Chris
@chris - woah... well that makes it easy!!!
quakkels