Usar o WinCrypt para Nf-e com xHarbour/Harbour

Projeto [x]Harbour - Compilador de código aberto compatível com o Clipper.

Moderador: Moderadores

Avatar do usuário
Wanderlei
Usuário Nível 3
Usuário Nível 3
Mensagens: 196
Registrado em: 25 Jan 2008 13:19
Localização: Goiânia - GO

Usar o WinCrypt para Nf-e com xHarbour/Harbour

Mensagem por Wanderlei »

Olá Pessoal,
Alguém do fórum já conseguiu utilizar o WinCrypt no lugar da Capicom para assinar e autorizar a NF-e?
Wanderlei Cardoso
Analista / Programador
XHarbour + GtWvW + FiveWin + HwGui + Firebird
Skype: cwanderlei
cwanderlei@yahoo.com.br
(62)98171-3059 - whatsapp

Imagem
Avatar do usuário
sygecom
Administrador
Administrador
Mensagens: 7131
Registrado em: 21 Jul 2006 10:12
Localização: Alvorada-RS
Contato:

Usar o WinCrypt para Nf-e com xHarbour/Harbour

Mensagem por sygecom »

Temos algumas referências para pegar no MSDN da Microsoft
https://learn.microsoft.com/en-us/windo ... efromstore

Para selecionar o certificado (peguei esse exemplo no https://forums.fivetechsupport.com/ )

Código: Selecionar todos

#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(SELECIONA_CERTIFICADO)
{

   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");  // abre a janela pra selecionar o certificado
      pCertFreeCC  = (PTYPECERTFREECC) GetProcAddress(HCrypt, "CertFreeCertificateContext");
      pCertCloseStore  = (PTYPECERTCLOSESTORE) GetProcAddress(HCrypt, "CertCloseStore");
   }

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

   if (hStore){
      // Diálogo de selección de certificado:
      pCertContext = pCertSelectDlg(hStore, NULL, NULL, NULL, CRYPTUI_SELECT_LOCATION_COLUMN, 0, NULL);

      if (pCertContext){
         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);
         }
      }

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

    FreeLibrary(HCrypt);
    FreeLibrary(HCrypt2);

    hb_retc(sNombre);

}
#pragma ENDDUMP
Mas ainda não consegui assinar
Leonardo Machado
xHarbour.org + Hwgui + PostgreSql
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Usar o WinCrypt para Nf-e com xHarbour/Harbour

Mensagem por JoséQuintas »

Wanderlei escreveu:Alguém do fórum já conseguiu utilizar o WinCrypt no lugar da Capicom para assinar e autorizar a NF-e?
Se capicom existe, e funciona, não tem motivo pra procurar alternativa.
Na prática, capicom são rotinas pra acessar a API do Windows de forma mais fácil.
Sendo assim, é de se imaginar que daria pra fazer sem a capicom.

NÃO SEI os detalhes, apenas por procurar muito sobre isso, vi algumas coisas:

Tem lá o XML.

1) Existe um padrão de formatação do XML, nem sempre o que vemos é o que vai ser assinado

2) São extraídas informações do XML pro processo.

3) ë calculado o hash encima do item 1, acho que nisso entra alguma definição de CODEPAGE

4) A assinatura seria o cálculo encima do hash, utilizando a chave particular

Pra testar a assinatura, teria que ter algum modelo referência de cada etapa, qualquer diferença nos processos não vai ter a mesma assinatura.
De repente até encontramos a forma de assinar correta, mas se o processo todo não estiver correto, a assinatura não vai bater.

Precisaríamos:
Pro item 1, ter um exemplo do que acontece na formatação
Pro item 2, ter um exemplo do que é extraído
Pro item 3, o cálculo do hash
Pro item 4, talvez um hash com assinatura, e fazer igual.

Outra opção seria usar o NET FRAMEWORK, presente em todas as versões do Windows.

Em NET FRAMEWORK existe a possibilidade de criar um componente COM, que significa usar funções do NET FRAMEWORK como se fossem funções normais de API Windows, como se fosse a CAPICOM por exemplo.
Pelo menos pra Windows seria uma alternativa.
Não sei se o framework pra linux facilita ou não isso daí.

Atualmente não se trata apenas de CAPICOM, mas de CAPICOM + MSXML5
Capicom faz a parte de assinatura, e MSXML5 faz as outras partes.
Lembrando que no Windows saíram as DLLs versões 2, 3, 4 e 6, mas MSXML5 só saiu como parte do office.

Outra possibilidade é manter uma máquina pra fazer isso, de forma remota, no caso de uma emergência até solução melhor.
Ou contratar serviço de terceiros, o governo é especialista em permitir terceiros em tudo.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Responder