Criptografia de Dados 128 Bits

Fabrizio Gianfratti (e-mail) trabalha com desenvolvimento desde 1995 e desenvolve com ASP, ASP.NET, JavaScript e SQL SERVER. É experiente no desenvolvimento de e-commerce e ferramentas para portais e de gerenciamento de conteúdo. Atualmente trabalha em projetos para desenvolvimento de sistemas na a área hospitalar. Disponibiliza muitas informações em seu site www.gianfratti.com.

Neste artigo vou mostrar como você pode usar na prática as classes que o .NET Framework oferece para realizar a criptografia. Vou começar com um exemplo de criptografia de chave privada ou criptografia simétrica, que indica que a mesma chave usada para cifrar é usada para decifrar. Iremos usar o algoritmo Rijndael que é o novo DES, definido pelo governo americano, o Rijndael utiliza uma chave mais forte (256bits).

A Criptografia tem infinitas usabilidades, isso todos sabem, vou dar apenas alguns exemplos de como ela poderia ser usada na WEB. Todo mundo passa parâmetros via QueryString (Ex. Usuario.asp?id=1), suponhamos que o usuário fique mudando o ID de usa aplicação e possa visualizar algum outro registro que não fosse o dele, isso serio muito ruim, além de não ter a mínima segurança. Então, nos ciframos o número 1 que foi passado como parâmetro, mas dessa vez cifrado (Ex. Usuario.asp?id=vLyHARA8A0m2SknVd0azxw==).

Como temos uma chave de até 32 posições, creio eu, que seria mais fácil alguém acertar na sena várias vezes do que acertar essa senha de uma forma aleatória, sendo que dentro as 32 posições nada impede de colocarmos caracteres especiais. Podemos também usar a criptografia para reduzirmos o uso de SQL INJECTION via QueryString.

Uma outra prática muito usável seria armazenar senhas e outros dados sigilosos dentro do banco de dados. Neste caso, guardaríamos a senha cifrada no banco de dados, e no momento que o usuário for se logar temos que cifrar a senha e comparar com a cifra que está no banco de dados. Mesmo que alguém obtenha o seu banco de dados, ele nunca descobrirá as senhas, pois a chave está encapsulada dentro de sua aplicação.

O.NET Framework fornece as seguintes classes que podem ser usadas para implementar um algoritmo de cifragem usando chave privada:

01. RC2CryptoServiceProvider (algoritmo RC2)
02. DESCryptoServiceProvider (algoritmo DES)
03. TrippleDESCryptoServiceProvider (algoritmo TrippleDES)
04. RijndaelManaged (algoritmo Rijndael ) -->> Estamos usando este método

Vamos criar um pequeno exemplo que irá cifrar e decifrar dados. Por Exemplo:

Nome a ser cifrado: Fabrizio Gianfratti
Resultado cifrado: Ia6tgzjAh5wYOCIRJLvxmnoFAPQnVghAnVJxWqyUaME=
Resultado decifrado: Fabrizio Gianfratti

Inicie um novo projeto no VS.NET e escolha um projeto do tipo Asp.net Web Application usando VB.NET.

Crie um novo WebForm com o nome de Default.asp e siga os passos abaixo.

' ****************************************************************
' ***** Use os seguintes imports                                       
' ****************************************************************

Imports System.Security.Cryptography
Imports System.IO
Imports System.Text


Public Class default2
Inherits System.Web.UI.Page

' ***************************************************************
' ***** Variável com a sua chave secreta                                                    
' ***** Sempre que o numero for alterado, a cifra será diferente                  
' ***** Pode ser passado até 32 caracteres                                                
' ***** Recomendo não deixar essa variável na sua aplicação, por                
' ***** mais estranho que posso ser, existem programas que tem a               
' ***** capacidade de ler a sua DLL, crie um arquivo texto com a                
' ***** sua chave e proteja essa pasta                                                           
' ***************************************************************

' ***************************************************************
' ***** ATENÇÃO!!!! ATENÇÃO!!!! ATENÇÃO!!!! ATENÇÃO!!!!    
' *****
É altamente recomendado que você altere
a variável             
' ***** ChaveSecreta para uma chave de sua escolha.                     
' ***************************************************************

Private ChaveSecreta As String = "0987612345!@#$%¨&*"

' ***************************************************************
' ***** Definimos uma variável a passamos o texto a ser cifrado      
   
' ***************************************************************

Dim Texto As String = "Fabrizio Gianfratti"

' ***************************************************************
' ***** No envento Page Load fazemos a chamadas das funções                  
' ***** No envento Page Load fazemos a chamadas das funções                
' ***************************************************************

Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Response.Write(Cifrar(Texto, ChaveSecreta) & "
")
Response.Write(Decifrar(Cifrar(Texto, ChaveSecreta), ChaveSecreta))
End Sub


' ***************************************************************
' ***** Função responsável por Cifrar a sua String                                
' ***** Use da seguinte forma:                                                               
' ***** Call Cifrar("Palavra", "SuaChaveSecreta(Ex.2345)")                   
' ***************************************************************

Private Function Cifrar(ByVal vstrTextToBeEncrypted As String, ByVal vstrEncryptionKey As String) As String

Dim bytValue() As Byte
Dim bytKey() As Byte
Dim bytEncoded() As Byte
Dim bytIV() As Byte = {121, 241, 10, 1, 132, 74, 11, 39, 255, 91, 45, 78, 14, 211, 22, 62}
Dim intLength As Integer
Dim intRemaining As Integer
Dim objMemoryStream As New MemoryStream
Dim objCryptoStream As CryptoStream
Dim objRijndaelManaged As RijndaelManaged


' ***************************************************************
' ****** Descarta todos os caracteres nulos da palavra a ser cifrada             
' *************************************************************
**

vstrTextToBeEncrypted = TiraCaracteresNulos(vstrTextToBeEncrypted)

' ***************************************************************
' ****** O valor deve estar dentro da tabela ASCII (i.e., no DBCS chars)    
' ***************************************************************

bytValue = Encoding.ASCII.GetBytes(vstrTextToBeEncrypted.ToCharArray)

intLength = Len(vstrEncryptionKey)

' ****************************************************************
' ****** A chave cifrada será de 256 bits long (32 bytes)                             
' ****** Se for maior que 32 bytes então será truncado.                               
' ****** Se for menor que 32 bytes será alocado.                                        
' ****** Usando upper-case Xs.                                                                  
' ****************************************************************

If intLength >= 32 Then
vstrEncryptionKey = Strings.Left(vstrEncryptionKey, 32)
Else
intLength = Len(vstrEncryptionKey)
intRemaining = 32 - intLength
vstrEncryptionKey = vstrEncryptionKey & Strings.StrDup(intRemaining, "X")
End If

bytKey = Encoding.ASCII.GetBytes(vstrEncryptionKey.ToCharArray)

objRijndaelManaged = New RijndaelManaged

' **************************************************************
' ****** Cria o valor a ser crifrado e depois escreve                                  
' ****** Convertido em uma disposição do byte                                       
' **************************************************************

Try

objCryptoStream = New CryptoStream(objMemoryStream, objRijndaelManaged.CreateEncryptor(bytKey, bytIV), CryptoStreamMode.Write)
objCryptoStream.Write(bytValue, 0, bytValue.Length)

objCryptoStream.FlushFinalBlock()

bytEncoded = objMemoryStream.ToArray
objMemoryStream.Close()
objCryptoStream.Close()
Catch

End Try

' **************************************************************
' ****** Retorna o valor cifrado (convertido de byte para base64)           
' **************************************************************

Return Convert.ToBase64String(bytEncoded)

End Function

' **************************************************************
' ***** Função Responsável por Decifrar a sua String Cifrada                     
' ***** Use da seguinte forma:                                                                    
' ***** Call Decifrar ("Palavra", "SuaChaveSecreta(Ex.2345)")                   
' **************************************************************

Private Function Decifrar(ByVal vstrStringToBeDecrypted As String, ByVal vstrDecryptionKey As String) As String

Dim bytDataToBeDecrypted() As Byte
Dim bytTemp() As Byte
Dim bytIV() As Byte = {121, 241, 10, 1, 132, 74, 11, 39, 255, 91, 45, 78, 14, 211, 22, 62}
Dim objRijndaelManaged As New RijndaelManaged
Dim objMemoryStream As MemoryStream
Dim objCryptoStream As CryptoStream
Dim bytDecryptionKey() As Byte

Dim intLength As Integer
Dim intRemaining As Integer
Dim intCtr As Integer
Dim strReturnString As String = String.Empty
Dim achrCharacterArray() As Char
Dim intIndex As Integer

' ***************************************************************
' ****** Convert base64 cifrada para byte array                          
     
' ****** Convert base64 cifrada para byte array                                
' ***************************************************************

bytDataToBeDecrypted = Convert.FromBase64String(vstrStringToBeDecrypted)

' ***************************************************************
' ****** A chave cifrada sera de 256 bits long (32 bytes)                           
' ****** Se for maior que 32 bytes então será truncado.                              
' ****** Se for menor que 32 bytes será alocado.                                       
' ****** Usando upper-case Xs.                                                              
' ***************************************************************

intLength = Len(vstrDecryptionKey)

If intLength >= 32 Then
vstrDecryptionKey = Strings.Left(vstrDecryptionKey, 32)
Else
intLength = Len(vstrDecryptionKey)
intRemaining = 32 - intLength
vstrDecryptionKey = vstrDecryptionKey & Strings.StrDup(intRemaining, "X")
End If

bytDecryptionKey = Encoding.ASCII.GetBytes(vstrDecryptionKey.ToCharArray)

ReDim bytTemp(bytDataToBeDecrypted.Length)

objMemoryStream = New MemoryStream(bytDataToBeDecrypted)

' ***************************************************************
' ****** Escrever o valor decifrado depois que é convertido                      
' ***************************************************************

Try

objCryptoStream = New CryptoStream(objMemoryStream, _
objRijndaelManaged.CreateDecryptor(bytDecryptionKey, bytIV), _
CryptoStreamMode.Read)

objCryptoStream.Read(bytTemp, 0, bytTemp.Length)

objCryptoStream.FlushFinalBlock()
objMemoryStream.Close()
objCryptoStream.Close()

Catch

End Try

' ***************************************************************
' ****** Retorna o valor decifrado                   
                
' ***************************************************************

Return TiraCaracteresNulos(Encoding.ASCII.GetString(bytTemp))

End Function

' ***************************************************************
' ***** Função responsável por tirar os espaços em branco da                      
' ***** variável a ser cifrada                                                                          
' ***** Esta função é chamada internamente                                                  
' ***************************************************************

Private Function TiraCaracteresNulos(ByVal vstrStringWithNulls As String) As String

Dim intPosition As Integer
Dim strStringWithOutNulls As String

intPosition = 1
strStringWithOutNulls = vstrStringWithNulls

Do While intPosition > 0
intPosition = InStr(intPosition, vstrStringWithNulls, vbNullChar)

If intPosition > 0 Then
strStringWithOutNulls = Left$(strStringWithOutNulls, intPosition - 1) & _
Right$(strStringWithOutNulls, Len(strStringWithOutNulls) - intPosition)
End If

If intPosition > strStringWithOutNulls.Length Then
Exit Do
End If
Loop

Return strStringWithOutNulls

End Function

End Class

Para fazer o download do código, clique aqui

Bom, é isso pessoal. Espero que tenham gostado da matéria e, principalmente, que tenha sido útil a todos.

Qualquer duvida estou a disposição no email
fabrizio@gianfratti.com.