V řadě případů potřebujeme v programu vygenerovat náhodná čísla. Účely se různí, od zobrazení náhodného "tipu dne" přes pohyb protihráče v počítačové hře až po kryptografické operace - šifrování a digitální podepisování.
Problém spočívá v tom, že získat skutečně náhodná čísla je pouze prostřednictvím běžného digitálního počítače principiálně nemožné. Počítač je z matematického hlediska deterministický konečněstavový automat: na stejnou sadu vstupních parametrů pokaždé vydá tentýž výsledek.
Běžná náhodná (ve skutečnosti pseudo-náhodná) čísla generovaná v .NETu např. třídou System.Random
jsou dobrá možná pro zobrazování oněch tipů, ale pro použití ke generování kryptografických klíčů se nehodí. Jsou v nich patrná schémata, která lze s dostatkem vstupních dat odhalit a bepečnost řady šifrovacích algoritmů závisí na kvalitě klíče.
Pro opravdu náhodná data je třeba využít speciální hardware, který využívá ke generování chaosu například vyzařování radioaktivního materiálu, atmosferický šum a nebo přechodové jevy na polovodičích. Takové komponenty ale nejsou součástí běžných počítačů.
Operační systémy proto obvykle obsahují mechanismus, který se snaží získat náhodnost z různých zdrojů, které sice nejsou úplně náhodné, ale jsou dostatečně nepředvídatelné k tomu, aby byly prakticky použitelné. Používají se např. přesně měřené intervaly mezi stisky kláves na klávesnici nebo příchody síťových paketů. V systému pak existuje služba (nazývaná např. entropy gathering daemon), která takto získané aplikace analyzuje, filtruje a používá ke generování náhodných dat.
RNGCryptoServiceProvider
Přístup k tomuto generátoru je možný pomocí třídy System.Security.Cryptography.RNGCryptoServiceProvider
. Ta má dvě metody, které naplní zvolené pole náhodnými daty: GetBytes
a GetNonZeroBytes
. Obě dělají totéž, až na to, že druhá jmenovaná z náhodného souboru vyřazuje bajty s hodnotou 0, protože v některých aplikacích znak s hodnotou 0 znamená konec hodnot.
Výsledkem volání těchto hodnot je pole bajtů, použitelné např. jako šifrovací klíč. Obvykle se zapisuje jako hodnota zakódovaná do tisknutelných znaků pomocí Base64 nebo Base16 (šestnáctkové číslice). Příslušný kód v C# může vypadat takto:
int keyLength = 24; // 24 bytes = 192 bits
// Generate random bytearray
byte[] key = new byte[keyLength];
System.Security.Cryptography.RNGCryptoServiceProvider rng = new System.Security.Cryptography.RNGCryptoServiceProvider();
rng.GetBytes(key);
// Convert key to Base64
string enc64 = System.Convert.ToBase64String(key);
// Convert key to Base16
System.Text.StringBuilder b16 = new System.Text.StringBuilder(keyLength * 2);
for (int i = 0; i < keyLength; i++) b16.AppendFormat("{0:X2}", key[i]);
string enc16 = b16.ToString();
Proměnná keyLength obsahuje délku klíče v bajtech. v proměnných enc64 a enc16 najdete tentýž náhodný klíč, zakódovaný pomocí Base64 a Base16.
Můžete si stáhnout ukázkovou stránku, která umožňuje generovat náhodné klíče různých délek.