Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > Varios
Registrarse FAQ Miembros Calendario Guía de estilo Buscar Temas de Hoy Marcar Foros Como Leídos

Grupo de Teaming del ClubDelphi

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 26-02-2012
johan johan is offline
Miembro
 
Registrado: may 2006
Posts: 38
Poder: 0
johan Va por buen camino
Firmar XML

Me han pedido poder firmar un fichero xml en formato PKCS#7, alguien tiene un pequeño ejemplo y como tratarlo desde D7 o donde puedo obtener mas información.
Ese fichero lo tendria que enviar a traves de un ws, pero con ese cifrado.

Gracias.
Responder Con Cita
  #2  
Antiguo 26-02-2012
Avatar de Al González
[Al González] Al González is offline
In .pas since 1991
 
Registrado: may 2003
Posts: 5.604
Poder: 29
Al González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en bruto
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
  #3  
Antiguo 02-04-2015
frankizzio frankizzio is offline
Miembro
NULL
 
Registrado: abr 2013
Posts: 10
Poder: 0
frankizzio Va por buen camino
Muchas gracias, estuve buscando información y felizmente utilizar una dll de .NET funcionó, pero tengo un inconveniente, a mi me piden firmar en una zona especifica del documento.

Además que utilizo un archivo .pfx para realizar la firma.

Como puedo indicarle que etiqueta es la que debe firmar, además de agregarle prefijos a la firma?
Responder Con Cita
  #4  
Antiguo 03-11-2016
gaunmanuel gaunmanuel is offline
Miembro
 
Registrado: may 2015
Posts: 48
Poder: 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
  #5  
Antiguo 20-03-2018
clauxs88 clauxs88 is offline
Miembro
 
Registrado: feb 2013
Ubicación: Asuncion
Posts: 11
Poder: 0
clauxs88 Va por buen camino
Tendrian la DLL para pasarmela??

Favor si tienen la DLL para pasarmela e mportarla.
Responder Con Cita
Respuesta


Herramientas Buscar en Tema
Buscar en Tema:

Búsqueda Avanzada
Desplegado

Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Firmar xml digitalmente. BuenaOnda Varios 2 21-10-2010 12:13:46
Firmar PDF keys Varios 1 06-05-2010 11:11:37
Firmar archivos XML chipsoni Seguridad 4 27-11-2008 12:53:37
Firmar PDF j_fdez Varios 1 02-04-2008 16:16:18
firmar ActiveX coulthard Internet 0 22-01-2005 19:58:55


La franja horaria es GMT +2. Ahora son las 16:46:24.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi