Chaves Simétricas (Privada) |
Para proteger a confidencialidade da informação transmitida/trocada , ela pode ser cifrada pelo remetente e decifrada pelo destinatário. Ambas as partes podem usar a mesma chave para cifrar e decifrar os dados usando um algoritmo de criptografia simétrica.
Assim um algoritmo de criptografia simétrica é um processo de criptografia em dois sentidos que usa a mesma chave para cifrar/decifrar a informação.
O emissor/remetente utiliza essa chave para cifrar a informação, e o receptor/destinatário utiliza a mesma chave para decifrá-la. Assim as chaves são compartilhadas e por utilizar a mesma chave no processo ele é conhecido como criptografia simétrica.
A dificuldade é que as chaves necessitam ser enviadas de forma segura entre as partes, pois qualquer pessoa que possua a chave pode ter acesso à informação trocada/transmitida.
Os algoritmos de chave simétrica podem cair em duas categorias :
Nota: O Advanced Encryption Standard (AES) utiliza a cifragem de bloco de 128 bits.
A seguir temos os algoritmos de criptografia simétrica incluídos na plataforma .NET
Os algoritmos AES, DES e Triple DES compartilham a classe base abstrata comum e todos herdam de SymmetricAlgorithm.
Dessa forma, uma informação sendo enviada de Maria para José onde os dois possuem acesso à mesma chave de encriptação(cifragem) pode ser cifrada por Maria.
Depois de receber a informação José pode usar o mesmo algoritmo para decifrar a informação preservando a confidencialidade da mesma.
Devido ao risco da chave ser interceptada durante a transmissão a integridade dos dados pode estar comprometida.
Outro problema enfrentado neste processo é o número de chaves necessárias para realizar a comunicação com mais de duas pessoas.
Se 3 pessoas desejam se comunicar usando chaves secretas serão necessárias 3 chaves :
Uma chave compartilhada entre a pessoa A e a pessoa B
Uma chave compartilhada entre a pessoa A e a pessoa C
Uma chave compartilhada entre a pessoa B e a pessoa C
Assim para realizar a comunicação entre n pessoas usando chaves privadas (secretas) seriam necessários (n) (n-1) / 2 chaves o que traz um grande problema de gerenciamento de chaves.
Uma tentativa de solucionar este problema é a criação de um centro de distribuição de chaves que faria a comunicação entre as pessoas aos pares, mas para isso a central de gerenciamento teria que possuir as chaves de todas as pessoas envolvidas no processo.
Criando chaves Simétricas |
Para começar vamos definir o conceito de cifras.
Uma cifra é definida sobre um par de algoritmos de encriptação (Enc) e um algoritmo de desencriptação (Des) da seguinte forma:
1- Processo de encriptaçãotexto cifrado = Encriptação( chave simétrica, mensagem(texto plano) ) ou tcf = Enc ( k, m)
2- Processo de desencriptação
mensagem(texto plano) = Desencriptação( chave simétrica, texto cifrado ) ou m = Des ( k, tcf)
Vejamos a seguir uma aplicação prática definida na plataforma .NET.
Encriptação e desencriptação com chave simétrica usando o algoritmo Rijndael
Em Criptografia, o Advanced Encryption Standard (AES, ou Padrão de Criptografia Avançada), também conhecido por Rijndael, é uma cifra de bloco adotada como padrão de criptografia pelo governo dos Estados Unidos.
Na plataforma .NET temos que a classe RijndaelManaged é a implementação concreta desse algoritmo.
No exemplo vamos demonstrar como gerar uma chave simétrica usando o algoritmo Rijndael e usar essa chave para criptogragar e descriptografar uma cadeia de texto. A chave será derivada de várias características que iremos informar para a rotina.
Vamos criar uma aplicação do tipo Windows Forms Application no Visual Studio Community 2015 e criar uma classe chamada Criptografia.
Nesta classe vamos implementar dois métodos estáticos (Shared) :
O método Encriptar - Cifra o texto informado usando uma chave simétrica;
O método Descriptar - Decifra um texto cifrado usando a chave simétrica;
A seguir a implementação dos métodos Encriptar() e Descriptar() no VB .NET :
Public Shared Function Encriptar _
(
ByVal textoPlano As String,
ByVal palavraPasse As String,
ByVal valorSal As String,
ByVal algoritmoHash As String,
ByVal senhaIteracoes As Integer,
ByVal vetorInicial As String,
ByVal tamanhoChave As Integer
) _
As String
' Converte strings em um array de byte
' Vamos assumir que a string contém somente código ASCII
' Se a string incluir caracteres Unicode, utilize o enconding UTF7 ou UTF8
Dim vetorInicialBytes As Byte()
vetorInicialBytes = Encoding.ASCII.GetBytes(vetorInicial)
Dim valorSalBytes As Byte()
valorSalBytes = Encoding.ASCII.GetBytes(valorSal)
' Converte o texto contido em textoPlano.Text em um array de byte
' Vamos assumir que o texto contém somente caracteres UTF8-encoded
Dim textoPlanoBytes As Byte()
textoPlanoBytes = Encoding.UTF8.GetBytes(textoPlano)
' Primeiro precisamos criar uma senha a partir da qual a chave será derivada,
' Esta senha será gerada a partir da palavraPasse informada e o valor do sal.
' Ela será criada usando um algoritmo de hash especifico
Dim password As PasswordDeriveBytes
password = New PasswordDeriveBytes _
(
palavraPasse,
valorSalBytes,
algoritmoHash,
senhaIteracoes
)
' Usa a senha para gerar bytes para a chave de encriptação.
' Especifique o tamanho da chave em bytes
Dim bytesChave As Byte()
bytesChave = password.GetBytes(tamanhoChave / 8)
' Cria um objeto de encriptação Rijndael
Dim chaveSimetrica As RijndaelManaged
chaveSimetrica = New RijndaelManaged()
' Definindo o modo de cifratem para Block Chaining (CBC)
chaveSimetrica.Mode = CipherMode.CBC
' Gera o encriptador a partri da chave existente e do vetor de inicialização.
' O tamanho da chave será defini basedo no número de bytes da chave
Dim encriptador As ICryptoTransform
encriptador = chaveSimetrica.CreateEncryptor(bytesChave, vetorInicialBytes)
' Define um memory stream o que será usado para tratar os dados cifrados
Dim memoryStream As MemoryStream
memoryStream = New MemoryStream()
' Define o stream criptrografico
Dim cryptoStream As CryptoStream
cryptoStream = New CryptoStream _
(
memoryStream,
encriptador,
CryptoStreamMode.Write
)
' Inicia a cifragem
cryptoStream.Write(textoPlanoBytes, 0, textoPlanoBytes.Length)
' Termina a cifragem
cryptoStream.FlushFinalBlock()
' Converte os dados cifrados a partir dá memória em um array de byte
Dim bytesTextoCifrado As Byte()
bytesTextoCifrado = memoryStream.ToArray()
' fecha os streams
memoryStream.Close()
cryptoStream.Close()
' Converte os dados crifados em uma string base64-encoded.
Dim textoCifrado As String
textoCifrado = Convert.ToBase64String(bytesTextoCifrado)
' Retorna a string cifrada
Encriptar = textoCifrado
End Function
|
Public Shared Function Descriptar _
(
ByVal textoCifrado As String,
ByVal palavraPasse As String,
ByVal valorSal As String,
ByVal algoritmoHash As String,
ByVal senhaIteracoes As Integer,
ByVal vetorInicial As String,
ByVal tamanhoChave As Integer
) _
As String
' Converte strings definindo as caracteristicas da chave de encriptação em um array de bytes
Dim vetorInicialBytes As Byte()
vetorInicialBytes = Encoding.ASCII.GetBytes(vetorInicial)
Dim valorSalBytes As Byte()
valorSalBytes = Encoding.ASCII.GetBytes(valorSal)
' Converte o nosso textoCifrado em um array de byte
Dim bytesTextoCifrado As Byte()
bytesTextoCifrado = Convert.FromBase64String(textoCifrado)
' Primeiro precisamos criar uma senha a partir da qual a chave será derivada,
' Esta senha será gerada a partir da palavraPasse informada e o valor do sal.
' Ela será criada usando um algoritmo de hash especifico
Dim password As PasswordDeriveBytes
password = New PasswordDeriveBytes _
(
palavraPasse,
valorSalBytes,
algoritmoHash,
senhaIteracoes
)
' Usa a senha para gerar bytes para a chave de encriptação.
' Especifique o tamanho da cahve em bytes
Dim bytesChave As Byte()
bytesChave = password.GetBytes(tamanhoChave / 8)
' Cria um objeto Rijndael
Dim chaveSimetrica As RijndaelManaged
chaveSimetrica = New RijndaelManaged()
' Definindo o modo de cifratem para Block Chaining (CBC)
chaveSimetrica.Mode = CipherMode.CBC
' Gera o descriptador a partir dos bytes da chave existente e do vetor de inicialização
' O tamanho da cahve será definido com base no número de bytes da chave
Dim descriptador As ICryptoTransform
descriptador = chaveSimetrica.CreateDecryptor(bytesChave, vetorInicialBytes)
' Define um memory stream o que será usado para tratar os dados cifrados
Dim memoryStream As MemoryStream
memoryStream = New MemoryStream(bytesTextoCifrado)
' Define um memory stream que sera usado para tratar os dados cifrados
Dim cryptoStream As CryptoStream
cryptoStream = New CryptoStream _
(
memoryStream,
descriptador,
CryptoStreamMode.Read
)
' Como não sabemos o tamanho dos dados decifrados
' alocamos o buffer com o tamanho suficiente para tratar os dados
Dim textoPlanoBytes As Byte()
ReDim textoPlanoBytes(bytesTextoCifrado.Length)
' Inicia a desencriptação
Dim contadorByteDescriptado As Integer
contadorByteDescriptado = cryptoStream.Read _
(
textoPlanoBytes,
0,
textoPlanoBytes.Length
)
' fecha os streams
memoryStream.Close()
cryptoStream.Close()
' Converte o dado decifrado em uma string
Dim textoPlano As String
textoPlano = Encoding.UTF8.GetString _
(
textoPlanoBytes,
0,
contadorByteDescriptado
)
' Retorna a string decifrada
Descriptar = textoPlano
End Function
|
Para testar a nossa implementação vamos incluir no formulário form1.vb os seguintes controles:
TextBox - txtTexto
TextBox - txtTextoCifrado
TextBox - txtTextoDecifrado2
2 Buttons - btnCifrar e btnDecifrar
Conforme o leiaute da figura abaixo:
A seguir defina o código abaixo para este formulário:
Public Class Form1
Dim plainText As String
Dim cipherText As String
Dim palavraPasse As String = "Pas5pr@se" ' pode ser qualquer string
Dim valorSal As String = "s@1tValue" ' pode ser qualquer string
Dim algoritmoHash As String = "SHA1" ' pode ser MD5
Dim senhaIteracoes As Integer = 2
Dim vetorInicial As String = "@1B2c3D4e5F6g7H8" ' tem que ser 16 bytes
Dim tamanhoChave As Integer = 256 ' pode ser 192 ou 128
Private Sub btnCifrar_Click(sender As Object, e As EventArgs) Handles btnCifrar.Click
If txtTexto.Text = String.Empty Then
MessageBox.Show("Informe o texto")
Return
Else
txtTextoCifrado.Text = ""
txtTextoCifrado.Text = Criptografia.Encriptar(txtTexto.Text,
palavraPasse,
valorSal,
algoritmoHash,
senhaIteracoes,
vetorInicial,
tamanhoChave)
End If
End Sub
Private Sub bnDecifrar_Click(sender As Object, e As EventArgs) Handles bnDecifrar.Click
If txtTextoCifrado.Text = String.Empty Then
MessageBox.Show("Não existe texto cifrado a decifrar")
Return
Else
txtTextoDecifrado.Text = ""
txtTextoDecifrado.Text = Criptografia.Descriptar(txtTextoCifrado.Text,
palavraPasse,
valorSal,
algoritmoHash,
senhaIteracoes,
vetorInicial,
tamanhoChave)
End If
End Sub
End Class
|
Observe que estamos definindo alguns valores padrão para os parâmetros usados pelo método Encriptar().
Executando o projeto e realizando as operações de cifragem e decifragem iremos obter o seguinte resultado:
Pegue o projeto completo com as implementações feitas em CSharp e VB .NET aqui : CriptografiaChaveSimetrica.zip
Na próxima aula vamos continuar a ver as demais técnicas de criptografia.
Na verdade, na verdade vos digo que
quem ouve a minha palavra, e crê naquele que me enviou, tem a vida eterna, e não
entrará em condenação, mas passou da morte para a vida.
João 5:24
Referências :