Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
153 views
in Technique[技术] by (71.8m points)

c# - Generating random string using RNGCryptoServiceProvider

I'm trying to generate a random string using a range of acceptable characters. I have a working implementation, which is included below, but I wanted to know if the logic of converting the random byte to a printable character exposes me to any risk or inadvertently exposes other internal states. I kept the number of available characters as a number evenly divisible by 256, to help prevent an uneven bias in the generated string.

using System.Security.Cryptography;
class Example {
  static readonly char[] AvailableCharacters = {
    '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', 
    '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', 
    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_'
  };

  internal static string GenerateIdentifier(int length) {
    char[] identifier = new char[length];
    byte[] randomData = new byte[length];

    using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider()) {
      rng.GetBytes(randomData);
    }

    for (int idx = 0; idx < identifier.Length; idx++) {
      int pos = randomData[idx] % AvailableCharacters.Length;
      identifier[idx] = AvailableCharacters[pos];
    }

    return new string(identifier);
  }
}

Running the above sample code 10 times with a length of 40 gives me the following output:

hGuFJjrr6xuuRDaOzJjaltL-ig09NNzbbvm2CyZG
BLcMF-xcKjmFr5fO-yryx8ZUSSRyXcTQcYRp4m1N
ARfPJhjENPxxAxlRaMBK-UFWllx_R4nT0glvQLXS
7r7lUVcCkxG4ddThONWkTJq0IOlHzzkqHeMi4ykU
TMwTRFORVYCLYc8iWFUbfZWG1Uk2IN35IKvGR0zX
hXNADtfnX4sjKdCgmvZUqdaXSFEr_c_mNB3HUcax
-3nvJyou8Lc-a0limUUZYRScENOoCoN9qxHMUs9Y
bQPmVvsEjx0nVyG0nArey931Duu7Pau923lZUnLp
b8DUUu6Rl0VwbH8jVTqkCifRJHCP3o5oie8rFG5J
HuxF8wcvHLpiGXedw8Jum4iacrvbgEWmypV6VTh-

The question I guess I'm asking, is this code relatively safe for use or is this a really, really bad idea? The end users never see this identifier and the lifetime is very short lived.

Additional information

In an attempt to describe more about the use of the identifier, it's intended use is to be used as a key for a short-lived request, used to pass information from one application to another, third-party system. Since the data has to go through the (untrusted) user's browser, we are storing the actual report information in a database and generating this identifier for the target application to be able to pick up and remove that information from the database.

Since the target information is in a third-party system outside of our control (development wise, still on-premises) and we can't directly authenticate our users against the third-party system, this token is intended to allow the user to be identified and for the report to be run with the information stored in the database. The report itself has to be public facing (on the internet) without authentication (because the majority of our users don't have account in the third-party system) and because the report deals with HIPAA/FERPA data we wanted to ensure as best we can that even with the identifier in the attackers control that they can't generate a valid request.

question from:https://stackoverflow.com/questions/19298801/generating-random-string-using-rngcryptoserviceprovider

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The additional information is helpful. I presume that you never send the token in the clear and never send it to an untrusted party.

To answer the question that was actually asked: yes, your code correctly generates a 40 character random string containing 240 bits of randomness. I note that of course you consume 320 bits of randomness to do so, but, whatever, bits are cheap.

Presumably the number of tokens thus generated is a very small fraction of 2240, and therefore it will be hard for an attacker to guess at a valid token. If tokens have a short lifespan -- if they are only in the database while the transaction is happening, and then go away a short time later -- that's even better. Defense in depth.

Note that a software RNG takes information from its environment as the seed entropy. If malware can be running on the machine doing the generation then it could be attempting to manipulate that environment, and thereby deduce part of the entropy. But if you have malware running on that machine, odds are good that you already have far larger problems.

I note also that the garbage collector does not make any guarantees about how long those strings and arrays containing the token hang around in memory. Again, if you have malware with admin privileges on your machine that starts up a debugger and interrogates memory, it can discover the keys. Of course that presumes that the bad actors are already on the wrong side of the airtight hatchway, as Raymond Chen says. Memory scanning by malware with admin privileges is the least of your worries!


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

57.0k users

...