3

If we compared my method below with RCIX's method in this answer to a question, which is more efficient and why?

private string RandomString(int length = 25)
{
    const string chars = "aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ0123456789#@%&";
    StringBuilder sbSalt = new StringBuilder();

    for (int i = 0; i < length; i++)
    {
        int inx = 0;

        inx = rnd.Next(0, chars.Length);
        sbSalt.Append(chars[inx]);
    }

    return sbSalt.ToString();
}

private Random rnd = new Random();

The reason I did "aAbBcC..." instead of "abc...ABC..." was to increase the chances of randomization between the lower and capital case of each letter since they are next to each other.

And also, for a password salt, is it best to keep duplicate characters or should I make sure that each character is only encountered once per salt? Then again, if I allow duplicate characters, the salt combination amount that can be generated is greater.

Thanks in advance!

UPDATE #1:

I realised that if I called the RandomString function again, it would return the exact same Random String, so to fix that I declared rnd as new Random only once by moving it outside the function.

Community
  • 1
  • 1
Hello World
  • 423
  • 5
  • 15
  • As for your update: the Random uses a seed in its constructor. The `.Next()` function return the same set of numbers when the same seed is provided. If the seed is not inserted into the `Random` constructor, it will use a DateTime.Now based value instead. – Stefan May 14 '14 at 11:32
  • That's another useful thing to remember. Is the work-around I used a good one? – Hello World May 14 '14 at 12:00
  • Well, actually, it's better the create a new `Random` object within the function `RandomString` function. It will be better readable and the performance overhead will be small. Besides although it is a technical detail, the longer a `Random` object lives, the bigger the fall of true randomness will be. For more info about it: http://stackoverflow.com/a/4440760/2416958 which will redirect you to the appropriate literature. – Stefan May 14 '14 at 12:08
  • @Stefan: I don't agree on creating the `Random` object within the function. This will always create a new instance based on the current time. If you would instantiate the class multiple times, chances are that it will create the same seed. Best is to create a `Random` object for a specific purpose and use it throughout the entire lifetime of the application to ensure correct distribution (of course, within period of repetition). – Caramiriel May 14 '14 at 12:22
  • @Caramiriel: let me recheck that; my info is based on the non-true-randomness of the psuedo-random algorithm. I'll defently admit it (might) only be an issue if you call the `.Next` function really really really often (like 10^10 times). I'll try to get some info and restate if I am wrong. Thanks. – Stefan May 14 '14 at 12:25
  • @Caramiriel: you are right, the default seed is based on a 32-bit number (ticks). Chances to get the same seed are probably bigger then hitting the non-randomness of the algorithm. – Stefan May 14 '14 at 12:34
  • I actually finally understand how Random gets its "random" value, which is indeed a pretty clever and good method of doing it. Thank you, Stefan. The function will be is currently within a static class, and is supposed to run on a server. Meaning a new instance of rnd as Random will only be created upon run-time and use the same instance of rnd for days and days, which according to Stefan is a bad idea and I agree. I have two solutions for that. – Hello World May 14 '14 at 12:40
  • 1. Make the class non-static and create a new instance of the class itself when needed. (quite resource-wasting I presume) 2. Find some part of the code which is guaranteed to be called frequently enough to create a new instance of rnd as Random. What do you think? What are your suggestions? – Hello World May 14 '14 at 12:43

2 Answers2

1

The reason I did "aAbBcC..." instead of "abc...ABC..." was to increase the chances of randomization between the lower and capital case of each letter since they are next to each other. this will not increase randomness between upper and lower case.

You can test this with a dice, the places of the numbers will not change the odds of even and odd numbers.

The efficiency will depend on how you define it. Do you want your code to be more or less readable? Do you need high performance? Maintainability?

In normal cases I wouldn't prefer the one above the other.

Is it best to keep duplicate characters or should I make sure that each character is only encountered once per salt?

actually, the amount of permutations increase if you allow double characters.

This means the string will be harder to crack in a brute force attack.

If you are using this salt for encryption techniques, it's best to use the framework's libraries. Like GetBytes():

http://msdn.microsoft.com/en-us/library/system.security.cryptography.rngcryptoserviceprovider.aspx

Stefan
  • 17,448
  • 11
  • 60
  • 79
  • The reason I think it will increase the randomness, is because I sort of don't trust the Random library for randomness enough. I don't really understand how it works either, and that troubles me about it. I've been taught at school that if your code is easily readable by other programmers, then it's a good piece of code. What is your opinion? And I'd rather a balance between safe, fast and less resource usage. Everything is turned into a byte array before blended and/or encrypted with the string to hash and/or encrypt. It's kind of a thing the libraries demand me to do. – Hello World May 14 '14 at 11:54
  • The randomness is pretty good (which is an understatement). Good readable code is usually the best criteria for good code (provided it is logical as well). Although in ultra-high performance environments, it might be better to tweak the code a bit, like reusing objects, avoid loops etc. Chances are big that the overhead of your code is minimal compared the the encryption algorithms. So unless you're running your code thousands of times its good enough. So it's up to you :) ... I hope this helped. – Stefan May 14 '14 at 12:16
1

The main use of salt is to make a encryption more difficult for a dictionary attack.

I do like to create dirt on the key itself and so far it is very efficient as i have encryption running couple hundred encryption/decryption per seconds over WCF services :

// sKey being the encryption key

// adding dirt to the string to make it harder to guess using a dictionary attack.
byte[] Dirt = Encoding.ASCII.GetBytes(sKey.Length.ToString());

// The Key will be generated from the specified Key and dirt.
PasswordDeriveBytes FinalKey = new PasswordDeriveBytes(sKey, Dirt);

// to use : FinalKey.GetBytes(16)
Franck
  • 4,438
  • 1
  • 28
  • 55
  • Ahh, I see. I would rather the dirt be something more variable, though. But that's just how I see it. Thank you for the answer! I'm pretty sure this knowledge will get in handy sometime in the future. – Hello World May 14 '14 at 11:48