Bagikan melalui


Kelas System.Security.Cryptography.Xml.SignedXml

Artikel ini menyediakan keterangan tambahan untuk dokumentasi referensi untuk API ini.

Kelas SignedXml ini adalah implementasi .NET dari Sintaks dan Spesifikasi Pemrosesan Tanda Tangan XML World Wide Web Consortium (W3C), juga dikenal sebagai XMLDSIG (XML Digital Signature). XMLDSIG adalah cara berbasis standar dan dapat dioperasikan untuk menandatangani dan memverifikasi semua atau sebagian dokumen XML atau data lain yang dapat diatasi dari Pengidentifikasi Sumber Daya Seragam (URI).

SignedXml Gunakan kelas setiap kali Anda perlu berbagi data XML yang ditandatangani antara aplikasi atau organisasi dengan cara standar. Setiap data yang ditandatangani menggunakan kelas ini dapat diverifikasi oleh implementasi spesifikasi W3C yang sesuai untuk XMLDSIG.

Kelas ini SignedXml memungkinkan Anda membuat tiga jenis tanda tangan digital XML berikut:

Tipe Tanda Tangan Deskripsi
Tanda tangan yang diselimuti Tanda tangan terkandung dalam elemen XML yang sedang ditandatangani.
Menyelimuti tanda tangan XML yang ditandatangani terkandung dalam <Signature> elemen .
Tanda tangan internal yang dilepas Tanda tangan dan XML yang ditandatangani berada dalam dokumen yang sama, tetapi tidak ada elemen yang berisi yang lain.

Ada juga jenis tanda tangan keempat yang disebut tanda tangan eksternal yang terlepas, yaitu ketika data dan tanda tangan berada dalam dokumen XML terpisah. Tanda tangan eksternal yang terlepas tidak didukung oleh SignedXml kelas .

Struktur tanda tangan XML

XMLDSIG membuat <Signature> elemen, yang berisi tanda tangan digital dokumen XML atau data lain yang dapat diatasi dari URI. Elemen ini <Signature> dapat secara opsional berisi informasi tentang tempat menemukan kunci yang akan memverifikasi tanda tangan dan algoritma kriptografi mana yang digunakan untuk penandatanganan. Struktur dasarnya adalah sebagai berikut:

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

Bagian utama dari struktur ini adalah:

  • Elemen <CanonicalizationMethod>

    Menentukan aturan untuk menulis Signature ulang elemen dari XML/teks ke dalam byte untuk validasi tanda tangan. Nilai default dalam .NET adalah http://www.w3.org/TR/2001/REC-xml-c14n-20010315, yang mengidentifikasi algoritma tepercaya. Elemen ini diwakili oleh SignedInfo.CanonicalizationMethod properti .

  • Elemen <SignatureMethod>

    Menentukan algoritma yang digunakan untuk pembuatan dan validasi tanda tangan, yang diterapkan ke <Signature> elemen untuk menghasilkan nilai dalam <SignatureValue>. Dalam contoh sebelumnya, nilai http://www.w3.org/2000/09/xmldsig#rsa-sha1 mengidentifikasi tanda tangan RSA PKCS1 SHA-1. Karena masalah tabrakan dengan SHA-1, Microsoft merekomendasikan model keamanan berdasarkan SHA-256 atau lebih baik. Elemen ini diwakili oleh SignatureMethod properti .

  • Elemen <SignatureValue>

    Menentukan tanda tangan kriptografi untuk <Signature> elemen . Jika tanda tangan ini tidak memverifikasi, maka beberapa bagian <Signature> blok dirusak, dan dokumen dianggap tidak valid. Selama <CanonicalizationMethod> nilainya dapat dipercaya, nilai ini sangat tahan terhadap perubahan. Elemen ini diwakili oleh SignatureValue properti .

  • Atribut URI<Reference> elemen

    Menentukan objek data menggunakan referensi URI. Atribut ini diwakili oleh Reference.Uri properti .

    • Tidak menentukan URI atribut, yaitu, mengatur Reference.Uri properti ke null, berarti bahwa aplikasi penerima diharapkan mengetahui identitas objek. Dalam kebanyakan kasus, null URI akan mengakibatkan pengecualian dilemparkan. Jangan gunakan null URI, kecuali aplikasi Anda beroperasi dengan protokol yang memerlukannya.

    • URI Mengatur atribut ke string kosong menunjukkan bahwa elemen akar dokumen sedang ditandatangani, bentuk tanda tangan yang diselimuti.

    • Jika nilai URI atribut dimulai dengan #, maka nilai harus diselesaikan ke elemen dalam dokumen saat ini. Formulir ini dapat digunakan dengan salah satu jenis tanda tangan yang didukung (tanda tangan yang diselimuti, menyelimuti tanda tangan atau tanda tangan internal yang terlepas).

    • Hal lain dianggap sebagai tanda tangan yang dilepaskan sumber daya eksternal dan tidak didukung oleh SignedXml kelas .

  • Elemen <Transforms>

    Berisi daftar <Transform> elemen yang diurutkan yang menjelaskan bagaimana penanda tangan memperoleh objek data yang dicerna. Algoritma transformasi mirip dengan metode kanonisisasi, tetapi alih-alih menulis <Signature> ulang elemen, ia menulis ulang konten yang diidentifikasi oleh URI atribut <Reference> elemen . Elemen <Transforms> diwakili oleh TransformChain kelas .

    • Setiap algoritma transformasi didefinisikan sebagai mengambil XML (set simpul XPath) atau byte sebagai input. Jika format data saat ini berbeda dari persyaratan input transformasi, aturan konversi diterapkan.

    • Setiap algoritma transformasi didefinisikan sebagai menghasilkan XML atau byte sebagai output.

    • Jika output algoritma transformasi terakhir tidak didefinisikan dalam byte (atau tidak ada transformasi yang ditentukan), maka metode kanonisisasi digunakan sebagai transformasi implisit (bahkan jika algoritma yang berbeda ditentukan dalam <CanonicalizationMethod> elemen ).

    • Nilai http://www.w3.org/2000/09/xmldsig#enveloped-signature untuk algoritma transformasi mengodekan aturan yang ditafsirkan sebagai hapus <Signature> elemen dari dokumen. Jika tidak, pemverifikasi tanda tangan yang diselimuti akan mencerna dokumen, termasuk tanda tangan, tetapi penanda tangan akan mencerna dokumen sebelum tanda tangan diterapkan, yang mengarah ke jawaban yang berbeda.

  • Elemen <DigestMethod>

    Mengidentifikasi metode hash (hash kriptografi) untuk diterapkan pada konten yang diubah yang diidentifikasi oleh URI atribut <Reference> elemen . Ini diwakili oleh Reference.DigestMethod properti .

Memilih metode kanonisisasi

Kecuali mengoperasikan dengan spesifikasi yang memerlukan penggunaan nilai yang berbeda, kami sarankan Anda menggunakan metode kanonisisasi .NET default, yang merupakan algoritma XML-C14N 1.0, yang nilainya adalah http://www.w3.org/TR/2001/REC-xml-c14n-20010315. Algoritma XML-C14N 1.0 diperlukan untuk didukung oleh semua implementasi XMLDSIG, terutama karena merupakan transformasi akhir implisit yang akan diterapkan.

Ada versi algoritma kanonisisasi yang mendukung mempertahankan komentar. Metode kanonisisasi yang mempertahankan komentar tidak disarankan karena melanggar prinsip "tanda apa yang terlihat". Artinya, komentar dalam <Signature> elemen tidak akan mengubah logika pemrosesan tentang bagaimana tanda tangan dilakukan, hanya apa nilai tanda tangannya. Ketika dikombinasikan dengan algoritma tanda tangan yang lemah, memungkinkan komentar disertakan memberi penyerang kebebasan yang tidak perlu untuk memaksa tabrakan hash, membuat dokumen yang diubah tampak sah. Di .NET Framework, hanya kanonisator bawaan yang didukung secara default. Untuk mendukung kanonisator tambahan atau kustom, lihat SafeCanonicalizationMethods properti . Jika dokumen menggunakan metode kanonisisasi yang tidak ada dalam koleksi yang diwakili oleh SafeCanonicalizationMethods properti , maka CheckSignature metode akan mengembalikan false.

Catatan

Aplikasi yang sangat defensif dapat menghapus nilai apa pun yang tidak diharapkan digunakan penanda tangan dari SafeCanonicalizationMethods koleksi.

Apakah nilai referensi aman dari perubahan?

Ya, <Reference> nilai aman dari perubahan. .NET memverifikasi komputasi <SignatureValue> sebelum memproses salah <Reference> satu nilai dan transformasi terkaitnya, dan akan membatalkan lebih awal untuk menghindari instruksi pemrosesan yang berpotensi berbahaya.

Pilih elemen yang akan ditandatangani

Kami menyarankan agar Anda menggunakan nilai "" untuk URI atribut (atau mengatur Uri properti ke string kosong), jika memungkinkan. Ini berarti seluruh dokumen dipertimbangkan untuk komputasi hash, yang berarti seluruh dokumen dilindungi dari perubahan.

Sangat umum untuk melihat URI nilai dalam bentuk jangkar seperti #foo, mengacu pada elemen yang atribut ID-nya adalah "foo". Sayangnya, mudah untuk ini dirusak karena ini hanya mencakup konten elemen target, bukan konteksnya. Menyalahgunakan perbedaan ini dikenal sebagai Pembungkus Tanda Tangan XML (XSW).

Jika aplikasi Anda menganggap komentar semantik (yang tidak umum saat berhadapan dengan XML), maka Anda harus menggunakan "#xpointer(/)" alih-alih "", dan "#xpointer(id('foo'))" alih-alih "#foo". Versi #xpointer ditafsirkan sebagai termasuk komentar, sementara formulir nama pendek tidak termasuk komentar.

Jika Anda perlu menerima dokumen yang hanya dilindungi sebagian dan Anda ingin memastikan bahwa Anda membaca konten yang sama dengan yang dilindungi tanda tangan, gunakan metode .GetIdElement

Pertimbangan keamanan tentang elemen KeyInfo

Data dalam elemen opsional <KeyInfo> (yaitu, KeyInfo properti ), yang berisi kunci untuk memvalidasi tanda tangan, tidak boleh dipercaya.

Secara khusus, ketika KeyInfo nilai mewakili kunci umum RSA, DSA, atau ECDSA yang telanjang, dokumen dapat dirusak, meskipun CheckSignature metode melaporkan bahwa tanda tangan valid. Ini dapat terjadi karena entitas yang melakukan perusakan hanya perlu menghasilkan kunci baru dan menandatangani kembali dokumen yang dirusak dengan kunci baru tersebut. Jadi, kecuali aplikasi Anda memverifikasi bahwa kunci publik adalah nilai yang diharapkan, dokumen harus diperlakukan seolah-olah itu dirusak. Ini mengharuskan aplikasi Anda memeriksa kunci publik yang disematkan dalam dokumen dan memverifikasinya terhadap daftar nilai yang diketahui untuk konteks dokumen. Misalnya, jika dokumen dapat dipahami untuk dikeluarkan oleh pengguna yang diketahui, Anda akan memeriksa kunci terhadap daftar kunci yang diketahui yang digunakan oleh pengguna tersebut.

Anda juga dapat memverifikasi kunci setelah memproses dokumen dengan menggunakan CheckSignatureReturningKey metode , alih-alih menggunakan CheckSignature metode . Tetapi, untuk keamanan optimal, Anda harus memverifikasi kunci sebelumnya.

Secara bergantian, pertimbangkan untuk mencoba kunci publik terdaftar pengguna, daripada membaca apa yang ada di <KeyInfo> elemen .

Pertimbangan keamanan tentang elemen X509Data

Elemen opsional <X509Data> adalah turunan dari <KeyInfo> elemen dan berisi satu atau beberapa sertifikat atau pengidentifikasi X509 untuk sertifikat X509. Data dalam <X509Data> elemen juga tidak boleh dipercaya secara inheren.

Saat memverifikasi dokumen dengan elemen yang disematkan <X509Data> , .NET hanya memverifikasi bahwa data diselesaikan ke sertifikat X509 yang kunci publiknya dapat berhasil digunakan untuk memvalidasi tanda tangan dokumen. Tidak seperti memanggil CheckSignature metode dengan parameter yang verifySignatureOnly diatur ke false, tidak ada pemeriksaan pencabutan yang dilakukan, tidak ada kepercayaan rantai yang diperiksa, dan tidak ada kedaluwarsa yang diverifikasi. Bahkan jika aplikasi Anda mengekstrak sertifikat itu sendiri dan meneruskannya ke CheckSignature metode dengan verifySignatureOnly parameter yang diatur ke false, itu masih belum cukup validasi untuk mencegah perusakan dokumen. Sertifikat masih perlu diverifikasi sebagai sesuai untuk dokumen yang ditandatangani.

Menggunakan sertifikat penandatanganan yang disematkan dapat memberikan strategi rotasi kunci yang berguna, baik di <X509Data> bagian atau di konten dokumen. Saat menggunakan pendekatan ini, aplikasi harus mengekstrak sertifikat secara manual dan melakukan validasi yang mirip dengan:

  • Sertifikat dikeluarkan secara langsung atau melalui rantai oleh Otoritas Sertifikat (CA) yang sertifikat publiknya disematkan dalam aplikasi.

    Menggunakan daftar kepercayaan yang disediakan OS tanpa pemeriksaan tambahan, seperti nama subjek yang diketahui, tidak cukup untuk mencegah perubahan di SignedXml.

  • Sertifikat diverifikasi belum kedaluwarsa pada saat penandatanganan dokumen (atau "sekarang" untuk pemrosesan dokumen mendekati real-time).

  • Untuk sertifikat berumur panjang yang dikeluarkan oleh CA yang mendukung pencabutan, verifikasi bahwa sertifikat tidak dicabut.

  • Subjek sertifikat diverifikasi sebagai sesuai dengan dokumen saat ini.

Memilih algoritma transformasi

Jika Anda mengoperasikan dengan spesifikasi yang telah menentukan nilai tertentu (seperti XrML), maka Anda perlu mengikuti spesifikasinya. Jika Anda memiliki tanda tangan yang diselimuti (seperti saat menandatangani seluruh dokumen), maka Anda perlu menggunakan http://www.w3.org/2000/09/xmldsig#enveloped-signature (diwakili oleh XmlDsigEnvelopedSignatureTransform kelas ). Anda juga dapat menentukan transformasi XML-C14N implisit, tetapi tidak perlu. Untuk tanda tangan yang menyelimuti atau dilepas, tidak diperlukan transformasi. Transformasi XML-C14N implisit mengurus semuanya.

Dengan keamanan yang diperbarui yang diperkenalkan oleh Buletin Keamanan Microsoft MS16-035, .NET telah membatasi transformasi apa yang dapat digunakan dalam verifikasi dokumen secara default, dengan transformasi yang tidak tepercaya menyebabkan CheckSignature selalu kembali false. Secara khusus, transformasi yang memerlukan input tambahan (ditentukan sebagai elemen turunan dalam XML) tidak lagi diizinkan karena kerentanan penyalahgunaan mereka oleh pengguna berbahaya. W3C menyarankan untuk menghindari transformasi XPath dan XSLT, yang merupakan dua transformasi utama yang terpengaruh oleh pembatasan ini.

Masalah dengan referensi eksternal

Jika aplikasi tidak memverifikasi bahwa referensi eksternal tampaknya sesuai untuk konteks saat ini, mereka dapat disalahgunakan dengan cara yang menyediakan banyak kerentanan keamanan (termasuk Penolakan Layanan, Penolakan Refleksi Terdistribusi Layanan, Pengungkapan Informasi, Bypass Tanda Tangan, dan Eksekusi Kode Jarak Jauh). Bahkan jika aplikasi memvalidasi URI referensi eksternal, akan tetap ada masalah sumber daya yang dimuat dua kali: sekali ketika aplikasi Anda membacanya, dan sekali ketika SignedXml membacanya. Karena tidak ada jaminan bahwa langkah-langkah baca dan verifikasi dokumen aplikasi memiliki konten yang sama, tanda tangan tidak memberikan kepercayaan.

Mengingat risiko referensi eksternal, SignedXml akan melemparkan pengecualian ketika referensi eksternal ditemui. Untuk informasi selengkapnya tentang masalah ini, lihat artikel KB 3148821.