Checagem de assinatura

Projeto hbNFe (Nota Fiscal Eletronica/Danfe) para [x]Harbour

Moderador: Moderadores

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

Checagem de assinatura

Mensagem por JoséQuintas »

Achei isto no site da Microsoft, mas ainda em fase de conversão.
Não vai ser muito diferente no Harbour, porque usa classes do XML 5.0
É pra validar a assinatura do XML.

Código: Selecionar todos

Dim xmldoc As New DOMDocument50
Dim xmldsig As New MXDigitalSignature50
Dim dsigKey As IXMLDSigKey
Dim dataObj As IXMLDOMNode

Const DSIGNS = "xmlns:ds='http://www.w3.org/2000/09/xmldsig#'"
Const INFILE = "signature.verify.dsa.xml"

Private Function WriteLine(ByVal str As String)
    Text1.Text = Text1.Text + str + vbNewLine
End Function
Private Function writeClear()
    Text1.Text = ""
End Function

Private Function LoadXML(ByVal file As String)
    ' Read input xml file and display the content in the text1.
    Path = App.Path + "\" + file
    xmldoc.async = False
    xmldoc.preserveWhiteSpace = True
    xmldoc.validateOnParse = False
    xmldoc.resolveExternals = False
    If xmldoc.Load(Path) = False Then
        WriteLine "Can't load " + Path
        WriteLine "Reason: " + xmldoc.parseError.reason
        LoadXML = False
        Exit Function
    End If
    xmldoc.setProperty "SelectionNamespaces", DSIGNS
    Set xmldsig.signature = xmldoc.selectSingleNode(".//ds:Signature")
    LoadXML = True
End Function


Private Function VerifyXML()
    If xmldsig.signature Is Nothing Then
        WriteLine "Invalid signature."
        VerifyXML = False
        Exit Function
    End If

    Set oKeyInfo = xmldoc.selectSingleNode(".//ds:KeyInfo/ds:KeyValue")
    If oKeyInfo Is Nothing Then
        WriteLine "Invalid <KeyInfo> element."
        VerifyXML = False
        Exit Function
    End If

    Set oPubKey = xmldsig.createKeyFromNode(oKeyInfo)
    If oPubKey Is Nothing Then
        WriteLine "Can't generate public key for verification."
        VerifyXML = False
        Exit Function
    End If

    Set oVerifiedKey = xmldsig.verify(oPubKey)
    If oVerifiedKey Is Nothing Then
        WriteLine "Signature not verified."
    End If

    WriteLine "Signature verified."
    VerifyXML = True
End Function

Private Sub Form_Load()

    writeClear
    WriteLine "Verifyin signature."
    If LoadXML(INFILE) = True Then
        VerifyXML
    End If
End Sub
Durante conversão pra Harbour, fui confirmar aqueles componentes iniciais, aonde eram usados no fonte e.... não encontrei.
Fui no VB, e acrescentei no fonte: "Option Explicit", algo como a checagem -w3 -es2 que existe no Harbour.
E não é que deu erro nas linhas, porque não usa pra bost. nenhuma.
Belo exemplo de colocar lixo em fonte.... rs
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

Checagem de assinatura

Mensagem por JoséQuintas »

Ainda não testado e nem melhorado.
Pra quem tiver tudo na mão e quiser "brincar".

Código: Selecionar todos

#define DSIGNS "xmlns:ds='http://www.w3.org/2000/09/xmldsig#'"
#define INFILE "signature.verify.dsa.xml"

MEMVAR XmlDoc, XmlDSig

PROCEDURE Main

   PRIVATE XmlDoc, XmlDSig

   XmlDoc  := win_OleCreateObject( "MSXML2.DOMDocument.5.0" )
   XmlDSig := win_OleCreateObject( "MSXML2.MXDigitalDignature.5.0" )

   IF LoadXml( INFILE )
      VerifyXml()
   ENDIF
   RETURN

FUNCTION LoadXml( cFile )

   XmlDoc:Async := .F.
   XmlDoc:PreserveWhiteSpace := .T.
   XmlDoc:ValidateOnParse := .F.
   XmlDoc:ResolveExternals := .F.

   IF XmlDoc:Load( cFile ) == .F.
      MsgExclamation( "Cannot load file. reason " + XmlDoc:ParseError:Reason )
      RETURN .F.
   ENDIF
   XmlDoc:SetProperty( "SelectionNameSpaces", DSIGNS )
   XmlDsig:Signature := XmlDoc:SelectSingleNode( ".//ds:Signature" )
   RETURN .T.

FUNCTION VerifyXml()

   LOCAL oKeyInfo, oPubKey, oVerifiedKey

   IF XmlDSig:Signature == NIL
      MsgExclamation( "Invalid Signature" )
      RETURN .F.
   ENDIF
   oKeyInfo := XmlDoc:selectSingleNode( ".//ds:KeyInfo/ds:KeyValue" )
   IF oKeyInfo == NIL
      MsgExclamation( "Invalid <KeyInfo> Element" )
      RETURN .F.
   ENDIF
   oPubKey := XmlDSig:CreateKeyFromNode( oKeyInfo )
   IF oPubKey == NIL
      MsgExclamation( "Cannot generate public key for verification" )
      RETURN .F.
   ENDIF
   oVerifiedKey := XmlDSig:Verify( oPubKey )
   IF oVerifiedKey == NIL
      MsgExclamation( "Signature not verified" )
      RETURN .F.
   ENDIF
   MsgExclamation( "Signature Ok" )
   RETURN .T.
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

Checagem de assinatura

Mensagem por JoséQuintas »

Depois do primeiro teste ok.

Código: Selecionar todos


#define DSIGNS "xmlns:ds='http://www.w3.org/2000/09/xmldsig#'"

PROCEDURE Main( cFileName )

   ? ChkSignature( cFileName )
   Inkey(0)
   RETURN


FUNCTION ChkSignature( cXml )

   LOCAL XmlDoc, XmlDSig, cXmlRetorno := "Undefined Error"
   LOCAL oKeyInfo, oPubKey, oVerifiedKey, oSignature

   BEGIN SEQUENCE WITH __BreakBlock()
      XmlDoc  := win_OleCreateObject( "MSXML2.DOMDocument.5.0" )
      XmlDSig := win_OleCreateObject( "MSXML2.MXDigitalSignature.5.0" )

      XmlDoc:Async              := .F.
      XmlDoc:PreserveWhiteSpace := .T.
      XmlDoc:ValidateOnParse    := .F.
      XmlDoc:ResolveExternals   := .F.

      IF .NOT. XmlDoc:Load( cXml )
         cXmlRetorno := "Cannot load file. reason " + XmlDoc:ParseError:Reason
         BREAK
      ENDIF
      XmlDoc:SetProperty( "SelectionNamespaces", DSIGNS )
      oSignature := XmlDoc:SelectSingleNode( ".//ds:Signature" )
      IF oSignature == NIL
         cXmlRetorno := "Not Found Signature"
         BREAK
      ENDIF
      XmlDSig:Signature := oSignature
      oKeyInfo := XmlDoc:selectSingleNode( ".//ds:KeyInfo/ds:X509Data" )
      IF oKeyInfo == NIL
         cXmlRetorno := "Invalid <KeyInfo> Element"
         BREAK
      ENDIF
      oPubKey := XmlDSig:CreateKeyFromNode( oKeyInfo )
      IF oPubKey == NIL
         cXmlRetorno := "Cannot generate public key for verification"
         BREAK
      ENDIF
      oVerifiedKey := XmlDSig:Verify( oPubKey )
      IF oVerifiedKey == NIL
         cXmlRetorno := "Signature not verified"
         BREAK
      ENDIF
      cXmlRetorno := "OK"
   END SEQUENCE
   RETURN cXmlRetorno
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

Checagem de assinatura

Mensagem por JoséQuintas »

Faltou dizer: precisa do XML5 instalado.
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

Checagem de assinatura

Mensagem por JoséQuintas »

Precisa melhorar a rotina, e pegar mais situações.
Quando a assinatura é inválida, gera erro de run-time e isso causa retornar "erro desconhecido".
Acaba deixando na dúvida se a rotina falhou ou se é erro de assinatura mesmo.

Neste momento imagino deixar o :Verify em bloco de erro separado do restante.
Ainda não sei se vai precisar mais partes separadas em bloco de erro próprio.
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

Checagem de assinatura

Mensagem por JoséQuintas »

Idéia:

Código: Selecionar todos

   ...
   cXmlRetorno := "Bad Signature or Digest Value"
   oVerifiedKey := XmlDSig:Verify( oPubKey ) 
   IF oVerifiedKey == NIL 
      cXmlRetorno := "Signature not verified" 
      BREAK 
   ENDIF 
   cRetorno := "OK"
END SEQUENCE
RETURN cRetorno
Se der erro, vai retornar "Bad Signature or Digest Value", porque sai do BEGIN/END, e mantém o último conteúdo em cXmlRetorno.
Se seguir em frente, e der NIL, mostra "SIgnature not verified"
E se for até o fim, vai retornar "OK".

Dá até pra usar esse esquema no restante, aonde for preciso.

Agora é testar com muitos XMLs pra pegar mais situações.

Nota: neste último teste, que gerou erro de run-time, apenas troquei duas letras do XML por "XX", pra tornar a assinatura inválida.


Nota2:

Código: Selecionar todos

oKeyInfo := XmlDoc:selectSingleNode( ".//ds:KeyInfo/ds:X509Data" )
Não pensem que sou expert nessas coisas, que não sou, isso foi no chute mesmo.
Me pareceu que o segundo ds: era um sub-elemento. Coloquei igual está no XML e deu certo..... rs
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
janio
Colaborador
Colaborador
Mensagens: 1846
Registrado em: 06 Jul 2004 07:43
Localização: UBAJARA - CE

Checagem de assinatura

Mensagem por janio »

JoseQuintas escreveu:
Faltou dizer: precisa do XML5 instalado.
Sem ter nada a ver com o assunto (ou talvez tenha), em uma rotina para consultar o CNPJ na receita federal, tem dado erro na rotina abaixo:

Código: Selecionar todos

	Try
		oServer:= CreateObject( "MSXML2.ServerXMLHTTP.5.0")
	Catch
		MsgStop('Erro na Criação do Serviço','Consulta')
		Return aRetorno
	End

Em todos os computadores que já testei sempre deu certo, mas em um especificamente tem dado erro: "ERRO NA CRIÇÃO DO SERVIÇO"!

Não consegui identificar o que essa maquina tem (ou não tem) que faz essa rotina não funcionar nela!

Tem ideia do que pode ser?

Janio
fui...
e-mail:janioaguiar@yahoo.com.br
msn: janio_aguiar@hotmail.com
xHarbour1.2.1/Harbour3.2 + wvg + hwgui + Mediator + MySql
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Checagem de assinatura

Mensagem por JoséQuintas »

Sim, para o tem a ver, e para o ter idéia... rs

O final 5.0 indica XML 5.0.
Isso não vém instalado no Windows. Só saiu como parte do Office.

Como usa CreateObject() é provável que use o xHarbour, então troque o 5.0 por 6.0.
O 5.0 é especial que vém no Office, é o único que trata assinatura digital.
Se isso não envolve assinatura/certificado, melhor o 6.0 que faz parte do Windows.

Notas:
Se for Harbour, e win_OleCreateObject(), nem precisa versão, já seleciona automático o que for preciso.
Pelo menos pra Fazenda/NFE, tem webservice que exige 5.0 ou 6.0, então é possível que algo no servidor possa obrigar determinada versão.
O ACBR também usa isso, talvez tenha instalado ACBR nas outras máquinas, o que já instalou o XML 5.0.
E se mexer com certificado/assinatura, também a CAPICOM.
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

Checagem de assinatura

Mensagem por JoséQuintas »

Ainda testando a rotina de checagem.
Por enquanto um teste encima de notas recentes, mas direto no XML autorizado, o que não seria correto.
O resultado foi este:

Código: Selecionar todos

TipoXml  OK      ERRO
110100   1713    178    
110111     30      2    
110110     70      3    
Acusou assinatura inválida em 10% dos XMLs. Depois vou tentar descobrir o motivo.
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