 VB 
.NET - Criando código mais seguro
 VB 
.NET - Criando código mais seguro
Quando você cria um aplicação não deve negligenciar um item fundamental mas muitas vezes deixado em segundo plano : a proteção do código , configurações e dados envolvidos na aplicação.
A proteção do seu código fonte assegura que seu trabalho intelectual não seja roubado a proteção dos dados tratados pela sua aplicação também é fundamental afinal você é o responsável pela aplicação e seu cliente vai querer que os dados que ela trate estejam seguros.
Neste artigo eu vou procurar dar em linhas gerais alguns procedimentos para tratar da proteção de uma aplicação : código fonte , dados e configuração. Quero entretanto deixar claro que você não deve tomar este artigo como a palavra final em segurança para aplicações . Ao contrário , ele é apenas uma introdução básica neste vasto e intrincado assunto muito em moda nos dias atuais : segurança.
1- Proteção de senhas e nomes de usuários
Nunca armazene senhas e nomes de usuários na forma de texto aberto. Aonde quer que você for armazenar senhas e chaves de usuários faça isto de forma mascarada via criptografia. Assim se alguém tiver acesso as senhas e nomes de usuários ele terá que ter o trabalho de decodificar a informação antes de usar. O VB .NET oferece recursos fáceis de usar para que este serviço seja feito.
Abaixo um exemplo onde um Hash é gerado para uma string informada:
| ImportsSystem.Security.Cryptography ImportsSystem.Text 
 ModuleModule1 
 Sub Main() 
 Dim SHA1HASHValue() As Byte Console.WriteLine("SHA1 HASH GENERATOR") Console.WriteLine("Entre com o texto a criptografar :") Dim sString As String = Console.ReadLine() 'Cria uma nova instância de UnicodeEncoding para 'converter a string em um array de bytes UnicodeDim UE As New UnicodeEncoding() 'Converte o stringem um array de bytes.Dim MessageBytes As Byte() = UE.GetBytes(sString) 'Cria uma instância de SHA1Managed para criar um valor hashDim SHhash As New SHA1Managed() 'Cria o valor hash SHA1HASHValue = SHhash.ComputeHash(MessageBytes) 'Exibe o valor hash value no console.Dim b As Byte For Each b In SHA1HASHValue Console.Write("{0} ", b) Next b 
 Console.ReadLine() End Sub End Module | 
O Hash gerado é um valor único de tamanho fixo representando uma quantidade de informação. Para o caso de senhas e chaves , se duas senhas ou chaves forem iguais elas irão gerar o mesmo Hash. Seu uso mais comum é nas assinaturas digitais e na integridade de dados.
Outra classe que pode ser usada para o mesmo objetivo é a classe - FormsAuthentication Class - que fornece métodos estáticos que podemos usar para gerenciar a autenticidade da informação. Seus membros principais relacionados com a segurança são:
| Authenticate | Tenta validar a credencial contra aquela contida na credencial configurada na armazenagem. | 
| Decrypt | Retorna uma instância de uma classe FormsAuthenticationTicket , gerando um tiquete de autenticação criptografada de um cookie HTTP. | 
| Encrypt | Produz uma string contento um tiquete de autenticação criptografado adequado para usar com um cookie HTTP. | 
| Equals (inherited from Object) | Determina se dois objetos de instância são iguais. | 
| HashPasswordForStoringInConfigFile | Dada uma senha e uma string de identificando o tipo de hash gera uma senha hash adequada para ser armazenada no arquivo de configuração. | 
Inicie um novo projeto no VS.NET do tipo Visual Basic modelo Windows e no formulário padrão inclua os controles conforme figura abaixo:
|  | - O objetivo 
    é gerar um hash para uma senha informada - Temos a opção de fazer a geração usando os algoritmos SHA1 ou MD5. | 
O código associado ao evento - Click - do botão - Gerar Hash da Senha - é :
| Private
    Sub 
    GenerateHashButton_Click(ByVal 
    sender As
    Object,
    ByVal e
    As System.EventArgs) Handles 
    GenerateHashButton.Click Const SenhaVazia As String = "A informação da senha é obrigatória" Const SenhaNaoConfere As String = "A senha não confere" Const SenhaComBrancos As String = "A senha não pode iniciar nem terminar com espaços." 
 HashedPasswordTextBox.Text = "" 
 'verifica se as senhas informadas estão vazias. If PasswordTextBox.Text.Trim() = [String].Empty Or ConfirmPasswordTextBox.Text.Trim() = [String].Empty Then MessageBox.Show(SenhaVazia) PasswordTextBox.SelectAll() PasswordTextBox.Focus() ReturnEnd If 
 'verifica se não espaços em branco no inicio e no final da senha informadaIf PasswordTextBox.Text.StartsWith(" ") Or PasswordTextBox.Text.EndsWith(" ") Then MessageBox.Show(SenhaComBrancos) PasswordTextBox.SelectAll() PasswordTextBox.Focus() ReturnEnd If 
 'verifica se as senhas são iguaisIf PasswordTextBox.Text <> ConfirmPasswordTextBox.Text Then MessageBox.Show(SenhaNaoConfere) PasswordTextBox.SelectAll() PasswordTextBox.Focus() ReturnEnd If 
 'gera o hash e exibe na caixa de texto - HashedPasswordTextBox HashedPasswordTextBox.Text = FormsAuthentication.HashPasswordForStoringInConfigFile(PasswordTextBox.Text, HashingAlgorithmName) If ClipboardCopyCheckBox.Checked Then Clipboard.SetDataObject(HashedPasswordTextBox.Text, False) End IfReturn 
 End Sub | 
A linha de código responsável pelo serviço é dada a seguir , o restante do código é somente validação:
HashedPasswordTextBox.Text = FormsAuthentication.HashPasswordForStoringInConfigFile(PasswordTextBox.Text, HashingAlgorithmName)
| Nota: Outra forma de gerar um hash MD5 e usando o seguinte código: 
 Function HashMD5(Senha as string) as string Dim md5Hasher As New System.Security.Cryptography.MD5CryptoServiceProvider() Dim hashedBytes As Byte() Dim encoder As New System.Text.UTF8Encoding() Dim saida As StringDim b As Byte 
 hashedBytes = md5Hasher.ComputeHash(encoder.GetBytes(Senha)) For Each y In hashedBytes saida &= y Next y 
 HashMD5 = saidsa 
 End Function | 
Podemos ainda usar o código a seguir . Para isto crie um novo projeto no VS.NET e no formulário padrão monte o layout conforme abaixo.
|  | - No formulário basta instânciar a classe e 
    usar : 
 | 
No menu Project selecione Add Class nomeando o arquivo como - clsCrypto.vb. Abaixo o código da classe - clsCrypto.vb.( Perceba que teremos acesso apenas ao método clsCrypto que é público.)
| 
    Imports System.Security.Cryptography   
    DES.Key = hashmd5.ComputeHash(ASCIIEncoding.ASCII.GetBytes(myKey)) 
     | 
Eu nem estou considerando que você vá guardar chave e senha no seu código apenas pensando que por esta compilado eles vão estar protegidos. Qualquer usuário com as ferramentas adequadas pode decompilar (Disassembling) o seu código e você terá senha e nomes expostos.
Protegendo seu código da decompilação
Quando você compila seu código-fonte C# ou VB.NET o compilador vai convertê-lo para uma linguagem intermediária chamada - MSIL - Microsoft Intermediate Language - que é um conjunto de instruções em um tipo de assembly independente da CPU. Ao gerar o MSIL o compilador também gera metadados que são as informações embutidas no seu projeto que descrevem os tipos e suas definições , as assinaturas dos membros de cada tipo e outros dados.
Nota: Se você conhece Java já sacou o conceito. Afinal em java o código compilado gera um bytecode que pode ser executado em qualquer plataforma que possua uma máquina virtual - JVM .
Abaixo temos um esquema representando esta operação , a compilação e geração de código MSIL e a decompilação e geração de código C# :

A MSIL possui uma vasta gama de instruções para carregar , armazenar , inicializar , chamar métodos em objetos , operações lógicas , controles de fluxo , acesso direto a memória e manipulação de exceções. Antes do código poder ser executado a MSIL precisa ser convertida para o código da CPU do ambiente em que vai rodar ; isto é feito por compiladores Just in time (JIT) que converte o código para assembly nativo.
No final do processo você terá um arquivo PE (Portable Executable) que contém a MSIL e os metadados que irá rodar na CLR - Common Language RunTime. O problema é que , como foi abordado no artigo - Decompilando seu projeto VB.NET , o seu código pode ser decompilado usando ferramentas apropriadas.
Você não esta acreditando muito nesta história ? Pois vou mostrar que usando uma ferramenta da própria Microsoft - ISDASM.EXE - podemos expor o seu código fonte. Crie a seguinte classe em um projeto do tipo Console.
Class1.vb
| imports system Namespace Macoratti class m       shared sub main | 
Após compilar este código teremos um arquivo executável de nome class1.exe. Abaixo uma figura onde estou exibindo as etapas seguidas para gerar e testar o arquivo class1.exe.
|  | As etapas 
    seguidas para gerar e testar o arquivo class1.exe - O arquivo class1.vb criado no bloco de notas - a compilação do arquivo class1.vb : vbc class1.vb - o arquivo class1.exe gerado - a execução do arquivo class1.exe exibindo a mensagem | 
Vamos agora usar o utilitário ILDASM para obter o código IL o qual é lido a partir do METADATA do assembly. Para isto basta digitar a seguinte linha de comando:
| ILDASM Class1.exe /out=Class1.il | 
Agora você pode dar uma espiada no arquivo class1.il gerado e poderá ver muito mais do que apenas bytes...
Você pode executar o utilitário ILDASM a partir do Windows . Ele geralmente esta na basta bin de FrameworkSDK na pasta onde você instalou o VS.NET. Veja abaixo a figura do ildasm.exe exibindo a class1.exe

Para obter mais detalhes sobre o código clique duas vezes sobre o item. Abaixo a figura exibindo detalhes do método main:

Acredita agora ??? Se com um simples utilitário Microsoft você conseguir tudo isto imagine com uma 
ferramenta especializada ????
 
Se com um simples utilitário Microsoft você conseguir tudo isto imagine com uma 
ferramenta especializada ????
Então eu pergunto : Existe alguma forma de proteção do código compilado sem ter que usar e pagar por ofuscadores de código de terceiros ?
Sim , existe uma forma de dificultar o processo. Você deve seguir os seguintes passos após gerar o seu executável - class1.exe.
| ILDASM class1.exe /out=class1.il | 
| ILASM /owner=mac class1.il | 
Desta forma o arquivo class1.exe criado com a chave owner=mac não poderá ser aberto usando o utilitário ILDASM , se alguém tentar vai obter a mensagem : "Copyrighted Material- can not disassemble"
Para conseguir é necessário saber a chave definida com owner :
| ILDASM /owner=mac Class1.exe | 
É claro que isto não vai proteger o seu código de forma definitiva mas já coloca uma barreira a mais a ser superada.
Sinceramente eu não uso arquivos UDL para fornecer dados para a string de conexão. Um arquivo UDL é um recurso externo a mais que você vai ter que proteger em sua aplicação . Se você estiver operando sob o NTFS pode até atribuir uma proteção de permissão de acesso a arquivo. Se não estiver , vai ter que procurar uma forma de esconder a informação do arquivo.
Mantenha - Persist Security Info - como False
Se você definir - Persist Security Info - como true ou yes , irá permitir que a chave e senha possam ser obtidas da conexão depois que a mesma for aberta. Se você estiver fornecendo chave e senha para abrir uma conexão esta informação deve ser usada e logo descartada. Para que isto ocorra defina - Persist Security Info - como False ou no.
Cuidado com strings de conexão criadas com entradas de usuário
Se você monta sua string de conexão a partir de uma informação fornecida pelo usuário ( senha e chave) você deve ter cuidado para ter certeza de que os valores usados para criar sua string de conexão não contenham informação extra que possam alterar o comportamento de sua conexão. Procure efetuar a validação da entrada do usuário verificando se o formato da string de conexão não será afetado.
As expressões regulares podem ser usadas para validar entradas de dados em um formato específico. O .NET Framework fornece o objeto Regex para validar um valor contra uma expressão. Para verificar se o valor de uma chave de usuário tem 8 caracteres alfanuméricos do tipo string podemos usar o código:
| Imports 
    System.Text.RegularExpressions Public Static Function ValidarUsuario(inString As String) As Boolean
  Dim r As Regex = New Regex("^[A-Za-z0-9]{8}$")
  Return r.IsMatch(inString)
End Function | 
Até mais ...

João 5:24 Em verdade, em verdade vos digo que quem ouve a minha palavra, e crê naquele que me enviou, tem a vida eterna e não entra em juízo, mas já passou da morte para a vida.
João 5:25 Em verdade, em verdade vos digo que vem a hora, e agora é, em que os mortos ouvirão a voz do Filho de Deus, e os que a ouvirem viverão.
João 5:26 Pois assim como o Pai tem vida em si mesmo, assim também deu ao Filho ter vida em si mesmos;
João 5:27 e deu-lhe autoridade para julgar, porque é o Filho do homem.
| Veja os
Destaques e novidades do
SUPER DVD VB  (sempre atualizado) : clique e confira ! Quer migrar para o VB .NET ? Veja mais sistemas completos para a plataforma .NET no Super DVD .NET , confira... Quer aprender C# ?? Chegou o Super DVD C# com exclusivo material de suporte e vídeo aulas com curso básico sobre C#. | 
Referências:
Super DVD Vídeo Aulas - Vídeo Aula sobre VB .NET, ASP .NET e C#
VB6 - Express-Test - Gerador de testes de avaliacao para estudantes