You're here: Snippet Directory » Microsoft .NET » Security (14)
Language:

Random Password

Language: English
Programming Language: C#
Published by: Thomas
Last Update: 5/4/2006
Views: 1195

Description

Generates a random Passwordstring. You can define which characters could be contained in it in constances PASSWORD_CHARS_LCASE, PASSWORD_CHARS_UCASE, PASSWORD_CHARS_NUMERIC and PASSWORD_CHARS_SPECIAL.

Code

1 using System; 2 3 namespace AppSecurity { 4 /////////////////////////////////////////////////////////////////////////////// 5 // SAMPLE: Generates random password, which complies with the strong password 6 // rules and does not contain ambiguous characters. 7 // 8 // To run this sample, create a new Visual C# project using the Console 9 // Application template and replace the contents of the Class1.cs file with 10 // the code below. 11 // 12 // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, 13 // EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED 14 // WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. 15 // 16 // Copyright (C) 2004. Obviex(TM). All rights reserved. 17 // 18 using System; 19 using System.Security.Cryptography; 20 21 /// <summary> 22 /// This class can generate random passwords, which do not include ambiguous 23 /// characters, such as I, l, and 1. The generated password will be made of 24 /// 7-bit ASCII symbols. Every four characters will include one lower case 25 /// character, one upper case character, one number, and one special symbol 26 /// (such as '%') in a random order. The password will always start with an 27 /// alpha-numeric character; it will not start with a special symbol. 28 /// </summary> 29 public class RandomPassword { 30 // Define default min and max password lengths. 31 private static int DEFAULT_MIN_PASSWORD_LENGTH = 8; 32 private static int DEFAULT_MAX_PASSWORD_LENGTH = 10; 33 34 // Define supported password characters divided into groups. 35 private static string PASSWORD_CHARS_LCASE = "abcdefgijkmnopqrstwxyz"; 36 private static string PASSWORD_CHARS_UCASE = "ABCDEFGHJKLMNPQRSTWXYZ"; 37 private static string PASSWORD_CHARS_NUMERIC= "23456789"; 38 private static string PASSWORD_CHARS_SPECIAL= "_";//"*$-+?_&=!%{}/"; 39 40 /// <summary> 41 /// Generates a random password. 42 /// </summary> 43 /// <returns> 44 /// Randomly generated password. 45 /// </returns> 46 /// <remarks> 47 /// The length of the generated password will be determined at 48 /// random. It will be no shorter than the minimum default and 49 /// no longer than maximum default. 50 /// </remarks> 51 public static string Generate() { 52 return Generate(DEFAULT_MIN_PASSWORD_LENGTH, 53 DEFAULT_MAX_PASSWORD_LENGTH); 54 } 55 56 /// <summary> 57 /// Generates a random password of the exact length. 58 /// </summary> 59 /// <param name="length"> 60 /// Exact password length. 61 /// </param> 62 /// <returns> 63 /// Randomly generated password. 64 /// </returns> 65 public static string Generate(int length) { 66 return Generate(length, length); 67 } 68 69 /// <summary> 70 /// Generates a random password. 71 /// </summary> 72 /// <param name="minLength"> 73 /// Minimum password length. 74 /// </param> 75 /// <param name="maxLength"> 76 /// Maximum password length. 77 /// </param> 78 /// <returns> 79 /// Randomly generated password. 80 /// </returns> 81 /// <remarks> 82 /// The length of the generated password will be determined at 83 /// random and it will fall with the range determined by the 84 /// function parameters. 85 /// </remarks> 86 public static string Generate(int minLength, 87 int maxLength) { 88 // Make sure that input parameters are valid. 89 if (minLength <= 0 || maxLength <= 0 || minLength > maxLength) 90 return null; 91 92 // Create a local array containing supported password characters 93 // grouped by types. 94 char[][] charGroups = new char[][] { 95 PASSWORD_CHARS_LCASE.ToCharArray(), 96 PASSWORD_CHARS_UCASE.ToCharArray(), 97 PASSWORD_CHARS_NUMERIC.ToCharArray(), 98 PASSWORD_CHARS_SPECIAL.ToCharArray() 99 }; 100 101 // Use this array to track the number of unused characters in each 102 // character group. 103 int[] charsLeftInGroup = new int[charGroups.Length]; 104 105 // Initially, all characters in each group are not used. 106 for (int i=0; i<charsLeftInGroup.Length; i++) 107 charsLeftInGroup[i] = charGroups[i].Length; 108 109 // Use this array to track (iterate through) unused character groups. 110 int[] leftGroupsOrder = new int[charGroups.Length]; 111 112 // Initially, all character groups are not used. 113 for (int i=0; i<leftGroupsOrder.Length; i++) 114 leftGroupsOrder[i] = i; 115 116 // Because we cannot use the default randomizer, which is based on the 117 // current time (it will produce the same "random" number within a 118 // second), we will use a random number generator to seed the 119 // randomizer. 120 121 // Use a 4-byte array to fill it with random bytes and convert it then 122 // to an integer value. 123 byte[] randomBytes = new byte[4]; 124 125 // Generate 4 random bytes. 126 RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider(); 127 rng.GetBytes(randomBytes); 128 129 // Convert 4 bytes into a 32-bit integer value. 130 int seed = (randomBytes[0] & 0x7f) << 24 | 131 randomBytes[1] << 16 | 132 randomBytes[2] << 8 | 133 randomBytes[3]; 134 135 // Now, this is real randomization. 136 Random random = new Random(seed); 137 138 // This array will hold password characters. 139 char[] password = null; 140 141 // Allocate appropriate memory for the password. 142 if (minLength < maxLength) 143 password = new char[random.Next(minLength, maxLength+1)]; 144 else 145 password = new char[minLength]; 146 147 // Index of the next character to be added to password. 148 int nextCharIdx; 149 150 // Index of the next character group to be processed. 151 int nextGroupIdx; 152 153 // Index which will be used to track not processed character groups. 154 int nextLeftGroupsOrderIdx; 155 156 // Index of the last non-processed character in a group. 157 int lastCharIdx; 158 159 // Index of the last non-processed group. Initially, we will skip 160 // special characters. 161 int lastLeftGroupsOrderIdx = leftGroupsOrder.Length - 1; 162 163 // Generate password characters one at a time. 164 for (int i=0; i<password.Length; i++) { 165 // If only one character group remained unprocessed, process it; 166 // otherwise, pick a random character group from the unprocessed 167 // group list. 168 if (lastLeftGroupsOrderIdx == 0) 169 nextLeftGroupsOrderIdx = 0; 170 else 171 nextLeftGroupsOrderIdx = random.Next(0, 172 lastLeftGroupsOrderIdx); 173 174 // Get the actual index of the character group, from which we will 175 // pick the next character. 176 nextGroupIdx = leftGroupsOrder[nextLeftGroupsOrderIdx]; 177 178 // Get the index of the last unprocessed characters in this group. 179 lastCharIdx = charsLeftInGroup[nextGroupIdx] - 1; 180 181 // If only one unprocessed character is left, pick it; otherwise, 182 // get a random character from the unused character list. 183 if (lastCharIdx == 0) 184 nextCharIdx = 0; 185 else 186 nextCharIdx = random.Next(0, lastCharIdx+1); 187 188 // Add this character to the password. 189 password[i] = charGroups[nextGroupIdx][nextCharIdx]; 190 191 // If we processed the last character in this group, start over. 192 if (lastCharIdx == 0) 193 charsLeftInGroup[nextGroupIdx] = 194 charGroups[nextGroupIdx].Length; 195 // There are more unprocessed characters left. 196 else { 197 // Swap processed character with the last unprocessed character 198 // so that we don't pick it until we process all characters in 199 // this group. 200 if (lastCharIdx != nextCharIdx) { 201 char temp = charGroups[nextGroupIdx][lastCharIdx]; 202 charGroups[nextGroupIdx][lastCharIdx] = 203 charGroups[nextGroupIdx][nextCharIdx]; 204 charGroups[nextGroupIdx][nextCharIdx] = temp; 205 } 206 // Decrement the number of unprocessed characters in 207 // this group. 208 charsLeftInGroup[nextGroupIdx]--; 209 } 210 211 // If we processed the last group, start all over. 212 if (lastLeftGroupsOrderIdx == 0) 213 lastLeftGroupsOrderIdx = leftGroupsOrder.Length - 1; 214 // There are more unprocessed groups left. 215 else { 216 // Swap processed group with the last unprocessed group 217 // so that we don't pick it until we process all groups. 218 if (lastLeftGroupsOrderIdx != nextLeftGroupsOrderIdx) { 219 int temp = leftGroupsOrder[lastLeftGroupsOrderIdx]; 220 leftGroupsOrder[lastLeftGroupsOrderIdx] = 221 leftGroupsOrder[nextLeftGroupsOrderIdx]; 222 leftGroupsOrder[nextLeftGroupsOrderIdx] = temp; 223 } 224 // Decrement the number of unprocessed groups. 225 lastLeftGroupsOrderIdx--; 226 } 227 } 228 229 // Convert password characters into a string and return the result. 230 return new string(password); 231 } 232 } 233 234 /// <summary> 235 /// Illustrates the use of the RandomPassword class. 236 /// </summary> 237 public class RandomPasswordTest { 238 /// <summary> 239 /// The main entry point for the application. 240 /// </summary> 241 [STAThread] 242 static void Main(string[] args) { 243 // Print 100 randomly generated passwords (8-to-10 char long). 244 for (int i=0; i<100; i++) 245 Console.WriteLine(RandomPassword.Generate(8, 10)); 246 } 247 } 248 } 249

No comments avaiable

Add a comment

Name *  

Email (won't be displayed) *    

Website  

Comment *  

Sicherheitscode Security Code *    

RSS