Temná zákoutí RSA implementace v .NETu?
Martin Vobr mě dnes ráno vyplašil odkazem na blog Michala Bláhy, kde prý upozorňuje na
nějaký zásadní problém v implementaci RSA v .NETu. Po blížším zkoumání jsem však zjistil,
že žádný problém ani chyba neexistuje a senzace se nekoná.
Michal upozorňuje na to, že třída RSACryptoServiceProvider nedokáže zašifrovat zprávu
soukromým klíčem a dešifrovat ji veřejným klíčem. Ostuda? Ani ne... Toto není ani chyba,
ani opomenutí, jak vysvětlím později. Tuto operace totiž neumí nejen CryptoAPI (RSA v
.NETu je jen wrapper), ale ani žádná jiná implementace standardu PKCS #1 (základní
standard pro RSA kryptografii) a Microsoft se v tomto případě opravdu nemá za co stydět -
snad jen za to, že toto nebyl schopen sepsat místo mě. A že ani Honza Šeda nedokázal najít
v MS nikoho, kdo by problém uvedl na pravou míru.
Klíčem k pochopení situace je drobný nesoulad mezi teorií a (nikoliv drsnou) praxí RSA,
který se ale po blížším zkoumání ukáže být naprosto samozřejmý. Michal má samozřejmě
pravdu v tom, že zprávu zašifrovanou pomocí privátního klíče P může dešifrovat kdokoliv s
veřejným klíčem V, a naopak zprávu zašifrovanou pomocí veřejného klíče V může dešifrovat
pouze a jenom vlastník privátního klíče P. Tolik teorie.
Ale zásadní otázka je - k čemu by nám zašifrování zprávy soukromým klíčem vlastně bylo?
Veřejný klíč má k dispozici každý (je veřejný), proto každý by mohl naši zprávu
dešifrovat. Existuje pouze jediný rozumný důvod k zašifrování zprávy soukromým klíčem, a
to dokázat vlastnictví soukromého klíče. Jenže k tomuto účelu je přeci určen elektronický
podpis! Který - jak jinak - spočívá právě v zašifrování zprávy (resp. jejího hashe)
soukromým klíčem...
A praxe této úvaze odpovídá - zašifrování pomocí privátního klíče a dešifrování pomocí
veřejného se opravdu používá vyhradně pro účely elektronického podpisu.
Zbytek tohoto příspěvku už není třeba číst, vše podstatné již bylo řečeno. Další řádky jen blíže přibližují praxi.
Základním dokumentem, který definuje co a jak, je PKCS #1 (jinak též znám jako např. RFC 3447),
jehož autorem je RSA Laboratories. A ten definuje pouze čtyři operace:
- RSAEP - zašifrování - zašifrování zprávy veřejným klíče
- RSADP - dešifrování - dešifrování zprávy soukromým klíče
- RSASP1 - podpis - vytvoření podpisu zprávy (hashe) soukromým klíčem (odpovídá
zašifrování soukromým klíčem)
- RSAVP1 - ověření - získání původní zprávy (hashe) z podpisu (odpovídá dešifrování
veřejným klíčem)
Následně jsou zde definována různá schémata formátování vstupních dat pro RSAEP a pro
RSASP1, pomocí kterých se data připraví do podoby vhodné k zašifrování - v žádném případě
není možné zašifrovat nebo dešifrovat neformátovaná data, a to z bezpečnostních důvodů,
které zde nemá smysl podrobněji rozebírat. Operace RSADP a RSAVP1 zas naopak po
dešifrování tato formátovaná data převedou do jejich původní podoby. Při podpisu se
například nezašifruje pouze hash zprávy, ale i ID algoritmu, pomocí kterého byl tento hash
vytvořen.
Za povšimnutí také stojí, že když cpete třídě RSACryptoServiceProvider privátní klíč, tak
jí cpete zárověň veřejný klíč, protože ten je součástí té stejné struktury.
Abych to shrnul - žádná implementace RSA dle PKCS #1 / RFC 3447 operaci "zašifrování dat
soukromým klíčem" umět nemůže, protože standard nic takového nedefinuje. A to z
pochopitelných důvodů uvedených výše.
A na závěr otázka pro Michala Bláhu, na kterou bych opravdu rád znal odpověď: K čemu
vlastně potřebujete šifrovat data soukromým klíčem? :-)