Firmar facturae

Re: Firmar facturae

Postby Xevi » Mon Jan 28, 2019 12:09 pm

Bien, poniendo a funcionar la firma electrónica de facturas, ahora me encuentro con un problema en algun certificado...

Si consulto los alias de certificados en mi almacén desde cmd...

AutofirmaCommandLine.exe listaliases -store windows
...
INFO: Solicitando los alias al KeyStore (SunMSCAPI version 9)
40123456X NOMBRE Y APELLIDOS (R: B12123123)
Disp. software de seguridad:50123456X NOMBRE2 Y APELLIDOS2 (R: B12123123)?s FNMT-RCM I
...

me devuelve los dos "alias" de los certificados que tengo instalados...
Bien, pues el segundo no se porqué narices me saca que es software de seguridad...
Por mas que he provado combinaciones (solo con el nombre, nombre y contenido entre parentesis), TODO el texto. Pues nada, que no reconoce ese "nombre" como certificado instalado.

Alguien le puede haber surgido este problema???

Lo he probado de hacer firmar con el programa Autofirma y si que lo firma correctamente, pero con el comando AutofirmaCommandLine, no hay manera de que me "pille" esa firma.

¿?¿?

Gracias por vuestro tiempo!!!
Un Saludo,
Xevi.

Aprendiz de la vida!!!
User avatar
Xevi
 
Posts: 169
Joined: Wed Nov 29, 2017 11:42 am
Location: Girona

Re: Firmar facturae

Postby darioflores » Mon Jan 28, 2019 12:41 pm

Buenas, os pongo de nuevo el código con la corrección de pulsar cancelar en el diálogo.
Ahora devuelve una cadena vacía al pulsar cancelar:

Code: Select all  Expand view

#include "fivewin.ch"


func main()


   MsgInfo("Seleccionado certificado: "+ToTxt(SELCERT()), "CryptoApi")



return nil

//*****************************************************************************
//*****************************************************************************

function ToTxt( uVal )

   local cType := ValType( uVal )

   do case
      case cType == "C" .or. cType == "M"
           return uVal

      case cType == "D"
           return DToC( uVal )

      case cType == "L"
           return If( uVal, ".T.", ".F." )

      case cType == "N"
           return AllTrim( Str( uVal ) )

      case cType == "B"
           return "{|| ... }"

      case cType == "A"
           return "{ ... }"

      case cType == "O"
           return If( __ObjHasData( uVal, "cClassName" ), uVal:cClassName, uVal:ClassName() )

      case cType == "H"
           return "{=>}"

      otherwise
           return ""
   endcase

return nil

//*****************************************************************************
//*****************************************************************************

#pragma BEGINDUMP

#include <windows.h>
//#include <psapi.h>
//#include <hbapi.h>
//#include <hbapierr.h>
//#include <hbapiitm.h>
//#include <wincrypt.h>

#define CRYPTUI_SELECT_LOCATION_COLUMN 0x000000010

//Definir el prototipo de las funciones:
typedef HCERTSTORE (WINAPI * PTYPECERTOPEN) (HCRYPTPROV, LPTSTR);
typedef PCCERT_CONTEXT (WINAPI * PTYPECERTSELECTDLG) (HCERTSTORE, HWND, LPCWSTR, LPCWSTR, DWORD, DWORD, void*);
typedef PCCERT_CONTEXT (WINAPI * PTYPECERTENUM) (HCERTSTORE, PCCERT_CONTEXT);
typedef DWORD (WINAPI * PTYPECERTGETNAME) (PCCERT_CONTEXT, DWORD, DWORD, VOID*, LPTSTR, DWORD);
typedef DWORD (WINAPI * PTYPECERTNAMETOSTR) (DWORD, PCERT_NAME_BLOB, DWORD, LPTSTR, DWORD);
typedef BOOL (WINAPI * PTYPECERTFREECC) (PCCERT_CONTEXT);
typedef BOOL (WINAPI * PTYPECERTCLOSESTORE) (HCERTSTORE, DWORD);

HB_FUNC(SELCERT)
{

   // Hay varios ejemplos en: https://msdn.microsoft.com/en-us/librar ... 61(v=vs.85).aspx

   HCERTSTORE hStore;
   PCCERT_CONTEXT PrevContext, CurContext;
   PCHAR sNombre;
   DWORD cbSize;
   PHB_ITEM pArray;
   PHB_ITEM pItem;
   PCCERT_CONTEXT   pCertContext;
   // Cargamos las librerías de las que queremos la dirección de las funciones.
   HMODULE HCrypt = LoadLibrary("Crypt32.dll");
   HMODULE HCrypt2 = LoadLibrary("Cryptui.dll");

   // Declaramos el tipo de puntero a la función, tenemos la definición arriba.
   PTYPECERTOPEN    pCertOpen;
   PTYPECERTSELECTDLG    pCertSelectDlg;
   PTYPECERTGETNAME pCertGetName;
   PTYPECERTNAMETOSTR pCertNameToStr;
   PTYPECERTFREECC pCertFreeCC;
   PTYPECERTCLOSESTORE pCertCloseStore;


   if (HCrypt != NULL && HCrypt2 != NULL){
      //Sacamos el puntero todas las funciones que vamos a usar mediante GetProcAddress:
      #ifdef UNICODE
         pCertOpen    = (PTYPECERTOPEN) GetProcAddress(HCrypt, "CertOpenSystemStoreW");
         pCertGetName = (PTYPECERTGETNAME) GetProcAddress(HCrypt, "CertGetNameStringW");
      #else
         pCertOpen    = (PTYPECERTOPEN) GetProcAddress(HCrypt, "CertOpenSystemStoreA");
         pCertGetName = (PTYPECERTGETNAME) GetProcAddress(HCrypt, "CertGetNameStringA");
      #endif
      pCertSelectDlg = (PTYPECERTSELECTDLG) GetProcAddress(HCrypt2, "CryptUIDlgSelectCertificateFromStore");
      pCertFreeCC  = (PTYPECERTFREECC) GetProcAddress(HCrypt, "CertFreeCertificateContext");
      pCertCloseStore  = (PTYPECERTCLOSESTORE) GetProcAddress(HCrypt, "CertCloseStore");
   }

   if (pCertOpen){
      // Llamada a CertOpenSystemStore:
      hStore = pCertOpen(NULL, TEXT("MY"));
   }

   if (hStore){
      pCertContext = pCertSelectDlg(hStore, NULL, NULL, NULL, CRYPTUI_SELECT_LOCATION_COLUMN, 0, NULL);

      if (pCertContext!=NULL){
         cbSize = pCertGetName(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, NULL, 0);
         if (cbSize>0) {
            //Reservamos la memoria que necesitamos para el texto que recibiremos
            sNombre = (LPTSTR)malloc(cbSize * sizeof(TCHAR));

            pCertGetName(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, sNombre, cbSize);


            // Llamada a CertFreeCertificateContext:
            pCertFreeCC(pCertContext);
         }
      } else {
         sNombre = "";
      }

      // Cerrar el almacen de certificados:
      // Llamada a CertCloseStore:
      pCertCloseStore(hStore, 0);
    }

    FreeLibrary(HCrypt);
    FreeLibrary(HCrypt2);

    hb_retc(sNombre);

}

#pragma ENDDUMP
 


Aunque funciona, el código dista mucho de ser perfecto, hay muchas comprobaciones que no se hacen o que se hacen y no terminan la ejecución. Además, el diálogo muestra todos los certificados, no solo los que tengan una clave privada, etc.
Pero vamos, para el uso que le vais a dar, funciona.


Por cierto, ya que estamos con el tema de facturae, si alguien tiene alguna clase que encapsule la generación del XML de la factura, se lo agradecería.

Un saludo.
darioflores
 
Posts: 17
Joined: Tue Oct 06, 2015 7:06 am

Re: Firmar facturae

Postby Xevi » Wed Jan 30, 2019 8:56 pm

Siguiendo con el tema de selección de certificado para procesar la firma seguidamente con AutofirmaCommandLine...

He localizado el error (o el porqué) que no me deja proceder a la firma con ese certificado.
Por lo visto, ese certificado tiene el campo "Nombre descriptivo" relleno, y es precisamente por ese motivo que no me deja utilizarlo luego.
O sea, SI UN CERTIFICADO tiene el campo "Nombre descriptivo" relleno (no vacio), no deja utilizar el certificado.

Igual es por algun parámetro que no lo estoy utilizando correctamente en el AutofirmaCommandLine,
Pero...
Yo lo que he hecho es eliminar el contenido de ese campo en ese certificado... y ahora ya SI me funciona correctamente.

No se si a alguien le puede suceder lo mismo que a mi, pero aquí lo dejo, por si acaso!!!
Es una solución.

Gracias por vuestro tiempo.
Un Saludo,
Xevi.

Aprendiz de la vida!!!
User avatar
Xevi
 
Posts: 169
Joined: Wed Nov 29, 2017 11:42 am
Location: Girona

Re: Firmar facturae

Postby AngelSalom » Thu Jan 31, 2019 7:25 am

Gracias Xevi, no se me ha dado el caso ... aún ;-) Es bueno saberlo.
Angel Salom
Visionwin Software - https://www.visionwin.com
------------------------------------------------------------
fwh 19.05 - harbour 3.2 - bcc 7.4
User avatar
AngelSalom
 
Posts: 708
Joined: Fri Oct 07, 2005 7:38 am
Location: Benicarló (Castellón ) - España

Re: Firmar facturae

Postby cwanderlei_cardoso » Thu Sep 28, 2023 11:54 am

Olá Dario, você tem as funções para assinar um XML com o certificado?

Aqui no Brasil eu uso o CAPICOM para usar o Certificado Digital, mais eu gostaria de usar os recursos da WinCrypt para pegar o certificado e assinar o XML.

Alguém do Fórum pode me ajudar?
cwanderlei_cardoso
 
Posts: 5
Joined: Mon May 20, 2019 3:49 pm

Re: Firmar facturae

Postby acuellar » Thu Sep 28, 2023 12:16 pm

Estimado cwanderlei_cardoso

Intenta con Chilkat
https://www.example-code.com/foxpro/xmldsig.asp
Saludos,

Adhemar C.
User avatar
acuellar
 
Posts: 1593
Joined: Tue Oct 28, 2008 6:26 pm
Location: Santa Cruz-Bolivia

Re: Firmar facturae

Postby cwanderlei_cardoso » Thu Sep 28, 2023 6:45 pm

Obrigado Adhemar,
Mais quero utilizar o wincrypt do windows para não ter de instalar nada, usar de forma nativa.

Hoje eu utilizo a dll do Capicom para assinar os XML de notas fiscais.
cwanderlei_cardoso
 
Posts: 5
Joined: Mon May 20, 2019 3:49 pm

Previous

Return to FiveWin para Harbour/xHarbour

Who is online

Users browsing this forum: No registered users and 65 guests