วิธีการใช้ใบรับรอง การเซ็นชื่อ และ เพื่อตรวจสอบวัตถุ SignedXml โดยการใช้ Visual C# .NET

การแปลบทความ การแปลบทความ
หมายเลขบทความ (Article ID): 320602 - ผลิตภัณฑ์ที่เกี่ยวข้องในบทความนี้
ขยายทั้งหมด | ยุบทั้งหมด

เนื้อหาบนหน้านี้

สรุป

บทความที่มีการทีละขั้นตอนนี้อธิบายวิธีการใช้ใบรับรอง เมื่อ ต้องการเข้าสู่ระบบ และ เพื่อตรวจสอบวัตถุSignedXml บทความนี้อธิบายวิธีการใช้ บริการใน.NET Visual Basic เมื่อต้องเรียกใช้ฟังก์ชัน Win32 API ที่เรียกใช้จากแพลตฟอร์ม เมื่อ ต้องการเข้าถึงใบรับรองในที่เก็บใบรับรอง และแนบคีย์ของพวกเขาเพื่อ วัตถุSignedXmlเพื่อเข้าสู่ระบบ และตรวจสอบวัตถุ บทความที่อธิบายถึง วิธีการใช้ แพลตฟอร์มให้เรียกใช้บริการการเรียกฟังก์ชัน Win32 API การแยกสาธารณะ คีย์จากวัตถุX509Certificate

บทความนี้อ้างถึงฟังก์ชัน Win32 API เป็น "ฟังก์ชัน"

ความต้องการ

บทความนี้อนุมานว่า คุณจะคุ้นเคยกับการเขียนโปรแกรมด้วย Microsoft Visual C# .NET

รายการต่อไปนี้แสดงฮาร์ดแวร์แนะนำ ซอฟต์แวร์ โครงสร้างพื้นฐานของเครือข่าย และ service pack ที่คุณต้องการ:
  • Microsoft Windows XP หรือ Microsoft Windows 2000
  • Microsoft Visual Studio .NET

ข้อมูลเพิ่มเติม

ระบุใบรับรอง

เนื้อหาต่อไปนี้อธิบายส่วนประกอบหลักของตัวอย่างรหัสต่อไปนี้
  • เรียกใช้ฟังก์ชันCertOpenSystemStoreเพื่อขอรับการ จัดการการจัดเก็บใบรับรองส่วนบุคคลของผู้ใช้
    uint hCertStore = Crypt32.CertOpenSystemStore(0, "My");
  • เรียกใช้ฟังก์ชันCertEnumCertificatesInStoreเพื่อขอรับตัวชี้บริบทของใบรับรองใบรับรอง
    while (0 != (pCertContext = Crypt32.CertEnumCertificatesInStore(hCertStore, (uint)pCertContext)))
  • สร้างวัตถุX509Certificateจากใบรับรอง บริบทตัวชี้
    X509Certificate x509 = new X509Certificate((IntPtr)pCertContext);
  • เรียกใช้ฟังก์ชันCertDuplicateCertificateContextเมื่อต้องเพิ่มจำนวนการอ้างอิงบนตัวชี้บริบทของใบรับรองดังกล่าว ที่คุณสามารถใช้ค่านี้ในภายหลัง
    CertDuplicateCertificateContext((IntPtr)pCertContext);
คุณสามารถใช้รหัสดังต่อไปนี้เพื่อระบุใบรับรอง

เมื่อต้องสรุปรหัส คุณระบุใบรับรองในเก็บใบรับรอง"ของฉัน"การเติมข้อมูลตัวควบคุมมุมมองรายการที่ มีชื่อเรื่องและผู้ออกใบรับรองแต่ละ แล้ว แนบตัวชี้บริบทของใบรับรองไปยังคุณสมบัติแท็กของสินค้าแต่ละมุมมองรายการ
private void button1_Click(object sender, System.EventArgs e)	
{
listView1.Items.Clear();
uint hCertStore = Crypt32.CertOpenSystemStore(0, "My");
if (hCertStore == 0)
 {
 MessageBox.Show("CertOpenSystemStore failed: " + Marshal.GetLastWin32Error().ToString());
 return;
 }
uint pCertContext = Crypt32.CertEnumCertificatesInStore(hCertStore, (uint)0);
while (pCertContext != 0) 
 {
 X509Certificate x509 = new X509Certificate((IntPtr)pCertContext);
 ListViewItem NewItem = listView1.Items.Add(x509.GetName());
 NewItem.SubItems.Add(x509.GetIssuerName());

// Increment the reference count so that you can use this value later.

 NewItem.Tag = Crypt32.CertDuplicateCertificateContext(pCertContext);
 pCertContext = Crypt32.CertEnumCertificatesInStore(hCertStore, pCertContext);
 } 
}

เข้าสู่ระบบเป็นวัตถุ SignedXml โดยการใช้ใบรับรอง

  1. เมื่อต้องทำงานต่อไปนี้ เรียกใช้ฟังก์ชันCertGetCertificateContextProperty :
    • การสอบถามสำหรับชื่อผู้ให้บริการการเข้ารหัสลับ
    • เมื่อต้องการสอบถามสำหรับการ ชนิดผู้ให้บริการบริการการเข้ารหัสลับ
    • การสอบถามสำหรับชื่อคีย์คอนเทนเนอร์ที่เชื่อมโยงด้วย บริบทเฉพาะของใบรับรอง
    • เมื่อต้องบรรจุข้อมูลนี้ลงในตัว วัตถุRSACryptoServiceProvider
    public RSACryptoServiceProvider RSACryptoServiceProviderFromCertContext (IntPtr pCertContext)
    {
      // Determine the size of the buffer that you need to allocate.
    
      uint cbData = 0;
      bool fStatus = Crypt32.CertGetCertificateContextProperty(pCertContext.ToInt32(),
      CERT_KEY_PROV_INFO_PROP_ID, (IntPtr)0, ref cbData);
      if (!fStatus)
     {
      MessageBox.Show("CertGetCertificateContextProperty failed: " + Marshal.GetLastWin32Error().ToString());
    
      // Get the CERT_KEY_PROV_HANDLE_PROP_ID value and the HCRYPTPROV value.
    
     cbData = 4;
     IntPtr pCryptKeyProvInfo = Marshal.AllocHGlobal(new IntPtr(cbData));
     fStatus = Crypt32.CertGetCertificateContextProperty(pCertContext.ToInt32(), CERT_KEY_PROV_INFO_PROP_ID,
     pCryptKeyProvInfo, 
     ref cbData);
    
     if (!fStatus)
      {
       MessageBox.Show("CertGetCertificateContextProperty failed: " + Marshal.GetLastWin32Error().ToString());
      }
    return null;
    }
    
    if (cbData != 0)
    {
    // Allocate an unmanaged buffer to store the CRYPT_KEY_PROV_INFO structure.
    
    IntPtr pCryptKeyProvInfo = Marshal.AllocHGlobal((int)cbData);
    
    // Get the CRYPT_KEY_PROV_INFO structure.
    
    fStatus = Crypt32.CertGetCertificateContextProperty(
    pCertContext.ToInt32(), 
    CERT_KEY_PROV_INFO_PROP_ID, 
    pCryptKeyProvInfo, 
    ref cbData);
    
    if (!fStatus)
    {
     MessageBox.Show("CertGetCertificateContextProperty failed: " + Marshal.GetLastWin32Error().ToString());
     Marshal.FreeHGlobal(pCryptKeyProvInfo);
    }
    else
    { 
    // Build a CspParameters object with the provider type, the provider name,
    // and the container name from the CRYPT_KEY_PROV_INFO structure.
    // The pointer to the container name is the first DWORD in the CRYPT_KEY_PROV_INFO
    // structure, the pointer to the provider name is the second DWORD, and 
    // the provider type is the third DWORD.
    
    try
     {
     CspParameters CspParams = new CspParameters(Marshal.ReadInt32((IntPtr)((int)pCryptKeyProvInfo + 8)), 
     Marshal.PtrToStringUni((IntPtr)Marshal.ReadInt32((IntPtr)((int)pCryptKeyProvInfo + 4))), 
     Marshal.PtrToStringUni((IntPtr)Marshal.ReadInt32(pCryptKeyProvInfo)));
     // Free the unmanaged CRYPT_KEY_PROV_INFO buffer.
     Marshal.FreeHGlobal(pCryptKeyProvInfo);
     return new RSACryptoServiceProvider(CspParams);
     }
    catch(Exception ex)
     {
      MessageBox.Show(ex.Message);
     }
    }
    }
    return null;
    }
  2. นำเข้าชื่อผู้ให้บริการ ชนิดของผู้ให้บริการ และคีย์ คอนเทนเนอร์ที่ข้อมูลในวัตถุRSACryptoServiceProviderเมื่อต้องการ วัตถุSystem.Security.Cryptography.RSA
    RSA key = RSA.Create();
    key.ImportParameters(rsacsp.ExportParameters(true));
  3. แนบวัตถุSystem.Security.Cryptography.RSAวัตถุSignedXmlแล้ว คำนวณลายเซ็น
    signedXml.SigningKey = key;
    signedXml.ComputeSignature();

การตรวจสอบเป็นวัตถุ SignedXml โดยการใช้ใบรับรอง

  1. แยกเลขชี้กำลังและมอดุลัสจากอินX509Certificate วัตถุ และบรรจุเลขชี้กำลังและมอดุลัสเป็นวัตถุRSACryptoServiceProvider
    /// <summary>
    /// This function creates and returns an RSACryptoServiceProvider object
    /// that contains only the public key, based on the supplied X509Certificate object.
    /// </summary>
    /// <param name="x509"></param>
    /// <returns></returns>
    
    public RSACryptoServiceProvider GetPublicKeyFromX509Certificate (X509Certificate x509)
     {
     RSACryptoServiceProvider rsacsp = null;
     uint hProv = 0;
     IntPtr pPublicKeyBlob = IntPtr.Zero;
    // Get a pointer to a CERT_CONTEXT structure from the raw certificate data.
     IntPtr pCertContext = IntPtr.Zero;
     pCertContext = (IntPtr)Crypt32.CertCreateCertificateContext(
     X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
     x509.GetRawCertData(),
     x509.GetRawCertData().Length);
     if (pCertContext == IntPtr.Zero)
     {
      MessageBox.Show("CertCreateCertificateContext failed: " + Marshal.GetLastWin32Error().ToString());
      goto Cleanup;
     }
     if (!Crypt32.CryptAcquireContext(ref hProv, null, null, PROV_RSA_FULL, 0)) 
      { 
       if (!Crypt32.CryptAcquireContext(ref hProv, null, null, PROV_RSA_FULL, CRYPT_NEWKEYSET)) 
       { 
        MessageBox.Show("CryptAcquireContext failed: " + Marshal.GetLastWin32Error().ToString());
       goto Cleanup;
      }
     }
    
    // Get a pointer to the CERT_INFO structure.
    // This pointer is the fourth DWORD of the CERT_CONTEXT structure.
    
    IntPtr pCertInfo = (IntPtr)Marshal.ReadInt32(pCertContext, 12);
    
    // Get a pointer to the CERT_PUBLIC_KEY_INFO structure.
    // This structure is located starting at the fifty-seventh byte
    // of the CERT_INFO structure.
    
    IntPtr pSubjectPublicKeyInfo = (IntPtr)(pCertInfo.ToInt32() + 56);
    
    // Import the public key information from the certificate context
    // into a key container by passing the pointer to the SubjectPublicKeyInfo
    // member of the CERT_INFO structure to the CryptImportPublicKeyInfoEx
    // Win32 API function.
    
    uint hKey = 0;
    if (!Crypt32.CryptImportPublicKeyInfo(hProv, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
    pSubjectPublicKeyInfo, ref hKey)) 
     {
      MessageBox.Show("CryptImportPublicKeyInfoEx failed: " + Marshal.GetLastWin32Error().ToString());
      goto Cleanup;
     }
    
    // Get the size of the buffer that is needed to contain the PUBLICKEYBLOB structure, and then
    // call the CryptExportKey Win32 API function to export the public key to the PUBLICKEYBLOB format.
    
     uint dwDataLen = 0;
     if (!Crypt32.CryptExportKey(hKey, 0, PUBLICKEYBLOB, 0, 0, ref dwDataLen))
     {
      MessageBox.Show("CryptExportKey failed: " + Marshal.GetLastWin32Error().ToString());
      goto Cleanup;
     }
    
    // Export the public key to the PUBLICKEYBLOB format.
    
    pPublicKeyBlob = Marshal.AllocHGlobal((int)dwDataLen);
    if (!Crypt32.CryptExportKey(hKey, 0, PUBLICKEYBLOB, 0, (uint)pPublicKeyBlob.ToInt32(), ref dwDataLen))
     {
      MessageBox.Show("CryptExportKey failed: " + Marshal.GetLastWin32Error().ToString());
      goto Cleanup;
     }
    
    // Get the public exponent.
    // The public exponent is located in bytes 17 through 20 of the 
    // earlier PUBLICKEYBLOB structure.
    
    byte[] Exponent = new byte[4];
    Marshal.Copy((IntPtr)(pPublicKeyBlob.ToInt32() + 16), Exponent, 0, 4);
    Array.Reverse(Exponent); 
    
    // Reverse the byte order.
    // Get the length of the modulus.
    // To do this, extract the bit length of the modulus from the PUBLICKEYBLOB structure.
    // The bit length of the modulus is located in bytes 13 through 17 of the PUBLICKEYBLOB structure.
    
    int BitLength = Marshal.ReadInt32(pPublicKeyBlob, 12);
    
    // Get the modulus.
    // The modulus starts at the twenty-first byte of the PUBLICKEYBLOB structure,
    // and is BitLength/8 bytes in length.
    
    byte[] Modulus = new byte[BitLength / 8];
    Marshal.Copy((IntPtr)(pPublicKeyBlob.ToInt32() + 20), Modulus, 0, BitLength / 8);
    Array.Reverse(Modulus); 
    
    // Reverse the byte order.
    // Put the modulus and the exponent into an RSAParameters object.
    
    RSAParameters rsaparms = new RSAParameters();
    rsaparms.Exponent = Exponent;
    rsaparms.Modulus = Modulus;
    
    // Import the modulus and the exponent into an RSACryptoServiceProvider object
    // by using the RSAParameters object.
    
    rsacsp = new RSACryptoServiceProvider(); 
    
    rsacsp.ImportParameters(rsaparms);
    Cleanup:
    
    if (pCertContext != IntPtr.Zero)
    Crypt32.CertFreeCertificateContext(pCertContext.ToInt32());
    
    if (hProv != 0)
    Crypt32.CryptReleaseContext(hProv, 0);
    
    if (pPublicKeyBlob != IntPtr.Zero)
    Marshal.FreeHGlobal(pPublicKeyBlob);
    return rsacsp;
    }
    uint hCrypt;
    RSACryptoServiceProvider rsacsp;
    private void button2_Click(object sender, System.EventArgs e)
    {
     if(listView1.SelectedItems.Count == 0)
      {
       MessageBox.Show("You must select at least one certificate in the list view");
       return;
      }
    hCrypt  = (uint)listView1.SelectedItems[0].Tag;
    rsacsp = RSACryptoServiceProviderFromCertContext(new IntPtr((int)hCrypt));
    if(rsacsp == null)
    return;
    
    // Create the SignedXml message.
    
    SignedXml signedXml = new SignedXml();
    RSA key = RSA.Create();
    key.ImportParameters(rsacsp.ExportParameters(true));
    signedXml.SigningKey = key;
    
    // Create a data object to store the data to sign.
    
    System.Security.Cryptography.Xml.DataObject dataObject = new System.Security.Cryptography.Xml.DataObject();
    dataObject.Data = xmlDocument.ChildNodes;
    dataObject.Id = "MyObjectId";
    
    // Add the data object to the signature.
    
    signedXml.AddObject(dataObject);
    
    // Create a reference to package information into the message.
    
    Reference reference = new Reference();
    reference.Uri = "#MyObjectId";
    
    // Add the reference to the message.
    
    signedXml.AddReference(reference);
    
    // Compute the signature.
    
    signedXml.ComputeSignature();
    
    // Get the XML representation of the signature.
    
    XmlElement xmlSignature = signedXml.GetXml();
    textBox2.Text = xmlSignature.OuterXml;
    }
  2. เมื่อต้องการตรวจสอบลายเซ็น ผ่านแบบRSACryptoServiceProvider วัตถุที่ประกอบด้วยคีย์สาธารณะX509CertificateกับวิธีCheckSignature ของออบเจ็กต์SignedXml
    if (signedXml.CheckSignature(rsa))
     MessageBox.Show ("The signature has been validated.");
    else
     MessageBox.Show ("The signature has NOT been validated.");

โค้ดตัวอย่างทีละขั้นตอน

  1. เริ่ม Visual Studio .NET
  2. ในการ แฟ้ม เมนู ชี้ไปที่ใหม่แล้ว คลิก โครงการ.
  3. ภายใต้ ชนิดโครงการคลิก แสดงผล โครงการ C#.
  4. ภายใต้ แม่แบบคลิก Windows แอพลิเคชันแล้ว คลิก ตกลง.
  5. ในการ โครงการ เมนู คลิก เพิ่ม ข้อมูลอ้างอิง.
  6. ในการ .NET แท็บของแบบ เพิ่ม ข้อมูลอ้างอิง กล่องโต้ตอบ คลิก System.Securityแล้ว คลิก เลือก
  7. คลิก ตกลง เมื่อต้องปิดการ เพิ่ม ข้อมูลอ้างอิง กล่องโต้ตอบ
  8. แทนรหัสที่มีอยู่ในแฟ้ม Form1.cs ด้วยการ โค้ดตัวอย่างที่ให้มาในตอนท้ายของส่วนนี้
  9. ในการ ตรวจแก้จุดบกพร่อง เมนู คลิกเริ่ม. โดยค่าเริ่มต้น การ Form1 แบบฟอร์ม ปรากฏขึ้น
  10. บน Form1คลิกEnumCert.

    ใบรับรองทั้งหมดในคอมพิวเตอร์ของคุณไว้ในกล่อง ที่อยู่เหนือการ EnumCert ปุ่ม
  11. ในกล่องที่อยู่เหนือการEnumCert ปุ่ม ให้ทำตามขั้นตอนเหล่านี้:
    1. เมื่อต้องการเข้าสู่ระบบเป็นวัตถุSignedXmlโดยการใช้ที่เลือก ใบรับรอง เลือกใบรับรองลายเซ็น รหัสแล้ว คลิก เข้าสู่ระบบ.
    2. เมื่อต้องการตรวจสอบเป็นวัตถุSignedXmlโดยการใช้ที่เลือก ใบรับรอง เลือกใบรับรองลายเซ็น รหัสแล้ว คลิก ตรวจสอบ.

รหัสสำหรับขั้นตอนที่ 8

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Xml;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography.Xml;
namespace _320602
{
   /// <summary>
   /// Summary description for Form1.
   /// </summary>
   public class Form1 : System.Windows.Forms.Form
   {
      private System.Windows.Forms.ListView listView1;
      private System.Windows.Forms.Button button1;
      private System.Windows.Forms.TextBox tbStoreName;
      private System.Windows.Forms.ColumnHeader columnHeader1;
      private System.Windows.Forms.ColumnHeader columnHeader2;
      private System.Windows.Forms.TextBox textBox1;
      private XmlDocument xmlDocument;
      private System.Windows.Forms.Button button2;
      private System.Windows.Forms.Button button3;
      private System.Windows.Forms.TextBox textBox2;
      private System.Windows.Forms.Label label1;
      private System.Windows.Forms.Label label2;
      /// <summary>
      /// Required designer variable.
      /// </summary>
      private System.ComponentModel.Container components = null;
      private const int CERT_KEY_PROV_INFO_PROP_ID = 2;
      private const int X509_ASN_ENCODING = 1;
      private const int PROV_RSA_FULL = 1;
      private const uint PKCS_7_ASN_ENCODING = 0x00010000;
      private const uint CRYPT_VERIFYCONTEXT = 0xF0000000;
      private const int CRYPT_NEWKEYSET = 8;
      private System.Windows.Forms.Label label3;
      private System.Windows.Forms.TextBox tbFileName;
      private const int PUBLICKEYBLOB = 6; 
      public Form1()
      {
         // Required for Windows Form Designer support.
         InitializeComponent();
         xmlDocument = new XmlDocument();
         XmlNode  node = xmlDocument.CreateNode(XmlNodeType.Element, "", "MyElement", "samples");
         node.InnerText = "This is a sample code to demonstrate SignedXml";
         xmlDocument.AppendChild(node);
         textBox1.Text = xmlDocument.OuterXml;
      }
      /// <summary>
      /// Clean up any resources that are being used.
      /// </summary>
      protected override void Dispose( bool disposing )
      {
         if( disposing )
         {
            if (components != null) 
            {
               components.Dispose();
            }
         }
         base.Dispose( disposing );
      }
		#region Windows Form Designer generated code
      /// <summary>
      /// Required method for Designer support. Do not modify
      /// the contents of this method by using the code editor.
      /// </summary>
      private void InitializeComponent()
      {
         this.listView1 = new System.Windows.Forms.ListView();
         this.columnHeader1 = new System.Windows.Forms.ColumnHeader();
         this.columnHeader2 = new System.Windows.Forms.ColumnHeader();
         this.button1 = new System.Windows.Forms.Button();
         this.tbStoreName = new System.Windows.Forms.TextBox();
         this.textBox1 = new System.Windows.Forms.TextBox();
         this.button2 = new System.Windows.Forms.Button();
         this.button3 = new System.Windows.Forms.Button();
         this.textBox2 = new System.Windows.Forms.TextBox();
         this.label1 = new System.Windows.Forms.Label();
         this.label2 = new System.Windows.Forms.Label();
         this.label3 = new System.Windows.Forms.Label();
         this.tbFileName = new System.Windows.Forms.TextBox();
         this.SuspendLayout();
         // 
         // listView1
         // 
         this.listView1.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] 
         {
            this.columnHeader1,
            this.columnHeader2
         });
         this.listView1.Location = new System.Drawing.Point(16, 16);
         this.listView1.Name = "listView1";
         this.listView1.Size = new System.Drawing.Size(392, 128);
         this.listView1.TabIndex = 0;
         this.listView1.View = System.Windows.Forms.View.Details;
         // 
         // columnHeader1
         // 
         this.columnHeader1.Text = "Certificate Name";
         this.columnHeader1.Width = 232;
         // 
         // columnHeader2
         // 
         this.columnHeader2.Text = "Issuer name";
         this.columnHeader2.Width = 149;
         // 
         // button1
         // 
         this.button1.Location = new System.Drawing.Point(16, 160);
         this.button1.Name = "button1";
         this.button1.Size = new System.Drawing.Size(80, 24);
         this.button1.TabIndex = 1;
         this.button1.Text = "EnumCert";
         this.button1.Click += new System.EventHandler(this.button1_Click);
         // 
         // tbStoreName
         // 
         this.tbStoreName.Location = new System.Drawing.Point(120, 160);
         this.tbStoreName.Name = "tbStoreName";
         this.tbStoreName.Size = new System.Drawing.Size(72, 20);
         this.tbStoreName.TabIndex = 2;
         this.tbStoreName.Text = "My";
         // 
         // textBox1
         // 
         this.textBox1.Location = new System.Drawing.Point(16, 240);
         this.textBox1.Multiline = true;
         this.textBox1.Name = "textBox1";
         this.textBox1.Size = new System.Drawing.Size(192, 168);
         this.textBox1.TabIndex = 3;
         this.textBox1.Text = "";
         // 
         // button2
         // 
         this.button2.Enabled = false;
         this.button2.Location = new System.Drawing.Point(216, 160);
         this.button2.Name = "button2";
         this.button2.Size = new System.Drawing.Size(80, 24);
         this.button2.TabIndex = 1;
         this.button2.Text = "Sign";
         this.button2.Click += new System.EventHandler(this.button2_Click);
         // 
         // button3
         // 
         this.button3.Enabled = false;
         this.button3.Location = new System.Drawing.Point(320, 160);
         this.button3.Name = "button3";
         this.button3.Size = new System.Drawing.Size(80, 24);
         this.button3.TabIndex = 1;
         this.button3.Text = "Verify";
         this.button3.Click += new System.EventHandler(this.button3_Click);
         // 
         // textBox2
         // 
         this.textBox2.Location = new System.Drawing.Point(216, 240);
         this.textBox2.Multiline = true;
         this.textBox2.Name = "textBox2";
         this.textBox2.Size = new System.Drawing.Size(192, 168);
         this.textBox2.TabIndex = 3;
         this.textBox2.Text = "";
         // 
         // label1
         // 
         this.label1.Location = new System.Drawing.Point(16, 216);
         this.label1.Name = "label1";
         this.label1.Size = new System.Drawing.Size(136, 16);
         this.label1.TabIndex = 4;
         this.label1.Text = "Raw XML";
         // 
         // label2
         // 
         this.label2.Location = new System.Drawing.Point(216, 216);
         this.label2.Name = "label2";
         this.label2.Size = new System.Drawing.Size(136, 16);
         this.label2.TabIndex = 4;
         this.label2.Text = "Signed XML";
         // 
         // label3
         // 
         this.label3.Location = new System.Drawing.Point(16, 192);
         this.label3.Name = "label3";
         this.label3.Size = new System.Drawing.Size(83, 16);
         this.label3.TabIndex = 4;
         this.label3.Text = "X509 Cert Path";
         // 
         // tbFileName
         // 
         this.tbFileName.Location = new System.Drawing.Point(120, 192);
         this.tbFileName.Name = "tbFileName";
         this.tbFileName.Size = new System.Drawing.Size(280, 20);
         this.tbFileName.TabIndex = 2;
         this.tbFileName.Text = "";
         // 
         // Form1
         // 
         this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
         this.ClientSize = new System.Drawing.Size(424, 422);
         this.Controls.Add(this.label1);
         this.Controls.Add(this.textBox1);
         this.Controls.Add(this.tbStoreName);
         this.Controls.Add(this.textBox2);
         this.Controls.Add(this.button1);
         this.Controls.Add(this.listView1);
         this.Controls.Add(this.button2);
         this.Controls.Add(this.button3);
         this.Controls.Add(this.label2);
         this.Controls.Add(this.label3);
         this.Controls.Add(this.tbFileName);
         this.Name = "Form1";
         this.Text = "Form1";
         this.ResumeLayout(false);
      }
		#endregion
      /// <summary>
      /// The main entry point for the application.
      /// </summary>
      [STAThread]
      static void Main() 
      {
         Application.Run(new Form1());
      }
      private void button1_Click(object sender, System.EventArgs e)
      {
         listView1.Items.Clear();
         uint hCertStore = Crypt32.CertOpenSystemStore(0, tbStoreName.Text);
         if (hCertStore == 0)
         {
            MessageBox.Show("CertOpenSystemStore failed: " + Marshal.GetLastWin32Error().ToString());
            return;
         }
         uint pCertContext = Crypt32.CertEnumCertificatesInStore(hCertStore, (uint)0);
         while (pCertContext != 0) 
         {
            X509Certificate x509 = new X509Certificate((IntPtr)pCertContext);
            ListViewItem NewItem = listView1.Items.Add(x509.GetName());
            NewItem.SubItems.Add(x509.GetIssuerName());
            // Increment the reference count so that you can use this value later.
            NewItem.Tag = Crypt32.CertDuplicateCertificateContext(pCertContext);
            pCertContext = Crypt32.CertEnumCertificatesInStore(hCertStore, pCertContext);
         } 
         button2.Enabled = true;
      }
      /// This function creates and returns an RSACryptoServiceProvider
      /// object that is based on the supplied certificate context pointer.
      public RSACryptoServiceProvider RSACryptoServiceProviderFromCertContext (IntPtr pCertContext)
      {
         // Determine the size of the buffer that you need to allocate.
         uint cbData = 0;
         bool fStatus = Crypt32.CertGetCertificateContextProperty(
            pCertContext.ToInt32(), 
            CERT_KEY_PROV_INFO_PROP_ID, 
            (IntPtr)0, 
            ref cbData);
         if (!fStatus)
         {
            MessageBox.Show("CertGetCertificateContextProperty failed: " + Marshal.GetLastWin32Error().ToString());
            // Get the CERT_KEY_PROV_HANDLE_PROP_ID value and the HCRYPTPROV value.
            cbData = 4;
            IntPtr pCryptKeyProvInfo = Marshal.AllocHGlobal(new IntPtr(cbData));
            fStatus = Crypt32.CertGetCertificateContextProperty(pCertContext.ToInt32(),CERT_KEY_PROV_INFO_PROP_ID, 
               pCryptKeyProvInfo, 
               ref cbData);
            if (!fStatus)
            {
               MessageBox.Show("CertGetCertificateContextProperty failed: " + Marshal.GetLastWin32Error().ToString());
            }
            return null;
         }
         if (cbData != 0)
         {
            // Allocate an unmanaged buffer to store the CRYPT_KEY_PROV_INFO structure.
            IntPtr pCryptKeyProvInfo = Marshal.AllocHGlobal((int)cbData);
            // Get the CRYPT_KEY_PROV_INFO structure.
            fStatus = Crypt32.CertGetCertificateContextProperty(pCertContext.ToInt32(),CERT_KEY_PROV_INFO_PROP_ID, 
               pCryptKeyProvInfo, 
               ref cbData);
            if (!fStatus)
            {
               MessageBox.Show("CertGetCertificateContextProperty failed: " + Marshal.GetLastWin32Error().ToString());
               Marshal.FreeHGlobal(pCryptKeyProvInfo);
            }
            else
            { 
               // Build a CspParameters object with the provider type, the provider name,
               // and the container name from the CRYPT_KEY_PROV_INFO structure.
               // The pointer to the container name is the first DWORD in the CRYPT_KEY_PROV_INFO
               // structure. The pointer to the provider name is the second DWORD. 
               // The provider type is the third DWORD.
               try
               {
                  CspParameters CspParams = new CspParameters(Marshal.ReadInt32((IntPtr)((int)pCryptKeyProvInfo + 8)), 
                     Marshal.PtrToStringUni((IntPtr)Marshal.ReadInt32((IntPtr)((int)pCryptKeyProvInfo + 4))), 
                     Marshal.PtrToStringUni((IntPtr)Marshal.ReadInt32(pCryptKeyProvInfo)));
                  // 
                  // Free the unmanaged CRYPT_KEY_PROV_INFO buffer.
                  // 
                  Marshal.FreeHGlobal(pCryptKeyProvInfo);
                  return new RSACryptoServiceProvider(CspParams);
               }
               catch(Exception ex)
               {
                  MessageBox.Show(ex.Message);
               }
            }
         }
         return null;
      }
      /// <summary>
      /// This function creates and returns an RSACryptoServiceProvider object
      /// that contains only the public key based on the supplied X509Certificate object.
      /// </summary>
      /// <param name="x509"></param>
      /// <returns></returns>
      public RSACryptoServiceProvider GetPublicKeyFromX509Certificate (X509Certificate x509)
      {
         RSACryptoServiceProvider rsacsp = null;
         uint hProv = 0;
         IntPtr pPublicKeyBlob = IntPtr.Zero;
         // Get a pointer to a CERT_CONTEXT structure from the raw certificate data.
         IntPtr pCertContext = IntPtr.Zero;
         pCertContext = (IntPtr)Crypt32.CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
            x509.GetRawCertData(),x509.GetRawCertData().Length);
         if (pCertContext == IntPtr.Zero)
         {
            MessageBox.Show("CertCreateCertificateContext failed: " + Marshal.GetLastWin32Error().ToString());
            goto Cleanup;
         }
         if (!Crypt32.CryptAcquireContext(ref hProv, null, null, PROV_RSA_FULL, 0)) 
         { 
            if (!Crypt32.CryptAcquireContext(ref hProv, null, null, PROV_RSA_FULL, CRYPT_NEWKEYSET)) 
            { 
               MessageBox.Show("CryptAcquireContext failed: " + Marshal.GetLastWin32Error().ToString());
               goto Cleanup;
            }
         }
         
         // Get a pointer to the CERT_INFO structure.
         // This pointer is the fourth DWORD of the CERT_CONTEXT structure.
         
         IntPtr pCertInfo = (IntPtr)Marshal.ReadInt32(pCertContext, 12);
         
         // Get a pointer to the CERT_PUBLIC_KEY_INFO structure.
         // This structure is located starting at the fifty-seventh byte
         // of the CERT_INFO structure.
         
         IntPtr pSubjectPublicKeyInfo = (IntPtr)(pCertInfo.ToInt32() + 56);
         
         // Import the public key information from the certificate context
         // into a key container by passing the pointer to the SubjectPublicKeyInfo
         // member of the CERT_INFO structure to the CryptImportPublicKeyInfoEx
         // Win32 API function.
         
         uint hKey = 0;
         if (!Crypt32.CryptImportPublicKeyInfo(hProv,X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
            pSubjectPublicKeyInfo,ref hKey)) 
         {
            MessageBox.Show("CryptImportPublicKeyInfoEx failed: " + Marshal.GetLastWin32Error().ToString());
            goto Cleanup;
         }

         // Get the size of the buffer that is needed to contain the PUBLICKEYBLOB structure, and then
         // call the CryptExportKey Win32 API function to export the public key to the PUBLICKEYBLOB format.

         uint dwDataLen = 0;
         if (!Crypt32.CryptExportKey(hKey, 0, PUBLICKEYBLOB, 0, 0, ref dwDataLen))
         {
            MessageBox.Show("CryptExportKey failed: " + Marshal.GetLastWin32Error().ToString());
            goto Cleanup;
         }
         
         // Export the public key to the PUBLICKEYBLOB format.
         
         pPublicKeyBlob = Marshal.AllocHGlobal((int)dwDataLen);
         if (!Crypt32.CryptExportKey(hKey, 0, PUBLICKEYBLOB, 0, (uint)pPublicKeyBlob.ToInt32(), ref dwDataLen))
         {
            MessageBox.Show("CryptExportKey failed: " + Marshal.GetLastWin32Error().ToString());
            goto Cleanup;
         }
         
         // Get the public exponent.
         // The public exponent is located in bytes 17 through 20 of the 
         // earlier PUBLICKEYBLOB structure.
         
         byte[] Exponent = new byte[4];
         Marshal.Copy((IntPtr)(pPublicKeyBlob.ToInt32() + 16), Exponent, 0, 4);
         Array.Reverse(Exponent); // Reverse the byte order.

         // Reverse the byte order.
         // Get the length of the modulus.
         // To do this, extract the bit length of the modulus from the PUBLICKEYBLOB structure.
         // The bit length of the modulus is located in bytes 13 through 17 of the PUBLICKEYBLOB structure.
         
         int BitLength = Marshal.ReadInt32(pPublicKeyBlob, 12);

         // Get the modulus.
         // The modulus starts at the twenty-first byte of the PUBLICKEYBLOB structure,
         // and is BitLength/8 bytes in length.
         
         byte[] Modulus = new byte[BitLength / 8];
         Marshal.Copy((IntPtr)(pPublicKeyBlob.ToInt32() + 20), Modulus, 0, BitLength / 8);
         Array.Reverse(Modulus);
         
         // Reverse the byte order.
         // Put the modulus and the exponent into an RSAParameters object.
         
         RSAParameters rsaparms = new RSAParameters();
         rsaparms.Exponent = Exponent;
         rsaparms.Modulus = Modulus;
         
         // Import the modulus and the exponent into an RSACryptoServiceProvider object
         // by using the RSAParameters object.
         
         rsacsp = new RSACryptoServiceProvider();
         rsacsp.ImportParameters(rsaparms);
         Cleanup:
            if (pCertContext != IntPtr.Zero)
               Crypt32.CertFreeCertificateContext(pCertContext.ToInt32());
         if (hProv != 0)
            Crypt32.CryptReleaseContext(hProv, 0);
         if (pPublicKeyBlob != IntPtr.Zero)
            Marshal.FreeHGlobal(pPublicKeyBlob);
         return rsacsp;
      }
      uint hCrypt;
      RSACryptoServiceProvider rsacsp;
      private void button2_Click(object sender, System.EventArgs e)
      {
         if(listView1.SelectedItems.Count == 0)
         {
            MessageBox.Show("You must select at least one certificate in the list view");
            return;
         }
         hCrypt  = (uint)listView1.SelectedItems[0].Tag;
         rsacsp = RSACryptoServiceProviderFromCertContext(new IntPtr((int)hCrypt));
         if(rsacsp == null)
            return;
         
         // Create the SignedXml message.
         SignedXml signedXml = new SignedXml();
         RSA key = RSA.Create();
         key.ImportParameters(rsacsp.ExportParameters(true));
         signedXml.SigningKey = key;
         
         // Create a data object to store the data to sign.
         System.Security.Cryptography.Xml.DataObject dataObject = new System.Security.Cryptography.Xml.DataObject();
         dataObject.Data = xmlDocument.ChildNodes;
         dataObject.Id = "MyObjectId";
         
         // Add the data object to the signature.
         signedXml.AddObject(dataObject);
         
         // Create a reference to package information into the message.
         Reference reference = new Reference();
         reference.Uri = "#MyObjectId";
         
         // Add the reference to the message.
         signedXml.AddReference(reference);
         
         // Compute the signature.
         signedXml.ComputeSignature();
         
         // Get the XML representation of the signature.
         XmlElement xmlSignature = signedXml.GetXml();
         textBox2.Text = xmlSignature.OuterXml;
         button3.Enabled = true;
      }
      private void button3_Click(object sender, System.EventArgs e)
      {
         // Load the XML representation.
         XmlDocument xmlDocument = new XmlDocument();
         xmlDocument.PreserveWhitespace = true;
         xmlDocument.LoadXml(textBox2.Text);
         SignedXml signedXml = new SignedXml(xmlDocument);
         XmlNodeList nodeList = xmlDocument.GetElementsByTagName("Signature");
         signedXml.LoadXml((XmlElement)nodeList[0]);
         
         // Create a SignedXml object.
         X509Certificate x509cert = X509Certificate.CreateFromCertFile(tbFileName.Text);
         RSACryptoServiceProvider rsacsp = GetPublicKeyFromX509Certificate(x509cert);
         if (signedXml.CheckSignature(rsacsp))
            MessageBox.Show ("The signature has been validated.");
         else
            MessageBox.Show ("The signature has NOT been validated."); 
      }
   }
   /// <summary>
   /// Summary description for Crypt32.
   /// </summary>
   public class Crypt32
   {
      [DllImport("Crypt32.dll", CharSet=CharSet.Auto)]
      internal extern static uint CertOpenSystemStore(int hprov, string szSubsystemProtocol);
      [DllImport("Crypt32.dll", CharSet=CharSet.Auto)]
      internal extern static uint CertEnumCertificatesInStore(uint hCertStore, uint pPrevCertContext);
      [DllImport("Crypt32.dll", CharSet=CharSet.Auto)]
      internal extern static uint CertDuplicateCertificateContext(uint pPrevCertContext);
      [DllImport("Crypt32.dll", CharSet=CharSet.Auto,SetLastError=true)]
      [return : MarshalAs(UnmanagedType.Bool)]
      internal extern static bool CertGetCertificateContextProperty(int pCertContext,int dwPropId,
         IntPtr pvData, ref uint pcbData);
      [DllImport("Crypt32.dll", CharSet=CharSet.Auto)]
      internal extern static uint CertCreateCertificateContext(uint dwCertEncodingType,
         [MarshalAs(UnmanagedType.LPArray)]byte[] pbCertEncoded, int cbCertEncoded);
      [DllImport("Advapi32.dll", CharSet=CharSet.Auto,SetLastError=true)]
      [return : MarshalAs(UnmanagedType.Bool)]
      internal extern static bool CryptAcquireContext(ref uint phProv,string pszContainer,
         string pszProvider,uint dwProvType,uint dwFlags);
      [DllImport("Crypt32.dll", CharSet=CharSet.Auto,SetLastError=true)]
      [return : MarshalAs(UnmanagedType.Bool)]
      internal extern static bool CryptImportPublicKeyInfoEx(uint hCryptProv ,uint dwCertEncodingType, 
         IntPtr pInfo, uint aiKeyAlg, uint dwFlags ,uint pvAuxInfo, ref uint phKey); 
      [DllImport("Crypt32.dll", CharSet=CharSet.Auto,SetLastError=true)]
      [return : MarshalAs(UnmanagedType.Bool)]
      internal extern static bool CryptImportPublicKeyInfo(uint hCryptProv ,uint dwCertEncodingType, 
         IntPtr pInfo, ref uint phKey); 
      [DllImport("Advapi32.dll", CharSet=CharSet.Auto,SetLastError=true)]
      [return : MarshalAs(UnmanagedType.Bool)]
      internal extern static bool CryptExportKey(uint hKey,uint hExpKey, uint dwBlobType, 
         uint dwFlags ,uint pbData, ref uint pdwDataLen);
      [DllImport("Crypt32.dll", CharSet=CharSet.Auto,SetLastError=true)]
      [return : MarshalAs(UnmanagedType.Bool)]
      internal extern static bool CertFreeCertificateContext(int pCertContext);
      [DllImport("Advapi32.dll", CharSet=CharSet.Auto,SetLastError=true)]
      [return : MarshalAs(UnmanagedType.Bool)]
      internal extern static bool CryptReleaseContext(uint hProv, uint dwFlags);
   }
}

การแก้ไขปัญหา

ใช้ใบรับรองลายเซ็นรหัสเท่านั้นเพื่อเข้าสู่ระบบแบบSignedXml วัตถุ ถ้าคุณไม่ได้ใช้ใบรับรองการเซ็นโค้ด ข้อยกเว้นอาจเกิดขึ้น

ข้อมูลอ้างอิง

สำหรับข้อมูลเพิ่มเติม โปรดเยี่ยมชม Microsoft ต่อไปนี้ นักพัฒนาไซต์เว็บเครือข่าย (MSDN):
การจัดการการเก็บใบรับรอง สถานะhttp://msdn.microsoft.com/en-us/library/aa919752.aspx

EncryptTo/DecryptTo: การเข้ารหัสลับใน.NET มีการเก็บใบรับรอง CryptoAPI http://msdn.microsoft.com/en-us/library/ms867080.aspx

คุณสมบัติ

หมายเลขบทความ (Article ID): 320602 - รีวิวครั้งสุดท้าย: 30 ตุลาคม 2555 - Revision: 5.0
ใช้กับ
  • Microsoft Visual C# .NET 2003 Standard Edition
  • Microsoft Visual C# .NET 2002 Standard Edition
Keywords: 
kbuser kbhowtomaster kbsecurity kbmt KB320602 KbMtth
แปลโดยคอมพิวเตอร์
ข้อมูลสำคัญ: บทความนี้แปลโดยซอฟต์แวร์การแปลด้วยคอมพิวเตอร์ของ Microsoft แทนที่จะเป็นนักแปลที่เป็นบุคคล Microsoft มีบทความที่แปลโดยนักแปลและบทความที่แปลด้วยคอมพิวเตอร์ เพื่อให้คุณสามารถเข้าถึงบทความทั้งหมดในฐานความรู้ของเรา ในภาษาของคุณเอง อย่างไรก็ตาม บทความที่แปลด้วยคอมพิวเตอร์นั้นอาจมีข้อบกพร่อง โดยอาจมีข้อผิดพลาดในคำศัพท์ รูปแบบการใช้ภาษาและไวยากรณ์ เช่นเดียวกับกรณีที่ชาวต่างชาติพูดผิดเมื่อพูดภาษาของคุณ Microsoft ไม่มีส่วนรับผิดชอบต่อความคลาดเคลื่อน ความผิดพลาดหรือความเสียหายที่เกิดจากการแปลเนื้อหาผิดพลาด หรือการใช้บทแปลของลูกค้า และ Microsoft มีการปรับปรุงซอฟต์แวร์การแปลด้วยคอมพิวเตอร์อยู่เป็นประจำ
ต่อไปนี้เป็นฉบับภาษาอังกฤษของบทความนี้:320602

ให้ข้อเสนอแนะ

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com