Aracılığıyla paylaş


System.Security.Cryptography.Xml.SignedXml sınıfı

Bu makale, bu API'nin başvuru belgelerine ek açıklamalar sağlar.

SignedXml sınıfı, XMLDSIG (XML Dijital İmza) olarak da bilinen World Wide Web Konsorsiyumu (W3C) XML İmza Söz Dizimi ve İşleme Belirtimi'nin .NET uygulamasıdır. XMLDSIG, bir XML belgesinin veya Tekdüzen Kaynak Tanımlayıcısı (URI) ile adreslenebilir diğer verilerin tümünü veya bir bölümünü imzalamanın ve doğrulamanın standartlara dayalı ve birlikte çalışabilir bir yoludur.

SignedXml Uygulamalar veya kuruluşlar arasında imzalı XML verilerini standart bir şekilde paylaşmanız gerektiğinde sınıfını kullanın. Bu sınıf kullanılarak imzalanan tüm veriler, XMLDSIG için W3C belirtiminin uyumlu herhangi bir uygulaması tarafından doğrulanabilir.

sınıfı, SignedXml aşağıdaki üç tür XML dijital imzası oluşturmanıza olanak tanır:

İmza Türü Açıklama
Zarflı imza İmza, imzalanan XML öğesinin içinde yer alır.
Çevreleyen imza İmzalı XML öğesinde <Signature> yer alır.
İç bağımsız imza İmza ve imzalı XML aynı belgede yer alır, ancak öğeden hiçbiri diğerini içermez.

Ayrıca, verilerin ve imzanın ayrı XML belgelerinde yer aldığı dış ayrılmış imza olarak adlandırılan dördüncü bir imza türü de vardır. SignedXml sınıfı dışarıya ayrılmış imzaları desteklemez.

XML imzasının yapısı

XMLDSIG, xml <Signature> belgesinin veya URI'den ele alınabilen diğer verilerin dijital imzalarını içeren bir öğe oluşturur. <Signature> öğesi isteğe bağlı olarak imzayı doğrulayacak bir anahtarın nerede bulunacağı ve imzalama için kullanılan şifreleme algoritması hakkında bilgi içerebilir. Temel yapı aşağıdaki gibidir:

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

Bu yapının ana bölümleri şunlardır:

  • <CanonicalizationMethod> öğesi

    İmza doğrulaması için XML/metin Signature öğesini baytlara yeniden yazma kurallarını belirtir. .NET'teki varsayılan değer, güvenilir bir algoritmayı tanımlayan değeridir http://www.w3.org/TR/2001/REC-xml-c14n-20010315. Bu öğe özelliğiyle SignedInfo.CanonicalizationMethod temsil edilir.

  • <SignatureMethod> öğesi

    <Signature> içindeki değeri üretmek için <SignatureValue> öğesine uygulanan imza oluşturma ve doğrulama için kullanılan algoritmayı belirtir. Önceki örnekte, değer http://www.w3.org/2000/09/xmldsig#rsa-sha1 bir RSA PKCS1 SHA-1 imzası tanımlar. SHA-1 ile ilgili çakışma sorunları nedeniyle Microsoft, SHA-256 veya üzerini temel alan bir güvenlik modeli önerir. Bu öğe özelliğiyle SignatureMethod temsil edilir.

  • <SignatureValue> öğesi

    öğesinin şifreleme imzasını <Signature> belirtir. Bu imza doğrulanmazsa, bloğun <Signature> bir bölümüyle oynanmış ve belge geçersiz kabul edilir. Değerin <CanonicalizationMethod> güvenilir olduğu sürece, bu değer kurcalamaya karşı son derece dayanıklıdır. Bu öğe özelliğiyle SignatureValue temsil edilir.

  • URI öğesinin <Reference> özniteliği

    URI referansını kullanan bir veri nesnesini belirtir. Bu öznitelik özelliğiyle Reference.Uri temsil edilir.

    • özniteliğini URI belirtmemek, yani özelliğini olarak Reference.Uriayarlamaknull, alıcı uygulamanın nesnenin kimliğini bilmesinin beklendiği anlamına gelir. Çoğu durumda, bir null URI özel durum atılmasına neden olur. Uygulamanız bunu gerektiren bir null protokolle birlikte çalışmadığı sürece URI kullanmayın.

    • özniteliğini URI boş bir dize olarak ayarlamak, belgenin kök öğesinin imzalandığını gösterir. Bu, zarflı bir imza biçimidir.

    • Özniteliğin URI değeri # ile başlıyorsa, değerin geçerli belgedeki bir öğeye çözümlenmesi gerekir. Bu form desteklenen imza türlerinden herhangi biriyle (zarflı imza, zarflı imza veya iç ayrılmış imza) kullanılabilir.

    • SignedXml sınıfı tarafından desteklenmeyen her şey, bir dış kaynak bağımsız imzası olarak kabul edilir.

  • <Transforms> öğesi

    İmzalayanın <Transform> özetlenen veri nesnesini nasıl edindiğini açıklayan sıralı bir öğe listesi içerir. Dönüştürme algoritması, kurallı hale getirme yöntemine benzer, ancak <Signature> öğesini yeniden yazmak yerine, URI öğesinin <Reference> niteliği tarafından tanımlanan içeriği yeniden yazar. <Transforms> öğesi sınıfı tarafından TransformChain temsil edilir.

    • Her dönüştürme algoritması, giriş olarak XML (XPath düğüm kümesi) veya bayt alma olarak tanımlanır. Geçerli verilerin biçimi dönüştürme giriş gereksinimlerinden farklıysa dönüştürme kuralları uygulanır.

    • Her dönüştürme algoritması, çıktı olarak XML veya bayt üretme olarak tanımlanır.

    • Son dönüştürme algoritmasının çıkışı bayt cinsinden tanımlanmamışsa (veya hiçbir dönüşüm belirtilmediyse), kurallı hale getirme yöntemi örtük bir dönüşüm olarak kullanılır (öğesinde <CanonicalizationMethod> farklı bir algoritma belirtilse bile).

    • Dönüştürme algoritmasının http://www.w3.org/2000/09/xmldsig#enveloped-signature değerine sahip olması, <Signature> öğesini belgede kaldıracak şekilde yorumlanan bir kuralı kodlar. Aksi takdirde, zarflı bir imzayı doğrulayan kişi, belgeyi imza ile birlikte özetler, ancak imzalayan kişi belgeyi imza uygulanmadan önce özetlediği için farklı sonuçlara yol açar.

  • <DigestMethod> öğesi

    URI öğesi tarafından <Reference> özniteliği ile tanımlanan dönüştürülmüş içeriğe uygulanacak özet (şifreleme karması) yöntemini tanımlar. Bu özellik tarafından Reference.DigestMethod temsil edilir.

Kurallı hale getirme yöntemi seçme

Farklı bir değerin kullanılmasını gerektiren bir belirtimle birlikte çalışmadığınız sürece, değeri http://www.w3.org/TR/2001/REC-xml-c14n-20010315olan XML-C14N 1.0 algoritması olan varsayılan .NET kurallı hale getirme yöntemini kullanmanızı öneririz. XML-C14N 1.0 algoritmasının, özellikle de uygulanacak örtük bir son dönüşüm olduğundan, XMLDSIG'nin tüm uygulamaları tarafından desteklenmesi gerekir.

Açıklamaları korumayı destekleyen kurallılaştırma algoritmalarının sürümleri vardır. Yorum koruma kurallı hale getirme yöntemleri "görülenleri işaretle" ilkesini ihlal ettiğinden önerilmez. Başka bir ifadeyle, bir <Signature> öğedeki açıklamalar, imzanın nasıl gerçekleştirileceğine ilişkin işlem mantığını değiştirmez, yalnızca imza değerinin ne olduğudur. Zayıf bir imza algoritmasıyla birleştirildiğinde, açıklamaların eklenmesine izin vermek, saldırgana bir karma çakışması yaratmak için gereksiz bir serbestlik tanır ve bu da üzerinde oynanmış bir belgenin meşru görünmesini sağlar. .NET Framework'te varsayılan olarak yalnızca yerleşik kurallı oluşturucular desteklenir. Ekstra veya özel kurallılaştırıcıları desteklemek için SafeCanonicalizationMethods özelliğine bakın. Belge özelliği tarafından SafeCanonicalizationMethods temsil edilen koleksiyonda olmayan bir kurallılaştırma yöntemi kullanıyorsa, CheckSignature yöntemi döndürür false.

Uyarı

Son derece savunma amaçlı bir uygulama, imzalayanların koleksiyondan SafeCanonicalizationMethods kullanmasını beklemediği tüm değerleri kaldırabilir.

Referans değerleri değişikliğe karşı korumalı mı?

Evet, <Reference> değerler kurcalanmaya karşı güvenlidir. .NET, herhangi bir <SignatureValue> değerini ve bunlarla ilişkili dönüşümlerini işlemeye başlamadan önce <Reference> hesaplamayı doğrular ve potansiyel olarak kötü niyetli işleme talimatlarını önlemek için işlemi erkenden iptal eder.

İmzalayacak öğeleri seçme

Mümkünse özniteliği için URI "" değerini kullanmanızı (veya özelliğini boş bir dize olarak ayarlamanızı Uri ) öneririz. Bu, tüm belgenin özet hesaplaması için dikkate alındığı anlamına gelir ve bu da belgenin tamamının kurcalanmaya karşı korunduğu anlamına gelir.

ID özniteliği "foo" olan bir öğeye işaret eden #foo gibi bağlantı biçimindeki URI değerlerini görmek çok yaygındır. Ne yazık ki, bağlamı değil yalnızca hedef öğenin içeriğini içerdiğinden, üzerinde oynanması kolaydır. Bu ayrımı kötüye kullanarak XML İmza Sarmalama (XSW) olarak bilinir.

Uygulamanız açıklamaların anlamsal olduğunu düşünüyorsa (XML ile çalışırken yaygın değildir), "" yerine "#xpointer(/)" ve "#foo" yerine "#xpointer(id('foo'))" kullanmanız gerekir. #xpointer sürümleri yorumlar dahil edilerek ele alınırken, kısa isim formları ise yorumları hariç tutar.

Belgelerin yalnızca kısmen korunduğu durumlarda ve imzanın koruduğu içeriği okuduğunuzdan emin olmak istediğinizde GetIdElement yöntemini kullanın.

KeyInfo öğesiyle ilgili güvenlik konuları

İmzayı doğrulamak için bir anahtar içeren isteğe bağlı <KeyInfo> öğesindeki (yani KeyInfo özelliğindeki) verilere güvenilmemelidir.

Özellikle, KeyInfo değeri bir RSA, DSA veya ECDSA çıplak ortak anahtarını temsil ettiğinde, imzanın geçerli olduğunu bildiren CheckSignature yöntemine rağmen belge üzerinde oynanmış olabilir. Bu durum, üzerinde değişiklik yapan varlığın yalnızca yeni bir anahtar oluşturması ve üzerinde oynanan belgeyi bu yeni anahtarla yeniden imzalaması gerektiğinden oluşabilir. Bu nedenle, uygulamanız ortak anahtarın beklenen bir değer olduğunu doğrulamadığı sürece, belge üzerinde oynanmış gibi davranılmalıdır. Bu, uygulamanızın belgenin içine eklenmiş ortak anahtarı incelemesini ve belge bağlamı için bilinen değerler listesinde doğrulamasını gerektirir. Örneğin, belgenin bilinen bir kullanıcı tarafından verildiği anlaşılabilseydi, bu kullanıcı tarafından kullanılan bilinen anahtarlar listesinde anahtarı denetlersiniz.

Belgeyi işledikten sonra CheckSignatureReturningKey yöntemi yerine CheckSignature yöntemini kullanarak anahtarı doğrulayabilirsiniz. Ancak en iyi güvenlik için anahtarı önceden doğrulamanız gerekir.

Alternatif olarak, <KeyInfo> öğesinin içindekileri okumak yerine, kullanıcının kayıtlı ortak anahtarlarını denemeyi düşünün.

X509Data öğesiyle ilgili güvenlik konuları

İsteğe bağlı <X509Data> öğe öğenin alt <KeyInfo> öğesidir ve X509 sertifikaları için bir veya daha fazla X509 sertifikası veya tanımlayıcısı içerir. öğesindeki <X509Data> verilere de doğal olarak güvenilmemelidir.

Eklenmiş <X509Data> öğeyle belge doğrulanırken, .NET yalnızca verilerin ortak anahtarı belge imzasını doğrulamak için başarıyla kullanılabilen bir X509 sertifikasına çözümlendiğini doğrular. CheckSignature yönteminin verifySignatureOnly olarak ayarlanmış false parametresiyle çağrılması durumunun aksine, herhangi bir iptal denetimi yapılmaz, zincir güveni kontrol edilmez ve süre sonu doğrulanmaz. Uygulamanız sertifikanın kendisini ayıklayıp CheckSignature parametresini verifySignatureOnly olarak ayarlayarak false yöntemine geçirse bile, bu yine de belge üzerinde değişiklik yapılmasını önlemek için yeterli bir doğrulama değildir. Sertifikanın imzalanan belge için uygun olduğu yine de doğrulanmalıdır.

Katıştırılmış bir imzalama sertifikası kullanmak, <X509Data> bölümünde ya da belge içeriğinde yararlı anahtar döndürme stratejileri sağlayabilir. Bu yaklaşımı kullanırken uygulamanın sertifikayı el ile ayıklaması ve aşağıdakine benzer bir doğrulama gerçekleştirmesi gerekir:

  • Sertifika, genel sertifikası uygulamaya eklenmiş olan bir Sertifika Yetkilisi (CA) tarafından doğrudan veya bir zincir üzerinden verildi.

    İşletim sistemi tarafından sağlanan güven listesini, bilinen bir konu adı gibi kriterlerle ek denetimler olmadan kullanmak, SignedXml üzerinde oynanmasını önlemek için yeterli değildir.

  • Sertifikanın belge imzalama sırasında süresinin dolmadığı doğrulanır (veya neredeyse gerçek zamanlı belge işleme için "şimdi").

  • ca tarafından verilen ve iptali destekleyen uzun süreli sertifikalar için sertifikanın iptal edilmediğini doğrulayın.

  • Sertifika konusu geçerli belgeye uygun olduğu doğrulanır.

Dönüştürme algoritmasını seçme

Belirli değerleri (XrML gibi) dikte eden bir belirtim ile çalışıyorsanız, belirtimi izlemeniz gerekir. Zarflı bir imzanız varsa (örneğin, belgenin tamamını imzalarken) kullanmanız http://www.w3.org/2000/09/xmldsig#enveloped-signature gerekir (sınıf tarafından XmlDsigEnvelopedSignatureTransform temsil edilir). Örtük XML-C14N dönüşümünü de belirtebilirsiniz, ancak bu gerekli değildir. Zarf biçiminde veya bağımsız imza için dönüşüm gerekmez. Örtük XML-C14N transformasyonu her şeyi halleder.

Microsoft Güvenlik Bülteni MS16-035 tarafından sunulan güvenlik güncelleştirmesiyle, .NET, belge doğrulamada varsayılan olarak hangi dönüşümlerin kullanılabileceğini kısıtladı ve güvenilmeyen dönüşümler kullanıldığında her zaman CheckSignature döndürülmesine sebep olur. Özellikle, ek giriş gerektiren dönüşümlere (XML'de alt öğe olarak belirtilen) kötü amaçlı kullanıcıların kötüye kullanımlarına maruz kalmalarından dolayı artık izin verilmiyor. W3C, bu kısıtlamalardan etkilenen iki ana dönüşüm olan XPath ve XSLT dönüşümlerinden kaçınmayı önerir.

Dış başvurularla ilgili sorun

Bir uygulama dış başvuruların geçerli bağlam için uygun göründüğünü doğrulamazsa, birçok güvenlik açığını (Hizmet Reddi, Dağıtılmış Yansıma Hizmet Reddi, Bilgilerin Açığa Çıkması, İmzayı Atlama ve Uzaktan Kod Yürütme dahil) sağlayacak şekilde kötüye kullanılabilir. Bir uygulama dış başvuru URI'sini doğrulasa bile, kaynağın iki kez yüklenmesiyle ilgili bir sorun kalır: biri uygulamanız tarafından okunduğunda ve diğeri SignedXml tarafından okunduğunda. Uygulama okuma ve belge doğrulama adımlarının aynı içeriğe sahip olduğunu garanti etmediğinden, imza güvenilirlik sağlamaz.

Dış başvuruların riskleri göz önüne alındığında, SignedXml dış başvuruyla karşılaşıldığında bir özel durum oluşturur. Bu sorun hakkında daha fazla bilgi için bkz . .NET Framework uygulamaları özel durum hatalarıyla karşılaşıyor.