Tema: Firmar XML
Ver Mensaje Individual
  #4  
Antiguo 02-11-2016
gaunmanuel gaunmanuel is offline
Miembro
 
Registrado: may 2015
Posts: 48
Reputación: 0
gaunmanuel Va por buen camino
Import Type Library

Hola, sabes al importar la DLL a Delphi 7.0, me marco error: Error Type Library/DLL.
que me habrá faltado?

Código:
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Net;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace INtradeHTTPLib
{
    [ComVisible(true)]
    [Guid("6f7755dd-227c-4d8f-b38b-2a2e994cdc8e")]
    public class TINtradeHTTP
    {

        public String Consulta(string url, string folio, string rfc)
        {
            using (var client = new WebClient())
            {
                var values = new NameValueCollection();
                values["folio"] = folio;
                values["rfc"] = rfc;
                var response = client.UploadValues(url, values);
                var responseString = Encoding.Default.GetString(response);
                return responseString;

            }
        }
    }
}

Cita:
Empezado por Al González Ver Mensaje
Hola johan.

Estando lejos de ser un experto en estas cosas, para la parte de la firma digital te sugiero echar un vistazo a este par de enlaces y valorar las recomendaciones que ahí se dan:

http://www.clubdelphi.com/foros/showthread.php?t=61897

http://www.clubdelphi.com/foros/show...376#post416376

Por si decides usar "COM Interop", dejo aquí el código que escribí cuando necesité hacer algo muy parecido a lo que buscas (también en Delphi 7):

Código:
/* FirmaXML 1.0
   Ensamblaje .NET para permitir el firmado XMLDSig de un documento fiscal mexicano de formato XML.
   DLL compilada con la versión de prueba de Visual Studio. */

using System;
using System.IO;
using System.Xml;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography.Xml;

namespace FirmaXML
{
  /* Permitimos que esta clase pueda ser exportada como interfaz COM, para ser utilizada en 
     entornos no .NET también. */
  [ComVisible (true)]
  [Guid ("4EA3AB36-9DD1-42C5-B57A-D0F89DC4711B")]

  public class FirmaXML
  {
    public string Firmar (string XML, string RFC)
    {
      /* Método que recibe el texto de un documento XML y regresa ese mismo texto pero conteniendo 
         una firma digital XMLDSig envolvente.
       
         Parámetro XML: Texto del documento a firmar.
         Parámetro RFC: RFC del contribuyente cuyo certificado se usará para la firma. */

      // Obtenemos el certificado correspondiente al RFC dado
      X509Certificate2 Certificado = BuscarCertificado (RFC);

      // Obtenemos el objeto de llave privada del certificado
      RSACryptoServiceProvider Llave = Certificado.PrivateKey as RSACryptoServiceProvider;

      // Creamos el objeto firmante (Firma) asignándole el texto XML y la llave del certificado
      XmlDocument Documento = new XmlDocument ();
      Documento.LoadXml (XML);
      SignedXml Firma = new SignedXml (Documento);
      Firma.SigningKey = Llave;
      
      /* Creamos el nodo <Reference> con un subnodo <Transforms> conteniendo el elemento
         <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />, y lo
         agregamos al objeto firmante */
      Reference Referencia = new Reference ();
      Referencia.Uri = "";  // Tomar ("digerir") todo el documento al crear la firma
      Referencia.AddTransform (new XmlDsigEnvelopedSignatureTransform ());
      Firma.AddReference (Referencia);

      /* Creamos el nodo <KeyInfo> con el subnodo <X509Data>, poniendo dentro de éste el 
         certificado, su número de serie y la entidad emisora del mismo (primero estos dos últimos
         como subnodo <X509IssuerSerial>), y agregando todo al objeto firmante. */
      KeyInfoX509Data NodoX509Data = new KeyInfoX509Data ();
      NodoX509Data.AddIssuerSerial (Certificado.Issuer, Certificado.GetSerialNumberString ());
      NodoX509Data.AddCertificate (Certificado);
      Firma.KeyInfo = new KeyInfo ();
      Firma.KeyInfo.AddClause (NodoX509Data);
      
      // Generamos la firma digital y la agregamos al objeto Documento
      Firma.ComputeSignature ();
      Documento.DocumentElement.AppendChild (Documento.ImportNode (Firma.GetXml (), true));

      // Devolvemos el XML firmado
      return Documento.OuterXml;
    }

    protected static X509Certificate2 BuscarCertificado (string RFC)
    {
      // Método para obtener el certificado que pertenece a un RFC

      // Cargamos la lista de certificados personales instalados en Windows
      X509Store Certificados = new X509Store (StoreName.My, StoreLocation.CurrentUser);
      Certificados.Open (OpenFlags.ReadOnly);

      // Buscamos el certificado del contribuyente
      foreach (X509Certificate2 Resultado in Certificados.Certificates)
        /* El sujeto (propiedad Subject) del certificado puede contener algo como:
           "OU=Unidad 1, SERIALNUMBER=" / AAAA010101HDFRXX01", " (continúa)
           "OID.2.5.4.45=AAA010101AAA / AAAA010101AAA, O=Matriz SA, " (continúa)
           "OID.2.5.4.41=Matriz SA, CN=Matriz SA" 
          
           "AAA010101AAA / AAAA010101AAA" son el RFC del contribuyente (persona moral o física) y,
           opcionalmente, el RFC de la persona física que representa a la persona moral 
           (posiblemente).  El primero es el que nos interesa y debe ser igual al parámetro RFC para
           dar por encontrado el certificado. 
         
           Revisaremos cada par "llave=valor" del sujeto.  NOTA: Puede que convenga robustecer el
           código de este ciclo anidado. */
        foreach (string Dato in Resultado.Subject.Split (','))
        {
          string[] LlaveValor = Dato.Trim().Split ('=');
          
          if ((LlaveValor.Length == 2) && LlaveValor [0].EndsWith ("2.5.4.45") && 
          (LlaveValor [1].Split ('/') [0].Trim () == RFC))
            return Resultado;  // Encontrado
        }

      throw new Exception ("No hay un certificado instalado para el RFC que se indicó.");
    }
  }
}
Lo probé de la siguiente manera en Delphi:
Código Delphi [-]
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, xmldom, XMLIntf, msxmldom, XMLDoc;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Doc: TXMLDocument;
    mm1: TMemo;
    mm2: TMemo;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

Uses
  { Unidad generada con la opción "Project | Import Type Library..." (para
    obtener acceso a la DLL creada en .NET) }
  FirmaXML_TLB;

procedure TForm1.FormCreate(Sender: TObject);
begin
  // Abrimos el documento XML señalado con la propiedad FileName
  Doc.Active := True;
  
  mm1.Text := Doc.XML.Text;
end;

procedure TForm1.Button1Click(Sender: TObject);
Var
  Firma :Variant;
  Resultado :String;
begin
  // Creamos el objeto firmante
  Firma := CoFirmaXML_.Create;

  { Firmamos el contenido XML con el certificado instalado del
    contribuyente AAA010101AAA (RFC) } 
  Resultado := Firma.Firmar (Doc.XML.Text, 'AAA010101AAA');

  { El resultado lo asignamos nuevamente al documento, pero con
    codificación UTF-8 para que no tenga problemas con los diacríticos
    (acentos, tildes y diéresis), además de darle formato visible
    "estructural" (saltos de línea y sangrado) para facilitar su lectura
    humana. }
  Doc.XML.Text := FormatXMLData (AnsiToUTF8 (Resultado));

  // Guardamos el documento resultante
  Doc.Active := True;
  Doc.SaveToFile ('XMLCancelacionResultado.xml');

  { Mostramos en pantalla el docmento firmado }
  mm2.Text := FormatXMLData (Resultado);
end;

end.

Lo mejor de todo es que funcionó, quedándome con una grata impresión de las bibliotecas nativas de .NET (lástima que su lenguaje puntero sea un derivado de C ).

Ojalá pueda servirte como base a ti o alguien más.

Saludos.

Al González.
Responder Con Cita