DateTime.Now.Ticks is too slow - c#

I am making a password generator which can generate a password.
var listOfCharacters = "abcdefghijklmnopqrstuvwxyz" //the chars which are using
chars = listOfCharacters.ToCharArray();
string password = string.Empty;
for (int i = 0; i < length; i++)
{
int x = random.Next(0, chars.Length); //with random he is picking a random char from my list from position 0 - 26 (a - z)
password += chars.GetValue(x); // putting x (the char which is picked) in the new generated password
}
if (length < password.Length) password = password.Substring(0, length); // if the password contains the correct length he will be returns
return password;
My random:
random = new Random((int)DateTime.Now.Ticks);
I am looking for a faster way to generate a password than using Ticks, because its not fast enough for me. I am looking for a simple code which i can easy put in my above code. I am just a beginner in C#. So that i still can use int x = random.Next(0, chars.Length); but instead of Random.next a faster one.
EDIT:
When i want two generate two passwords in a short time .Ticks is to slow
My test code:
[TestMethod]
public void PasswordGeneratorShouldRenderUniqueNextPassword()
{
// Create an instance, and generate two passwords
var generator = new PasswordGenerator();
var firstPassword = generator.Generate(8); //8 is the length of the password
var secondPassword = generator.Generate(8);
// Verify that both passwords are unique
Assert.AreNotEqual(firstPassword, secondPassword);
}

You could use the hashcode of a Guid as seed value for your Random instance. It should be random enough for your case.
random = new Random(Guid.NewGuid().GetHashCode());

Either create the Random instance once at startup or use the RNGCryptoServiceProvider.
// Create the random instance only once.
private static Random _Random = new Random();
static void Main(string[] args)
{
var listOfCharacters = "abcdefghijklmnopqrstuvwxyz".ToList();
var result = new StringBuilder();
for (int i = 0; i < 20; i++)
{
// Consider creating the provider only once!
var provider = new RNGCryptoServiceProvider();
// The same is true for the byte array.
var bytes = new byte[4];
provider.GetBytes(bytes);
var number = BitConverter.ToInt32(bytes, 0);
var index = Math.Abs(number % listOfCharacters.Count);
result.Append(listOfCharacters[index]);
}
Console.WriteLine(result.ToString());
Console.ReadKey();
}
Bias testing
static void Main(string[] args)
{
var listOfCharacters = "abcdefghijklmnopqrstuvwxyz".ToList();
var occurences = new Dictionary<char, int>();
foreach (var character in listOfCharacters)
{
occurences.Add(character, 0);
}
var provider = new RNGCryptoServiceProvider();
var bytes = new byte[4];
for (int i = 0; i < 1000000; i++)
{
provider.GetBytes(bytes);
var number = BitConverter.ToInt32(bytes, 0);
var index = Math.Abs(number % listOfCharacters.Count);
occurences[listOfCharacters[index]]++;
}
var orderedOccurences = occurences.OrderBy(kvp => kvp.Value);
var minKvp = orderedOccurences.First();
var maxKvp = orderedOccurences.Last();
Console.WriteLine("Min occurence: " + minKvp.Key + " Times: " + minKvp.Value);
Console.WriteLine("Max occurence: " + maxKvp.Key + " Times: " + maxKvp.Value);
Console.WriteLine("Difference: " + (maxKvp.Value - minKvp.Value));
Console.ReadKey();
}
The result is that between the highest occurrence and the lowest is a value somewhere between 700 - 800 which means the bias is somewhere at 0.08% and the two characters with the maximum difference always differs. So i really can't see any bias.

The following program generates ~500 passwords / millisecond on my computer:
class Program
{
static void Main(string[] args)
{
var g = new Generator();
IEnumerable<string> passwords = new List<string>();
var startTime = DateTime.Now;
passwords = g.GetPassword().ToList();
}
}
class Generator
{
Random r = new Random(Guid.NewGuid().GetHashCode());
string randomCharsList;
const int length = 8;
const int randomLength = 8000;
const string listOfCharacters = "abcdefghijklmnopqrstuvwxyz";
public Generator()
{
CreateRandom();
}
private void CreateRandom()
{
var randomChars = new StringBuilder();
string password = string.Empty;
for (int i = 0; i < randomLength + length; i++)
{
var random = new Random(i * Guid.NewGuid().ToByteArray().First());
int x = random.Next(0, listOfCharacters.Length);
randomChars.Append(listOfCharacters[x]);
}
randomCharsList = randomChars.ToString();
}
public IEnumerable<string> GetPassword()
{
int pos;
var startTime = DateTime.Now;
while ((DateTime.Now - startTime).Milliseconds < 1)
{
pos = r.Next(randomLength);
yield return randomCharsList.Substring(pos, length);
}
}
}

Just wanted to add a note here about the thread safety issue in generating random numbers (such as a high volume webserver where we ran into this issue).
Essentially, Random class is NOT thread safe and if collision occurs, it will return 0 (not what i expected) which needless to say can really wreak havoc in your logic :) So if using in a multi-threaded environment then make sure to protect access to any shared Random objects.
See section on the 'The System.Random class and thread safety' at https://msdn.microsoft.com/en-us/library/system.random(v=vs.110).aspx for more details.
Hope this helps someone.

Related

C# Programming Assignment

The teacher wants me to create 2 files & insert random characters inside. Both files should be the same length. In one file a keyword "Hello" should be inserted randomly.
I did this for the first file:
var stringChars = new char[100];
var random = new Random();
var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
for (int i = 0; i < stringChars.Length; i++)
{
stringChars[i] = chars[random.Next(chars.Length)];
}
I did this for the second file:
var stringChars2 = new char[100];
var random2 = new Random();
var chars2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZxxxxx";
for (int i = 0; i < stringChars2.Length; i++)
{
stringChars2[i] = chars2[random2.Next(chars2.Length)];
}
string string2 = new string(stringChars2);
string2 = string2.Replace("x", "\"Hello\"");
My problem is I don't know how to make the length of both files equal with the string replace trick. The second file will always be longer.
Here's an object oriented approach. I emphasize this approach since you have to perform similar operations multiple times (two). Thus, you shouldn't repeat yourself (google DRY prinicpal).
I won't tell you how to use these methods, you can figure that our for yourself:
public static class StringManipulation
{
public static string GetXRandomCharacters(int x)
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
var random = new Random();
var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
for (int i = 0; i < stringChars.Length; i++)
{
sb.Append(chars[random.Next(chars.Length)]);
}
return sb;
}
public static string InjectWordAtRandom(string str, string word)
{
var random = new Random();
int start = random.Next(str.Length - word.Length);
str.Remove(start, word.Length).Insert(start, word);
}
}
Hint: I have provided static methods but you don't have to do it that way. Try removing static from the method headers and creating an instance of the class to access it's properties.

Generate multiple unique strings in C#

For my project, I have to generate a list of unique strings.
Everything works fine, but my problem is that it is very slow at the end.
I've tried using Parallel-Loops, but I found out that my ConcurrentBag<T>, which I was using, is also slow.
Now I'm using a simple for-loop and List<T> and it is now a little bit faster, but also really slow.
Here's my code:
private List<string> Generate(int start, int end, bool allowDupes)
{
var list = new List<string>();
var generator = new StringGenerator(LowerCase, UpperCase, Digits, NumberOfCharacters);
for (var i = start; i < end; i++)
{
StringBuilder sb;
while (true)
{
sb = new StringBuilder();
for (var j = 0; j < NumberOfSegments; j++)
{
sb.Append(generator.GenerateRandomString());
if (j < NumberOfSegments - 1)
{
sb.Append(Delimiter);
}
}
if (!allowDupes)
{
if (list.Contains(sb.ToString()))
{
continue;
}
}
break;
}
list.Add(sb.ToString());
GeneratedStringCount = i + 1;
}
return new List<string>(list);
}
I've also talked to my teacher and he would use the same algorithm for generating these strings.
Do you know a better solution? (The GenerateRandomString() Method in StringGenerator is simple and does not consume much performance. list.Contains(xy) is consuming alot of resources. [Performance Analysis in Visual Studio])
List.Contains is slow. Use a HashSet instead.
private List<string> Generate(int start, int end, bool allowDupes)
{
var strings = new HashSet<string>();
var list = new List<string>();
var generator = new StringGenerator(LowerCase, UpperCase, Digits, NumberOfCharacters);
for (var i = start; i < end; i++)
{
while (true)
{
string randomString = GetRandomString();
if (allowDupes || strings.Add(randomString))
{
list.Add(randomString);
break;
}
}
GeneratedStringCount = i + 1;
}
return new List<string>(list);
}
private string GetRandomString()
{
var segments = Enumerable.Range(1, NumberOfSegments)
.Select(_ => generator.GenerateRandomString());
var result = string.Join(Delimeter, segments);
return result;
}
This still has the chance for slow performance, but you could remedy that with a smart GenerateRandomString function.
public static String GenerateEightCode( int codeLenght, Boolean isCaseSensitive)
{
char[] chars = GetCharsForCode(isCaseSensitive);
byte[] data = new byte[1];
RNGCryptoServiceProvider crypto = new RNGCryptoServiceProvider();
crypto.GetNonZeroBytes(data);
data = new byte[codeLenght];
crypto.GetNonZeroBytes(data);
StringBuilder sb = new StringBuilder(codeLenght);
foreach (byte b in data)
{
sb.Append(chars[b % (chars.Length)]);
}
string key = sb.ToString();
if (codeLenght == 8)
key = key.Substring(0, 4) + "-" + key.Substring(4, 4);
else if (codeLenght == 16)
key = key.Substring(0, 4) + "-" + key.Substring(4, 4) + "-" + key.Substring(8, 4) + "-" + key.Substring(12, 4);
return key.ToString();
}
private static char[] GetCharsForCode(Boolean isCaseSensitive)
{
// all - abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890
char[] chars = new char[58];
if (isCaseSensitive)
{
chars = "abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ123456789".ToCharArray();//počet unikátních kombinací 4 - 424 270, 8 - 1 916 797 311, 16 - 7.99601828013E+13
}
else
{
chars = new char[35];
chars = "ABCDEFGHIJKLMNPQRSTUVWXYZ123456789".ToCharArray();//počet unikátních kombinací 4 - 52 360, 8 - 23 535 820, 16 - 4 059 928 950
}
return chars;
}

Random number generator - variable length

Currently my program generates random 8 character strings made from numbers.
See below
public static string GenerateNewCode()
{
string newCode = String.Empty;
int seed = unchecked(DateTime.Now.Ticks.GetHashCode());
Random random = new Random(seed);
// keep going until we find a unique code
do
{
newCode = random.Next(0, 9999).ToString("0000")
+ random.Next(0, 9999).ToString("0000");
}
while (!ConsumerCode.isUnique(newCode));
// return
return newCode;
}
However, I want to be able to create random codes of 8, 9, 10, 11 and 12 numbers.
Not sure the most efficient way of doing this.
My idea was to create a random number between 0 - 9 and then do this X amount of times based on the length of code required.
There must be an easy/more efficient way to doing this .....
Unless this is time critical I would just generate a 12-digit random number every time and just use the 8-12 digits I need. You're testing and retrying for uniqueness, so that should still work.
internal class Program {
private static void Main(string[] args) {
Console.WriteLine(GetNumber(7));
Console.WriteLine(GetNumber(8));
Console.WriteLine(GetNumber(12));
Console.WriteLine(GetNumber(500));
}
public static string GetNumber(int length) {
return string.Concat(RandomDigits().Take(length));
}
public static IEnumerable<int> RandomDigits() {
var rng = new Random(System.Environment.TickCount);
while (true) yield return rng.Next(10);
}
}
or
internal class Program {
private static void Main(string[] args) {
Console.WriteLine(GetNumber(12));
}
public static string GetNumber(int length) {
var rng = new Random(Environment.TickCount);
return string.Concat(Enumerable.Range(0, length).Select((index) => rng.Next(10).ToString()));
}
}
Easy? yes. Most efficient? maybe not.
var r = new Random();
z = 12
Enumerable.Range(1,z).Select(x => r.Next(10).ToString()).Aggregate((x,y) => x + y)
maybe not that efficient but looks cool :D
If you want to length of the code be predefind use:
public static string GenerateNewCode(int length)
{
string newCode = String.Empty;
int seed = unchecked(DateTime.Now.Ticks.GetHashCode());
Random random = new Random(seed);
// keep going until we find a unique code
do
{
newCode = random.Next(Math.Pow(10,length-1), Math.Pow(10,length)-1).ToString("0000")
}
while (!ConsumerCode.isUnique(newCode));
// return
return newCode;
}
if you want the length to be random use this:
public static string GenerateNewCode()
{
string newCode = String.Empty;
int seed = unchecked(DateTime.Now.Ticks.GetHashCode());
Random random = new Random(seed);
int length = random.Next(9,12);
// keep going until we find a unique code
do
{
newCode = random.Next(Math.Pow(10,length-1), Math.Pow(10,length)-1).ToString("0000")
}
while (!ConsumerCode.isUnique(newCode));
// return
return newCode;
}
I would do it like this:
List<int> li = new List<int>();
for(int i = 0; i<=9999; i++)
{
li.Add(i);
}
List<int> liRandom = new List<int>();
for(int i = 0; i<= 9999; i++) //replace 9999 with a number you need to gen
{
int randomIndex = rand.Next(0,li.Length);
liRandom.Add(li[randomIndex]);
li.Remove(li[randomIndex]);
}// liRandom now contains needed numbers
Hope you got the idea :)
and this one might actually be efficient
public static string GetNumber(int length) {
var rng = new Random(Environment.TickCount);
var number = rng.NextDouble().ToString("0.000000000000").Substring(2, length);
return number;
}
works up to 12 characters, may work up to 16.

How to generate a random string, and specify the length you want, or better generate unique string on specification you want

There is a library to generate Random numbers, so why isn't there a library for generation of random strings?
In other words how to generate a random string, and specify desired length, or better, generate unique string on specification you want i.e. specify the length, a unique string within my application is enough for me.
I know I can create a Guid (Globally Unique IDentifier) but those are quite long, longer they need to be.
int length = 8;
string s = RandomString.NextRandomString(length)
uniquestringCollection = new UniquestringsCollection(length)
string s2 = uniquestringCollection.GetNext();
I can't recall where I got this, so if you know who originally authored this, please help me give attribution.
private static void Main()
{
const string AllowedChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz##$^*()";
Random rng = new Random();
foreach (string randomString in rng.NextStrings(AllowedChars, (15, 64), 25))
{
Console.WriteLine(randomString);
}
Console.ReadLine();
}
private static IEnumerable<string> NextStrings(
this Random rnd,
string allowedChars,
(int Min, int Max)length,
int count)
{
ISet<string> usedRandomStrings = new HashSet<string>();
(int min, int max) = length;
char[] chars = new char[max];
int setLength = allowedChars.Length;
while (count-- > 0)
{
int stringLength = rnd.Next(min, max + 1);
for (int i = 0; i < stringLength; ++i)
{
chars[i] = allowedChars[rnd.Next(setLength)];
}
string randomString = new string(chars, 0, stringLength);
if (usedRandomStrings.Add(randomString))
{
yield return randomString;
}
else
{
count++;
}
}
}
How about-
static Random rd = new Random();
internal static string CreateString(int stringLength)
{
const string allowedChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz0123456789!#$?_-";
char[] chars = new char[stringLength];
for (int i = 0; i < stringLength; i++)
{
chars[i] = allowedChars[rd.Next(0, allowedChars.Length)];
}
return new string(chars);
}
How about
string.Join("", Enumerable.Repeat(0, 100).Select(n => (char)new Random().Next(127)));
or
var rand = new Random();
string.Join("", Enumerable.Repeat(0, 100).Select(n => (char)rand.Next(127)));
Random string using Concatenated GUIDs
This approach uses the minimum number of concatenated GUIDs to return a random string of the desired number of characters.
/// <summary>
/// Uses concatenated then SubStringed GUIDs to get a random string of the
/// desired length. Relies on the randomness of the GUID generation algorithm.
/// </summary>
/// <param name="stringLength">Length of string to return</param>
/// <returns>Random string of <paramref name="stringLength"/> characters</returns>
internal static string GetRandomString(int stringLength)
{
StringBuilder sb = new StringBuilder();
int numGuidsToConcat = (((stringLength - 1) / 32) + 1);
for(int i = 1; i <= numGuidsToConcat; i++)
{
sb.Append(Guid.NewGuid().ToString("N"));
}
return sb.ToString(0, stringLength);
}
Example output with a length of 8:
39877037
2f1461d8
152ece65
79778fc6
76f426d8
73a27a0d
8efd1210
4bc5b0d2
7b1aa10e
3a7a5b3a
77676839
abffa3c9
37fdbeb1
45736489
Example output with a length of 40 (note the repeated '4' - in a v4 GUID, thee is one hex digit that will always be a 4 (effectively removing 4 bits) -- the algorithm could be improved by removing the '4' to improve randomness, given that the returned length of the string can be less than the length of a GUID (32 chars)...):
e5af105b73924c3590e99d2820e3ae7a3086d0e3
e03542e1b0a44138a49965b1ee434e3efe8d063d
c182cecb5f5b4b85a255a397de1c8615a6d6eef5
676548dc532a4c96acbe01292f260a52abdc4703
43d6735ef36841cd9085e56f496ece7c87c8beb9
f537d7702b22418d8ee6476dcd5f4ff3b3547f11
93749400bd494bfab187ac0a662baaa2771ce39d
335ce3c0f742434a904bd4bcad53fc3c8783a9f9
f2dd06d176634c5b9d7083962e68d3277cb2a060
4c89143715d34742b5f1b7047e8107fd28781b39
2f060d86f7244ae8b3b419a6e659a84135ec2bf8
54d5477a78194600af55c376c2b0c8f55ded2ab6
746acb308acf46ca88303dfbf38c831da39dc66e
bdc98417074047a79636e567e4de60aa19e89710
a114d8883d58451da03dfff75796f73711821b02
C# Fiddler Demo: https://dotnetfiddle.net/Y1j6Dw
I commonly use code like the following to generate a random string:
internal static class Utilities {
static Random randomGenerator = new Random();
internal static string GenerateRandomString(int length) {
byte[] randomBytes = new byte[randomGenerator.Next(length)];
randomGenerator.NextBytes(randomBytes);
return Convert.ToBase64String(randomBytes);
}
}
This will create a Base64 encoded string of the random bytes generated by the random object. It isn't thread safe so multiple threads will have to lock around it. Additionally I use a static Random object so two calls to the method at the same time won't get the same initial seed.
A library for generating random strings wouldn't be very useful. It would either be too simple, so that you often need to replace it anyway, or too complex in order to be able to cover any possible situation, that you replace it because it's to complicated to use.
Creating random strings is quite easy by using the random geneator for numbers, given the exact details of your needs. It's just more efficient to write the code specifically for each situation.
If you want a unique string, there is two possibilities. You can either keep every random string that is created, so that you can check for uniqueness, or you can make it really long so that it's incredibly unlikely that there would be duplicates. A GUID does the latter (which explains why it's so long), so there is already an implementation for that.
Sometimes a random string can be useful in something like a unit test, if it was me I would add the AutoFixture nuget package and then do something like this.
In my example I need a 121 character string...
var fixture = new Fixture();
var chars = fixture.CreateMany<char>(121).ToArray();
var myString = new string(chars);
If this wasn't in a unit test then I'd create myself a nuget package and use Autofixture in that, or something else if I needed only certain character types.
You've sort of answered your own question; there is no RandomString() function because you can use a random number generator to generate a string easily.
1) Make the range of numbers between the ASCII characters that you wish to include
2) Append each character to a string until the desired length is reached.
3) Rise and repeat for each string needed (add them to an array, etc.)
Surely that'd do it?
How about something like this...
static string GetRandomString(int lenOfTheNewStr)
{
string output = string.Empty;
while (true)
{
output = output + Path.GetRandomFileName().Replace(".", string.Empty);
if (output.Length > lenOfTheNewStr)
{
output = output.Substring(0, lenOfTheNewStr);
break;
}
}
return output;
}
Output
static void Main(string[] args)
{
for (int x = 0; x < 10; x++)
{
string output = GetRandomString(20);
Console.WriteLine(output);
}
Console.ReadKey();
}
 
r323afsluywgozfpvne4
qpfumdh3pmskleiavi3x
nq40h0uki2o0ptljxtpr
n4o0rzwcz5pdvfhmiwey
sihfvt1pvofgxfs3etxg
z3iagj5nqm4j1f5iwemg
m2kbffbyqrjs1ad15kcn
cckd1wvebdzcce0fpnru
n3tvq0qphfkunek0220d
ufh2noeccbwyfrtkwi02
Online Demo: https://dotnetfiddle.net/PVgf0k
References
• https://www.dotnetperls.com/random-string
public static String getAlphaNumericString(int n) {
String AlphaNumericString = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789" + "abcdefghijklmnopqrstuvxyz";
StringBuilder sb = new StringBuilder(n);
for (int i = 0; i < n; i++) {
// generate a random number between
// 0 to AlphaNumericString variable length
int index = (int) (AlphaNumericString.length() * Math.random());
// add Character one by one in end of sb
sb.append(AlphaNumericString.charAt(index));
}
return sb.toString();
}
Here is some modification from above answers.
private static string GetFixedLengthStrinng(int len)
{
const string possibleAllChars = "ABCDEFGHJKLMNOPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz0123456789!##$%^&*()_+{}:',.?/";
StringBuilder sb = new StringBuilder();
Random randomNumber = new Random();
for (int i = 0; i < len; i++)
{
sb.Append(possibleAllChars[randomNumber.Next(0, possibleAllChars.Length)]);
}
return sb.ToString();
}

attempting to create string of random values

I'm trying to generate a string of a random length which consists out of random chars.
To do so I have this code:
class Program
{
static void Main(string[] args)
{
for (int i = 0; i < 1000; i++)
{
MyString test = new MyString();
test.Random();
Console.WriteLine(test.Value);
}
Console.ReadLine();
}
}
public class MyString
{
private string value = string.Empty;
private Random r = new Random();
public string Value
{
get { return this.value; }
set { this.value = value; }
}
public void Random()
{
int length = (r.Next() % (100)) + 1;
for(int i = 0; i < length; i++)
{
value = value + RandomChar();
}
}
public char RandomChar()
{
// 32 to 126
int c = (r.Next() % 95) + 32;
char ch = (char)c;
return ch;
}
}
Now, lets look at a part of the output:
As you can see, the output is far from random, it contains a lot of repeating strings. How is this possible, and how do I solve it?
It looks like you are creating a new instance of the Random class every time your MyString constructor is called. The Random class probably seeds itself based on the current time (to some resolution). Random number generators seeded with the same value will generate the same pseudo-random sequence.
The solution is to construct one instance of Random and use that everywhere.
http://msdn.microsoft.com/en-us/library/system.io.path.getrandomfilename.aspx
string randomName = Path.GetRandomFileName();
randomName = randomName.Replace(".", string.Empty);
// take substring...

Categories