Assinar texto/arquivo com certificado digital pelo windows

Aqui você poderá oferecer suas Contribuições, Dicas e Tutoriais (Texto ou Vídeo) que sejam de interesse de todos.

Moderador: Moderadores

Avatar do usuário
dbsh
Usuário Nível 3
Usuário Nível 3
Mensagens: 128
Registrado em: 14 Jul 2004 14:19
Localização: ES

Assinar texto/arquivo com certificado digital pelo windows

Mensagem por dbsh »

Gera DigestValue, SignatureValue, X509 para incluir em XML
DigestValue = Hash SHA256/SHA512, entre outros
SignatureValue = DigestValue assinado

Assina texto/arquivo digitalmente

Código: Selecionar todos

#pragma /es3
#pragma /w3

#define __TESTE__

//xp, window vista, 2003 server ou posterior
//Capicom.dll - Capicom 2.0 - Capicom.h

#define CAPICOM_HASH_ALGORITHM_SHA1     0
#define CAPICOM_HASH_ALGORITHM_MD2      1
#define CAPICOM_HASH_ALGORITHM_MD4      2
#define CAPICOM_HASH_ALGORITHM_MD5      3
#define CAPICOM_HASH_ALGORITHM_SHA_256  4
#define CAPICOM_HASH_ALGORITHM_SHA_384  5
#define CAPICOM_HASH_ALGORITHM_SHA_512  6

#define CAPICOM_ENCRYPTION_ALGORITHM_RC2  0
#define CAPICOM_ENCRYPTION_ALGORITHM_RC4  1
#define CAPICOM_ENCRYPTION_ALGORITHM_DES  2
#define CAPICOM_ENCRYPTION_ALGORITHM_3DES 3
#define CAPICOM_ENCRYPTION_ALGORITHM_AES  4 // v2.0

#define CAPICOM_ENCRYPTION_KEY_LENGTH_MAXIMUM  0 
#define CAPICOM_ENCRYPTION_KEY_LENGTH_40_BITS  1 
#define CAPICOM_ENCRYPTION_KEY_LENGTH_56_BITS  2 
#define CAPICOM_ENCRYPTION_KEY_LENGTH_128_BITS 3 
#define CAPICOM_ENCRYPTION_KEY_LENGTH_192_BITS 4 // AES v2.0 
#define CAPICOM_ENCRYPTION_KEY_LENGTH_256_BITS 5 // AES v2.0 

#define CAPICOM_ENCODE_ANY    0xffffffff 
#define CAPICOM_ENCODE_BASE64 0 
#define CAPICOM_ENCODE_BINARY 1 

#define CAPICOM_CERTIFICATE_INCLUDE_CHAIN_EXCEPT_ROOT 0
#define CAPICOM_CERTIFICATE_INCLUDE_WHOLE_CHAIN       1
#define CAPICOM_CERTIFICATE_INCLUDE_END_ENTITY_ONLY   2

#define CAPICOM_LOCAL_MACHINE_STORE          1
#define CAPICOM_CURRENT_USER_STORE           2
#define CAPICOM_STORE_OPEN_READ_ONLY         0
#define CAPICOM_STORE_OPEN_READ_WRITE        1
#define CAPICOM_STORE_OPEN_MAXIMUM_ALLOWED   2
#define CAPICOM_CERTIFICATE_FIND_SHA1_HASH   0
#define CAPICOM_AUTHENTICATED_ATTRIBUTE_SIGNING_TIME 0

#define CAPICOM_VERIFY_SIGNATURE_ONLY 0

#ifdef __TESTE__
PROCEDURE TesteCapicom
LOCAL sTexto, aAss, sCript, sDescript, DigestValue, SignatureValue, x509

sTexto         := "texto a ser gerado hash, no caso de arquivo, carregue o arquivo e passe para esta funcao"

DigestValue    := HashCapicom( sTexto )
aAss           := SignatureCapicom( DigestValue )
SignatureValue := aAss[1]
X509           := aAss[2]

HB_SYMBOL_UNUSED( x509 )

?
? DigestValue == CHKSignatureCapicom( SignatureValue )
? IsValidSignatureCapicom( DigestValue, SignatureValue )

sCript    := CriptCapiCom( sTexto, DigestValue, 4, 5 )
sDescript := DescriptCapiCom( sCript, DigestValue, 4, 5 )

?
? sDescript == sTexto

//sCript    := criptCapiCom( sTexto, PafChavePrivada(), 4, 5 )
//sDescript := DescriptCapiCom( sCript, PafChavePublica(), 4, 5 )

?
? sDescript == sTexto

wait
RETURN
#endif


//Esta função só cria um hash da string passada como parâmetro
FUNCTION HashCapicom( sTexto, AlgoritimoHash  )
LOCAL objHash

IF sTexto = NIL
   sTexto := DToS(Date()) + Time()
ENDIF

IF AlgoritimoHash = NIL
   AlgoritimoHash := CAPICOM_HASH_ALGORITHM_SHA_256
ENDIF

objHash := CreateObject("CAPICOM.HashedData.1")
objHash:Algorithm := AlgoritimoHash
objHash:Hash( sTexto )

RETURN objHash:Value


//Esta função assina string passada como parâmetro
//DigestValue = Hash Gerado por HashCapicom
FUNCTION SignatureCapicom( DigestValue, Cert, Encode )
LOCAL SignedData, CertBase64, Signer, sRet, TimeAttrib

//System.Security.Cryptography.Pkcs

IF DigestValue = NIL
   RETURN NIL
ENDIF

IF Encode = NIL
   Encode := CAPICOM_ENCODE_BASE64
ENDIF

//Signer := CreateObject("CAPICOM.Signer.1")  //versao 1
Signer := CreateObject("CAPICOM.Signer.2")  //versao 2

IF Cert = NIL
   Cert := SelecionaCertificadoCapicom()
   IF Cert = NIL
      RETURN NIL
   ENDIF
   Signer:Certificate := cert
ELSE
   Signer:Certificate := cert:DefaultInterface
ENDIF

IF !(Signer:Certificate:HasPrivateKey ;
   .and. DToS(Signer:Certificate:ValidFromDate) <= DToS(Date()) ;
   .and. DToS(Signer:Certificate:ValidToDate) >= DToS(Date()) )
   RETURN NIL
ENDIF

Signer:Options := CAPICOM_CERTIFICATE_INCLUDE_CHAIN_EXCEPT_ROOT

//usado na chave <X509Certificate>
CertBase64 := Signer:Certificate:Export(CAPICOM_ENCODE_BASE64)
CertBase64 := Trim(StrTran(certBase64, Chr(13) + Chr(10), ''))

TimeAttrib :=  CreateObject("CAPICOM.Attribute")
TimeAttrib:Name := CAPICOM_AUTHENTICATED_ATTRIBUTE_SIGNING_TIME
TimeAttrib:Value = DateTime()

Signer:AuthenticatedAttributes:Add(TimeAttrib)

SignedData := CreateObject("CAPICOM.SignedData.1")
SignedData:Content := DigestValue

//segundo parametro falso, apenas retona assinatura do texto, não inclui no texto
sRet := SignedData:Sign(Signer, .F., Encode)

RETURN {sRet, CertBase64}


//Esta função retorna Hash sem Assinatura
//sAss = Hash Assinada
FUNCTION CHKSignatureCapicom( sAss )
LOCAL SignedData

IF sAss = NIL
   RETURN NIL
ENDIF

SignedData := CreateObject("CAPICOM.SignedData.1")
SignedData:Verify( sAss, .F., CAPICOM_VERIFY_SIGNATURE_ONLY);

RETURN SignedData:Content


//Esta função Verifica se assinatura e valida
//DigestValue = Hash
//SignatureValue = Hash Assinada
FUNCTION IsValidSignatureCapicom( DigestValue, SignatureValue )

IF DigestValue = NIL .or. SignatureValue = NIL
   RETURN .F.
ENDIF

RETURN CHKSignatureCapicom( SignatureValue ) == DigestValue


//carrega certificado digital
FUNCTION SelecionaCertificadoCapicom()
LOCAL MyStore, Certificates

MyStore := CreateObject("CAPICOM.Store")
MyStore:Open(CAPICOM_CURRENT_USER_STORE, "My", CAPICOM_STORE_OPEN_READ_ONLY)

begin sequence with {|| Break() }
   Certificates := MyStore:Certificates:Select("Selecione um certificado digital","Algoritimo de Assinatura SHA256RSA")
recover
   RETURN NIL
end

IF MyStore:certificates:Count = 0
   RETURN NIL
ENDIF

RETURN certificates:Item(1)



010011110010000001110011011101010110001101100101011100110111001101101111001000001110100100100000011000110110111101101110011100110111010001110010011101011110110101100100011011110010000001100001001000000110111001101111011010010111010001100101
01001101011000010111001001100011011011110111001100100000010000010110111001110100011011110110111001101001011011110010000001000100011001010010000001000010011011110110111001101001
0101010001100101011011000011101000100000001010000011001000110111001010010011100100101101001110010011100000110100001100110010110100110101001100100011100100110000
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Assinar texto/arquivo com certificado digital pelo windows

Mensagem por JoséQuintas »

Legal.
Testar isso pra ver se bate com a assinatura que uso hoje.
Se isso eliminar a necessidade do MSXML5 vai ser bom.
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/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Assinar texto/arquivo com certificado digital pelo windows

Mensagem por JoséQuintas »

Ainda não comparei com a que uso pra assinar XML, mas coloquei na pasta de rascunhos (drafts) da Sefazclass.
Fonte modificado e usando classe.

https://github.com/JoseQuintas/sefazcla ... apicom.prg

Até aproveitei pra criar um CH completo da CAPICOM, com tudo que pude encontrar.
Pode ser útil pra qualquer fonte que use CAPICOM.

https://github.com/JoseQuintas/sefazcla ... capicom.ch

Lembrando que, como está na pasta da sefazclass, pra quem usar, basta indicar sefazclass.hbc (e mais o #include lógico)
Neste caso a indicação da sefazclass só vai servir pra indicar aonde encontrar o arquivo capicom.ch e nada mais.
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/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Assinar texto/arquivo com certificado digital pelo windows

Mensagem por JoséQuintas »

A propósito....
O Harbour tem funções de hash.
Caso dê certo, talvez dê pra fazer pelo Harbour, e só reste a assinatura mesmo.
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/
AlainSilva
Usuário Nível 1
Usuário Nível 1
Mensagens: 12
Registrado em: 04 Dez 2017 10:47
Localização: Rancharia/SP

Assinar texto/arquivo com certificado digital pelo windows

Mensagem por AlainSilva »

Ola bom dia, sou novo no fórum. Estou usando a classe e estou tendo o seguinte erro:
METHOD HashData( cData, nAlgorithm ) CLASS CapicomClass
LOCAL oCapicom
IF cData = NIL
cData := DToS( Date() ) + Time()
ENDIF
IF nAlgorithm = NIL
nAlgorithm := CAPICOM_HASH_ALGORITHM_SHA_256
ENDIF
oCapicom := CreateObject("CAPICOM.HashedData.1")
oCapicom:Algorithm := nAlgorithm
oCapicom:Hash( cData )
RETURN oCapicom:Value

Error occurred at: 04/12/2017, 08:50:26
   Error description: Error CAPICOM.HashedData.1/9  The HashedData object does not contain hashed value.
: _ALGORITHM
   Args:
     [   1] = N   4

Seria a versão da capicom.dll? Se for onde baixo essa dll?
Obrigado
Avatar do usuário
Daniel
Usuário Nível 3
Usuário Nível 3
Mensagens: 373
Registrado em: 13 Ago 2003 22:42
Localização: Apucarana - PR

Assinar texto/arquivo com certificado digital pelo windows

Mensagem por Daniel »

Daniel

Harbour + Minigui + dbfcdx
Marinas-Gui Pena que parou o suporte
AlainSilva
Usuário Nível 1
Usuário Nível 1
Mensagens: 12
Registrado em: 04 Dez 2017 10:47
Localização: Rancharia/SP

Assinar texto/arquivo com certificado digital pelo windows

Mensagem por AlainSilva »

Ola Daniel, não adiantou, atualizei, alias era a que eu já tinha, registrei e o erro continua.
Não aceita o oCapicom:Algorithm := nAlgorithm (nAlgorithm = 4 )
Error description: Error CAPICOM.HashedData.1/9 The specified encryption algorithm is invalid.
: _ALGORITHM
Args:
[ 1] = N 4
Avatar do usuário
Daniel
Usuário Nível 3
Usuário Nível 3
Mensagens: 373
Registrado em: 13 Ago 2003 22:42
Localização: Apucarana - PR

Assinar texto/arquivo com certificado digital pelo windows

Mensagem por Daniel »

você tem certeza que esta pegando a versão nova?
pelo cmd usa este comando na pasta raiz
dir /s capicom.dll
ele vai mostra onde as capicom.dll esta
Daniel

Harbour + Minigui + dbfcdx
Marinas-Gui Pena que parou o suporte
AlainSilva
Usuário Nível 1
Usuário Nível 1
Mensagens: 12
Registrado em: 04 Dez 2017 10:47
Localização: Rancharia/SP

Assinar texto/arquivo com certificado digital pelo windows

Mensagem por AlainSilva »

Sim Daniel, é a mesma que eu uso pra nfe. Registrei regsvr32 capicom
.DLL certinho. O detalhe é que estou utilizando o xbarbour e não o harbour. Será que pode ser isso? O sha1 vai de boa. Sha256 da pau.
Avatar do usuário
Daniel
Usuário Nível 3
Usuário Nível 3
Mensagens: 373
Registrado em: 13 Ago 2003 22:42
Localização: Apucarana - PR

Assinar texto/arquivo com certificado digital pelo windows

Mensagem por Daniel »

tem esta linha
#define CAPICOM_HASH_ALGORITHM_SHA_256 4
se tiver ai e erro no xHarbour
testei aqui deu certo

testa assim pra ver se da certo

Código: Selecionar todos

FUNCTION HashCapicom(stexto, AlgoritimoHash   )
	LOCAL objHash

	IF sTexto = NIL
	   sTexto := DToS(Date()) + Time()
	ENDIF

	IF AlgoritimoHash = NIL
	   AlgoritimoHash := 4
	ENDIF

	objHash := CreateObject("CAPICOM.HashedData.1")
	objHash:Algorithm := AlgoritimoHash
	objHash:Hash( sTexto )

	RETURN objHash:Value
Daniel

Harbour + Minigui + dbfcdx
Marinas-Gui Pena que parou o suporte
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Assinar texto/arquivo com certificado digital pelo windows

Mensagem por JoséQuintas »

Problema 1: dependendo da versão da CAPICOM, ela não tem o algorítmo SHA256

Problema 2: XHARBOUR, LIBs e BORLAND C

Por mais que se fale.... não adianta... volta sempre a mesma questão.

XHarbour... é interessante... mas não tem atualização, tem problemas.
LIBs... tentam consertar o XHarbour... cada uma faz de um jeito a mesma coisa...
Borland C... permite rotinas duplicadas no EXE... ou seja, nunca se sabe o que vai ser executado, pode ser a rotina certa, pode ser a rotina errada...

Tente num fonte em separado, antes de acrescentar ao aplicativo.
De preferência, CONSOLE, pra não precisar de nenhuma LIB Lixo.

Se assim funcionar, aí avise a LIB Lixo pra ser corrigida.
Avisar XHarbour não adianta... nunca mais vão corrigir nada nele....
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/
AlainSilva
Usuário Nível 1
Usuário Nível 1
Mensagens: 12
Registrado em: 04 Dez 2017 10:47
Localização: Rancharia/SP

Assinar texto/arquivo com certificado digital pelo windows

Mensagem por AlainSilva »

Bom dia, Daniel eu já tinha feito isso de passar o valor direto para a variável mas o erro persiste. Bom, primeiro acho que preciso saber se estou com a capicom correta.
Se possível tem como me enviar a capicom que tem o algoritimo sha256?
meu email: alainsilva73@gmail.com

Minha capicom: data: 11/04/2007 CAPICOM.DLL tam: 511.328 bytes


Agora se eu estiver a capicom correta e o problema for o xharbour não tem outra opção, vou ter que passar a usar o harbour.
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Assinar texto/arquivo com certificado digital pelo windows

Mensagem por JoséQuintas »

O que faço sempre é tentar fazer o programador usar a cabeça.
Não precisa acreditar no que escrevem, e também não adianta nada virar "copiador de fonte".

Isso não é nada do outro mundo, é relativamente simples.
MICROSOFT FORNECE ÚLTIMA CAPICOM.

uma rápida pesquisa no google sobre capicom e sha256:
capicom.png
O primeiro link aberto
capicom2.png
Uma pesquisa de capicom download
capicom3.png
Olhem só que interessante....
O KIT CAPICOM da Microsoft vém até com muitos exemplos.
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/
AlainSilva
Usuário Nível 1
Usuário Nível 1
Mensagens: 12
Registrado em: 04 Dez 2017 10:47
Localização: Rancharia/SP

Assinar texto/arquivo com certificado digital pelo windows

Mensagem por AlainSilva »

Obrigado pela ajuda, consegui rodar a rotina, vou fazer mais testes.
AlainSilva
Usuário Nível 1
Usuário Nível 1
Mensagens: 12
Registrado em: 04 Dez 2017 10:47
Localização: Rancharia/SP

Assinar texto/arquivo com certificado digital pelo windows

Mensagem por AlainSilva »

boa tarde, como eu já tenho as funções da nfe e do manifesto que utiliza sha1, estou fazendo os testes pra ver se assinatura fica igual.
Percebi o seguinte. O xml seria esse:
cTexto := '<envEvento xmlns="http://www.portalfiscal.inf.br/nfe" versao="1.00"><idLote>1</idLote><evento xmlns="http://www.portalfiscal.inf.br/nfe" versao="1.00"><infEvento Id="ID2102103517115233147700015355001000097206106174393001"><cOrgao>91</cOrgao><tpAmb>2</tpAmb><CNPJ>43198696000468</CNPJ><chNFe>35171152331477000153550010000972061061743930</chNFe><dhEvento>2017-12-06T11:24:08-02:00</dhEvento><tpEvento>210210</tpEvento><nSeqEvento>1</nSeqEvento><verEvento>1.00</verEvento><detEvento versao="1.00"><descEvento>Ciencia da Operacao</descEvento></detEvento></infEvento><Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><Si ... tionMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n- ... tureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/><Reference URI="#ID2102103517115233147700015355001000097206106174393001"><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#envel ... <Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n- ... gestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" ... /envEvento>'

A tag <X509Certificate> traz igual. Já a TAg <DigestValue> na minha rotina sempre traz um valor diferente. por exemplo: em 3 envios do mesmo xml ficou assim:
1vez)SbaWmCq15aemJKCpXeRbqh5padA=
2vez)HKckad0MNEeT5MomesU6eoG936A=
3vez)r8xDsLDicSAsUFTK8JlYacfm2Ko=

Já nessa rotina o cDigestValue é sempre o mesmo e diferente desses: F0D98762598842AE8C61B6CE5A595E397C698D87

obs: eu alterei para sha1 ok ( nAlgorithm := CAPICOM_HASH_ALGORITHM_SHA1 ou 0)
Responder