How To: Generate a Random Password (C#/VB.NET)
The code below can be used to generate a strong random password, which does not contain ambiguous characters (such as [1,l,I] or [O,0]). Code samples are provided in C# and Visual Basic.NET.
C# code
[printer-friendly version] [code output]
using System;
using System.Security.Cryptography;
public class RandomPassword
{
private static int DEFAULT_MIN_PASSWORD_LENGTH = 8;
private static int DEFAULT_MAX_PASSWORD_LENGTH = 10;
private static string PASSWORD_CHARS_LCASE = "abcdefgijkmnopqrstwxyz";
private static string PASSWORD_CHARS_UCASE = "ABCDEFGHJKLMNPQRSTWXYZ";
private static string PASSWORD_CHARS_NUMERIC= "23456789";
private static string PASSWORD_CHARS_SPECIAL= "*$-+?_&=!%{}/";
public static string Generate()
{
return Generate(DEFAULT_MIN_PASSWORD_LENGTH,
DEFAULT_MAX_PASSWORD_LENGTH);
}
public static string Generate(int length)
{
return Generate(length, length);
}
public static string Generate(int minLength,
int maxLength)
{
if (minLength <= 0 || maxLength <= 0 || minLength > maxLength)
return null;
char[][] charGroups = new char[][]
{
PASSWORD_CHARS_LCASE.ToCharArray(),
PASSWORD_CHARS_UCASE.ToCharArray(),
PASSWORD_CHARS_NUMERIC.ToCharArray(),
PASSWORD_CHARS_SPECIAL.ToCharArray()
};
int[] charsLeftInGroup = new int[charGroups.Length];
for (int i=0; i<charsLeftInGroup.Length; i++)
charsLeftInGroup[i] = charGroups[i].Length;
int[] leftGroupsOrder = new int[charGroups.Length];
for (int i=0; i<leftGroupsOrder.Length; i++)
leftGroupsOrder[i] = i;
byte[] randomBytes = new byte[4];
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
rng.GetBytes(randomBytes);
int seed = (randomBytes[0] & 0x7f) << 24 |
randomBytes[1] << 16 |
randomBytes[2] << 8 |
randomBytes[3];
Random random = new Random(seed);
char[] password = null;
if (minLength < maxLength)
password = new char[random.Next(minLength, maxLength+1)];
else
password = new char[minLength];
int nextCharIdx;
int nextGroupIdx;
int nextLeftGroupsOrderIdx;
int lastCharIdx;
int lastLeftGroupsOrderIdx = leftGroupsOrder.Length - 1;
for (int i=0; i<password.Length; i++)
{
if (lastLeftGroupsOrderIdx == 0)
nextLeftGroupsOrderIdx = 0;
else
nextLeftGroupsOrderIdx = random.Next(0,
lastLeftGroupsOrderIdx);
nextGroupIdx = leftGroupsOrder[nextLeftGroupsOrderIdx];
lastCharIdx = charsLeftInGroup[nextGroupIdx] - 1;
if (lastCharIdx == 0)
nextCharIdx = 0;
else
nextCharIdx = random.Next(0, lastCharIdx+1);
password[i] = charGroups[nextGroupIdx][nextCharIdx];
if (lastCharIdx == 0)
charsLeftInGroup[nextGroupIdx] =
charGroups[nextGroupIdx].Length;
else
{
if (lastCharIdx != nextCharIdx)
{
char temp = charGroups[nextGroupIdx][lastCharIdx];
charGroups[nextGroupIdx][lastCharIdx] =
charGroups[nextGroupIdx][nextCharIdx];
charGroups[nextGroupIdx][nextCharIdx] = temp;
}
charsLeftInGroup[nextGroupIdx]--;
}
if (lastLeftGroupsOrderIdx == 0)
lastLeftGroupsOrderIdx = leftGroupsOrder.Length - 1;
else
{
if (lastLeftGroupsOrderIdx != nextLeftGroupsOrderIdx)
{
int temp = leftGroupsOrder[lastLeftGroupsOrderIdx];
leftGroupsOrder[lastLeftGroupsOrderIdx] =
leftGroupsOrder[nextLeftGroupsOrderIdx];
leftGroupsOrder[nextLeftGroupsOrderIdx] = temp;
}
lastLeftGroupsOrderIdx--;
}
}
return new string(password);
}
}
public class RandomPasswordTest
{
[STAThread]
static void Main(string[] args)
{
for (int i=0; i<100; i++)
Console.WriteLine(RandomPassword.Generate(8, 10));
}
}
^ Back to top
VB.NET code
[printer-friendly version] [code output]
Imports System
Imports System.Security.Cryptography
Module Module1
Public Class RandomPassword
Private Shared DEFAULT_MIN_PASSWORD_LENGTH As Integer = 8
Private Shared DEFAULT_MAX_PASSWORD_LENGTH As Integer = 10
Private Shared PASSWORD_CHARS_LCASE As String = "abcdefgijkmnopqrstwxyz"
Private Shared PASSWORD_CHARS_UCASE As String = "ABCDEFGHJKLMNPQRSTWXYZ"
Private Shared PASSWORD_CHARS_NUMERIC As String= "23456789"
Private Shared PASSWORD_CHARS_SPECIAL As String= "*$-+?_&=!%{}/"
Public Shared Function Generate() As String
Generate = Generate(DEFAULT_MIN_PASSWORD_LENGTH, _
DEFAULT_MAX_PASSWORD_LENGTH)
End Function
Public Shared Function Generate(length As Integer) As String
Generate = Generate(length, length)
End Function
Public Shared Function Generate(minLength As Integer, _
maxLength As Integer) _
As String
If (minLength <= 0 Or maxLength <= 0 Or minLength > maxLength) Then
Generate = Nothing
End If
Dim charGroups As Char()() = New Char()() _
{ _
PASSWORD_CHARS_LCASE.ToCharArray(), _
PASSWORD_CHARS_UCASE.ToCharArray(), _
PASSWORD_CHARS_NUMERIC.ToCharArray(), _
PASSWORD_CHARS_SPECIAL.ToCharArray() _
}
Dim charsLeftInGroup As Integer() = New Integer(charGroups.Length-1){}
Dim I As Integer
For I=0 To charsLeftInGroup.Length-1
charsLeftInGroup(I) = charGroups(I).Length
Next
Dim leftGroupsOrder As Integer() = New Integer(charGroups.Length-1){}
For I=0 To leftGroupsOrder.Length-1
leftGroupsOrder(I) = I
Next
Dim randomBytes As Byte() = New Byte(3){}
Dim rng As RNGCryptoServiceProvider = New RNGCryptoServiceProvider()
rng.GetBytes(randomBytes)
Dim seed As Integer = ((randomBytes(0) And &H7f) << 24 Or _
randomBytes(1) << 16 Or _
randomBytes(2) << 8 Or _
randomBytes(3))
Dim random As Random = New Random(seed)
Dim password As Char() = Nothing
If (minLength < maxLength) Then
password = New Char(random.Next(minLength-1, maxLength)){}
Else
password = New Char(minLength-1){}
End If
Dim nextCharIdx As Integer
Dim nextGroupIdx As Integer
Dim nextLeftGroupsOrderIdx As Integer
Dim lastCharIdx As Integer
Dim lastLeftGroupsOrderIdx As Integer = leftGroupsOrder.Length-1
For I=0 To password.Length-1
If (lastLeftGroupsOrderIdx = 0) Then
nextLeftGroupsOrderIdx = 0
Else
nextLeftGroupsOrderIdx = random.Next(0, lastLeftGroupsOrderIdx)
End If
nextGroupIdx = leftGroupsOrder(nextLeftGroupsOrderIdx)
lastCharIdx = charsLeftInGroup(nextGroupIdx)-1
If (lastCharIdx = 0) Then
nextCharIdx = 0
Else
nextCharIdx = random.Next(0, lastCharIdx+1)
End If
password(I) = charGroups(nextGroupIdx)(nextCharIdx)
If (lastCharIdx = 0) Then
charsLeftInGroup(nextGroupIdx) = _
charGroups(nextGroupIdx).Length
Else
If (lastCharIdx <> nextCharIdx) Then
Dim temp As Char = charGroups(nextGroupIdx)(lastCharIdx)
charGroups(nextGroupIdx)(lastCharIdx) = _
charGroups(nextGroupIdx)(nextCharIdx)
charGroups(nextGroupIdx)(nextCharIdx) = temp
End If
charsLeftInGroup(nextGroupIdx) = _
charsLeftInGroup(nextGroupIdx)-1
End If
If (lastLeftGroupsOrderIdx = 0) Then
lastLeftGroupsOrderIdx = leftGroupsOrder.Length-1
Else
If (lastLeftGroupsOrderIdx <> nextLeftGroupsOrderIdx) Then
Dim temp As Integer = _
leftGroupsOrder(lastLeftGroupsOrderIdx)
leftGroupsOrder(lastLeftGroupsOrderIdx) = _
leftGroupsOrder(nextLeftGroupsOrderIdx)
leftGroupsOrder(nextLeftGroupsOrderIdx) = temp
End If
lastLeftGroupsOrderIdx = lastLeftGroupsOrderIdx - 1
End If
Next
Generate = New String(password)
End Function
End Class
Sub Main()
Dim I As Integer
For I=1 To 100
Console.WriteLine(RandomPassword.Generate(8, 10))
Next
End Sub
End Module
^ Back to top
Code Output
B$g3-6YpjA
Nk5{!Yb37
P}o8wX7$!
Dc5+t=Q8}P
gG_2?a4H
yW}5K3w*9
Qr9%5-jHg
8Bg%s*A63q
3Nd?E{5jxY
2Kf!s}E9
3z$XN9q*+
...
T!b68C*wt
^ Back to top
|
请发表评论