Sdílet prostřednictvím


System.Security.Cryptography.Xml.SignedXml – třída

Tento článek obsahuje doplňující poznámky k referenční dokumentaci pro toto rozhraní API.

Třída SignedXml je implementace .NET specifikace XML Signature Syntax and Processing World Wide Web Consortium (W3C), také známá jako XMLDSIG (XML digitální podpis). XMLDSIG je interoperabilní způsob podepisování a ověřování všech nebo částí dokumentu XML nebo jiných dat, která je adresovatelná z identifikátoru URI (Uniform Resource Identifier).

SignedXml Třídu používejte vždy, když potřebujete sdílet podepsaná data XML mezi aplikacemi nebo organizacemi standardním způsobem. Všechna data podepsaná pomocí této třídy lze ověřit jakoukoli implementací odpovídající specifikace W3C pro XMLDSIG.

Třída SignedXml umožňuje vytvořit následující tři druhy digitálních podpisů XML:

Typ podpisu Popis
Obálkový podpis Podpis je obsažen v elementu XML, který je podepsán.
Obálkování podpisu Podepsaný KÓD XML je obsažen v elementu <Signature> .
Interní odpojený podpis Podpis a podepsaný XML jsou ve stejném dokumentu, ale žádný prvek neobsahuje druhý prvek.

Existuje také čtvrtý druh podpisu nazývaného externí odpojený podpis, což je, když jsou data a podpis v samostatných dokumentech XML. Třída SignedXml nepodporuje externí odpojené podpisy.

Struktura podpisu XML

XMLDSIG vytvoří <Signature> prvek, který obsahuje digitální podpis dokumentu XML nebo jiná data, která lze adresovat z identifikátoru URI. Prvek <Signature> může volitelně obsahovat informace o tom, kde najít klíč, který ověří podpis a který kryptografický algoritmus byl použit k podepisování. Základní struktura je následující:

<Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
    <SignedInfo>
      <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
      <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
      <Reference URI="">
        <Transforms>
          <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
        </Transforms>
        <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
        <DigestValue>Base64EncodedValue==</DigestValue>
      </Reference>
    </SignedInfo>
    <SignatureValue>AnotherBase64EncodedValue===</SignatureValue>
</Signature>

Hlavní části této struktury jsou:

  • Element <CanonicalizationMethod>

    Určuje pravidla pro přepsání elementu Signature z XML/textu do bajtů pro ověření podpisu. Výchozí hodnota v .NET je http://www.w3.org/TR/2001/REC-xml-c14n-20010315, která identifikuje důvěryhodný algoritmus. Tento prvek je reprezentován SignedInfo.CanonicalizationMethod vlastností.

  • Element <SignatureMethod>

    Určuje algoritmus použitý pro generování a ověřování podpisu, který byl použit pro <Signature> prvek k vytvoření hodnoty v <SignatureValue>. V předchozím příkladu hodnota http://www.w3.org/2000/09/xmldsig#rsa-sha1 identifikuje podpis SHA-1 PKCS1 RSA. Vzhledem k problémům s kolizemi u SHA-1 Microsoft doporučuje model zabezpečení založený na algoritmu SHA-256 nebo lepším. Tento prvek je reprezentován SignatureMethod vlastností.

  • Element <SignatureValue>

    Určuje kryptografický podpis prvku <Signature> . Pokud tento podpis neověří, některá část <Signature> bloku byla manipulována a dokument je považován za neplatný. <CanonicalizationMethod> Pokud je hodnota důvěryhodná, je tato hodnota vysoce odolná vůči manipulaci. Tento prvek je reprezentován SignatureValue vlastností.

  • Atribut URI elementu <Reference>

    Určuje datový objekt pomocí odkazu na identifikátor URI. Tento atribut je reprezentován Reference.Uri vlastností.

    • Pokud není specifikován atribut URI, nastavení vlastnosti Reference.Uri na null znamená, že přijímající aplikace má znát identitu objektu. Ve většině případů null URI způsobí vyvolání výjimky. Nepoužívejte null identifikátor URI, pokud vaše aplikace nespolupracuje s protokolem, který ho vyžaduje.

    • Nastavením atributu URI na prázdný řetězec se označuje, že kořenový prvek dokumentu je podepsán, což je forma obaleného podpisu.

    • Pokud hodnota atributu URI začíná znakem #, musí se hodnota přeložit na prvek v aktuálním dokumentu. Tento formulář lze použít s libovolnými podporovanými typy podpisů (obálková podpis, obalující podpis nebo interní oddělený podpis).

    • Cokoli jiného se považuje za externí prostředek s odpojeným podpisem a třída SignedXml ho nepodporuje.

  • Element <Transforms>

    Obsahuje uspořádaný seznam prvků <Transform>, které popisují, jak podepisovatel získal datový objekt, který byl vytvořen. Transformační algoritmus je podobný metodě kanonizace, ale místo přepsání <Signature> prvku přepíše obsah identifikovaný URI atributem <Reference> prvku. Prvek <Transforms> je reprezentován TransformChain třídou.

    • Každý transformační algoritmus je definován tak, že jako vstup přebírá xml (sadu uzlů XPath) nebo bajty. Pokud se formát aktuálních dat liší od požadavků na vstup transformace, použijí se pravidla převodu.

    • Každý transformační algoritmus je definován jako produkce XML nebo bajtů jako výstup.

    • Pokud výstup posledního transformačního algoritmu není definován v bajtech (nebo nebyly zadány žádné transformace), použije se metoda kanonizace jako implicitní transformace (i když byl v <CanonicalizationMethod> prvku zadán jiný algoritmus).

    • Hodnota transformačního http://www.w3.org/2000/09/xmldsig#enveloped-signature algoritmu kóduje pravidlo, které je interpretováno jako odebrání <Signature> prvku z dokumentu. V opačném případě ověřovatel obálkového podpisu zpracuje dokument, včetně podpisu, ale podepisující by dokument zpracoval před uplatněním podpisu, což by vedlo k rozdílným výsledkům.

  • Element <DigestMethod>

    Identifikuje metodu (kryptografický hash) pro aplikaci na transformovaný obsah identifikovaný atributem URI prvku <Reference>. Tato vlastnost je reprezentována Reference.DigestMethod vlastností.

Volba metody kanonizace

Pokud nespolupracuje se specifikací, která vyžaduje použití jiné hodnoty, doporučujeme použít výchozí metodu kanonizace .NET, což je algoritmus XML-C14N 1.0, jehož hodnota je http://www.w3.org/TR/2001/REC-xml-c14n-20010315. Algoritmus XML-C14N 1.0 musí být podporován všemi implementacemi XMLDSIG, zejména proto, že se jedná o implicitní konečnou transformaci, která se má použít.

Existují verze algoritmů kanonizace, které podporují zachování komentářů. Kanonizační metody zachovávající komentáře se nedoporučují, protože porušují princip "podepsat to, co je vidět". To znamená, že komentáře v <Signature> prvku nezmění logiku zpracování způsobu provedení podpisu, pouze to, co je hodnota podpisu. Kombinace se slabým podpisovým algoritmem a zahrnutí komentářů dává útočníkovi zbytečnou volnost vyvolat kolizi hash, takže pozměněný dokument vypadá jako legitimní. V rozhraní .NET Framework jsou ve výchozím nastavení podporovány pouze předdefinované kanonizátory. Pokud chcete podporovat další nebo vlastní kanonizační metody, podívejte se na SafeCanonicalizationMethods vlastnost. Pokud dokument používá kanonizační metodu, která není v kolekci reprezentované SafeCanonicalizationMethods vlastností, metoda CheckSignature vrátí false.

Poznámka:

Extrémně obranná aplikace může odebrat jakékoli hodnoty, které neočekává, že podepisující osoby budou používat z kolekce SafeCanonicalizationMethods.

Jsou referenční hodnoty bezpečné před manipulací?

Ano, <Reference> hodnoty jsou v bezpečí před manipulací. .NET ověří výpočet <SignatureValue> před zpracováním jakýchkoli <Reference> hodnot a jejich souvisejících transformací a v případě zjištění potenciálně škodlivých instrukcí proces brzy přeruší.

Zvolte prvky, které chcete podepsat.

Pokud je to možné, doporučujeme použít hodnotu "" pro atribut URI (nebo nastavit vlastnost Uri na prázdný řetězec). To znamená, že celý dokument je zohledněn při výpočtu souhrnu, což znamená, že je celý dokument chráněn před neoprávněnou manipulací.

Je velmi běžné vidět URI hodnoty ve formě kotev, jako je #foo, odkazující na prvek, jehož atribut id je "foo". Bohužel je snadné s tím manipulovat, protože to zahrnuje pouze obsah cílového prvku, nikoli kontext. Zneužití tohoto rozdílu je známé jako XSW (XML Signature Wrapping).

Pokud vaše aplikace považuje komentáře za sémantické (což není běžné při práci s XML), měli byste místo "#foo" použít "#xpointer(/)" a "#xpointer(id('foo')". Verze #xpointer jsou interpretovány tak, že zahrnují komentáře, zatímco zkrácené formy je vylučují.

Pokud potřebujete přijmout dokumenty, které jsou pouze částečně chráněné a chcete zajistit, abyste četli stejný obsah, který je chráněný podpisem, použijte metodu GetIdElement .

Důležité informace o zabezpečení elementu KeyInfo

Data v volitelném <KeyInfo> prvku (tj KeyInfo . vlastnost), která obsahuje klíč k ověření podpisu, by neměla být důvěryhodná.

Konkrétně pokud KeyInfo hodnota představuje holý RSA, DSA nebo ECDSA veřejný klíč, dokument mohl být manipulován, i když CheckSignature metoda hlásí, že podpis je platný. K tomu může dojít, protože entita, která manipuluje, musí vygenerovat nový klíč a znovu podepsat zfalšovaný dokument s tímto novým klíčem. Pokud tedy aplikace nevěří, že veřejný klíč má očekávanou hodnotu, měl by se dokument považovat za manipulovaný. To vyžaduje, aby aplikace prozkoumala veřejný klíč vložený v dokumentu a ověřila ho v seznamu známých hodnot pro kontext dokumentu. Pokud je například možné, že dokument vydá známý uživatel, zkontrolujete klíč na seznamu známých klíčů používaných tímto uživatelem.

Klíč můžete také ověřit po zpracování dokumentu pomocí CheckSignatureReturningKey metody místo CheckSignature metody. Pokud ale chcete zajistit optimální zabezpečení, měli byste klíč ověřit předem.

Alternativně zvažte možnost vyzkoušet zaregistrované veřejné klíče uživatele místo čtení toho, co je v <KeyInfo> prvku.

Důležité informace o zabezpečení elementu X509Data

Volitelný prvek <X509Data> je podřízeným prvkem <KeyInfo> a obsahuje jeden nebo více certifikátů X509 nebo identifikátorů pro certifikáty X509. Data v <X509Data> prvku by také neměla být ze své podstaty důvěryhodná.

Při ověřování dokumentu pomocí vloženého <X509Data> prvku .NET ověří pouze to, že se data přeloží na certifikát X509, jehož veřejný klíč lze úspěšně použít k ověření podpisu dokumentu. Na rozdíl od volání CheckSignature metody s parametrem nastaveným na verifySignatureOnlyfalse, neprovádí se žádná kontrola odvolání, nehodnotí se žádná důvěra v řetězec, a neověřuje se žádné vypršení platnosti. I když vaše aplikace extrahuje samotný certifikát a předá CheckSignature ho metodě s parametrem verifySignatureOnly nastaveným na false, to stále není dostatečné ověření, aby se zabránilo manipulaci s dokumentem. Certifikát je stále potřeba ověřit podle toho, jak je vhodný pro podepsaný dokument.

Použití vloženého podpisového certifikátu může poskytovat užitečné strategie obměně klíčů, ať už v oddílu <X509Data> nebo v obsahu dokumentu. Při použití tohoto přístupu by aplikace měla certifikát extrahovat ručně a provést ověření podobné:

  • Certifikát byl vydán přímo nebo prostřednictvím řetězu certifikační autoritou (CA), jejíž veřejný certifikát je vložen do aplikace.

    Použití seznamu důvěryhodnosti poskytnutého operačním systémem bez dalších kontrol, jako je známý název subjektu, není dostačující k zamezení manipulaci v SignedXml.

  • Certifikát je ověřen, aby nebyl po době podepisování dokumentu (nebo "nyní" pro zpracování dokumentů v téměř reálném čase) propadlý.

  • U dlouhodobých certifikátů vydaných certifikační autoritou, která podporuje odvolání, ověřte, že certifikát nebyl odvolán.

  • Subjekt certifikátu je ověřen jako vhodný pro aktuální dokument.

Volba transformačního algoritmu

Pokud spolupracujete se specifikací, která diktovala konkrétní hodnoty (například XrML), musíte postupovat podle specifikace. Pokud máte podepsaný obálkový podpis (například při podepisování celého dokumentu), musíte použít http://www.w3.org/2000/09/xmldsig#enveloped-signature (reprezentovaný třídou XmlDsigEnvelopedSignatureTransform). Můžete také zadat implicitní XML-C14N transformaci, ale není to nutné. Pro obalující nebo oddělený podpis nejsou vyžadovány žádné transformace. Implicitní transformace XML-C14N se postará o všechno.

S aktualizací zabezpečení zavedenou bulletinem zabezpečení společnosti Microsoft MS16-035 je technologie .NET ve výchozím nastavení omezena na transformace, které mohou být použity při ověřování dokumentů; nedůvěryhodné transformace způsobují, že CheckSignature vždy vrací false. Transformace, které vyžadují další vstup (určené jako podřízené prvky v XML), již nejsou povoleny kvůli jejich citlivosti zneužití škodlivými uživateli. W3C doporučuje vyhnout se transformacíM XPath a XSLT, což jsou dvě hlavní transformace ovlivněné těmito omezeními.

Problém s externími odkazy

Pokud aplikace neověřuje, že externí odkazy vypadají jako vhodné pro aktuální kontext, mohou být zneužity způsoby, které poskytují mnoho ohrožení zabezpečení (včetně odepření služby, distribuované reflexe odepření služby, zpřístupnění informací, obejití podpisu a vzdáleného spuštění kódu). I kdyby aplikace měla ověřit URI externího odkazu, zůstával by problém s tím, že se prostředek načte dvakrát: jednou, když jej čte vaše aplikace, a jednou, když jej čte SignedXml. Vzhledem k tomu, že neexistuje žádná záruka, že kroky ověření dokumentu a čtení aplikace mají stejný obsah, podpis neposkytuje důvěryhodnost.

Vzhledem k rizikům externích odkazů vyvolá SignedXml výjimku, když dojde k výskytu externího odkazu. Další informace o tomto problému najdete v článku znalostní báze 3148821.