Although online password generators are never truly random, the chances of someone guessing the password created are incredibly slim. Therefore, it can easily be said that using a random password generator is generally safe.
No, not all “random password generators” create truly random results. If I use a generic random password generator to create 10,000 new passwords, the passwords I generated are the result of a phenomenon called pseudo-random, meaning the results appear random when they really aren't.
Google Chrome offers to save passwords for all your online accounts. It then stores and syncs them to your Google account as part of the Smart Lock feature. Chrome also has a built-in password generator that automatically creates strong passwords at the click of a button.
There's always System.Web.Security.Membership.GeneratePassword(int length, int numberOfNonAlphanumericCharacters
).
public string CreatePassword(int length)
{
const string valid = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
StringBuilder res = new StringBuilder();
Random rnd = new Random();
while (0 < length--)
{
res.Append(valid[rnd.Next(valid.Length)]);
}
return res.ToString();
}
This has a good benefit of being able to choose from a list of available characters for the generated password (e.g. digits only, only uppercase or only lowercase etc.)
The main goals of my code are:
The first property is achieved by taking a 64 bit value modulo the alphabet size. For small alphabets (such as the 62 characters from the question) this leads to negligible bias. The second and third property are achieved by using RNGCryptoServiceProvider
instead of System.Random
.
using System;
using System.Security.Cryptography;
public static string GetRandomAlphanumericString(int length)
{
const string alphanumericCharacters =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
"abcdefghijklmnopqrstuvwxyz" +
"0123456789";
return GetRandomString(length, alphanumericCharacters);
}
public static string GetRandomString(int length, IEnumerable<char> characterSet)
{
if (length < 0)
throw new ArgumentException("length must not be negative", "length");
if (length > int.MaxValue / 8) // 250 million chars ought to be enough for anybody
throw new ArgumentException("length is too big", "length");
if (characterSet == null)
throw new ArgumentNullException("characterSet");
var characterArray = characterSet.Distinct().ToArray();
if (characterArray.Length == 0)
throw new ArgumentException("characterSet must not be empty", "characterSet");
var bytes = new byte[length * 8];
new RNGCryptoServiceProvider().GetBytes(bytes);
var result = new char[length];
for (int i = 0; i < length; i++)
{
ulong value = BitConverter.ToUInt64(bytes, i * 8);
result[i] = characterArray[value % (uint)characterArray.Length];
}
return new string(result);
}
(This is a copy of my answer to How can I generate random 8 character, alphanumeric strings in C#?)
public string GenerateToken(int length)
{
using (RNGCryptoServiceProvider cryptRNG = new RNGCryptoServiceProvider())
{
byte[] tokenBuffer = new byte[length];
cryptRNG.GetBytes(tokenBuffer);
return Convert.ToBase64String(tokenBuffer);
}
}
(You could also have the class where this method lives implement IDisposable, hold a reference to the RNGCryptoServiceProvider
, and dispose of it properly, to avoid repeatedly instantiating it.)
It's been noted that as this returns a base-64 string, the output length is always a multiple of 4, with the extra space using =
as a padding character. The length
parameter specifies the length of the byte buffer, not the output string (and is therefore perhaps not the best name for that parameter, now I think about it). This controls how many bytes of entropy the password will have. However, because base-64 uses a 4-character block to encode each 3 bytes of input, if you ask for a length that's not a multiple of 3, there will be some extra "space", and it'll use =
to fill the extra.
If you don't like using base-64 strings for any reason, you can replace the Convert.ToBase64String()
call with either a conversion to regular string, or with any of the Encoding
methods; eg. Encoding.UTF8.GetString(tokenBuffer)
- just make sure you pick a character set that can represent the full range of values coming out of the RNG, and that produces characters that are compatible with wherever you're sending or storing this. Using Unicode, for example, tends to give a lot of Chinese characters. Using base-64 guarantees a widely-compatible set of characters, and the characteristics of such a string shouldn't make it any less secure as long as you use a decent hashing algorithm.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With