System.Security.Cryptography.Xml.SignedXml osztály

Megjegyzés:

Ez a cikk kiegészítő megjegyzéseket tartalmaz az API referenciadokumentációjához.

Az SignedXml osztály a World Wide Web Consortium (W3C) XML Signature Szintaxis és Feldolgozási Specifikáció .NET-implementációja, más néven XMLDSIG (XML Digital Signature). Az XMLDSIG szabványalapú, interoperábilis módszer egy XML-dokumentum vagy más, egységes erőforrás-azonosítóból (URI) címezhető adatok egészének vagy egy részének aláírására és ellenőrzésére.

Használja az SignedXml osztályt, amikor szabványos módon kell megosztania az aláírt XML-adatokat az alkalmazások vagy szervezetek között. Az osztály használatával aláírt adatok az XMLDSIG W3C-specifikációjának megfelelő implementációval ellenőrizhetők.

Az SignedXml osztály lehetővé teszi a következő három típusú XML digitális aláírás létrehozását:

Aláírás típusa Leírás
Borítékos aláírás Az aláírás az aláírt XML-elemen belül található.
Betakaró aláírás Az aláírt XML az elemen <Signature> belül található.
Belső leválasztott aláírás Az aláírás és az aláírt XML ugyanabban a dokumentumban található, de egyik elem sem tartalmazza a másikat.

Van egy negyedik típusú aláírás is, amelyet külső különálló aláírásnak neveznek, amely akkor van, ha az adatok és az aláírás külön XML-dokumentumokban találhatók. A külső leválasztott aláírásokat az SignedXml osztály nem támogatja.

XML-aláírás felépítése

Az XMLDSIG létrehoz egy <Signature> elemet, amely egy XML-dokumentum vagy más, URI-ból kezelhető adat digitális aláírását tartalmazza. Az <Signature> elem opcionálisan információkat is tartalmazhat arról, hogy hol található egy kulcs, amely ellenőrzi az aláírást, és hogy melyik titkosítási algoritmust használták az aláíráshoz. Az alapstruktúra a következő:

<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>

A struktúra fő részei a következők:

  • Az <CanonicalizationMethod> elem

    Megadja az elemek XML-ből/szövegből bájtokra történő újraírásának Signature szabályait aláírás-ellenőrzés céljából. A .NET alapértelmezett értéke egy http://www.w3.org/TR/2001/REC-xml-c14n-20010315megbízható algoritmust azonosít. Ezt az elemet a SignedInfo.CanonicalizationMethod tulajdonság jelöli.

  • Az <SignatureMethod> elem

    Az aláírás-létrehozáshoz és -ellenőrzéshez használt algoritmust adja meg, amelyet az <Signature> elemre alkalmaztak az <SignatureValue> érték előállításához. Az előző példában az érték http://www.w3.org/2000/09/xmldsig#rsa-sha1 egy RSA PKCS1 SHA-1 aláírást azonosít. Az SHA-1 ütközési problémái miatt a Microsoft az SHA-256-ra vagy annál jobbra épülő biztonsági modellt javasol. Ezt az elemet a SignatureMethod tulajdonság jelöli.

  • Az <SignatureValue> elem

    Megadja az elem titkosítási aláírását <Signature> . Ha ez az aláírás nem igazolható, akkor a <Signature> blokk valamely részét módosították, és a dokumentum érvénytelennek minősül. Mindaddig, amíg az <CanonicalizationMethod> érték megbízható, ez az érték erősen ellenáll a illetéktelen beavatkozásnak. Ezt az elemet a SignatureValue tulajdonság jelöli.

  • Az URI elem <Reference> attribútuma

    Adatobjektumot határoz meg URI-hivatkozással. Ezt az attribútumot a Reference.Uri tulajdonság jelöli.

    • Ha nem adja meg az URI attribútumot, vagyis a Reference.Uri tulajdonságot null állítja be, az azt jelenti, hogy a fogadó alkalmazásnak tudnia kell az objektum identitását. A legtöbb esetben az null URI kivételt eredményez. Ne használjon null URI-t, kivéve, ha az alkalmazás olyan protokollal működik, amely megköveteli.

    • Ha az URI attribútumot üres sztringre állítja, az azt jelzi, hogy a dokumentum gyökéreleme alá van írva, egy borítékos aláírás formájában.

    • Ha az attribútum értéke URI #-val kezdődik, akkor az értéknek az aktuális dokumentum egy elemére kell feloldania. Ez az űrlap bármely támogatott aláírástípussal használható (borítékolt aláírás, burkoló aláírás vagy belső leválasztású aláírás).

    • Minden más külső erőforrás leválasztott aláírásnak minősül, és az SignedXml osztály nem támogatja.

  • Az <Transforms> elem

    Azoknak az elemeknek <Transform> a rendezett listáját tartalmazza, amelyek azt írják le, hogy az aláíró hogyan szerezte be a kivonatolt adatobjektumot. Az átalakítási algoritmus hasonló a canonicalization metódushoz, de az <Signature> elem újraírása helyett újraírja az elem attribútuma URI által <Reference> azonosított tartalmat. Az <Transforms> elemet az TransformChain osztály jelöli.

    • Minden átalakítási algoritmus úgy van definiálva, hogy az XML-t (XPath-csomópontkészletet) vagy bájtokat bemenetként használja. Ha az aktuális adatok formátuma eltér az átalakítás bemeneti követelményeitől, a rendszer konverziós szabályokat alkalmaz.

    • Az egyes átalakító algoritmusok kimenetként XML vagy bájtok előállítására szolgálnak.

    • Ha az utolsó átalakítási algoritmus kimenete nincs bájtban definiálva (vagy nem adott meg átalakításokat), akkor a rendszer implicit átalakításként használja a canonicalization metódust (még akkor is, ha egy másik algoritmust adott meg az <CanonicalizationMethod> elemben).

    • Az átalakító algoritmus értéke http://www.w3.org/2000/09/xmldsig#enveloped-signature kódol egy szabályt, amely úgy értelmezve van, hogy eltávolítja az <Signature> elemet a dokumentumból. Ellenkező esetben a borítékos aláírás hitelesítője megemészti a dokumentumot, beleértve az aláírást is, de az aláíró az aláírás alkalmazása előtt megemésztette volna a dokumentumot, ami eltérő válaszokat eredményezett volna.

  • Az <DigestMethod> elem

    Azonosítja a URI elem <Reference> attribútuma által azonosított átalakított tartalomra alkalmazandó kriptográfiai kivonatolási metódust. Ezt a Reference.DigestMethod tulajdonság jelöli.

A kanonikalizációs módszer kiválasztása

Ha nem olyan specifikációval működik együtt, amely más érték használatát igényli, javasoljuk, hogy az alapértelmezett .NET-canonicalization metódust használja, amely az XML-C14N 1.0 algoritmus, amelynek értéke .http://www.w3.org/TR/2001/REC-xml-c14n-20010315 A XML-C14N 1.0 algoritmust az XMLDSIG összes implementációjának támogatnia kell, különösen mivel implicit végső átalakítást kell alkalmaznia.

A canonicalization algoritmusoknak vannak olyan verziói, amelyek támogatják a megjegyzések megőrzését. A megjegyzésmegőrző kanonizációs módszerek nem ajánlottak, mert megsértik a "ami látható, azt írjuk alá" elvet. Vagyis az elemek megjegyzései <Signature> nem módosítják az aláírás végrehajtásának feldolgozási logikáját, csupán azt, hogy mi az aláírás értéke. Gyenge aláírási algoritmussal kombinálva a megjegyzések belefoglalása szükségtelen szabadságot ad a támadónak a kivonat ütközésének kényszerítéséhez, így a módosított dokumentum jogszerűnek tűnik. A .NET-keretrendszerben alapértelmezés szerint csak a beépített canonicalizerek támogatottak. További vagy egyéni kanonizálók támogatásához tekintse meg a SafeCanonicalizationMethods tulajdonságot. Ha a dokumentum olyan canonicalization metódust használ, amely nem szerepel a SafeCanonicalizationMethods tulajdonság által képviselt gyűjteményben, akkor a CheckSignature metódus vissza fog térni false.

Megjegyzés:

A rendkívül védekező alkalmazás eltávolíthat minden olyan értéket, amelyet nem vár el az aláíróktól a SafeCanonicalizationMethods gyűjteményből.

Biztonságban vannak-e a referenciaértékek a manipulációtól?

Igen, az <Reference> értékek biztonságban vannak az illetéktelen módosítástól. A .NET ellenőrzi a számítást az <SignatureValue> értékek és a <Reference> hozzájuk kapcsolódó átalakítások feldolgozása előtt, és korán leáll, hogy elkerülje a potenciálisan rosszindulatú feldolgozási utasításokat.

Jelölje ki az aláírandó elemeket

Javasoljuk, hogy a "" értéket használja az URI attribútumhoz (vagy állítsa a Uri tulajdonságot üres sztringre), ha lehetséges. Ez azt jelenti, hogy a teljes dokumentumot figyelembe kell venni az kivonatoló számításhoz, ami azt jelenti, hogy a teljes dokumentum védett az illetéktelen módosításokkal szemben.

Nagyon gyakori, hogy az értékeket horgonyok, például #foo formájában tekintik meg URI , egy olyan elemre hivatkozva, amelynek azonosító attribútuma "foo". Ez sajnos könnyen módosítható, mert ez csak a célelem tartalmát tartalmazza, nem a kontextust. Ezzel a megkülönböztetéssel való visszaélést XML-aláírásburkolásnak (XSW) nevezzük.

Ha az alkalmazás szemantikainak tekinti a megjegyzéseket (ami az XML kezelésekor nem gyakori), akkor a " helyett a "#xpointer(/)" és a "#xpointer(id('foo'))" helyett a "#foo" kifejezést kell használnia. A #xpointer verziók megjegyzésként vannak értelmezve, míg a rövidnévű űrlapok nem tartalmazzák a megjegyzéseket.

Ha olyan dokumentumokat kell elfogadnia, amelyek csak részben védettek, és biztosítani szeretné, hogy ugyanazt a tartalmat olvassa, amelyet az aláírás védett, használja a GetIdElement módszert.

A KeyInfo elem biztonsági szempontjai

Az opcionális <KeyInfo> elemben (vagyis a KeyInfo tulajdonságban) szereplő adatok, amelyek az aláírás ellenőrzéséhez szükséges kulcsot tartalmazzák, nem megbízhatók.

Különösen akkor, ha az KeyInfo érték egy önmagában álló RSA, DSA vagy ECDSA nyilvános kulcsot jelöl, a dokumentumot hamisíthatták annak ellenére, hogy az CheckSignature módszer azt jelzi, az aláírás érvényes. Ez azért fordulhat elő, mert a módosítást végző entitásnak csak új kulcsot kell létrehoznia, és újra alá kell írnia a módosított dokumentumot az új kulccsal. Ezért, ha az alkalmazás nem ellenőrzi, hogy a nyilvános kulcs a várt érték, a dokumentumot úgy kell kezelni, mintha azt manipulálták volna. Ehhez az alkalmazásnak meg kell vizsgálnia a dokumentumba ágyazott nyilvános kulcsot, és ellenőriznie kell azt a dokumentumkörnyezet ismert értékeinek listájában. Ha például a dokumentumot ismert felhasználó állítja ki, akkor a kulcsot az adott felhasználó által használt ismert kulcsok listájában ellenőrizheti.

A dokumentum feldolgozása után is ellenőrizheti a kulcsot a CheckSignatureReturningKey metódus használata CheckSignature helyett. Az optimális biztonság érdekében azonban előzetesen ellenőriznie kell a kulcsot.

Másik lehetőségként érdemes kipróbálni a felhasználó regisztrált nyilvános kulcsait, ahelyett, hogy a <KeyInfo> elemet olvasná.

Az X509Data elem biztonsági szempontjai

Az opcionális <X509Data> elem az <KeyInfo> elem gyermeke, és egy vagy több X509-tanúsítványt vagy azonosítót tartalmaz az X509-tanúsítványokhoz. Az <X509Data> elem adatait sem szabad eredendően megbízhatónak tekinteni.

A beágyazott <X509Data> elemekkel rendelkező dokumentumok ellenőrzésekor a .NET csak azt ellenőrzi, hogy az adatok egy X509-tanúsítványra kerülnek-e feloldva, amelynek nyilvános kulcsával sikeresen érvényesíthető a dokumentum aláírása. A CheckSignature metódus metódus ellentétében a verifySignatureOnly paraméter false értékének megadásánál nem történik visszavonási ellenőrzés, nem ellenőrzik a lánc megbízhatóságát, és nem vizsgálják a lejáratot. Még akkor is, ha az alkalmazás maga vonja ki a tanúsítványt, és átadja azt a CheckSignature metódusnak a verifySignatureOnly paramétert false-re állítva, ez még mindig nem elegendő a dokumentum meghamisításának megakadályozásához. A tanúsítványt továbbra is ellenőrizni kell az aláírt dokumentum megfelelőjeként.

A beágyazott aláíró tanúsítvány hasznos kulcsrotációs stratégiákat kínálhat, akár a <X509Data> szakaszban, akár a dokumentum tartalmában. Ha ezt a módszert használja, az alkalmazásnak manuálisan kell kinyernie a tanúsítványt, és a következőhöz hasonló ellenőrzést kell végrehajtania:

  • A tanúsítványt közvetlenül vagy láncon keresztül adta ki egy hitelesítésszolgáltató (CA), amelynek nyilvános tanúsítványa beágyazva van az alkalmazásba.

    Az operációs rendszer által biztosított hitelesítési lista további ellenőrzéseinek, például egy ismert tárgynév nélkül történő használata nem elegendő a manipuláció SignedXml megakadályozásához.

  • A rendszer ellenőrzi, hogy a tanúsítvány nem járt-e le a dokumentum aláírásakor (vagy "most" a közel valós idejű dokumentumfeldolgozáshoz).

  • A visszavonást támogató hitelesítésszolgáltató által kibocsátott hosszú élettartamú tanúsítványok esetében ellenőrizze, hogy a tanúsítványt nem vonták-e vissza.

  • A tanúsítvány tulajdonosát az aktuális dokumentumnak megfelelőnek tekinti a rendszer.

Az átalakító algoritmus kiválasztása

Ha olyan specifikációval működik együtt, amely meghatározott értékeket (például XrML) diktált, akkor a specifikációt kell követnie. Ha borítékolt aláírással rendelkezik (például a teljes dokumentum aláírásakor), akkor használnia kell http://www.w3.org/2000/09/xmldsig#enveloped-signature, amit az XmlDsigEnvelopedSignatureTransform osztály képvisel. Megadhatja az implicit XML-C14N átalakítást is, de nem szükséges. A burkoló vagy leválasztott aláírás esetén nincs szükség transzformációra. Az implicit XML-C14N átalakítás mindenről gondoskodik.

A Microsoft Security Bulletin MS16-035 által bevezetett biztonsági frissítés hatására a .NET alapértelmezés szerint korlátozza a dokumentumellenőrzésben használható átalakításokat, úgy hogy a nem megbízható átalakítások mindig CheckSignature visszatérjenek false-vel. A további bemenetet igénylő átalakítások (amelyeket az XML gyermekelemeiként határoznak meg) már nem engedélyezettek, mert rosszindulatú felhasználók visszaélésre fogékonyak. A W3C azt javasolja, hogy kerülje az XPath és az XSLT átalakításokat, amelyek a korlátozások által érintett két fő átalakítást érintik.

A külső hivatkozásokkal kapcsolatos probléma

Ha egy alkalmazás nem ellenőrzi, hogy a külső hivatkozások megfelelőnek tűnnek-e a jelenlegi környezethez, számos biztonsági rést (például szolgáltatásmegtagadást, elosztott tükröződésmegtagadást, információfeltárást, aláírás-megkerülést és távoli kódvégrehajtást) biztosító módon lehet visszaélni. Még ha egy alkalmazás is ellenőrizné a külső referencia URI-t, továbbra is fennáll a probléma, hogy az erőforrás kétszer töltődik be: egyszer, amikor az alkalmazás felolvassa, és egyszer, amikor SignedXml beolvassa. Mivel nincs garancia arra, hogy az alkalmazás olvasási és dokumentum-ellenőrzési lépései azonos tartalommal rendelkeznek, az aláírás nem biztosít megbízhatóságot.

Külső hivatkozások kockázataira tekintettel SignedXml kivételt dob, ha külső hivatkozás található. A problémával kapcsolatos további információkért tekintse meg a .NET-keretrendszer alkalmazásainak kivételhibáit.