Symetrické šifrování AES/Rijndael v .NET

Současným průmyslovým standardem pro symetrické šifrování je algoritmus AES (Advanced Encryption Standard), nazývaný též Rijndael. Je k dispozici i jako součást Microsoft .NET Frameworku a je k dispozici všem programátorům.

Rijndael nebo AES?

Jako většina šifrovacích algoritmů, i Rijndael odvozuje svůj název od jmen svých autorů: Joan Daemen a Vincent Rijmen. Rijndael je původní název algoritmu, který byl v roce 2001 přijat americkým Národním institutem pro standardizaci a technologie (NIST) pod názvem Advanced Encryption Standard jako standard pro šifrování v rámci amerických vládních úřadů a nazván. V této roli nahradil algoritmus DES (Data Encryption Standard), považovaný již za zastaralý. V praxi tedy názvy "Rijdael" a "AES" odkazují na totéž.

Symetrické a asymetrické algoritmy

V případě Rijndael/AES jde o symetrický algoritmus, což znamená, že používá sdílený klíč: tentýž klíč slouží k zašifrování i dešifrování dat. Délka klíče je 128, 196 nebo 256 bitů.

Hlavní výhodou symetrického šifrování je, že je obecně velmi rychlé a dá se použít pro šifrování velkého objemu dat. Zásadní nevýhodou (pro řadu aplikací) je ale samotné použití sdíleného klíče: ten kdo data zašifroval je umí i dešifrovat a komunikují-li spolu dvě strany, je nutné, aby si klíč bezpečně předaly důvěrnou cestou. Bezpečnost šifry také závisí na kvalitě použitého klíče, musí být dostatečně komplexní a dostatečně náhodný, jinak je šifra snadno prolomitelná.

Oproti tomu asymetrické šifrování (jako např. RSA) využívá dvou klíčů: veřejného (ten se použije pro zašifrování dat) a soukromého (používá se pro dešifrování), přičemž tyto klíče mohou být od sebe odděleny. Asymetrické algoritmy jsou ale velmi pomalé a prakticky nepoužitelné pro šifrování velkého objemu dat.

V praxi se často obě metody kombinují: vlastní data se zašifrují pomocí symetrického algoritmu (AES) a použitý jednorázový klíč (který je dosti malý) se zašifruje pomocí asymetrického algoritmu (RSA). Na toto použití se podíváme v samostatném článku, v tomto se zaměříme na vlastní použití symetrického algoritmu.

I samostatné použití symetrického šifrovacího algoritmu má samozřejmě svůj význam. V případě že ho dokážete bezpečně uschovat/předat a oddělení šifrovacího a dešifrovacího klíče pro vás nemá význam, protože z hlediska architektury systému by stejně obě části musely být uschovány na tomtéž místě.

Modes of operation, IV, padding

Rijndael je blokový šifrovací algoritmus. Je aplikován na data s pevně danou délkou - v tomto konkrétním případě 128 bitů. Pokud jsou šifrovaná data delší, zpracovávají se po jednotlivých blocích. Pokud jsou data kratší (typicky v případě posledního bloku se zbytkem dat), je potřeba je doplnit na odpovídající délku.

Onomu doplnění na odpovídající délku se říká "padding". Existuje pro něj několik algoritmů, od primitivního doplnění nulami po složitější schémata. Nejčastěji se používá mechanismus podle PKCS #7 (podrobnější popis najdete např v RFC2315, ale nemusí vás příliš zajímat, tento mechanismus je vestavěn v .NET Frameworku).

Naivní implementace blokové šifry by spočívala v tom, že by se šifra aplikovala na jednotlivé bloky tak, jak jdou za sebou. Tomuto postupu se říká ECB (Electronic Codebook) a jeho použití se nedoporučuje. Jeho výsledkem totiž je, že stejné bloky otevřeného textu budou zašifrovány vždy stejně. Vzhledem k poměrně malé velikosti jednotlivých bloků to může znamenat, že ve výsledné zprávě budou patrná stejná schémata jako v původním dokumentu (viz např. vizuální reprezentace na Wikipedii).

V praxi se tedy používají takové algoritmy, které toto nebezpečí odstraňují. Nejjednodušším z nich je CBC - Cipher Block Chaining. Ten funguje tak, že před zašifrováním se odpovídající blok otevřeného textu XORuje předcházejícím blokem zašifrovaného textu. To znamená, že jednotlivé bloky jsou na sobě závislé, abyste dešifrovali konkrétní blok, musíte dešifrovat i všechny předchozí.

V tomto případě ale máte problém - čím XORovat první blok, když ještě nemáte k dispozici blok předchozí? Inu, použijeme osvědčenou metodu socialistických vlád: když informace nemáme, prostě si je vymyslíme. Jeden blok se vygeneruje náhodně a přidá se k zašifrovaným datům jako "nultý blok". Tomuto bloku se pak říká "inicializační vektor" (IV). Tento blok se použije k dešifrování prvního bloku a pak zahodí.

Zdrojové kódy

Šifrování dat

Nyní již máme dostatek informací k tomu, abychom pomocí třídy System.Web.Security.Cryptography.RijndaelManaged dokázali zašifrovat libovolná data. Pro pořádek poznamenávám, že vstupem i výstupem všech těchto operací je pole bajtů. Chci-li pracovat s textem, musím ho na pole bajtů převést (třeba pomocí System.Text.Encoding.UTF8.GetBytes) a výsledek zakódovat, třeba pomocí Base64.

// Vytvo it instanci AES/Rijdael algoritmu

System.Security.Cryptography.RijndaelManaged aes = new System.Security.Cryptography.RijndaelManaged();

 

// Nastavit CBC block mode

aes.Mode = System.Security.Cryptography.CipherMode.CBC;

 

// Nastavit standardní PKCS7 padding posledního bloku

aes.Padding = System.Security.Cryptography.PaddingMode.PKCS7;

 

// Vygenerovat náhodný klíč

aes.GenerateKey();

 

// Vygenerovat inicializační vektor (IV)

aes.GenerateIV();

 

// Převést text na pole bajtů

byte[] plainData = System.Text.Encoding.UTF8.GetBytes(this.TextBoxPlaintext.Text);

 

// Zašifrovat data

byte[] cipherData;

using (System.Security.Cryptography.ICryptoTransform enc = aes.CreateEncryptor()) {

    cipherData = enc.TransformFinalBlock(plainData, 0, plainData.Length);

}

 

// Zobrazit výsledek

this.MultiViewPage.SetActiveView(this.ViewResult);

this.LiteralKey.Text = System.Convert.ToBase64String(aes.Key);

this.LiteralIV.Text = System.Convert.ToBase64String(aes.IV);

this.LiteralCiphertext.Text = System.Convert.ToBase64String(cipherData, Base64FormattingOptions.InsertLineBreaks).Replace("\r\n", "<br />");

V uvedeném kódu náhodně vygeneruji klíč (mohl bych ho samozřejmě i výslovně definovat, pokud by byl pevně zadaný) a inicializační vektor. Poté zašifruji data a vše uvedené (klíč, IV a ciphertext) zobrazím v Base64 formě uživateli. Za normálních okolností bývá IV prostě přidán na začátek šifrovaného textu, neukládá se zvlášť, ale já ho zde pro názornost vypisuji zvlášť.

Dešifrování

Dešifrování je realizováno obdobným kódem:

// Vytvořit instanci AES/Rijdael algoritmu

System.Security.Cryptography.RijndaelManaged aes = new System.Security.Cryptography.RijndaelManaged();

 

// Nastavit CBC block mode

aes.Mode = System.Security.Cryptography.CipherMode.CBC;

 

// Nastavit standardní PKCS7 padding posledního bloku

aes.Padding = System.Security.Cryptography.PaddingMode.PKCS7;

 

// Načíst klíč

aes.Key = System.Convert.FromBase64String(this.TextBoxKey.Text);

 

// Načíst IV

aes.IV = System.Convert.FromBase64String(this.TextBoxIV.Text);

 

// Načíst  šifrovaná data

byte[] cipherData = System.Convert.FromBase64String(this.TextBoxCiphertext.Text);

 

// Dešifrovat data

byte[] plainData;

using (System.Security.Cryptography.ICryptoTransform dec = aes.CreateDecryptor()) {

    plainData = dec.TransformFinalBlock(cipherData, 0, cipherData.Length);

}

string plainText = System.Text.Encoding.UTF8.GetString(plainData);

 

// Zobrazit výsledek

plainText = plainText.Replace("\r\n", "<br />");

this.MultiViewPage.SetActiveView(this.ViewResult);

this.LiteralPlaintext.Text = plainText;

Slovo závěrem

Uvědomte si prosím, že zašifrováním tajemství nezmizí. Pouze se zmenší. Místo abyste chránili velký dokument, musíte chránit jenom malý dokument - klíč. Jeho ochrana je ale to nejdůležitější - v praxi je u moderních algoritmů mnohem důležitější ochrana klíče, než jeho délka. K tomuto tématu se ještě vrátím v dalších článcích.

Titulek:
Text komentáře:
Vaše jméno:
Váš e-mail: (nebude zveřejněn)

WWW stránka:
Opište text z obrázku:
odpovědětodpovědět Gravatar

Krátké texty, bezpečnost

Fajn článek. Jak je však AES bezpečný,když s ním budu chtít kódovat krátké texty, tak 100-200 ASCII znaků, které se mohou opakovat, být si velmi podobné? Nehrozí tam uhádnutí hesla? Zabrání tomu CBC?

odpovědětodpovědět Gravatar

RE: Krátké texty, bezpečnost

Skvělý článek,ale přednaška na TechEdu byla lepší ;-)

odpovědětodpovědět Gravatar

RE: Krátké texty, bezpečnost

Články jsou (resp. budou, na toto téma jich píšu několik) zase podrobnější. Už takhle mám špatné svědomí z toho, že furt jenom někde vykládám a nic nepíšu.

odpovědětodpovědět Gravatar

RE: Krátké texty, bezpečnost

Dostatečně. Ta šifra pracuje se 128bit bloky, takže na 100-200 ASCII znaků jich budete mít 7-13. CBC a náhodně vygenerovaný inicializační vektor zase zajistí, že i když bude plaintext stejný, bude ciphertext pokaždé jiný.

odpovědětodpovědět Gravatar

RE: Krátké texty, bezpečnost

19.4.2007 11:33:0819.4.2007 11:33:08 Jan SedaJan Seda ---.karneval.cz

Tohle je velmi dobry dotaz. Kdyz se AES hodnotilo, tak prave tohle byl jeden z bodu, co navrhovatele k tomu popisovali (tusim, ze jsem to cetl bud na jejich webu). Obecne existuji prave utoky na blokove sifry, ktere jsou zalozene na velmi kratkych zpravach a jejich analyze. Odpoved na vasi otazku lezi v podobe dat a ve zvolenem modu. Odpoved tedy neni 100% a jednoznacna. Na tohle by se dala udelat cela prednaska, ale koho zajima profesionalni kryptografie, doporucuji dokumenty od NISTu napr. doporuceni na jednotlive mody pro zakladni seznameni s problematikou: http://csrc.nist.gov/CryptoToolkit/modes…

odpovědětodpovědět Gravatar

Upresneni

19.4.2007 11:01:4619.4.2007 11:01:46 Jan SedaJan Seda ---.karneval.cz

Sorry michale, musim pridat komentar, protoze toto je "moje" tema :) 1) Padding je dan jiz v pkcs5, ale v novem dokumentu byl prenesen do 10.3 sekce pkcs7 a jinak je presne specifikovan od RSA, jak jsem rekl, je to jiz od pkcs5 protoze ten padding je kriticky pro generovani klicu a nasledne je odvozen pro standard tykajici se sprav. 2) Doporucovat CBC jako "lepsi" mod je nesmysl. Neni to ani zadny algoritmus, ale je to chovani blokove sifry a jako takove ma svoje specifika. Vypic jednotlivych modu je mozne najit zde vcetne grafickeho zobrazeni (http://skilldrive.com/book/DOTNETinSampl…) a pouziti jednotliveho modu je pak zavisle od typu a formatu dat, ktera se sifruji. Urcite mody maji lepsi heuristiku pro binarni data, delsi data atd. Proto jsou ty mody zavedeny, aby se podle charakteru dat volily.

Cílem tohoto seriálu je dát základní vhled do praktického použití šifrovacích metod pohodlně dostupných webovým vývojářům v .NET Frameworku a vyhnout se nejkřiklavějším chybám. Většina lidí podle mých zkušeností vůbec netuší, co jsou symetrické a asymetrické šifry a jaký je mezi nimi rozdíl atd.

Budu velmi rád, pokud toto téma pojednáš pro zájemce o hlubší pochopení podrobněji a pošleš sem relevantní odkazy. Ostatně, jak sám píšeš, je to tvůj obor - já se jím zabývám proto, že jsem k tomu byl okolnostmi donucen ;-)

dekuji za skvely clanek

  • Altairis
  • Nemesis
  • Microsoft MVP
  • IIS
  • ASP.NET