C# random string generator with atleast one numeric - c#

I am using this logic to generate random string. How do I force this to have at least one numeric digit in it?
var charsALL = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
var randomIns = new Random();
var resultGenerated = new string(
Enumerable.Repeat(charsALL, 6)
.Select(stringgen => stringgen[randomIns.Next(stringgen.Length)])
.ToArray());
return resultGenerated.ToString();

var charsALL = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
var randomIns = new Random();
int N = 6;
var rndChars = Enumerable.Range(0, N)
.Select(_ => charsALL[randomIns.Next(charsALL.Length)])
.ToArray();
rndChars[randomIns.Next(rndChars.Length)] = "0123456789"[randomIns.Next(10)];
var randomstr = new String(rndChars);

You can check if it contains a digit with:
while(!resultGenerated.Any(c => Char.IsDigit(c)))
{
// try again until you have a digit
}

I think that the faster solution is insert a random number at a random position into the string:
char[] chars = Enumerable.Repeat( charsALL, 6 )
.Select( stringgen => stringgen[ randomIns.Next( stringgen.Length ) ] )
.ToArray( );
if (!chars.Any(c => Char.IsDigit(c)))
chars[ randomIns.Next( chars.Length ) ] = randomIns.Next( 10 ).ToString( )[ 0 ];
return new string(chars);

You could randomize with the asci codes of a-z, A-Z and 0 -9
public static string GetRandomString(int randomStrLength)
{
Random rand = new Random(DateTime.Now.Millisecond);
char[] randomString = new char[randomStrLength];
int randCode = 0;
bool containsDigit = false;
while (containsDigit == false)
{
for (int i = 0; i < randomStrLength; i++)
{
// Get random asci codes (allowed: a-z, A-Z, 0-9)
do
{
randCode = rand.Next(48, 122);
}
while (randCode > 57 && randCode < 65 || randCode > 90 && randCode < 97);
randomString[i] = (char)randCode;
// We want at least one digit.
if (randCode >= 48 && randCode <= 57)
{
containsDigit = true;
}
}
}
return new String(randomString);
}

generate your random string
generate a random digit between 0 and 9
insert the random digit at a random index of your string.
If that's not random enough for you, than I'm afraid you'll have to stick with Tim's answer.

My version (Tried and Tested) ;)
namespace PasswordGenerator
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Your new password is : " + CreateRandomPassword(8));
Console.ReadLine();
}
private static string CreateRandomPassword(int passwordLength)
{
string allowedChars = "abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ0123456789!#$?_-";
char[] chars = new char[passwordLength];
Random random = new Random();
bool containsNum = false;
do {
for (int i = 0; i < passwordLength; i++)
{
chars[i] = allowedChars[random.Next(0, allowedChars.Length)];
if(Char.IsDigit(chars[i])){
containsNum = true;
}
}
} while(!containsNum);
return new string(chars);
}
}
}

I dont know if this helps but this is my class I use to generate a random string. In my use of it before the string is generated there are checkboxes to decide if it has to have at least 1 upper case/symbols/digit etc. May be long winded for some but it does the job for me.
class RandomString
{
private bool m_HasCaps;
private bool m_HasNumbers;
private bool m_HasSymbols;
private int m_StringLength;
private string characterString;
private string randomString;
//Set possible characters to char array rather than a string for potential future method involving chars
private char[] lower = "abcdefghijklmnopqrstuvwxyz".ToCharArray();
private char[] upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray();
private char[] numbers = "0123456789".ToCharArray();
private char[] symbols = "!£$%&()<>[]?#-+=".ToCharArray();
/// <summary>
/// The returned string can contain just lowercase or a mixture of upper, digits and symbols depending on params and
/// the lenght of the string return can also be set
/// </summary>
/// <param name="caps">Does the string need to conatain at least 1 upper case</param>
/// <param name="nums">does the string need to contain at least 1 numeral</param>
/// <param name="symbols">does the string need to contain at least 1 symbol</param>
/// <param name="length">the length of the string to return </param>
public RandomString(bool caps, bool nums,bool symbols,int length)
{
m_HasCaps = caps;
m_HasNumbers = nums;
m_HasSymbols = symbols;
m_StringLength = length;
}
public string CreatePassword()
{
BuildCharacterstring();
BuildRandomString();
return randomString;
}
//Check to see what the string must contain and add those characters to the
//Character string
private void BuildCharacterstring()
{
characterString = new string(lower);
if (m_HasCaps)
{
string upperString = new string(upper);
characterString += upperString;
}
if (m_HasNumbers)
{
string numberString = new string(numbers);
characterString += numberString;
}
if (m_HasSymbols)
{
string symbolString = new string(symbols);
characterString += symbolString;
}
}
//
private void BuildRandomString()
{
Random rdm = new Random();
bool validPassword = false;
while (validPassword == false)
{
//blank the string before each run otherwise you end up with double the characters
randomString = "";
for (int x = 0; x < m_StringLength; x++)
{
//select a char from the password character string
int place = rdm.Next(0, characterString.Length);
char character = characterString[place];
randomString += character;
}
//Check that the password has the appropriate characters
validPassword = CheckParams();
}
}
//checks that each required preference is met and that the string includes at least 1 of what
//is selected. If the parameter is not required ie symbols are not required set it to true to pass
//the test anyway.
private bool CheckParams()
{
bool capsPassed;
bool numeralPassed;
bool symbolPassed;
bool lowerPassed;
//If caps are not required set to true to pass the test automatically
if(m_HasCaps == false)
{
capsPassed = true;
}
else
{
//check if the password contains an uppercase letter
capsPassed = (randomString.Any(char.IsUpper)) ? true : false;
}
if(m_HasNumbers == false)
{
numeralPassed = true;
}
else
{
numeralPassed = (randomString.Any(char.IsDigit)) ? true : false;
}
if(m_HasSymbols == false)
{
symbolPassed = true;
}
else
{
symbolPassed = (randomString.Any(char.IsSymbol)) ? true : false;
}
lowerPassed = (randomString.Any(char.IsLower)) ? true : false;
//All 4 must pass to return true and stop password generation
if (capsPassed && numeralPassed && symbolPassed &&lowerPassed)
{
return true;
}
else
{
return false;
}
}
}

Related

Get Difference Between Two Strings in Terms of Remove and Insert Actions

So I have a text box and on the text changed event I have the old text and the new text, and want to get the difference between them. In this case, I want to be able to recreate the new text with the old text using one remove function and one insert function. That is possible because there are a few possibilities of the change that was in the text box:
Text was only removed (one character or more using selection) - ABCD -> AD
Text was only added (one character or more using paste) - ABCD -> ABXXCD
Text was removed and added (by selecting text and entering text in the same action) - ABCD -> AXD
So I want to have these functions:
Sequence GetRemovedCharacters(string oldText, string newText)
{
}
Sequence GetAddedCharacters(string oldText, string newText)
{
}
My Sequence class:
public class Sequence
{
private int start;
private int end;
public Sequence(int start, int end)
{
StartIndex = start; EndIndex = end;
}
public int StartIndex { get { return start; } set { start = value; Length = end - start + 1; } }
public int EndIndex { get { return end; } set { end = value; Length = end - start + 1; } }
public int Length { get; private set; }
public override string ToString()
{
return "(" + StartIndex + ", " + EndIndex + ")";
}
public static bool operator ==(Sequence a, Sequence b)
{
if(IsNull(a) && IsNull(b))
return true;
else if(IsNull(a) || IsNull(b))
return false;
else
return a.StartIndex == b.StartIndex && a.EndIndex == b.EndIndex;
}
public override bool Equals(object obj)
{
return base.Equals(obj);
}
public static bool operator !=(Sequence a, Sequence b)
{
if(IsNull(a) && IsNull(b))
return false;
else if(IsNull(a) || IsNull(b))
return true;
else
return a.StartIndex != b.StartIndex && a.EndIndex != b.EndIndex;
}
public override int GetHashCode()
{
return base.GetHashCode();
}
static bool IsNull(Sequence sequence)
{
try
{
return sequence.Equals(null);
}
catch(NullReferenceException)
{
return true;
}
}
}
Extra Explanation: I want to know which characters were removed and which characters were added to the text in order to get the new text so I can recreate this. Let's say I have ABCD -> AXD. 'B' and 'C' would be the characters that were removed and 'X' would be the character that was added. So the output from the GetRemovedCharacters function would be (1, 2) and the output from the GetAddedCharacters function would be (1, 1). The output from the GetRemovedCharacters function refers to indexes in the old text and the output from the GetAddedCharacters function refers to indexes in the old text after removing the removed characters.
EDIT: I've thought of a few directions:
This code I created* which returns the sequence that was affected - if characters were removed it returns the sequence of the characters that were removed in the old text; if characters were added it returns the sequence of the characters that were added in the new text. It does not return the right value (which I myself not sure what I want it to be) when removing and adding text.
Maybe the SelectionStart property in the text box could help - the position of the caret after the text was changed.
*
private static Sequence GetChangeSequence(string oldText, string newText)
{
if(newText.Length > oldText.Length)
{
for(int i = 0; i < newText.Length; i++)
if(i == oldText.Length || newText[i] != oldText[i])
return new Sequence(i, i + (newText.Length - oldText.Length) - 1);
return null;
}
else if(newText.Length < oldText.Length)
{
for(int i = 0; i < oldText.Length; i++)
if(i == newText.Length || oldText[i] != newText[i])
return new Sequence(i, i + (oldText.Length - newText.Length) - 1);
return null;
}
else
return null;
}
Thanks.
A simple string comparison wont do the job since you are asking for a algorithm which supports added and removed chars at the same time and is hence not easy to achive in a few lines of code. Id suggest to use a library instead of writing your own comparison algorithm.
Have a look at this project for example.
I quickly threw this together to give you an idea of what I did to solve your question. It doesn't use your classes but it does find an index so it's customizable for you.
There are also obvious limitations to this as it is just bare bones.
This method will spot out changes made to the original string by comparing it to the changed string
// Find the changes made to a string
string StringDiff (string originalString, string changedString)
{
string diffString = "";
// Iterate over the original string
for (int i = 0; i < originalString.Length; i++)
{
// Get the character to search with
char diffChar = originalString[i];
// If found char in the changed string
if (FindInString(diffChar, changedString, out int index))
{
// Remove from the changed string at the index as we don't want to match to this char again
changedString = changedString.Remove(index, 1);
}
// If not found then this is a difference
else
{
// Add to diff string
diffString += diffChar;
}
}
return diffString;
}
This method will return true at the first matching occurrence (an obvious limitation but this is more to give you an idea)
// Find char at first occurence in string
bool FindInString (char c, string search, out int index)
{
index = -1;
// Iterate over search string
for (int i = 0; i < search.Length; i++)
{
// If found then return true with index
if (c == search[i])
{
index = i;
return true;
}
}
return false;
}
This is a simple helper method to show you an example
void SplitStrings(string oldStr, string newStr)
{
Console.WriteLine($"Old : {oldStr}, New: {newStr}");
Console.WriteLine("Removed - " + StringDiff(oldStr, newStr));
Console.WriteLine("Added - " + StringDiff(newStr, oldStr));
}
I've done it.
static void Main(string[] args)
{
while(true)
{
Console.WriteLine("Enter the Old Text");
string oldText = Console.ReadLine();
Console.WriteLine("Enter the New Text");
string newText = Console.ReadLine();
Console.WriteLine("Enter the Caret Position");
int caretPos = int.Parse(Console.ReadLine());
Sequence removed = GetRemovedCharacters(oldText, newText, caretPos);
if(removed != null)
oldText = oldText.Remove(removed.StartIndex, removed.Length);
Sequence added = GetAddedCharacters(oldText, newText, caretPos);
if(added != null)
oldText = oldText.Insert(added.StartIndex, newText.Substring(added.StartIndex, added.Length));
Console.WriteLine("Worked: " + (oldText == newText).ToString());
Console.ReadKey();
Console.Clear();
}
}
static Sequence GetRemovedCharacters(string oldText, string newText, int caretPosition)
{
int startIndex = GetStartIndex(oldText, newText);
if(startIndex != -1)
{
Sequence sequence = new Sequence(startIndex, caretPosition + (oldText.Length - newText.Length) - 1);
if(SequenceValid(sequence))
return sequence;
}
return null;
}
static Sequence GetAddedCharacters(string oldText, string newText, int caretPosition)
{
int startIndex = GetStartIndex(oldText, newText);
if(startIndex != -1)
{
Sequence sequence = new Sequence(GetStartIndex(oldText, newText), caretPosition - 1);
if(SequenceValid(sequence))
return sequence;
}
return null;
}
static int GetStartIndex(string oldText, string newText)
{
for(int i = 0; i < Math.Max(oldText.Length, newText.Length); i++)
if(i >= oldText.Length || i >= newText.Length || oldText[i] != newText[i])
return i;
return -1;
}
static bool SequenceValid(Sequence sequence)
{
return sequence.StartIndex >= 0 && sequence.EndIndex >= 0 && sequence.EndIndex >= sequence.StartIndex;
}

Reading the multiline text box in Windows AS it is Entered by user

I have a static width of the multiline text box.
When i Continuously type long text it is showing in single line in the code behind when i try to read.
I wanted to use this data to print in the component One {C1PrintDocument} . As user entered . but it showing everything in the same line and it is getting truncated .
I am dealing japense as well as English language .
Below is the same of the JP text.
Text Example: "れはれはれはれはれはれはれ1はれはれはれはれはれはれはれはれはれはれはれはれはれはれはれはれはれはれはれはれはれはれはれはれはれはれはれははれはれはれはれはれはれはれはれはれはれはれはれはれはれはれはれはれ6はれはれれれれれはれはれはれはれはれはれはれはれはれはれはれはれはれはれはれはれはれはれはれはれはれはれはれはれはれはれはれはれはれはれはれはれはれはれれれれれはれはれはれはれはれはれはれはれはれはれはれはれはれはれはれはれはれはれはれはれはれはれはれはれはれはれはれはれはれはれはれはれはれはれれれれれ7はれはれはれはれはれはれは" .
I want to internally identify the new line as user enter in the system.
i tried using Environment.NewLine . but it doesn't work because this is the continuous text.
Help me to read the text as it is appeared in the windows text box to print that.
Algorithm i wrote to solve this problem is as below :
// <summary>
// Functions takes the Large text and split the string according to the maximum length of the string per line.
// </summary>
// <param name="strData">String Data</param>
// <param name="intMaxSize">Maximum Size of the row</param>
// <returns></returns>
public static List<string> GetLines(string strData, int intMaxSize)
{
List<string> strReturn = new List<string>();
string[] strLineSplited = strData.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None);
for (int intNoOfLine = 0; intNoOfLine < strLineSplited.Length; intNoOfLine++)
{
List<KeyValuePair<char, int>> listOfChar = new List<KeyValuePair<char, int>>();
string strValue = strLineSplited[intNoOfLine];
StringBuilder sbSingleLine = new StringBuilder();
if (!string.IsNullOrEmpty(strValue))
{
char[] charArr = strValue.ToCharArray();
int intCharCount = 0;
byte[] bascii = Encoding.ASCII.GetBytes(strValue);
for (int intCounter = 0; intCounter < bascii.Length; intCounter++)
{
int intASCIICode = bascii[intCounter];
if (intASCIICode >= 32 && intASCIICode <= 62)
{
listOfChar.Add(new KeyValuePair<char, int>(charArr[intCounter], 1));
}
else if (intASCIICode >= 65 && intASCIICode <= 122)
{
listOfChar.Add(new KeyValuePair<char, int>(charArr[intCounter], 1));
}
else
{
listOfChar.Add(new KeyValuePair<char, int>(charArr[intCounter], 2));
}
}
bool bFlag = true;
foreach (var charValue in listOfChar)
{
intCharCount += Convert.ToInt32(charValue.Value);
if (intCharCount < intMaxSize)
{
sbSingleLine.Append(charValue.Key);
bFlag = true;
}
else
{
sbSingleLine.Append(charValue.Key);
strReturn.Add(sbSingleLine.ToString());
sbSingleLine.Length = 0;
sbSingleLine.Capacity = 0;
intCharCount = 0;
bFlag = false;
}
}
if (intCharCount < intMaxSize && bFlag)
{
strReturn.Add(sbSingleLine.ToString());
}
}
else
{
strReturn.Add(sbSingleLine.ToString());
}
}
return strReturn;
}

While loop for alphabet

I am trying to code the following example.
Input ABCDEFGHIJKLMNOPQRSTUVWXYZ
Output ZYXWVUTSRQPONMLKJIHGFEDCBA
If user types in A it will output Z. It has to go past 25 characters to reach Z. So I am guessing a while loop will be needed, then if B it has to go through 23 times, so – 2 and so on until it reaches M as it will skip though 1 to reach N, then start again at 25.
Any suggestion on how to approach this?
Capital ASCII characters range according to the ASCII-table from 65 (0x41, 'A') to 90 (0x5A, 'Z').
This is the algorithm:
// inputChar is a char holding your character
char inputChar = getCharFromUser();
int inputVal = inputChar - 65; // e.g. 0 for 'A', 1 for 'B'
char outputChar = 90 - inputVal; // e.g. 90 - 1 = 89 = 'Y'
outputCharToUser(outputChar);
And this is how you might implement it in C#:
while (true)
{
var key = Console.ReadKey(intercept: true);
var inputChar = char.ToUpper(key.KeyChar);
var outputChar = (char)('Z' - inputChar + 'A');
Console.Write("{0}={1} ", inputChar, outputChar);
}
You could use two dictionaries which enable to lookup the char from index and vice-versa:
var indexLookup = "abcdefghijklmnopqrstuvwxyz"
.Select((chr, index) => new { chr, index })
.ToDictionary(x => x.chr, x => x.index);
var charLookup = "abcdefghijklmnopqrstuvwxyz"
.Select((chr, index) => new { chr, index })
.ToDictionary(x => x.index, x => x.chr);
Now it's simple, the essential part is charLookup[25 - indexOfChar]:
string userInput = "B";
bool isUpper = char.IsUpper(userInput[0]);
char inputChar = Char.ToLowerInvariant(userInput[0]);
if(indexLookup.ContainsKey(inputChar))
{
int indexOfChar = indexLookup[inputChar];
char oppositeChar = charLookup[25 - indexOfChar];
string result = isUpper ? Char.ToUpperInvariant(oppositeChar).ToString() : oppositeChar.ToString();
Console.Write(result); // Y
}
Actually you don't need two dictionaries but only one since the string can already be used to lookup a char by index. Here is a class which provides the logic:
public class CharSwap
{
private string alphabet;
private Dictionary<char, int> indexLookup;
public CharSwap() : this("abcdefghijklmnopqrstuvwxyz") { }
public CharSwap(string alphabet)
{
if(alphabet == null) throw new ArgumentNullException("alphabet");
this.alphabet = alphabet;
indexLookup = alphabet.Select((chr, index) => new { chr, index }).ToDictionary(x => x.chr, x => x.index);
}
public char? OppositeChar(char input)
{
char lowerChar = Char.ToLowerInvariant(input);
if (!indexLookup.ContainsKey(lowerChar))
return null;
int indexOfChar = indexLookup[lowerChar];
int indexOpposite = alphabet.Length - 1 - indexOfChar;
return Char.IsUpper(input)
? Char.ToUpperInvariant(alphabet[indexOpposite])
: alphabet[indexOpposite];
}
}
Test:
CharSwap cw = new CharSwap();
char? oppositeChar = cw.OppositeChar('B');
Console.Write(oppositeChar);
char input = 'B';
string Range = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char result = Range[Range.Length - 1 - Range.IndexOf(input)]; //Y
or maybe another approach
char input = 'B';
string Range = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char result = Range.Reverse().ElementAt(Range.IndexOf(input)); //Y
How about something like this?
char[] alphabet = {'A','B', 'C'} // and so on
char[] mapsTo = {'Z', 'Y', 'X'} // and so on, excluded for brevity
public function string changeLetter(char input)
{
int i = 0;
foreach (char c in alphabet) {
if (c == input) {
return mapsTo[i];
}
i++;
}
return '';
}
Converted to c#:
char[] alphabet = {'A','B', 'C'}; // and so on
char[] mapsTo = {'Z', 'Y', 'X'}; // and so on, excluded for brevity
public string changeLetter(char input)
{
int i = 0;
foreach (char c in alphabet) {
if (c == input) {
return mapsTo[i].ToString();
}
i++;
}
return default(char).ToString();
}
You would call this function like this (for instance):
public static void RunProgram()
{
Console.WriteLine("Please type in character");
input = Console.ReadKey().KeyChar;
Console.WriteLine("You typed in " + input + ". This results in: " + ChangeInput(input));
}
... where "ChangeInput" is the function defined earlier.
The easy way to solve this is to use a Dictionary<char, char>:
public class Atbash {
static string source = "abcdefghijklmnopqrstuvwxyz";
static List<char> keys = source.ToList();
static List<char> values = source.Reverse().ToList();
static Dictionary<char, char> Converter = keys.ToDictionary(x => x, x => values[keys.IndexOf(x)]);
public static char Convert(char input)
{
char output;
bool isUpper = char.IsUpper(input);
input = char.ToLowerInvariant(input);
if(Converter.ContainsKey(input)) {
output = Converter[input];
return (isUpper) ? char.ToUpperInvariant(output) : output;
}
throw new ArgumentOutOfRangeException("Input char is unknown");
// of course, it can return default(char) instead of throwing an exception.
}
}
Why Atbash? read about it here.

Determine if string has all unique characters

I'm working through an algorithm problem set which poses the following question:
"Determine if a string has all unique characters. Assume you can only use arrays".
I have a working solution, but I would like to see if there is anything better optimized in terms of time complexity. I do not want to use LINQ. Appreciate any help you can provide!
static void Main(string[] args)
{
FindDupes("crocodile");
}
static string FindDupes(string text)
{
if (text.Length == 0 || text.Length > 256)
{
Console.WriteLine("String is either empty or too long");
}
char[] str = new char[text.Length];
char[] output = new char[text.Length];
int strLength = 0;
int outputLength = 0;
foreach (char value in text)
{
bool dupe = false;
for (int i = 0; i < strLength; i++)
{
if (value == str[i])
{
dupe = true;
break;
}
}
if (!dupe)
{
str[strLength] = value;
strLength++;
output[outputLength] = value;
outputLength++;
}
}
return new string(output, 0, outputLength);
}
If time complexity is all you care about you could map the characters to int values, then have an array of bool values which remember if you've seen a particular character value previously.
Something like ... [not tested]
bool[] array = new bool[256]; // or larger for Unicode
foreach (char value in text)
if (array[(int)value])
return false;
else
array[(int)value] = true;
return true;
try this,
string RemoveDuplicateChars(string key)
{
string table = string.Empty;
string result = string.Empty;
foreach (char value in key)
{
if (table.IndexOf(value) == -1)
{
table += value;
result += value;
}
}
return result;
}
usage
Console.WriteLine(RemoveDuplicateChars("hello"));
Console.WriteLine(RemoveDuplicateChars("helo"));
Console.WriteLine(RemoveDuplicateChars("Crocodile"));
output
helo
helo
Crocdile
public boolean ifUnique(String toCheck){
String str="";
for(int i=0;i<toCheck.length();i++)
{
if(str.contains(""+toCheck.charAt(i)))
return false;
str+=toCheck.charAt(i);
}
return true;
}
EDIT:
You may also consider to omit the boundary case where toCheck is an empty string.
The following code works:
static void Main(string[] args)
{
isUniqueChart("text");
Console.ReadKey();
}
static Boolean isUniqueChart(string text)
{
if (text.Length == 0 || text.Length > 256)
{
Console.WriteLine(" The text is empty or too larg");
return false;
}
Boolean[] char_set = new Boolean[256];
for (int i = 0; i < text.Length; i++)
{
int val = text[i];//already found this char in the string
if (char_set[val])
{
Console.WriteLine(" The text is not unique");
return false;
}
char_set[val] = true;
}
Console.WriteLine(" The text is unique");
return true;
}
If the string has only lower case letters (a-z) or only upper case letters (A-Z) you can use a very optimized O(1) solution.Also O(1) space.
c++ code :
bool checkUnique(string s){
if(s.size() >26)
return false;
int unique=0;
for (int i = 0; i < s.size(); ++i) {
int j= s[i]-'a';
if(unique & (1<<j)>0)
return false;
unique=unique|(1<<j);
}
return true;
}
Remove Duplicates in entire Unicode Range
Not all characters can be represented by a single C# char. If you need to take into account combining characters and extended unicode characters, you need to:
parse the characters using StringInfo
normalize the characters
find duplicates amongst the normalized strings
Code to remove duplicate characters:
We keep track of the entropy, storing the normalized characters (each character is a string, because many characters require more than 1 C# char). In case a character (normalized) is not yet stored in the entropy, we append the character (in specified form) to the output.
public static class StringExtension
{
public static string RemoveDuplicateChars(this string text)
{
var output = new StringBuilder();
var entropy = new HashSet<string>();
var iterator = StringInfo.GetTextElementEnumerator(text);
while (iterator.MoveNext())
{
var character = iterator.GetTextElement();
if (entropy.Add(character.Normalize()))
{
output.Append(character);
}
}
return output.ToString();
}
}
Unit Test:
Let's test a string that contains variations on the letter A, including the Angstrom sign Å. The Angstrom sign has unicode codepoint u212B, but can also be constructed as the letter A with the diacritic u030A. Both represent the same character.
// ÅÅAaA
var input = "\u212BA\u030AAaA";
// ÅAa
var output = input.RemoveDuplicateChars();
Further extensions could allow for a selector function that determines how to normalize characters. For instance the selector (x) => x.ToUpperInvariant().Normalize() would allow for case-insensitive duplicate removal.
public static bool CheckUnique(string str)
{
int accumulator = 0;
foreach (int asciiCode in str)
{
int shiftedBit = 1 << (asciiCode - ' ');
if ((accumulator & shiftedBit) > 0)
return false;
accumulator |= shiftedBit;
}
return true;
}

Generating Random Passwords

When a user on our site loses his password and heads off to the Lost Password page we need to give him a new temporary password. I don't really mind how random this is, or if it matches all the "needed" strong password rules, all I want to do is give them a password that they can change later.
The application is a Web application written in C#. so I was thinking of being mean and going for the easy route of using part of a Guid. i.e.
Guid.NewGuid().ToString("d").Substring(1,8)
Suggesstions? thoughts?
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 distribution of strings is almost uniform (don't care about minor deviations, as long as they're small)
It outputs more than a few billion strings for each argument set. Generating an 8 character string (~47 bits of entropy) is meaningless if your PRNG only generates 2 billion (31 bits of entropy) different values.
It's secure, since I expect people to use this for passwords or other security tokens.
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.
This is a lot larger, but I think it looks a little more comprehensive:
http://www.obviex.com/Samples/Password.aspx
///////////////////////////////////////////////////////////////////////////////
// SAMPLE: Generates random password, which complies with the strong password
// rules and does not contain ambiguous characters.
//
// To run this sample, create a new Visual C# project using the Console
// Application template and replace the contents of the Class1.cs file with
// the code below.
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
// EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
//
// Copyright (C) 2004 Obviex(TM). All rights reserved.
//
using System;
using System.Security.Cryptography;
/// <summary>
/// This class can generate random passwords, which do not include ambiguous
/// characters, such as I, l, and 1. The generated password will be made of
/// 7-bit ASCII symbols. Every four characters will include one lower case
/// character, one upper case character, one number, and one special symbol
/// (such as '%') in a random order. The password will always start with an
/// alpha-numeric character; it will not start with a special symbol (we do
/// this because some back-end systems do not like certain special
/// characters in the first position).
/// </summary>
public class RandomPassword
{
// Define default min and max password lengths.
private static int DEFAULT_MIN_PASSWORD_LENGTH = 8;
private static int DEFAULT_MAX_PASSWORD_LENGTH = 10;
// Define supported password characters divided into groups.
// You can add (or remove) characters to (from) these groups.
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= "*$-+?_&=!%{}/";
/// <summary>
/// Generates a random password.
/// </summary>
/// <returns>
/// Randomly generated password.
/// </returns>
/// <remarks>
/// The length of the generated password will be determined at
/// random. It will be no shorter than the minimum default and
/// no longer than maximum default.
/// </remarks>
public static string Generate()
{
return Generate(DEFAULT_MIN_PASSWORD_LENGTH,
DEFAULT_MAX_PASSWORD_LENGTH);
}
/// <summary>
/// Generates a random password of the exact length.
/// </summary>
/// <param name="length">
/// Exact password length.
/// </param>
/// <returns>
/// Randomly generated password.
/// </returns>
public static string Generate(int length)
{
return Generate(length, length);
}
/// <summary>
/// Generates a random password.
/// </summary>
/// <param name="minLength">
/// Minimum password length.
/// </param>
/// <param name="maxLength">
/// Maximum password length.
/// </param>
/// <returns>
/// Randomly generated password.
/// </returns>
/// <remarks>
/// The length of the generated password will be determined at
/// random and it will fall with the range determined by the
/// function parameters.
/// </remarks>
public static string Generate(int minLength,
int maxLength)
{
// Make sure that input parameters are valid.
if (minLength <= 0 || maxLength <= 0 || minLength > maxLength)
return null;
// Create a local array containing supported password characters
// grouped by types. You can remove character groups from this
// array, but doing so will weaken the password strength.
char[][] charGroups = new char[][]
{
PASSWORD_CHARS_LCASE.ToCharArray(),
PASSWORD_CHARS_UCASE.ToCharArray(),
PASSWORD_CHARS_NUMERIC.ToCharArray(),
PASSWORD_CHARS_SPECIAL.ToCharArray()
};
// Use this array to track the number of unused characters in each
// character group.
int[] charsLeftInGroup = new int[charGroups.Length];
// Initially, all characters in each group are not used.
for (int i=0; i<charsLeftInGroup.Length; i++)
charsLeftInGroup[i] = charGroups[i].Length;
// Use this array to track (iterate through) unused character groups.
int[] leftGroupsOrder = new int[charGroups.Length];
// Initially, all character groups are not used.
for (int i=0; i<leftGroupsOrder.Length; i++)
leftGroupsOrder[i] = i;
// Because we cannot use the default randomizer, which is based on the
// current time (it will produce the same "random" number within a
// second), we will use a random number generator to seed the
// randomizer.
// Use a 4-byte array to fill it with random bytes and convert it then
// to an integer value.
byte[] randomBytes = new byte[4];
// Generate 4 random bytes.
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
rng.GetBytes(randomBytes);
// Convert 4 bytes into a 32-bit integer value.
int seed = BitConverter.ToInt32(randomBytes, 0);
// Now, this is real randomization.
Random random = new Random(seed);
// This array will hold password characters.
char[] password = null;
// Allocate appropriate memory for the password.
if (minLength < maxLength)
password = new char[random.Next(minLength, maxLength+1)];
else
password = new char[minLength];
// Index of the next character to be added to password.
int nextCharIdx;
// Index of the next character group to be processed.
int nextGroupIdx;
// Index which will be used to track not processed character groups.
int nextLeftGroupsOrderIdx;
// Index of the last non-processed character in a group.
int lastCharIdx;
// Index of the last non-processed group.
int lastLeftGroupsOrderIdx = leftGroupsOrder.Length - 1;
// Generate password characters one at a time.
for (int i=0; i<password.Length; i++)
{
// If only one character group remained unprocessed, process it;
// otherwise, pick a random character group from the unprocessed
// group list. To allow a special character to appear in the
// first position, increment the second parameter of the Next
// function call by one, i.e. lastLeftGroupsOrderIdx + 1.
if (lastLeftGroupsOrderIdx == 0)
nextLeftGroupsOrderIdx = 0;
else
nextLeftGroupsOrderIdx = random.Next(0,
lastLeftGroupsOrderIdx);
// Get the actual index of the character group, from which we will
// pick the next character.
nextGroupIdx = leftGroupsOrder[nextLeftGroupsOrderIdx];
// Get the index of the last unprocessed characters in this group.
lastCharIdx = charsLeftInGroup[nextGroupIdx] - 1;
// If only one unprocessed character is left, pick it; otherwise,
// get a random character from the unused character list.
if (lastCharIdx == 0)
nextCharIdx = 0;
else
nextCharIdx = random.Next(0, lastCharIdx+1);
// Add this character to the password.
password[i] = charGroups[nextGroupIdx][nextCharIdx];
// If we processed the last character in this group, start over.
if (lastCharIdx == 0)
charsLeftInGroup[nextGroupIdx] =
charGroups[nextGroupIdx].Length;
// There are more unprocessed characters left.
else
{
// Swap processed character with the last unprocessed character
// so that we don't pick it until we process all characters in
// this group.
if (lastCharIdx != nextCharIdx)
{
char temp = charGroups[nextGroupIdx][lastCharIdx];
charGroups[nextGroupIdx][lastCharIdx] =
charGroups[nextGroupIdx][nextCharIdx];
charGroups[nextGroupIdx][nextCharIdx] = temp;
}
// Decrement the number of unprocessed characters in
// this group.
charsLeftInGroup[nextGroupIdx]--;
}
// If we processed the last group, start all over.
if (lastLeftGroupsOrderIdx == 0)
lastLeftGroupsOrderIdx = leftGroupsOrder.Length - 1;
// There are more unprocessed groups left.
else
{
// Swap processed group with the last unprocessed group
// so that we don't pick it until we process all groups.
if (lastLeftGroupsOrderIdx != nextLeftGroupsOrderIdx)
{
int temp = leftGroupsOrder[lastLeftGroupsOrderIdx];
leftGroupsOrder[lastLeftGroupsOrderIdx] =
leftGroupsOrder[nextLeftGroupsOrderIdx];
leftGroupsOrder[nextLeftGroupsOrderIdx] = temp;
}
// Decrement the number of unprocessed groups.
lastLeftGroupsOrderIdx--;
}
}
// Convert password characters into a string and return the result.
return new string(password);
}
}
/// <summary>
/// Illustrates the use of the RandomPassword class.
/// </summary>
public class RandomPasswordTest
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
// Print 100 randomly generated passwords (8-to-10 char long).
for (int i=0; i<100; i++)
Console.WriteLine(RandomPassword.Generate(8, 10));
}
}
//
// END OF FILE
///////////////////////////////////////////////////////////////////////////////
I created this class that uses RNGCryptoServiceProvider and it is flexible. Example:
var generator = new PasswordGenerator(minimumLengthPassword: 8,
maximumLengthPassword: 15,
minimumUpperCaseChars: 2,
minimumNumericChars: 3,
minimumSpecialChars: 2);
string password = generator.Generate();
I know that this is an old thread, but I have what might be a fairly simple solution for someone to use. Easy to implement, easy to understand, and easy to validate.
Consider the following requirement:
I need a random password to be generated which has at least 2 lower-case letters, 2 upper-case letters and 2 numbers. The password must also be a minimum of 8 characters in length.
The following regular expression can validate this case:
^(?=\b\w*[a-z].*[a-z]\w*\b)(?=\b\w*[A-Z].*[A-Z]\w*\b)(?=\b\w*[0-9].*[0-9]\w*\b)[a-zA-Z0-9]{8,}$
It's outside the scope of this question - but the regex is based on lookahead/lookbehind and lookaround.
The following code will create a random set of characters which match this requirement:
public static string GeneratePassword(int lowercase, int uppercase, int numerics) {
string lowers = "abcdefghijklmnopqrstuvwxyz";
string uppers = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
string number = "0123456789";
Random random = new Random();
string generated = "!";
for (int i = 1; i <= lowercase; i++)
generated = generated.Insert(
random.Next(generated.Length),
lowers[random.Next(lowers.Length - 1)].ToString()
);
for (int i = 1; i <= uppercase; i++)
generated = generated.Insert(
random.Next(generated.Length),
uppers[random.Next(uppers.Length - 1)].ToString()
);
for (int i = 1; i <= numerics; i++)
generated = generated.Insert(
random.Next(generated.Length),
number[random.Next(number.Length - 1)].ToString()
);
return generated.Replace("!", string.Empty);
}
To meet the above requirement, simply call the following:
String randomPassword = GeneratePassword(3, 3, 3);
The code starts with an invalid character ("!") - so that the string has a length into which new characters can be injected.
It then loops from 1 to the # of lowercase characters required, and on each iteration, grabs a random item from the lowercase list, and injects it at a random location in the string.
It then repeats the loop for uppercase letters and for numerics.
This gives you back strings of length = lowercase + uppercase + numerics into which lowercase, uppercase and numeric characters of the count you want have been placed in a random order.
I'll add another ill-advised answer to the pot.
I have a use case where I need random passwords for machine-machine communication, so I don't have any requirement for human readability. I also don't have access to Membership.GeneratePassword in my project, and don't want to add the dependency.
I am fairly certain Membership.GeneratePassword is doing something similar to this, but here you can tune the pools of characters to draw from.
public static class PasswordGenerator
{
private readonly static Random _rand = new Random();
public static string Generate(int length = 24)
{
const string lower = "abcdefghijklmnopqrstuvwxyz";
const string upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const string number = "1234567890";
const string special = "!##$%^&*_-=+";
// Get cryptographically random sequence of bytes
var bytes = new byte[length];
new RNGCryptoServiceProvider().GetBytes(bytes);
// Build up a string using random bytes and character classes
var res = new StringBuilder();
foreach(byte b in bytes)
{
// Randomly select a character class for each byte
switch (_rand.Next(4))
{
// In each case use mod to project byte b to the correct range
case 0:
res.Append(lower[b % lower.Count()]);
break;
case 1:
res.Append(upper[b % upper.Count()]);
break;
case 2:
res.Append(number[b % number.Count()]);
break;
case 3:
res.Append(special[b % special.Count()]);
break;
}
}
return res.ToString();
}
}
And some example output:
PasswordGenerator.Generate(12)
"pzY=64#-ChS$"
"BG0OsyLbYnI_"
"l9#5^2&adj_i"
"#++Ws9d$%O%X"
"IWhdIN-#&O^s"
To preempt complaints about the use of Random: The primary source of randomness is still the crypto RNG. Even if you could deterministically preordain the sequence coming out of Random (say it only produced 1) you still wouldn't know the next char that would be picked (though that would limit the range of possibilities).
One simple extension would be to add weighting to the different character sets, which could be as simple as upping the max value and adding fall-through cases to increase weight.
switch (_rand.Next(6))
{
// Prefer letters 2:1
case 0:
case 1:
res.Append(lower[b % lower.Count()]);
break;
case 2:
case 3:
res.Append(upper[b % upper.Count()]);
break;
case 4:
res.Append(number[b % number.Count()]);
break;
case 5:
res.Append(special[b % special.Count()]);
break;
}
For a more humanistic random password generator I once implemented a prompt system using the EFF dice-word list.
I don't like the passwords that Membership.GeneratePassword() creates, as they're too ugly and have too many special characters.
This code generates a 10 digit not-too-ugly password.
string password = Guid.NewGuid().ToString("N").ToLower()
.Replace("1", "").Replace("o", "").Replace("0","")
.Substring(0,10);
Sure, I could use a Regex to do all the replaces but this is more readable and maintainable IMO.
For this sort of password, I tend to use a system that's likely to generate more easily "used" passwords. Short, often made up of pronouncable fragments and a few numbers, and with no intercharacter ambiguity (is that a 0 or an O? A 1 or an I?). Something like
string[] words = { 'bur', 'ler', 'meh', 'ree' };
string word = "";
Random rnd = new Random();
for (i = 0; i < 3; i++)
word += words[rnd.Next(words.length)]
int numbCount = rnd.Next(4);
for (i = 0; i < numbCount; i++)
word += (2 + rnd.Next(7)).ToString();
return word;
(Typed right into the browser, so use only as guidelines. Also, add more words).
I created this method similar to the available in the membership provider. This is usefull if you don't want to add the web reference in some applications.
It works great.
public static string GeneratePassword(int Length, int NonAlphaNumericChars)
{
string allowedChars = "abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ0123456789";
string allowedNonAlphaNum = "!##$%^&*()_-+=[{]};:<>|./?";
Random rd = new Random();
if (NonAlphaNumericChars > Length || Length <= 0 || NonAlphaNumericChars < 0)
throw new ArgumentOutOfRangeException();
char[] pass = new char[Length];
int[] pos = new int[Length];
int i = 0, j = 0, temp = 0;
bool flag = false;
//Random the position values of the pos array for the string Pass
while (i < Length - 1)
{
j = 0;
flag = false;
temp = rd.Next(0, Length);
for (j = 0; j < Length; j++)
if (temp == pos[j])
{
flag = true;
j = Length;
}
if (!flag)
{
pos[i] = temp;
i++;
}
}
//Random the AlphaNumericChars
for (i = 0; i < Length - NonAlphaNumericChars; i++)
pass[i] = allowedChars[rd.Next(0, allowedChars.Length)];
//Random the NonAlphaNumericChars
for (i = Length - NonAlphaNumericChars; i < Length; i++)
pass[i] = allowedNonAlphaNum[rd.Next(0, allowedNonAlphaNum.Length)];
//Set the sorted array values by the pos array for the rigth posistion
char[] sorted = new char[Length];
for (i = 0; i < Length; i++)
sorted[i] = pass[pos[i]];
string Pass = new String(sorted);
return Pass;
}
I've always been very happy with the password generator built-in to KeePass. Since KeePass is a .Net program, and open source, I decided to dig around the code a bit. I ended up just referncing KeePass.exe, the copy provided in the standard application install, as a reference in my project and writing the code below. You can see how flexible it is thanks to KeePass. You can specify length, which characters to include/not include, etc...
using KeePassLib.Cryptography.PasswordGenerator;
using KeePassLib.Security;
public static string GeneratePassword(int passwordLength, bool lowerCase, bool upperCase, bool digits,
bool punctuation, bool brackets, bool specialAscii, bool excludeLookAlike)
{
var ps = new ProtectedString();
var profile = new PwProfile();
profile.CharSet = new PwCharSet();
profile.CharSet.Clear();
if (lowerCase)
profile.CharSet.AddCharSet('l');
if(upperCase)
profile.CharSet.AddCharSet('u');
if(digits)
profile.CharSet.AddCharSet('d');
if (punctuation)
profile.CharSet.AddCharSet('p');
if (brackets)
profile.CharSet.AddCharSet('b');
if (specialAscii)
profile.CharSet.AddCharSet('s');
profile.ExcludeLookAlike = excludeLookAlike;
profile.Length = (uint)passwordLength;
profile.NoRepeatingCharacters = true;
KeePassLib.Cryptography.PasswordGenerator.PwGenerator.Generate(out ps, profile, null, _pool);
return ps.ReadString();
}
I like to look at generating passwords, just like generating software keys. You should choose from an array of characters that follow a good practice. Take what #Radu094 answered with and modify it to follow good practice. Don't put every single letter in the character array. Some letters are harder to say or understand over the phone.
You should also consider using a checksum on the password that was generated to make sure that it was generated by you. A good way of accomplishing this is to use the LUHN algorithm.
public static string GeneratePassword(int passLength) {
var chars = "abcdefghijklmnopqrstuvwxyz##$&ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
var random = new Random();
var result = new string(
Enumerable.Repeat(chars, passLength)
.Select(s => s[random.Next(s.Length)])
.ToArray());
return result;
}
This package allows you to generate a random password while fluently indicating which characters it should contain (if needed):
https://github.com/prjseal/PasswordGenerator/
Example:
var pwd = new Password().IncludeLowercase().IncludeUppercase().IncludeSpecial();
var password = pwd.Next();
If you want to make use of the cryptographically secure random number generation used by System.Web.Security.Membership.GeneratePassword but also want to restrict the character set to alphanumeric characters, you can filter the result with a regex:
static string GeneratePassword(int characterCount)
{
string password = String.Empty;
while(password.Length < characterCount)
password += Regex.Replace(System.Web.Security.Membership.GeneratePassword(128, 0), "[^a-zA-Z0-9]", string.Empty);
return password.Substring(0, characterCount);
}
check this code...
I added the .remove(length) to improve anaximander's response
public string GeneratePassword(int length)
{
using(RNGCryptoServiceProvider cryptRNG = new RNGCryptoServiceProvider();)
{
byte[] tokenBuffer = new byte[length];
cryptRNG.GetBytes(tokenBuffer);
return Convert.ToBase64String(tokenBuffer).Remove(length);
}
}
How to Generate the Random Password in C#.
Output : (https://prnt.sc/11fac8v)
Run : https://onlinegdb.com/HJe5OHBLu
private static Random random = new Random();
public static void Main()
{
Console.WriteLine("Random password with length of 8 character.");
Console.WriteLine("===========================================");
Console.WriteLine("Capital latters : 2");
Console.WriteLine("Number latters : 2");
Console.WriteLine("Special latters : 2");
Console.WriteLine("Small latters : 2");
Console.WriteLine("===========================================");
Console.Write("The Random Password : ");
Console.WriteLine(RandomStringCap(2) + RandomStringNum(2) + RandomStringSpe(2) + RandomStringSml(2));
Console.WriteLine("===========================================");
}
public static string RandomStringCap(int length)
{
const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
return new string(Enumerable.Repeat(chars, length)
.Select(s => s[random.Next(s.Length)]).ToArray());
}
public static string RandomStringNum(int length)
{
const string chars = "0123456789";
return new string(Enumerable.Repeat(chars, length)
.Select(s => s[random.Next(s.Length)]).ToArray());
}
public static string RandomStringSml(int length)
{
const string chars = "abcdefghijklmnopqrstuvwxyz";
return new string(Enumerable.Repeat(chars, length)
.Select(s => s[random.Next(s.Length)]).ToArray());
}
public static string RandomStringSpe(int length)
{
const string chars = "!##$%^&*_-=+";
return new string(Enumerable.Repeat(chars, length)
.Select(s => s[random.Next(s.Length)]).ToArray());
}
Pretty easy way to require one from each group using Random and linq-to-objects.
Randomize each group
Select random amount from first group
Select remaining random amounts from following groups
 
Random rand = new Random();
int min = 8;
int max = 16;
int totalLen = rand.Next(min, max);
int remainingGroups = 4;
string[] allowedLowerChars = "a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z".Split(',');
string [] allowedUpperChars = "A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z".Split(',');
string [] allowedNumbers = "1,2,3,4,5,6,7,8,9,0".Split(',');
string [] allowedSpecialChars = "!,#,#,$,%,&,?".Split(',');
var password = allowedLowerChars.OrderBy(c => rand.Next()).Take(rand.Next(1, totalLen-remainingGroups--)).ToList();
password.AddRange(allowedUpperChars.OrderBy(c => rand.Next()).Take(rand.Next(1, totalLen-password.Count-remainingGroups--)).ToList());
password.AddRange(allowedNumbers.OrderBy(c => rand.Next()).Take(rand.Next(1, totalLen-password.Count-remainingGroups--)).ToList());
password.AddRange(allowedSpecialChars.OrderBy(c => rand.Next()).Take(totalLen-password.Count).ToList());
password = password.OrderBy(c => rand.Next()).ToList(); // randomize groups
Inspired by the answer from #kitsu.eb, but using RandomNumberGenerator instead of Random or RNGCryptoServiceProvider (deprecated in .NET 6), and added a few more special characters.
Optional parameter to exclude characters that will be escaped when using System.Text.Json.JsonSerializer.Serialize - for example & which is escaped as \u0026 - so that you can guarantee the length of the serialized string will match the length of the password.
For .NET Core 3.0 and above.
public static class PasswordGenerator
{
const string lower = "abcdefghijklmnopqrstuvwxyz";
const string upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const string number = "1234567890";
const string special = "!##$%^&*()[]{},.:`~_-=+"; // excludes problematic characters like ;'"/\
const string specialJsonSafe = "!##$%^*()[]{},.:~_-="; // excludes problematic characters like ;'"/\ and &`+
const int lowerLength = 26; // lower.Length
const int upperLength = 26; // upper.Length;
const int numberLength = 10; // number.Length;
const int specialLength = 23; // special.Length;
const int specialJsonSafeLength = 20; // specialJsonSafe.Length;
public static string Generate(int length = 96, bool jsonSafeSpecialCharactersOnly = false)
{
Span<char> result = length < 1024 ? stackalloc char[length] : new char[length].AsSpan();
for (int i = 0; i < length; ++i)
{
switch (RandomNumberGenerator.GetInt32(4))
{
case 0:
result[i] = lower[RandomNumberGenerator.GetInt32(0, lowerLength)];
break;
case 1:
result[i] = upper[RandomNumberGenerator.GetInt32(0, upperLength)];
break;
case 2:
result[i] = number[RandomNumberGenerator.GetInt32(0, numberLength)];
break;
case 3:
if (jsonSafeSpecialCharactersOnly)
{
result[i] = specialJsonSafe[RandomNumberGenerator.GetInt32(0, specialJsonSafeLength)];
}
else
{
result[i] = special[RandomNumberGenerator.GetInt32(0, specialLength)];
}
break;
}
}
return result.ToString();
}
}
Since Random is not secure and RNGCryptoServiceProvider is obsolte I ended up doing this:
// possible characters that password can have
private const string passChars =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
"abcdefghijklmnopqrstuvwxyz" +
"0123456789" +
"!##$%.-_"
;
public static string GetRandomPassword(int length)
{
char[] p = new char[length];
for (int i = 0; i < length; i++)
p[i] = passChars[RandomNumberGenerator.GetInt32(0, passChars.Length)];
return new string(p);
}
Here is a solution that uses RNGCryptoServiceProvider to mimic the functionality of Membership.GeneratePassword from the System.Web.Security namespace.
I needed a drop-in replacement for running it in Azure Function.
It can be tested here:
https://dotnetfiddle.net/V0cNJw
public static string GeneratePassword(int length, int numberOfNonAlphanumericCharacters)
{
const string allowedChars = "abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ0123456789";
const string nonAlphanumericChars = "!##$%^&*()_-+=[{]};:<>|./?";
var randNum = new byte[4];
using (var rng = new RNGCryptoServiceProvider())
{
rng.GetBytes(randNum);
var randomSeed = BitConverter.ToInt32(randNum, 0);
var random = new Random(randomSeed);
var chars = new char[length];
var allowedCharCount = allowedChars.Length;
var nonAlphanumericCharCount = nonAlphanumericChars.Length;
var numNonAlphanumericCharsAdded = 0;
for (var i = 0; i < length; i++)
{
if (numNonAlphanumericCharsAdded < numberOfNonAlphanumericCharacters && i < length - 1)
{
chars[i] = nonAlphanumericChars[random.Next(nonAlphanumericCharCount)];
numNonAlphanumericCharsAdded++;
}
else
{
chars[i] = allowedChars[random.Next(allowedCharCount)];
}
}
return new string(chars);
}
}
Here is a version that runs on .Net 6.0+
Sandbox: https://dotnetfiddle.net/XqgTSg
public static string GeneratePassword(int length, int numberOfNonAlphanumericCharacters)
{
const string allowedChars = "abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ0123456789";
const string nonAlphanumericChars = "!##$%^&*()_-+=[{]};:<>|./?";
var randNum = new byte[4];
using (var rng = RandomNumberGenerator.Create())
{
rng.GetBytes(randNum);
var randomSeed = BitConverter.ToInt32(randNum, 0);
var random = new Random(randomSeed);
var chars = new char[length];
var allowedCharCount = allowedChars.Length;
var nonAlphanumericCharCount = nonAlphanumericChars.Length;
var numNonAlphanumericCharsAdded = 0;
for (var i = 0; i < length; i++)
{
if (numNonAlphanumericCharsAdded < numberOfNonAlphanumericCharacters && i < length - 1)
{
chars[i] = nonAlphanumericChars[random.Next(nonAlphanumericCharCount)];
numNonAlphanumericCharsAdded++;
}
else
{
chars[i] = allowedChars[random.Next(allowedCharCount)];
}
}
return new string(chars);
}
}
On my website I use this method:
//Symb array
private const string _SymbolsAll = "~`!##$%^&*()_+=-\\|[{]}'\";:/?.>,<";
//Random symb
public string GetSymbol(int Length)
{
Random Rand = new Random(DateTime.Now.Millisecond);
StringBuilder result = new StringBuilder();
for (int i = 0; i < Length; i++)
result.Append(_SymbolsAll[Rand.Next(0, _SymbolsAll.Length)]);
return result.ToString();
}
Edit string _SymbolsAll for your array list.
Added some supplemental code to the accepted answer. It improves upon answers just using Random and allows for some password options. I also liked some of the options from the KeePass answer but did not want to include the executable in my solution.
private string RandomPassword(int length, bool includeCharacters, bool includeNumbers, bool includeUppercase, bool includeNonAlphaNumericCharacters, bool includeLookAlikes)
{
if (length < 8 || length > 128) throw new ArgumentOutOfRangeException("length");
if (!includeCharacters && !includeNumbers && !includeNonAlphaNumericCharacters) throw new ArgumentException("RandomPassword-Key arguments all false, no values would be returned");
string pw = "";
do
{
pw += System.Web.Security.Membership.GeneratePassword(128, 25);
pw = RemoveCharacters(pw, includeCharacters, includeNumbers, includeUppercase, includeNonAlphaNumericCharacters, includeLookAlikes);
} while (pw.Length < length);
return pw.Substring(0, length);
}
private string RemoveCharacters(string passwordString, bool includeCharacters, bool includeNumbers, bool includeUppercase, bool includeNonAlphaNumericCharacters, bool includeLookAlikes)
{
if (!includeCharacters)
{
var remove = new string[] { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z" };
foreach (string r in remove)
{
passwordString = passwordString.Replace(r, string.Empty);
passwordString = passwordString.Replace(r.ToUpper(), string.Empty);
}
}
if (!includeNumbers)
{
var remove = new string[] { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" };
foreach (string r in remove)
passwordString = passwordString.Replace(r, string.Empty);
}
if (!includeUppercase)
passwordString = passwordString.ToLower();
if (!includeNonAlphaNumericCharacters)
{
var remove = new string[] { "!", "#", "#", "$", "%", "^", "&", "*", "(", ")", "-", "_", "+", "=", "{", "}", "[", "]", "|", "\\", ":", ";", "<", ">", "/", "?", "." };
foreach (string r in remove)
passwordString = passwordString.Replace(r, string.Empty);
}
if (!includeLookAlikes)
{
var remove = new string[] { "(", ")", "0", "O", "o", "1", "i", "I", "l", "|", "!", ":", ";" };
foreach (string r in remove)
passwordString = passwordString.Replace(r, string.Empty);
}
return passwordString;
}
This was the first link when I searched for generating random passwords and the following is out of scope for the current question but might be important to consider.
Based upon the assumption that System.Web.Security.Membership.GeneratePassword is cryptographically secure with a minimum of 20% of the characters being Non-Alphanumeric.
Not sure if removing characters and appending strings is considered good practice in this case and provides enough entropy.
Might want to consider implementing in some way with SecureString for secure password storage in memory.
validChars can be any construct, but I decided to select based on ascii code ranges removing control chars. In this example, it is a 12 character string.
string validChars = String.Join("", Enumerable.Range(33, (126 - 33)).Where(i => !(new int[] { 34, 38, 39, 44, 60, 62, 96 }).Contains(i)).Select(i => { return (char)i; }));
string.Join("", Enumerable.Range(1, 12).Select(i => { return validChars[(new Random(Guid.NewGuid().GetHashCode())).Next(0, validChars.Length - 1)]; }))
This is short and it works great for me.
public static string GenerateRandomCode(int length)
{
Random rdm = new Random();
StringBuilder sb = new StringBuilder();
for(int i = 0; i < length; i++)
sb.Append(Convert.ToChar(rdm.Next(101,132)));
return sb.ToString();
}
Here Is what i put together quickly.
public string GeneratePassword(int len)
{
string res = "";
Random rnd = new Random();
while (res.Length < len) res += (new Func<Random, string>((r) => {
char c = (char)((r.Next(123) * DateTime.Now.Millisecond % 123));
return (Char.IsLetterOrDigit(c)) ? c.ToString() : "";
}))(rnd);
return res;
}
Generate random password of specified length with
- Special characters
- Number
- Lowecase
- Uppercase
public static string CreatePassword(int length = 12)
{
const string lower = "abcdefghijklmnopqrstuvwxyz";
const string upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const string number = "1234567890";
const string special = "!##$%^&*";
var middle = length / 2;
StringBuilder res = new StringBuilder();
Random rnd = new Random();
while (0 < length--)
{
if (middle == length)
{
res.Append(number[rnd.Next(number.Length)]);
}
else if (middle - 1 == length)
{
res.Append(special[rnd.Next(special.Length)]);
}
else
{
if (length % 2 == 0)
{
res.Append(lower[rnd.Next(lower.Length)]);
}
else
{
res.Append(upper[rnd.Next(upper.Length)]);
}
}
}
return res.ToString();
}
I use this code for generate password with balance composition of alphabet, numeric and non_alpha_numeric chars.
public static string GeneratePassword(int Length, int NonAlphaNumericChars)
{
string allowedChars = "abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ0123456789";
string allowedNonAlphaNum = "!##$%^&*()_-+=[{]};:<>|./?";
string pass = "";
Random rd = new Random(DateTime.Now.Millisecond);
for (int i = 0; i < Length; i++)
{
if (rd.Next(1) > 0 && NonAlphaNumericChars > 0)
{
pass += allowedNonAlphaNum[rd.Next(allowedNonAlphaNum.Length)];
NonAlphaNumericChars--;
}
else
{
pass += allowedChars[rd.Next(allowedChars.Length)];
}
}
return pass;
}
Insert a Timer: timer1, 2 buttons: button1, button2, 1 textBox: textBox1, and a comboBox: comboBox1. Make sure you declare:
int count = 0;
Source Code:
private void button1_Click(object sender, EventArgs e)
{
// This clears the textBox, resets the count, and starts the timer
count = 0;
textBox1.Clear();
timer1.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
// This generates the password, and types it in the textBox
count += 1;
string possible = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
string psw = "";
Random rnd = new Random { };
psw += possible[rnd.Next(possible.Length)];
textBox1.Text += psw;
if (count == (comboBox1.SelectedIndex + 1))
{
timer1.Stop();
}
}
private void Form1_Load(object sender, EventArgs e)
{
// This adds password lengths to the comboBox to choose from.
comboBox1.Items.Add("1");
comboBox1.Items.Add("2");
comboBox1.Items.Add("3");
comboBox1.Items.Add("4");
comboBox1.Items.Add("5");
comboBox1.Items.Add("6");
comboBox1.Items.Add("7");
comboBox1.Items.Add("8");
comboBox1.Items.Add("9");
comboBox1.Items.Add("10");
comboBox1.Items.Add("11");
comboBox1.Items.Add("12");
}
private void button2_click(object sender, EventArgs e)
{
// This encrypts the password
tochar = textBox1.Text;
textBox1.Clear();
char[] carray = tochar.ToCharArray();
for (int i = 0; i < carray.Length; i++)
{
int num = Convert.ToInt32(carray[i]) + 10;
string cvrt = Convert.ToChar(num).ToString();
textBox1.Text += cvrt;
}
}

Categories

Resources