Generate a random string in C#
RandomNumberGenerator.GetString and GetHexString arrived in .NET 8, and Base64Url in .NET 9. Before that, RandomNumberGenerator.GetInt32 picks one character at a time without bias.
Why not System.Random?
System.Random and Random.Shared are fast, but they are not cryptographically secure: someone who sees enough output can predict what comes next, and new Random(seed) gives the same sequence every time. That is fine for shuffling a playlist or test data, and wrong for anything an attacker would like to guess.
The two classes look alike, which makes the mistake easy: Random has GetItems since .NET 8, and .NET 10 added Random.GetString and Random.GetHexString with the same shape as the RandomNumberGenerator methods. For passwords, API keys, tokens, reset codes and salts, use RandomNumberGenerator.
No modulo bias
The naive way, choices[randomByte % choices.Length], favors the first characters whenever 256 is not a multiple of the number of choices. .NET avoids that: with a power of two it masks the extra bits, and otherwise it masks and throws away the values that are out of range, then draws again. This page uses the same algorithm, so every character is equally likely.
How long should it be?
Strength is entropy: the length times log2 of the number of possible characters. OWASP requires at least 64 bits for session IDs, and 128 bits is a common floor for API keys and other long-lived secrets.
| Characters | Bits per character | Length for 128 bits |
|---|---|---|
| 0-9 (10) | 3.32 | 39 |
| Hex (16) | 4 | 32 |
| A-Z and 0-9 without look-alikes (32) | 5 | 26 |
| Base64Url (64) | 6 | 22 (16 bytes) |
| Letters and digits (62) | 5.95 | 22 |
| Letters, digits and 28 symbols (90) | 6.49 | 20 |
FAQ
How do I generate a random string in C#?
On .NET 8 and later, call RandomNumberGenerator.GetString(choices, length) from System.Security.Cryptography. It picks each character from choices with a cryptographically secure generator and without modulo bias. On older versions, pick each character with RandomNumberGenerator.GetInt32(choices.Length).
Why not use System.Random for random strings?
System.Random is not cryptographically secure: its output can be predicted, and new Random(seed) repeats the same sequence. Use it for simulations and games, and RandomNumberGenerator for passwords, tokens, keys and reset codes.
How long should a random token be?
Count bits of entropy, not characters: length times log2 of the number of possible characters. OWASP requires at least 64 bits for session IDs, and 128 bits is a common choice for API keys: for example 16 random bytes as Base64Url, or 22 letters and digits.
Can I require at least one digit or symbol?
RandomNumberGenerator has no option for it. Generate a string and try again while it lacks what you need; that keeps every accepted string equally likely. Forcing a character into a fixed position makes the result more predictable.
Why are duplicate characters removed?
A character that appears twice in choices is picked twice as often. The page removes repeats before it builds the C# string.
Can I use emoji or other characters outside the BMP?
Not with GetString: it picks single UTF-16 char values, so it would split a character that needs two (a surrogate pair). The page leaves them out and says so.
Are the strings sent anywhere?
No. They are generated in your browser with crypto.getRandomValues and never leave the page.