Página 1 de 1

Usar o WinCrypt para Nf-e com xHarbour/Harbour

Enviado: 27 Set 2023 13:25
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?

Usar o WinCrypt para Nf-e com xHarbour/Harbour

Enviado: 11 Jan 2024 10:13
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

Usar o WinCrypt para Nf-e com xHarbour/Harbour

Enviado: 11 Jan 2024 17:34
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.