Como usar certificados para assinar e verificar SignedXml objetos usando o Visual translation from VPE for Csharp .NET

IMPORTANTE: Este artigo foi traduzido por um sistema de tradução automática (também designado por Machine Translation ou MT), não tendo sido portanto traduzido ou revisto por pessoas. A Microsoft possui artigos traduzidos por aplicações (MT) e artigos traduzidos por tradutores profissionais, com o objetivo de oferecer em português a totalidade dos artigos existentes na base de dados de suporte. No entanto, a tradução automática não é sempre perfeita, podendo conter erros de vocabulário, sintaxe ou gramática. A Microsoft não é responsável por incoerências, erros ou prejuízos ocorridos em decorrência da utilização dos artigos MT por parte dos nossos clientes. A Microsoft realiza atualizações freqüentes ao software de tradução automática (MT). Obrigado.

Clique aqui para ver a versão em Inglês deste artigo: 320602
Este artigo foi arquivado. É oferecido "como está" e não será mais atualizado.
Sumário
Este artigo passo a passo descreve como usar certificados para assinar e verificar SignedXml objetos. O artigo descreve como usar a plataforma chamar serviços no Visual Basic .NET para chamar funções da API Win32 para acessar certificados em armazenamentos de certificados e anexar suas chaves a SignedXml objetos para assinar e verificar os objetos. O artigo também descreve como usar a plataforma chamar serviços para chamar funções de API do Win32 para extrair a chave pública de um objeto X509Certificate .

Este artigo se refere a funções da API do Win32 como "funções".

back to the top

Requisitos

Este artigo presume que você esteja familiarizado com programação com o Microsoft Visual translation from VPE for Csharp. NET.

A lista a seguir descreve o hardware recomendado, software, infra-estrutura de rede e service packs que você precisa:
  • Microsoft Windows XP ou Microsoft Windows 2000
  • Microsoft Visual Studio .NET
back to the top
Mais Informações

Enumerar os certificados

Os pontos a seguir descrevem as partes principais do código de exemplo que segue.
  • Chamar a função CertOpenSystemStore para obter um identificador para o armazenamento certificado pessoal. do usuário
    uint hCertStore = Crypt32.CertOpenSystemStore(0, "My");
  • Chamar a função CertEnumCertificatesInStore para obter ponteiros de contexto de certificado para certificados.
    while (0 != (pCertContext = Crypt32.CertEnumCertificatesInStore(hCertStore, (uint)pCertContext)))
  • Criar um objeto X509Certificate a partir de um certificado contexto ponteiro.
    X509Certificate x509 = new X509Certificate((IntPtr)pCertContext);
  • Chamada a função CertDuplicateCertificateContext para incrementar a referência contar com o ponteiro de contexto de certificado para que você possa usar esse valor mais tarde.
    CertDuplicateCertificateContext((IntPtr)pCertContext);
Você pode usar o código a seguir para enumerar os certificados.

Para resumir o código, você enumerar os certificados no armazenamento de "My" certificados, preencher um controle ListView com os nomes de assunto e emissor de cada certificado e anexar um ponteiro de contexto de certificado a propriedade de marca de cada item de ListView .
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); } }
back to the top

Assinar um objeto SignedXml usando um certificado

  1. Para fazer as seguintes tarefas, chame a função CertGetCertificateContextProperty :
    • Para consultar o nome do provedor de serviços de criptografia.
    • Para consultar o tipo de provedor de serviços de criptografia.
    • Para consultar o nome de recipiente de chave que está associado a um contexto de certificado específico.
    • Para compactar essas informações em um objeto 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. Importar o nome do provedor, o tipo de provedor e as informações de recipiente de chave no objeto RSACryptoServiceProvider para um objeto System.Security.Cryptography.RSA .
    RSA key = RSA.Create();key.ImportParameters(rsacsp.ExportParameters(true));
  3. Anexar o objeto System.Security.Cryptography.RSA ao objeto SignedXml e, em seguida, calcular a assinatura.
    signedXml.SigningKey = key;signedXml.ComputeSignature();
back to the top

Verificar um objeto SignedXml usando um certificado

  1. Extrair o expoente e o resto de um X509Certificate objeto e compactar o expoente e o módulo em um RSACryptoServiceProvider object.
    /// <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. Para verificar a assinatura, passar RSACryptoServiceProvider objeto que contém a chave pública X509Certificate para o método CheckSignature do objeto SignedXml .
    if (signedXml.CheckSignature(rsa)) MessageBox.Show ("The signature has been validated.");else MessageBox.Show ("The signature has NOT been validated.");
back to the top

Código de exemplo passo a passo

  1. Inicie o Visual Studio NET..
  2. No menu arquivo , aponte para novo e, em seguida, clique em Project .
  3. Em Project Types , clique em projetos translation from VPE for Csharp Visual .
  4. Em modelos , clique em Windows Application e em seguida, clique em OK .
  5. No menu Project , clique em Adicionar referência .
  6. Na guia .NET da caixa de diálogo Add Reference , clique em System.Security e clique em Selecionar.
  7. Clique em OK para fechar o Adicionar referência caixa de diálogo.
  8. Substitua o código existente no arquivo Form1.cs com o código de exemplo que está incluído no final desta seção.
  9. No menu Debug , clique em Iniciar . Por padrão, o formulário de Form1 aparece.
  10. No Form1 , clique em EnumCert .

    Todos os certificados em seu computador estão listados na caixa que está localizada acima do botão EnumCert .
  11. Na caixa que está acima do botão EnumCert , execute estas etapas:
    1. Para assinar um objeto SignedXml usando o certificado selecionado, selecione um certificado de assinatura de código e, em seguida, clique em entrar .
    2. Para verificar um objeto SignedXml usando o certificado selecionado, selecione um certificado de assinatura de código e, em seguida, clique em Verificar .

Código para a etapa 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);   }}
back to the top

Solução de problemas

Usar código somente certificados de assinatura para assinar um SignedXml objeto. Se você não usar certificados de assinatura de código, poderão ocorrer exceções.

back to the top
Referências
Para obter mais informações, visite os seguintes sites do Microsoft Developer Network (MSDN) da:
Gerenciando um armazenamento de certificado estado http://msdn.microsoft.com/en-us/library/aa919752.aspx

EncryptTo/DecryptTo: Criptografia no .NET com certificados de CryptoAPI armazena http://msdn.microsoft.com/en-us/library/ms867080.aspx
back to the top

Aviso: este artigo foi traduzido automaticamente

Propriedades

ID do Artigo: 320602 - Última Revisão: 12/07/2015 10:26:12 - Revisão: 1.2

Bibliotecas de Classes do Microsoft .NET Framework 1.1, Microsoft Visual C# .NET 2003 Standard Edition, Microsoft Visual C# .NET 2002 Standard Edition

  • kbnosurvey kbarchive kbmt kbuser kbhowtomaster kbsecurity KB320602 KbMtpt
Comentários