Skip Navigation Links



Translate this page now :



»Programação
»Programação.NET
»Banco de Dados
»Webdesign
»Office
» Certificações Microsoft 4
»Treinamentos4
»Programação 4
»Webdesign«
»Office & User Tips«
»Grupos de UsuĆ”rios
»CĆ©lulas AcadĆŖmicas«

Micro de mulher
Você já está cadastrado e participa do grupo de usuários de sua cidade ? Se não, comente o porque.
 
 
FaƧa um pequeno teste com 10 questƵes de VB
.:.
Teste seus conhecimentos em Visual Basic, SQL Server e ASP 3.0 com nossas provas on-line
.:.
Aprimore seus conhecimentos em programaĆ§Ć£o com nosso treinamento on-line de lĆ³gica de programaĆ§Ć£o
.:.
Veja nosso calendƔrio de treinamentos
Gostou da PƔgina?
Então

para um amigo!

Pesquisa personalizada
Pesquisar Dicas:

 







Utilizando algorítimos de Hash para validar mensagens

 

No .NET Framework temos os seguintes algorítimos de Hash a disposição :

Algorítimo
Tamanho max. da mensagem(bits)
Tamanho da chave (bits)
MD5
2^64
128
SHA-1
2^64
160
SHA-256
2^64
256
SHA-384
2^128
384
SHA-512
2^129
512

 

Para cada algorítimo temos 2 classes no Framework. Por exemplo, para o SH-1 temos SHA1 e SHA1Managed. O mesmo ocorre para os demais algorítimos, a excessão do MD5.

As classes "Managed" rodam apenas em código gerenciado, enquanto que as demais utilizam a Crypto API do windows. A utilização da Crypto API gera uma maior versatilidade devido ao fato de que se houver correção na Crypto API através de algum service pack sua aplicação estará sempre utilizando a versão mais atualizada dos algorítimos.

Vamos começar com um exemplo bem simples, montado em um formulário Windows. Vamos criar uma textbox chamada txtMensagem e 2 botões, Criar Hash e Validar Hash.

O formulário precisará de 2 imports, um para as classes de criptografia e outro para a manipulação de arrays de bytes, veja :

         Imports System.Security.Cryptography
         Imports System.Text.ASCIIEncoding

Precisaremos de uma variável no form para guardar o Hash, será um array de bytes :

          dim b as byte()

Precisaremos também de uma função que compare dos arrays de bytes, para determinar se o hash está ou não válido. Veja como fica :

           Private Function CompararHash(ByVal hash1 As Byte(), ByVal hash2 As Byte())
                If hash1.Length <> hash2.Length Then
                    Return (False)
                Else
                   Dim i As Integer
                   For i = 0 To hash1.Length - 1
                       If hash1(i) <> hash2(i) Then
                          Return (False)
                       End If
                   Next
                   Return (True)
                End If
           End Function

Enfim, temos os botões, bem simples por sinal. Veja como fica o botão para criar o hash (Observe o uso do método getBytes para converter string em array de bytes) :

         Dim obj As New MD5CryptoServiceProvider
         b=obj.ComputeHash(ASCII.GetBytes(txtmensagem.text))
         msgbox("Ok!")

E, por fim, o botão para validar o hash :

       Dim obj As New MD5CryptoServiceProvider
       Dim c as byte()
       c=obj.ComputeHash(ASCII.GetBytes(txtmensagem.text))
       If compararhash(b,c) Then
          MsgBox("A mensagem está válida!")
       Else
          MsgBox("A mensagem está inválida!")
       End If
       

Rodando este exemplo podemos digitar uma mensagem na caixa de texto e clicarmos no botão para gerar o hash. Se de imediato clicarmos em validar o hash, a mensagem estará válida. Se alterarmos a caixa de texto e tentarmos novamente validar, a mensagem estará inválida, até que voltemos com o texto original.

Imaginemos então que desejamos exibir o hash para o usuário. Exibir até é simples, mas temos um problema : Se o hash for jogado em uma caixa de texto e recuperado, a tranformação distorce os bytes e a mensagem não pode mais ser validada.

Precisamos então formatar o hash de uma forma que possa ser exibido. Uma boa alternativa de formatação é exibi-lo na forma de valores em hexadecimal.

Veja como fica a função de formatação :

      Private Function formatarhash(ByVal hash As Byte()) As String
         Dim r As String
         Dim a As Integer
         For a = 0 To hash.Length - 1
             r &= Hex(hash(a)) & " "
         Next
         Return (Trim(r))
      End Function

Esta função retorna uma string representando o hash. Precisaremos então de uma função que possa reverter a formatação, gerando o hash novamente a partir da string. Veja como fica :

Private Function InterpretarHash(ByVal hash As String) As Byte()

   Dim r As Byte()
   Dim ar As String() = hash.Split(" ")
   Dim a As Integer
   r = New Byte(ar.Length - 1) {}
   For a = 0 To r.Length - 1
       r(a) = Byte.Parse(ar(a), System.Globalization.NumberStyles.HexNumber)
   Next
   Return (r)
End Function

Observe a utilização do Byte.Parse, que transforma um valor string em hexa em seu respectivo byte.

Com isso podemos abandonar a variável b e utilizar uma textbox, txtHash, para guardarmos o hash, veja :

Botão para criar o hash :

   Dim obj As New MD5CryptoServiceProvider
   txthash.text=formatarhash(obj.ComputeHash(ASCII.GetBytes(txtmensagem.text)))
   msgbox("Ok!")
       

Botão para validar o hash :

   Dim obj As New MD5CryptoServiceProvider
   Dim c as byte()
   c=obj.ComputeHash(ASCII.GetBytes(txtmensagem.text))
   If compararhash(interpretarhash(txthash.text),c) Then
      MsgBox("A mensagem está válida!")
   Else
      MsgBox("A mensagem está inválida!")
   End If
       

Pode parecer apenas detalhe, mas a formatação do hash se torna muito importante em determinados cenários. Por exemplo, se desejarmos transmitir o hash através de um webService.

Então, neste ponto, temos uma aplicação windows que cria um hash de uma mensagem. Porém, por mais que o código não tenha sido demasiadamente complexo, foi necessário algum trabalho para chegarmos a esse resultado.

Podemos então criar uma classe que facilite a construção de hashs, podemos chamar de clsHashHelper. Nesta classe estaremos inserindo as funções de formatação e interpretação do hash. Também poderemos criar funções para gerar e validar o hash.

Veja como fica a classe :

   Imports System.Security.Cryptography
   Imports System.Text.ASCIIEncoding
   Public Class clHashHelper
   
        Public Shared Function InterpretarHash(ByVal hash As String) As Byte()
            Dim r As Byte()
            Dim ar As String() = hash.Split(" ")
            Dim a As Integer
            r = New Byte(ar.Length - 1) {}
            For a = 0 To r.Length - 1
                r(a) = Byte.Parse(ar(a), System.Globalization.NumberStyles.HexNumber)
            Next
            Return (r)
       End Function
       Public Shared Function formatarhash(ByVal hash As Byte()) As String
            Dim r As String
            Dim a As Integer
            For a = 0 To hash.Length - 1
                r &= Hex(hash(a)) & " "
            Next
            Return (Trim(r))
       End Function
       Public Shared Function CompararHash(ByVal hash1 As Byte(), ByVal hash2 As Byte())
            If hash1.Length <> hash2.Length Then
               Return (False)
            Else
               Dim i As Integer
               For i = 0 To hash1.Length - 1
                  If hash1(i) <> hash2(i) Then
                     Return (False)
                  End If
               Next
               Return (True)
            End If
       End Function
       Public Shared Function GerarHash(ByVal mensagem As String) As String
           Dim obj As New MD5CryptoServiceProvider
           Return (formatarhash(obj.ComputeHash(ASCII.GetBytes(mensagem))))
       End Function
       Public Shared Function ValidarHash(ByVal mensagem As String, ByVal hash As String) _
               As Boolean
          Dim obj As New MD5CryptoServiceProvider
          Return (CompararHash(InterpretarHash(hash), _
               obj.ComputeHash(ASCII.GetBytes(mensagem))))
        End Function
   End Class
       

Observe que todas as funções foram definidas como shared para não termos o trabalho de criarmos uma instância desta classe. Essa classe pode ser inserida em um projeto de Class Library. Então no projeto WindowsApplication fazemos references para ela e usamos imports.

Veja como fica o código do formulário :

   Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
         Handles Button1.Click
       txthash.Text = GerarHash(txtMensagem.Text)
   End Sub
   Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
       Handles Button2.Click
      If ValidarHash(txtMensagem.Text, txthash.Text) Then
         MsgBox("A mensagem está válida!")
      Else
         MsgBox("A mensagem está inválida!")
      End If
   End Sub
       

Assim ficará bem mais simples para utilizar um hash quando desejarmos.

Vamos então criar um webService para testarmos a utilização deste hash com a resposta de um webService. Vamos adicionar um adapter, conexão e dataSet no serviço para retornar um dataset de clientes.

O webService então precisará retornar duas informações : O dataSet de clientes e o hash. Para resolver isso vamos criar uma classe contendo essas duas informações. Em seguida dizemos que o retorno do serviço será a classe. Veja como fica :

 <WebMethod()> _
   Public Function RetornaClientes() As Retorno
       Dim obj As New Retorno
       DA.Fill(Ds1)
       obj.dados = Ds1
       obj.Hash = clHashHelper.GerarHash(Ds1.GetXml)
       Return (obj)
   End Function
 <Serializable()> _
   Public Class Retorno
       Public dados As DS
       Public Hash As String
   End Class

O hash do dataSet é calculado sobre o XML que o dataset possui, utilizando a propriedade getXML. É então inserido dentro de uma instancia da classe retorno, junto com o dataSet, e devolvido para o client. Observe o uso de nossa biblioteca HashHelper.

Podemos usar a mesma windowsApplication como client deste webService, criando um formulário a mais para esta WindowsApplication e adicionando uma WebReference. Veja como fica o código :

   Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
       Handles Button1.Click
      Dim obj As New srvDados.Service1
      Dim ret As srvDados.Retorno
      ret = obj.RetornaClientes
      ' ret.dados.Customers.Rows(1).Delete()
      If ValidarHash(ret.dados.GetXml, ret.Hash) Then
         MsgBox("Dados Válidos !")
         DG.DataSource = ret.dados.Customers
      Else
         MsgBox("dados Inválidos !")
      End If
   End Sub


Para provocarmos um erro no hash podemos adicionar o delete de um registro no dataSet antes da validação, então veremos o dataSet não será validado. Desta forma, usando o hash protejemos a comunicação entre client e webService garantindo que a comunicação não foi adulterada no meio do caminho.

Dennes Torres
MCAD,MCSD,MCSE,MCDBA





Envie seus comentįrios sobre este artigo

Nome :

E-mail :

Comentários :


Avise-me quando houverem novos comentįrios nesta pįgina

Veja abaixo os comentários já enviados :

Nome : Rodrigo E-Mail : pu@bol.com.br
Dennes, parabéns... muito bacana esse seu artigo.

Você poderia me dar outros exemplos de utilização dessa técnica sem ser em WebServices...

O quando custa fazer isso em termos de processamento?

Em quais casos não vale a pena usar?

Grato

Rodrigo
Nome : Jooaquim E-Mail : joaquimerivelto@bol.com.br
Tá legal
Nome : Dennes Torres E-Mail : dennes@bufaloinfo.com.br

Qualquer tipo de comunicação de informações pode fazer uso da técnica de hash. Por exemplo, o viewState do ASP.NET utiliza a técnica de hash para impedir que algum usuário "esperto" tente adulterar o viewstate... é difícil precisar o custo de processamento, mas com o exemplo do viewstate acho que já é possível ter uma idéia...

Nome : Celso E-Mail : cm.junior@gmail.com
Olá... achei o artigo muito bom, parabéns.

Eu só gostaris de saber como fazer para isso funcionar em Visual Basic 6.0... tem jeito???

Aguardo resposta.

Até logo.
Nome : Dennes E-Mail : dennes@bufaloinfo.com.br

As classes que demonstrei no artigo fazem acesso na Crypto API. Então vc precisaria acessar as funções da CryptoAPI, que não são tão amigáveis.

Outra opção seria gerar um componente COM através do .NET, esse componente poderia ser acessado pelo VB 6

[]'s

Dennes
Nome : Altair Costa E-Mail : altairc@hotmail.com
olá,
Achei muito bom o seu artigo, mas tenho uma pergunta:
Isso funcionaria para imagem? tenho imagens em hexadecimal que preciso armazenar num banco, antes preciso tranformar para bytes, neste caso funcionaria?
aguardo resposta.

Altair Costa
Nome : Ênio Faria de Almeida E-Mail : enio@enioalmeida.com.br
O artigo está muito bom, porém fui mostrar o hash para o usuário (não tenho a inteção de recuperar) eo hash exibido em formato string não é o mesmo hash que calculei em outro site (a frase foi a mesma).
Nome : 1 E-Mail : 1
-1'
Nome : -1' E-Mail : 1
1
Nome : 1 E-Mail : -1'
1
Nome : 1 E-Mail : 1
1
Nome : 1 E-Mail : 1
1
Nome : -1' E-Mail : 1
1
Nome : 1 E-Mail : -1'
1
Nome : 1 E-Mail : 1
1
Nome : 1 E-Mail : 1
1
Nome : 1 E-Mail : 1
1

::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
Conheça mais sobre o nosso site :

::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::



Quer saber mais?
Faça um curso na Búfalo Informática, Treinamento e Consultoria e
Prepare-se para o Mercado!
Veja o que a Búfalo tem para você.

ļæ½ BĆŗfalo InformĆ”tica, Treinamento e Consultoria - Rua Ɓlvaro Alvim, 37 Sala 920 - CinelĆ¢ndia - Rio de Janeiro / RJ
Tel.: (21)2262-1368 (21) 9240-5134 (21) 9240-7281 e-Mail:
contato@bufaloinfo.com.br