Vamos criar um pequeno aplicativo de validação da Nf-e, executável
em uma chamada por parâmetro. Para executar esse aplicativo, simplesmente
você deverá clicar no botão Iniciar no Windows e selecionar a opção Executar
no menu, informando o seguinte comando:
C:\ValidarNfe.exe C:\NF-E\13090404672291000115550040000000270000000730-nfe.xml
Veja o o exemplo na figura abaixo:
1) Inicie um novo projeto no Vb.NET.
2) Defina nas referências do projeto (Menu Projects - ValidarNfe Properties - aba References) os seguintes namespaces:
System
System.Data
System.Deployment
System.Drawing
System.Security
System.Web.Services
System.Windows.Forms
System.Xml
3) Inclua no formulário uma timer, uma label, um listbox e um botão.
A tela deve ficar como o mostrado abaixo:
4) Defina a propriedade interval do timer em 1000, e dê dois cliques sobre ele. Informe o seguinte código para o Timer:
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
Me.Show()
End Sub
5) Dentro do código do formulário (form1.vb), no início do mesmo, inclua as seguintes referências:
Imports System.Collections.Generic
Imports System.Text
Imports System.Xml
Imports System.Xml.Schema
Imports System.IO
Imports System.Windows.Forms
Imports System.Security.Cryptography.Xml
Imports System.Security.Cryptography.X509Certificates
6) No evento Load do formulário, acrescente este código:
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim Valor As String
Me.Show()
If Command() <> "" Then
Valor = Command()
ValidaNfe(Valor)
Me.Focus()
Me.Show()
Me.WindowState = FormWindowState.Normal
End If
End Sub
7) O código do botão Fechar deve ser o que segue abaixo:
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
End
End Sub
8) A função ValidaNfe é a que segue abaixo:
Private Sub ValidaNfe(ByVal NfeAler As String)
Try
'Abrir agora o arquivo XML criado e inserir o Protocolo encontrado!!
Dim arquivo2 As String = NfeAler
Dim xDoc As New XmlDocument : xDoc.Load(arquivo2)
Dim Tamanho As String
Dim Nfe As String
Nfe = arquivo2
Tamanho = Replace(Nfe, "C:\", "")
Tamanho = Replace(Tamanho, "F:\SisWin\NFE\BACKUP\200905\", "")
Tamanho = Replace(Tamanho, "F:\SisWin\NFE\BACKUP", "")
Tamanho = Replace(Tamanho, "F:\SisWin\NFE\AENVIAR", "")
Tamanho = Replace(Tamanho, "F:\SisWin\NFE\AENVIAR", "")
Tamanho = Replace(Tamanho, "\", "")
Tamanho = Replace(Tamanho, "\NF-E", "")
Tamanho = Replace(Tamanho, "NF-E", "")
Tamanho = Replace(Tamanho, "SisWin", "")
Tamanho = Replace(Tamanho, "SisWin", "")
'Fazer uma cópia d arquivo XML para gerar a assinatura
Dim CaminhoArquivo As String = "C:\NF-E\XML\" + Tamanho
'Salva o Arquivo
xDoc.Save(CaminhoArquivo)
'Selecionar certificado
SelecionarCertificado()
'Assinar o XML
Dim OAd As New AssinaturaDigitalClass()
Dim pDadosNfe As String
Dim vStringNfe As String
'Dim msgResultado As String
OAd.Assinar(CaminhoArquivo, "infNFe", oCertificado)
If OAd.vResultado = 0 Then 'Assinado corretamente
pDadosNfe = OAd.vXMLStringAssinado
vStringNfe = pDadosNfe.Substring(pDadosNfe.IndexOf("<
NFe"), pDadosNfe.Length - pDadosNfe.IndexOf("<
NFe"))Else 'Ocorreu algum erro na assinatura
MessageBox.Show(OAd.vResultadoString, "Erro", MessageBoxButtons.OK, MessageBoxIcon.Error)
End If
'Validar o XML
Dim TxtXSD As String
TxtXSD = "C:\tmp\Schemas NF-e\nfe_v1.10.xsd"
If Not CaminhoArquivo = String.Empty And Not TxtXSD = String.Empty Then
Resultado = True
Dim settings As New XmlReaderSettings()
AddHandler settings.ValidationEventHandler, AddressOf Me.ValidationEventHandler
'Valida o arquivo XML com o seu Schema XSD
lstValida.Items.Add("Validando o arquivo XML " & CaminhoArquivo & " com o arquivo de Schema : " & TxtXSD)
Try
settings.ValidationType = ValidationType.Schema
settings.Schemas.Add("http://www.portalfiscal.inf.br/nfe",xmlReader.Create(TxtXSD))
Using XmlValidatingReader As XmlReader = XmlReader.Create(CaminhoArquivo, settings)
While XmlValidatingReader.Read()
End While
End Using
Catch ex As Exception
lstValida.Items.Add(ex.Message)
Exit Sub
End Try
lstValida.Items.Add("Status Validação -> " & IIf(Resultado = True, "Arquivo validado com SUCESSO", "Validação FALHOU"))
Else
MsgBox("Informe o arquivo XML e o arquivo XSD.")
End If
Catch ex As Exception
'se ocorrer uma exceção exibe a mensagem
lstValida.Items.Add(ex.Message)
End Try
End Sub
A função ValidaNfe chama outras duas funções em seu início: uma que seleciona o certificado automaticamente e outra que assina o documento. O código da função SelecionarCertificado() é que segue abaixo:
Function SelecionarCertificado() As Boolean
Dim vRetorna As Boolean
Dim oX509Cert As New X509Certificate2
Dim store As New X509Store
Dim collection As New X509Certificate2Collection
Dim collection1 As New X509Certificate2Collection
Dim collection2 As New X509Certificate2Collection
Dim scollection As New X509Certificate2Collection
Dim msgResultado As String
Dim xnome As String
xnome = "CN=CERTIFICADOTESTE:09999991000115, OU=Autenticado por AR Fenacon, OU=RFB e-CNPJ A1, OU=Secretaria da Receita Federal do Brasil - RFB, L=Manaus, S=AM, O=ICP-Brasil, C=BR"
oX509Cert = New X509Certificate2()
store = New X509Store("MY", StoreLocation.CurrentUser)
store.Open(OpenFlags.ReadOnly Or OpenFlags.OpenExistingOnly)
collection = store.Certificates
collection1 = collection.Find(X509FindType.FindByTimeValid, DateTime.Now, False)
collection2 = collection.Find(X509FindType.FindByKeyUsage, X509KeyUsageFlags.DigitalSignature, False)
'Encontra o certificado digital pelo nome do mesmo, se precisar pergunta por isso
'Resolvido em 13/05/2009 às 15:05h
scollection = collection.Find(X509FindType.FindBySubjectDistinguishedName, xnome, False)
'Para selecionar o certificado de uma lista
'scollection = X509Certificate2UI.SelectFromCollection(collection2, "Certificado(s) Digital(is) disponível(is)", "Selecione o certificado digital para uso no aplicativo", X509SelectionFlag.SingleSelection)
If (scollection.Count = 0) Then
msgResultado = "Nenhum certificado digital foi selecionado ou o certificado selecionado está com problemas."
MessageBox.Show(msgResultado, "Advertência", MessageBoxButtons.OK, MessageBoxIcon.Warning)
vRetorna = False
Else
oX509Cert = scollection.Item(0) 'Para selecionar o item em Vb.NET
oCertificado = oX509Cert
vRetorna = True
'msgResultado = "Certificado Selecionado."
'MessageBox.Show(msgResultado, "Advertência", MessageBoxButtons.OK, MessageBoxIcon.Warning)
Return vRetorna
End If
End Function
-----------------
Voce deve informar em xnome o nome por extenso do Certificado que irá usar para validar a XML a ser assinado. Para obter o nome por extenso do seu certificado você pode usar a próprioa função acima habilitando a que pede a seleção de certicados de uma lista e colocando o seguinte comando no Else da função acima:
xnome = oCertificado.Subject.ToString
Esse comando colocará o nome do certificado na variável xnome. Se você debugar, pode pegar o nome extenso do certificado que deve usar para validar o XML e colocar dentro da váriavel, como fiz no início do código:
xnome = "CN=CERTIFICADOTESTE:09999991000115, OU=Autenticado por AR Fenacon, OU=RFB e-CNPJ A1, OU=Secretaria da Receita Federal do Brasil - RFB, L=Manaus, S=AM, O=ICP-Brasil, C=BR"
Para a assinatura digital uma classe é acrescentada totalmente no final da classe do formulário. Essa classe é responsável pela assinatura do XML. Eis o código abaixo:
Public Class AssinaturaDigitalClass
Public vResultado As Integer
Public vResultadoString As String
Public vXMLStringAssinado As String
Public XmlDoc As XmlDocument
Sub Assinar(ByVal pArqXMLAssinar As String, ByVal pUri As String, ByVal pCertificado As X509Certificate2)
'Abrir o arquivo XML a ser assinado e ler o seu conteúdo
Dim SR As StreamReader
Dim vXMLString As String
SR = File.OpenText(pArqXMLAssinar)
vXMLString = SR.ReadToEnd()
SR.Close()
' //Atualizar atributos de retorno com conteúdo padrão
vResultado = 0
vResultadoString = "Assinatura realizada com sucesso"
Try
'Verifica o certificado a ser utilizado na assinatura
Dim _xnome As String
Dim _X509Cert As X509Certificate2
Dim store As X509Store
Dim collection As X509Certificate2Collection
Dim collection1 As X509Certificate2Collection
_xnome = ""
_xnome = pCertificado.Subject.ToString()
_X509Cert = New X509Certificate2()
store = New X509Store("MY", StoreLocation.CurrentUser)
store.Open(OpenFlags.ReadOnly Or OpenFlags.OpenExistingOnly)
collection = store.Certificates
collection1 = collection.Find(X509FindType.FindBySubjectDistinguishedName, _xnome, False)
If (collection1.Count = 0) Then
vResultado = 2
vResultadoString = "Problemas no certificado digital"
Else
' certificado ok
'oX509Cert = scollection.Item(0)
_X509Cert = collection1.Item(0)
Dim x As String
x = _X509Cert.GetKeyAlgorithm().ToString()
' Create a new XML document.
Dim doc As New XmlDocument
doc = New XmlDocument()
'Format the document to ignore white spaces.
doc.PreserveWhitespace = False
' Load the passed XML file using it’s name.
Try
doc.LoadXml(vXMLString)
' Verifica se a tag a ser assinada existe é única
Dim qtdeRefUri As Integer
qtdeRefUri = doc.GetElementsByTagName(pUri).Count
If (qtdeRefUri = 0) Then
' a URI indicada não existe
vResultado = 4
vResultadoString = "A tag de assinatura " + pUri.Trim() + " não existe"
Else
' Existe mais de uma tag a ser assinada
If (qtdeRefUri > 1) Then
' existe mais de uma URI indicada
vResultado = 5
vResultadoString = "A tag de assinatura " + pUri.Trim() + " não é unica"
Else
Try
' Create a SignedXml object.
Dim signedXml As SignedXml
signedXml = New SignedXml(doc)
' Add the key to the SignedXml document
signedXml.SigningKey = _X509Cert.PrivateKey
' Create a reference to be signed
Dim reference As New Reference
reference = New Reference()
'--------- RETIRAR COMENTÁRIOS DAS LINHAS ABAIXO
' pega o uri que deve ser assinada
Dim _Uri As XmlAttributeCollection
Dim _atributo As XmlAttribute
_Uri = doc.GetElementsByTagName(pUri).Item(0).Attributes
For Each _atributo In _Uri
If (_atributo.Name = "Id") Then
reference.Uri = "#" + _atributo.InnerText
End If
Next
' Add an enveloped transformation to the reference.
Dim env As New XmlDsigEnvelopedSignatureTransform
env = New XmlDsigEnvelopedSignatureTransform()
reference.AddTransform(env)
Dim c14 As New XmlDsigC14NTransform
c14 = New XmlDsigC14NTransform()
reference.AddTransform(c14)
' Add the reference to the SignedXml object.
signedXml.AddReference(reference)
' Create a new KeyInfo object
Dim keyinfo As New KeyInfo
keyinfo = New KeyInfo()
' Load the certificate into a KeyInfoX509Data object
' and add it to the KeyInfo object.
keyinfo.AddClause(New KeyInfoX509Data(_X509Cert))
' Add the KeyInfo object to the SignedXml object.
signedXml.KeyInfo = keyinfo
signedXml.ComputeSignature()
' Get the XML representation of the signature and save
' it to an XmlElement object.
Dim xmlDigitalSignature As XmlElement
xmlDigitalSignature = signedXml.GetXml()
' Gravar o elemento no documento XML
doc.DocumentElement.AppendChild(doc.ImportNode(xmlDigitalSignature, True))
XmlDoc = New XmlDocument()
XmlDoc.PreserveWhitespace = False
XmlDoc = doc
' Atualizar a string do XML já assinada
vXMLStringAssinado = XmlDoc.OuterXml
' Gravar o XML no HD
' abre um stream para escrita e cria um StreamWriter para implementar o stream
Dim fs As New FileStream(pArqXMLAssinar, FileMode.OpenOrCreate, FileAccess.Write)
Dim SW_2 As New StreamWriter(fs)
SW_2.Flush()
SW_2.BaseStream.Seek(0, SeekOrigin.Begin)
SW_2.Write(vXMLStringAssinado)
SW_2.Flush()
SW_2.Close()
Catch ex As Exception
vResultado = 6
vResultadoString = "Erro ao assinar o documento - " + ex.Message
End Try
End If
End If
Catch ex As Exception
vResultado = 3
vResultadoString = "XML mal formado - " + ex.Message
End Try
End If
Catch ex As Exception
vResultado = 1
vResultadoString = "Problema ao acessar o certificado digital" + ex.Message
End Try
End Sub
End Class
9) Dentro do botão que faz a validação é repassado o código do arquivo XSD que faz a validação:
TxtXSD = "C:\tmp\Schemas NF-e\nfe_v1.10.xsd"
Um EventHandler se faz necessário para a leitura da validação do XSD.
Abaixo, vemos o código da função de validação do EventHandler:
Public Sub ValidationEventHandler(ByVal sender As Object, ByVal args As ValidationEventArgs)
Resultado = False
'lstValida.Items.Add(vbTab + "Erro de Validação : " + args.Message)
If args.Severity = XmlSeverityType.Warning Then
MsgBox("Nenhum arquivo de Schema foi encontrado para efetuar a validação...")
ElseIf args.Severity = XmlSeverityType.Error Then
lstValida.Items.Add(args.Message)
'MsgBox("Ocorreu um erro durante a validação....")
End If
If Not (args.Exception Is Nothing) Then ' Erro na validação do schema XSD
'lstValida.Items.Add(args.Exception.SourceUri + "," & args.Exception.LinePosition & "," & args.Exception.LineNumber)
'MsgBox(args.Exception.SourceUri + "," & args.Exception.LinePosition & "," & args.Exception.LineNumber)
End If
End Sub
Essa função será chamada para retornar o erro que possa estar acontecendo com algum ponto do arquivo XML.
Pronto!!
Cada passo de uma validação para a Nf-e foi descrita acima.
Posto o código completo do arquivo form1.VB abaixo para dirrimir quaisquer dúvidas:
'Validador para arquivos Nf-e
'Data de criação: 12/05/2009
'Para ser utilizado com o Visual Basic 6
'A aplicação funciona com chamada de parâmetro na linha digitável
'Para executar esse aplicativo, use a linha de comando do Windwos
'clicando no botão iniciar de depois em Executar:
'Exemplo de chamada: C:\ValidarNfe.exe C:\NF-E\13090404672291000115550040000000270000000730-nfe.xml
'Desenvolvedor: Manoel Leonardo Metelis Florindo
Imports System.Collections.Generic
Imports System.Text
Imports System.Xml
Imports System.Xml.Schema
Imports System.IO
Imports System.Windows.Forms
Imports System.Security.Cryptography.Xml
Imports System.Security.Cryptography.X509Certificates
Public Class Form1
Private Resultado As Boolean = True
Public oCertificado As New X509Certificate2
Public vStrXmlRetorno As String
Public vArqERRRetorno As String
Public vPastaXMLErro As String
Public vPastaXMLEnvio As String
Public vArqXMLRetorno As String
Public vPastaXMLRetorno As String
Public vXmlNfeDadosMsg As String
Public vAmbiente As Integer
Public vUF As Integer
Private Sub ValidaNfe(ByVal NfeAler As String)
Try
'Abrir agora o arquivo XML criado e inserir o Protocolo encontrado!!
Dim arquivo2 As String = NfeAler
Dim xDoc As New XmlDocument : xDoc.Load(arquivo2)
Dim Tamanho As String
Dim Nfe As String
Nfe = arquivo2
Tamanho = Replace(Nfe, "C:\", "")
Tamanho = Replace(Tamanho, "F:\SisWin\NFE\BACKUP\200905\", "")
Tamanho = Replace(Tamanho, "F:\SisWin\NFE\BACKUP", "")
Tamanho = Replace(Tamanho, "F:\SisWin\NFE\AENVIAR", "")
Tamanho = Replace(Tamanho, "F:\SisWin\NFE\AENVIAR", "")
Tamanho = Replace(Tamanho, "\", "")
Tamanho = Replace(Tamanho, "\NF-E", "")
Tamanho = Replace(Tamanho, "NF-E", "")
Tamanho = Replace(Tamanho, "SisWin", "")
Tamanho = Replace(Tamanho, "SisWin", "")
'Fazer uma cópia d arquivo XML para gerar a assinatura
Dim CaminhoArquivo As String = "C:\NF-E\XML\" + Tamanho
'Salva o Arquivo
xDoc.Save(CaminhoArquivo)
'Selecionar certificado
SelecionarCertificado()
'Assinar o XML
Dim OAd As New AssinaturaDigitalClass()
Dim pDadosNfe As String
Dim vStringNfe As String
'Dim msgResultado As String
OAd.Assinar(CaminhoArquivo, "infNFe", oCertificado)
If OAd.vResultado = 0 Then 'Assinado corretamente
pDadosNfe = OAd.vXMLStringAssinado
vStringNfe = pDadosNfe.Substring(pDadosNfe.IndexOf("<
NFe"), pDadosNfe.Length - pDadosNfe.IndexOf("<
NFe"))Else 'Ocorreu algum erro na assinatura
MessageBox.Show(OAd.vResultadoString, "Erro", MessageBoxButtons.OK, MessageBoxIcon.Error)
End If
'Validar o XML
Dim TxtXSD As String
TxtXSD = "C:\tmp\Schemas NF-e\nfe_v1.10.xsd"
If Not CaminhoArquivo = String.Empty And Not TxtXSD = String.Empty Then
Resultado = True
Dim settings As New XmlReaderSettings()
AddHandler settings.ValidationEventHandler, AddressOf Me.ValidationEventHandler
'Valida o arquivo XML com o seu Schema XSD
lstValida.Items.Add("Validando o arquivo XML " & CaminhoArquivo & " com o arquivo de Schema : " & TxtXSD)
Try
settings.ValidationType = ValidationType.Schema
settings.Schemas.Add("http://www.portalfiscal.inf.br/nfe", XmlReader.Create(TxtXSD))
Using XmlValidatingReader As XmlReader = XmlReader.Create(CaminhoArquivo, settings)
While XmlValidatingReader.Read()
End While
End Using
Catch ex As Exception
lstValida.Items.Add(ex.Message)
Exit Sub
End Try
lstValida.Items.Add("Status Validação -> " & IIf(Resultado = True, "Arquivo validado com SUCESSO", "Validação FALHOU"))
Else
MsgBox("Informe o arquivo XML e o arquivo XSD.")
End If
Catch ex As Exception
'se ocorrer uma exceção exibe a mensagem
lstValida.Items.Add(ex.Message)
End Try
End Sub
Function SelecionarCertificado() As Boolean
Dim vRetorna As Boolean
Dim oX509Cert As New X509Certificate2
Dim store As New X509Store
Dim collection As New X509Certificate2Collection
Dim collection1 As New X509Certificate2Collection
Dim collection2 As New X509Certificate2Collection
Dim scollection As New X509Certificate2Collection
Dim msgResultado As String
Dim xnome As String
xnome = "CN=COPLAST INDUSTRIA E COMERCIO DE RESIDUOS PLASTICO:04672291000115, OU=Autenticado por AR Fenacon, OU=RFB e-CNPJ A1, OU=Secretaria da Receita Federal do Brasil - RFB, L=Manaus, S=AM, O=ICP-Brasil, C=BR"
oX509Cert = New X509Certificate2()
store = New X509Store("MY", StoreLocation.CurrentUser)
store.Open(OpenFlags.ReadOnly Or OpenFlags.OpenExistingOnly)
collection = store.Certificates
collection1 = collection.Find(X509FindType.FindByTimeValid, DateTime.Now, False)
collection2 = collection.Find(X509FindType.FindByKeyUsage, X509KeyUsageFlags.DigitalSignature, False)
'Encontra o certificado digital pelo nome do mesmo, se precisar pergunta por isso
'Resolvido em 13/05/2009 às 15:05h
scollection = collection.Find(X509FindType.FindBySubjectDistinguishedName, xnome, False)
'Para selecionar o certificado de uma lista
'scollection = X509Certificate2UI.SelectFromCollection(collection2, "Certificado(s) Digital(is) disponível(is)", "Selecione o certificado digital para uso no aplicativo", X509SelectionFlag.SingleSelection)
If (scollection.Count = 0) Then
msgResultado = "Nenhum certificado digital foi selecionado ou o certificado selecionado está com problemas."
MessageBox.Show(msgResultado, "Advertência", MessageBoxButtons.OK, MessageBoxIcon.Warning)
vRetorna = False
Else
oX509Cert = scollection.Item(0) 'Para selecionar o item em Vb.NET
oCertificado = oX509Cert
xnome = oCertificado.Subject.ToString
vRetorna = True
'msgResultado = "Certificado Selecionado."
'MessageBox.Show(msgResultado, "Advertência", MessageBoxButtons.OK, MessageBoxIcon.Warning)
Return vRetorna
End If
End Function
Public Sub ValidationEventHandler(ByVal sender As Object, ByVal args As ValidationEventArgs)
Resultado = False
'lstValida.Items.Add(vbTab + "Erro de Validação : " + args.Message)
If args.Severity = XmlSeverityType.Warning Then
MsgBox("Nenhum arquivo de Schema foi encontrado para efetuar a validação...")
ElseIf args.Severity = XmlSeverityType.Error Then
lstValida.Items.Add(args.Message)
'MsgBox("Ocorreu um erro durante a validação....")
End If
If Not (args.Exception Is Nothing) Then ' Erro na validação do schema XSD
'lstValida.Items.Add(args.Exception.SourceUri + "," & args.Exception.LinePosition & "," & args.Exception.LineNumber)
'MsgBox(args.Exception.SourceUri + "," & args.Exception.LinePosition & "," & args.Exception.LineNumber)
End If
End Sub
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
End
End Sub
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim Valor As String
Me.Show()
'Valor = "F:\SisWin\NFE\BACKUP\200905\13090504672291000115550040000001520000002017-nfe.XML"
'ValidaNfe(Valor)
If Command() <> "" Then
Valor = Command()
ValidaNfe(Valor)
Me.Focus()
Me.Show()
Me.WindowState = FormWindowState.Normal
End If
End Sub
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
Me.Show()
End Sub
End Class
Public Class AssinaturaDigitalClass
Public vResultado As Integer
Public vResultadoString As String
Public vXMLStringAssinado As String
Public XmlDoc As XmlDocument
Sub Assinar(ByVal pArqXMLAssinar As String, ByVal pUri As String, ByVal pCertificado As X509Certificate2)
'Abrir o arquivo XML a ser assinado e ler o seu conteúdo
Dim SR As StreamReader
Dim vXMLString As String
SR = File.OpenText(pArqXMLAssinar)
vXMLString = SR.ReadToEnd()
SR.Close()
' //Atualizar atributos de retorno com conteúdo padrão
vResultado = 0
vResultadoString = "Assinatura realizada com sucesso"
Try
'Verifica o certificado a ser utilizado na assinatura
Dim _xnome As String
Dim _X509Cert As X509Certificate2
Dim store As X509Store
Dim collection As X509Certificate2Collection
Dim collection1 As X509Certificate2Collection
_xnome = ""
_xnome = pCertificado.Subject.ToString()
_X509Cert = New X509Certificate2()
store = New X509Store("MY", StoreLocation.CurrentUser)
store.Open(OpenFlags.ReadOnly Or OpenFlags.OpenExistingOnly)
collection = store.Certificates
collection1 = collection.Find(X509FindType.FindBySubjectDistinguishedName, _xnome, False)
If (collection1.Count = 0) Then
vResultado = 2
vResultadoString = "Problemas no certificado digital"
Else
' certificado ok
'oX509Cert = scollection.Item(0)
_X509Cert = collection1.Item(0)
Dim x As String
x = _X509Cert.GetKeyAlgorithm().ToString()
' Create a new XML document.
Dim doc As New XmlDocument
doc = New XmlDocument()
'Format the document to ignore white spaces.
doc.PreserveWhitespace = False
' Load the passed XML file using it’s name.
Try
doc.LoadXml(vXMLString)
' Verifica se a tag a ser assinada existe é única
Dim qtdeRefUri As Integer
qtdeRefUri = doc.GetElementsByTagName(pUri).Count
If (qtdeRefUri = 0) Then
' a URI indicada não existe
vResultado = 4
vResultadoString = "A tag de assinatura " + pUri.Trim() + " não existe"
Else
' Existe mais de uma tag a ser assinada
If (qtdeRefUri > 1) Then
' existe mais de uma URI indicada
vResultado = 5
vResultadoString = "A tag de assinatura " + pUri.Trim() + " não é unica"
Else
Try
' Create a SignedXml object.
Dim signedXml As SignedXml
signedXml = New SignedXml(doc)
' Add the key to the SignedXml document
signedXml.SigningKey = _X509Cert.PrivateKey
' Create a reference to be signed
Dim reference As New Reference
reference = New Reference()
'--------- RETIRAR COMENTÁRIOS DAS LINHAS ABAIXO
' pega o uri que deve ser assinada
Dim _Uri As XmlAttributeCollection
Dim _atributo As XmlAttribute
_Uri = doc.GetElementsByTagName(pUri).Item(0).Attributes
For Each _atributo In _Uri
If (_atributo.Name = "Id") Then
reference.Uri = "#" + _atributo.InnerText
End If
Next
' Add an enveloped transformation to the reference.
Dim env As New XmlDsigEnvelopedSignatureTransform
env = New XmlDsigEnvelopedSignatureTransform()
reference.AddTransform(env)
Dim c14 As New XmlDsigC14NTransform
c14 = New XmlDsigC14NTransform()
reference.AddTransform(c14)
' Add the reference to the SignedXml object.
signedXml.AddReference(reference)
' Create a new KeyInfo object
Dim keyinfo As New KeyInfo
keyinfo = New KeyInfo()
' Load the certificate into a KeyInfoX509Data object
' and add it to the KeyInfo object.
keyinfo.AddClause(New KeyInfoX509Data(_X509Cert))
' Add the KeyInfo object to the SignedXml object.
signedXml.KeyInfo = keyinfo
signedXml.ComputeSignature()
' Get the XML representation of the signature and save
' it to an XmlElement object.
Dim xmlDigitalSignature As XmlElement
xmlDigitalSignature = signedXml.GetXml()
' Gravar o elemento no documento XML
doc.DocumentElement.AppendChild(doc.ImportNode(xmlDigitalSignature, True))
XmlDoc = New XmlDocument()
XmlDoc.PreserveWhitespace = False
XmlDoc = doc
' Atualizar a string do XML já assinada
vXMLStringAssinado = XmlDoc.OuterXml
' Gravar o XML no HD
' abre um stream para escrita e cria um StreamWriter para implementar o stream
Dim fs As New FileStream(pArqXMLAssinar, FileMode.OpenOrCreate, FileAccess.Write)
Dim SW_2 As New StreamWriter(fs)
SW_2.Flush()
SW_2.BaseStream.Seek(0, SeekOrigin.Begin)
SW_2.Write(vXMLStringAssinado)
SW_2.Flush()
SW_2.Close()
Catch ex As Exception
vResultado = 6
vResultadoString = "Erro ao assinar o documento - " + ex.Message
End Try
End If
End If
Catch ex As Exception
vResultado = 3
vResultadoString = "XML mal formado - " + ex.Message
End Try
End If
Catch ex As Exception
vResultado = 1
vResultadoString = "Problema ao acessar o certificado digital" + ex.Message
End Try
End Sub
End Class
2 comentários:
Fico muito agradecido pelas dicas disponibilizadas.
Obrigado
Muito legal, estou testando...
Postar um comentário