Asymetrické šifrování RSA v .NET - správa klíčů

V prvním dílu seriálu Přísně tajné šifry jsem popisoval použití symetrické šifry Rijndael alias AES. Zásadní nevýhodou symatrického šifrování je, že používá sdílený klíč, shodný pro šifrování a dešifrování. Tuto nevýhodu odstraňují asymetrické šifrovací algoritmy. Ve druhém dílu našeho seriálu se podíváme na správu klíčů nejobvyklejšího z nich - RSA.

Rivest - Shamir - Adleman

Stejně jako Rijndael a celá řada dalších algoritmů, i RSA odvozuje svůj název od jmen svých objevitelů. V tomto případě jsou jimi pánové Ronald Rivest, Adi Shamir a Leonard Adleman.

RSA je asymetrický algoritmus, což znamená, že používá ne jeden, ale dva klíče:

  • Veřejný klíč (public key) slouží k zašifrování dat. Tento klíč není třeba nijak tajit či chránit, ba naopak. Každý, kdo vám chce poslat zašifrovanou zprávu, ho musí mít k dispozici a je tedy nutné zajistit, aby ho mohl získat.
  • Soukromý klíč (private key, nazývaný též tajný klíč) slouží k dešifrování dat. Tento klíč musíte naopak žárlivě střežit a ochraňovat.

Zjednodušený popis RSA algoritmu můžete najít například na Wikipedii.

RSA klíče

Mezi klíči pro symetrické algoritmy (jako je AES) a pro algoritmy asymetrické (jako je RSA) je zásadní rozdíl. Generování klíčů pro AES je jednoduché, protože klíčem může být cokoliv, jakákoliv dostatečně dlouhá náhodná hodnota. Proto se také v případě AES tak často používají jednorázové klíče. Generování RSA klíčů je výpočetně dosti náročné, protože se nejedná o prosté sbírání chaosu, ale o výpočet extrémně velkých prvočísel. RSA klíče se obvykle pečlivě uchovávají a používají se opakovaně.

V případě RSA je také nutné pečlivě zvolit požadovanou délku klíče. V případě AES je volba jednoduchá, v drtivé většině případů se používá 256bitový klíč, tedy ten nejdelší, jaký algoritmus podporuje. U RSA s délkou klíče stoupá obtížnost prolomení šifry, ale zároveň také náročnost všech operací s šifrováním spojených - generování klíče, šifrování i dešifrování, a to nikoliv lineárně.

Zvýšíte-li délku klíče na dvojnásobek, zvýší se v průměru:

  • doba generování klíče 16×,
  • doba potřebná pro dešifrování (a další operace s tajným klíčem) 8×,
  • doba potřebná pro šifrování (a další operace s veřejným klíčem) 4×.

Délka klíče tedy závisí na několika faktorech. Klíčová je samozřejmě míra důvěrnosti utajovaných dat a zejména doba, po kterou bude nutné je chránit. Pokud mají být data důvěrná třeba i za několik desítek let, je nutné volit vyšší délku klíče, protože je nutno počítat s vývojem výpočetní techniky v této době. Pokud budete data přechovávat po krátkou dobu, nemusíte tuto otázku řešit.

Pokud máte k dispozici speciální hardware s procesory specializovanými na kryptografické operace, můžete si dovolit použít klíče s vyšší délkou, protože operace budou probíhat rychleji.

Klíče o délce 512 bitů bylo možno již v roce 1997 prolomit s hardwarem v ceně za milión dolarů v době okolo osmi měsíců. V současné době RSA Laboratories doporučují použití klíče o délce alespoň 1024 bitů, pro obzvláště důležité informace pak 2048 bitů. Nejdelší klíč, se kterým je na běžném HW možné normálně pracovat, je 4069 bitů.

Uchovávání a ochrana soukromých klíčů

Pro uchovávání RSA klíčů se používají tzv. kontajnery (key containers). Kontainerem je typicky soubor uložený na harddisku počítače (a chráněný prostředky operačního systému), ale může jím být i speciální hardwarové zařízení. Například čipová karta nebo šifrovací token, připojovaný přes USB rozhraní.

Ochrana soukromého klíče je totiž nejslabším článkem celého systému a jakékoliv implementace šifrování. Z praktického pohledu můžeme považovat všechny dnes standardně používané implementace šifrovacích algoritmů za bezpečné a současnými prostředky neprolomitelné. Největší bezpečnostní riziko tedy představuje, že se dostane do nesprávných rukou samotný klíč.

Pro důležitost zde znovu opakuji základní krédo jakékoliv kryptografie: šifrováním tajemství nezmizí, pouze se zmenší jeho objem. Místo zajištění bezpečného úložiště pro data sama musíme zajistit bezpečné úložiště pro klíč, který je umí dešifrovat.

Ultimátní obranou je fyzické odstranění klíče ze systému, když se nepoužívá. Čipové karty a šifrovací tokeny mohou v tomto směru být velkou pomocí. Neslouží totiž jenom jako paměťové médium, na kterém je klíč uložen, ale obsahují přímo kryptografický procesor, který provádí všechny operace s privátním klíčem. Klíč tedy kartu nikdy neopustí: je na ní vygenerován a veškeré operace s ním (dešifrování, podepisování...) probíhají přímo v jejím procesoru. Bývá dokonce hardwarově navržena tak, že klíč není možné získat a při pokusu o to se karta i s klíčem zničí.

Asymetrické algoritmy nabízejí ještě jednu možnost: v řadě případů není nutné, aby ten, kdo zprávu zašifroval, ji uměl též dešifrovat. Pokud budete například provozovat internetový obchod a uchovávat údaje o platebních kartách, pak web server (který je nejčastějším a nejsnazším cílem útoku) může disponovat pouze veřejným klíčem, protože data pouze šifruje. O jejich zpracování se může starat samostatný server, běžným smrtelníkům nedostupný.

Výhodou je, že kód pro generování klíčů a práci s nimi je v podstatě stejný, bez ohledu na to, jakého kryptografického providera použijete. Následující příklady používají jako úložiště dat disk počítače, ale jejich úprava pro použití např. čipové karty není nikterak náročná.

User store a machine store

Windows používá dvě základní úložiště pro RSA klíče: User Store a Machine Store. User store je určen pro data konkrétního přihlášeného uživatele a je přístupný pouze tehdy, pokud má uživatel natažený svůj profil. Používá se tedy typicky pro interaktivní aplikace. Machine store je určen pro data, která mají být obecně přístupna pro všechny uživatele na daném počítači. Konkrétní klíče jsou uloženy jako samostatné soubory, klíče v machine store je tedy možné (a vhodné) dále zabezpečit pomocí nastavení práv v NTFS filesystému.

Pro použití v rámci webové nebo jinak neinteraktivní aplikace (např. služby ve Windows) je zpravidla nutné použít machine store, protože nemáte k dispozici uživatelský profil a tudíž nemůžete využívat user store. Z toho vycházejí i následující příklady, které všechny využívají právě machine store.

User store je v adresáři %APPDATA%\Microsoft\Crypto\RSA\SID-uživatele. Machine store je v adresáři %PROGRAMDATA%\Microsoft\Crypto\RSA\MachineKeys (na Windows Vista) nebo %ALLUSERSPROFILE%\Application Data\Microsoft\Crypto\RSA\MachineKeys (na starších verzích Windows).

Generování klíčů

O práci s RSA algoritmem, tedy generování klíčů, šifrování a dešifrování se stará třída System.Security.Cryptography.RSACryptoServicesProvider. Pro vytvoření nového klíče potřebujeme znát pouze jeho požadovanou délku:

// using System.Security.Cryptography;

// using System.Xml;

 

int keyLength = int.Parse(this.DropDownListKeyLength.SelectedValue);

 

CspParameters csp = new CspParameters();

csp.KeyContainerName = "DEMO_RsaKeyGen_" + Guid.NewGuid().ToString("N");

csp.Flags = CspProviderFlags.UseMachineKeyStore | // uložit do machine store, nutné pro uživatele bez profilu

            CspProviderFlags.NoPrompt |           // dávkový (neinteraktivní) režim

            CspProviderFlags.UseArchivableKey;    // umožnit export privátního klíče

 

RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(keyLength, csp);

 

string publicKey = rsa.ToXmlString(false);

string bothKeys = rsa.ToXmlString(true);

Výše uvedený příklad je přiložen k článku jako soubor RsaGetKey.aspx. V reálné aplikaci by generování klíče patrně neprováděla webová aplikace, protože se jedná o úkon relativně zřídkavý, v dalších článcích si ukážeme jiné alternativy. Tato aplikace bude nicméně chodit, pokud ji spustíte pod uživatelem s distatečnými právy, jako například v rámci ASP.NET Developer Serveru, který běží v kontextu právě přihlášeného uživatele.

Pro další použití klíče je důležité znát název kontajneru, v němž je klíč uložen. Ten je definován vlastností KeyContainerName a ve shora uvedeném příkladu má formát "DEMO_RsaKeyGen_guid".

Pomocí metody ToXmlString můžete vyexportovat veřejný klíč nebo oba klíče do XML formátu.

Ve shora uvedeném schématu (web server má jenom veřejný klíč, backend oba) byste postupovali tak, že byste na zabezpečeném (backend) serveru vygenerovali klíč a pomocí metody ToXmlString vyexportovali veřejný klíč. Ten byste potom zkopírovali na web server, např. do konfigurace.

Práce s key containery

Privátní klíč sice také můžete exportovat do XML a pracovat s ním přímo, v praxi ho ale většinou necháte uložen v patřičném containeru. K tomu, abyste poté klíč získali, potřebujete znát název containeru, který jste zadali při jeho vytváření. Kód pro načtení klíče z containeru je následující:

CspParameters csp = new CspParameters();

csp.KeyContainerName = container;

csp.Flags = CspProviderFlags.UseMachineKeyStore | // použít machine store, nutné pro uživatele bez profilu

            CspProviderFlags.NoPrompt |           // dávkový (neinteraktivní) režim

            CspProviderFlags.UseArchivableKey;    // umožnit export privátního klíče

 

RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(csp);

 

string publicKey = rsa.ToXmlString(false);

string privateKey = rsa.ToXmlString(true);

Microsoft .NET Framework neobsahuje žádné managed rozhraní, pomocí kterého byste si mohli vypsat seznam všech existujících containerů. Pokud po tom prahnete, musíte pomocí P/Invoke volat přímo CryptoAPI. Následující metoda vám vrátí pole obsahující seznam jmen všech containerů (pozn.: jedná se o minimální implementaci, která neprovádí žádné ošetřování chyb a podobně):

// using System.Security.Cryptography;

// using System.Runtime.InteropServices;

private static string[] GetContainers() {

    const uint CRYPT_VERIFYCONTEXT = 0xF0000000;

    const uint CRYPT_MACHINE_KEYSET = 0x00000020;

    const uint PROV_RSA_FULL = 0x00000001;

    const uint PP_ENUMCONTAINERS = 0x00000002;

    const uint CRYPT_FIRST = 0x00000001;

    const uint CRYPT_NEXT = 0x00000002;

 

    System.Collections.Generic.List<string> r = new System.Collections.Generic.List<string>();

 

    IntPtr h;

 

    // Otevřít context

    CryptAcquireContext(out h, null, null,

        PROV_RSA_FULL,

        CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET);

 

    // Načíst jména všech containerů

    uint flags = CRYPT_FIRST;   // chci první container

    uint cch = 512;            // max. délka jména

    StringBuilder sb = new StringBuilder((int)cch);

    while (CryptGetProvParamAnsiString(h, PP_ENUMCONTAINERS, sb, ref cch, flags)) {

        r.Add(sb.ToString());

        flags = CRYPT_NEXT;    // chci další container

    }

 

    // Zavřít kontext

    CryptReleaseContext(h, 0);

 

    // Vrátit jména všech kontajnerů jako pole stringů

    return r.ToArray();

}

 

[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]

[return: MarshalAs(UnmanagedType.Bool)]

private static extern bool CryptAcquireContext(out IntPtr hProv, string pszContainer, string pszProvider, uint dwProvType, uint dwFlags);

 

[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]

[return: MarshalAs(UnmanagedType.Bool)]

private static extern bool CryptReleaseContext(IntPtr hProv, uint dwFlagsMustBeZero);

 

[DllImport("advapi32.dll", CharSet = CharSet.Ansi, SetLastError = true, EntryPoint = "CryptGetProvParam", ExactSpelling = true)]

[return: MarshalAs(UnmanagedType.Bool)]

private static extern bool CryptGetProvParamAnsiString(IntPtr hProv, uint dwParam, StringBuilder sb, ref uint cch, uint dwFlags);

V příkladech najdete stránku RsaKeyGet.aspx, která vám zobrazí seznam všech dostupných containerů a umožní vám zobrazit jejich klíče.

Slovo závěrem

V tomto článku jste se naučili, jak vytvářet a spravovat RSA klíče, což je nutnou podmínkou k tomu, abyste mohli využívat asymetrické RSA šifrování. O jeho vlastní implementaci si povíme v následujícím díle tohoto seriálu.

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

Upresneni II

19.4.2007 11:15:2919.4.2007 11:15:29 Jan SedaJan Seda ---.karneval.cz

No uz do toho nechci vice rypat :) Ale musim nesouhlasit i ted :) Hodim jedinou poznamku. Zmineni, ze user store je pro interaktivni aplikace a nebo ze pro web aplikace je machine store vhodnejsi je s prominutim silne nepresne. Naopak user store a profily jsou velmi silna vlastnost s ohledem na kombinovane prostredi nekolila serveru, typicky u web farmy, kde to ani jinak nejde. Tedy jde, ale je nutne delat urcite hacky do Windows. Jeste bych mel nekolik doplneni k samotnemu popuziti RSA a zpusobu jak se klice maji generovat a jak se to propocitava s ohledem na risk management, ale vzhledem k tomu, ze to pises jen o sprave klicu, tak predpokladam, ze je asi zminis v jinem clanku, takze je zatim nepisu :)

odpovědětodpovědět Gravatar

čipové karty, usb token z asp.net

19.4.2007 11:52:5519.4.2007 11:52:55 PetrPetr 195.113.98.---

je možno cist klic s token (usb) i z asp.net?? - autorizace uzivatele do webove aplikace? Bude o tom neco v tomto serialu?

odpovědětodpovědět Gravatar

RE: čipové karty, usb token z asp.net

Odpověď na tuto otázku je poněkud složitější. Obecně můžete mít klíč uložen (případně též vygenerován) na USB tokenu nebo čipové kartě a přistupovat k němu přes CAPI.

Pro autentizaci uživatelů ve webových aplikacích se typicky používají klientské certifikáty. Kde je budete mít uloženy je věc klienta, ne serveru, ten to neřeší.

odpovědětodpovědět Gravatar

Je možné obnovit smazaný klíč?

15.5.2007 4:21:1415.5.2007 4:21:14 KatkaKatka ---.193.broadband4.iol.cz

Dobrý den. Na tento web jsem zabloudila spíše náhodou. Omylem jsem si ze svého asi před týdnem smazala z tohoto umístění C:\Documents and Settings\All Users\Application Data\Microsoft\Crypto\RSA\MachineKeys jakýsi soubor a tak se snažím zjistit, co jsem to vlastně vyvedla. Asi je vám jasné, že moje znalosti v této oblasti, a to i po přečtení tohoto článku, jsou nevalné. Pochopila jsem snad jen tolik, že jsem si patrně smazala jeden ze dvou, nasobě závislých, klíčů. Buďte někdo z vás tak moc hodný a poraďte mi, jak můžu napravit co jsem způsobila. Děkuju

odpovědětodpovědět Gravatar

neni

14.2.2009 19:19:0814.2.2009 19:19:08 NNNN 62.240.184.---

Kde máš další článek?

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