Esteganálise
A evolução da Criptologia se deve, em grande parte, às linhas de pesquisa que visam justamente explorar falhas em seu funcionamento, como a Criptoanálise e a Esteganálise.
Como seus nomes indicam, elas consistem na análise de falhas nos algoritmos de criptografia e esteganografia, respectivamente, seja para interceptar informações, garantir a eficiência de determinado método ou buscar falhas que contribuam com o aprimoramento de futuros algoritmos.
As técnicas de esteganálise exploram o funcionamento do algoritmo empregado para ocultar a informação digital. Portanto, cada técnica é específica para determinado tipo de esteganografia. Os algoritmos que serão discutidos a seguir empregam as análises, também conhecidas como ataques, estrutural, visual e estatística, com foco nas imagens esteganografadas com a técnica LSB.
Conforme descrito anteriormente, a esteganografia LSB (Least Significant Bit) consiste em se ocultar bits de informação nos bits menos significativos de cada tom de cor primária que compõe os pixels de uma imagem. Além de não alterar o tamanho do arquivo (já que reorganiza bits ao invés de adicioná-los), esta técnica produz alterações imperceptíveis a olho nu, mesmo comparando-se a imagem esteganografada com a original.
O processo de esteganálise dessas imagens consiste na busca de padrões que permitam identificar a existência de alguma informação embutida nas imagens suspeitas.
A recuperação da informação esteganografada já é um passo mais complexo, uma vez que ela pode estar disposta de forma imprevista, evitando a obviedade de se utilizar os bits menos significativos dos pixels sequencialmente. Além disso, a mensagem pode estar ilegível, uma vez que as técnicas de esteganografia e criptografia costumam ser empregadas em conjunto para proporcionar uma dupla camada de proteção.
Ataque estrutural
Este tipo de ataque tem como foco a análise das propriedades estruturais do arquivo suspeito, no caso as propriedades das imagens digitais.
Em teoria, uma imagem com dados embutidos nos bits menos significativos não possui diferença no tamanho em disco em relação à original, já que não houve inserção propriamente dita de bits extras. Entretanto, alguns formatos de imagem como o PNG realizam uma compressão sem perdas, agregando padrões repetidos e reduzindo o tamanho em disco da mesma.
Mas enquanto os bits da imagem original seguem uma variação padronizada, os da imagem esteganografada possuem bits que tendem a ser randômicos (os bits de informação nos LSBs), o que dificulta a busca de padrões para compressão. Consequentemente, a imagem esteganografada fica maior que a original (já que a sua compressão não é tão eficiente), o que acaba por denunciar o processo de esteganografia.
Já em formatos de imagem que não empregam técnicas de compressão, como o BMP, não é possível determinar se existem dados embutidos apenas observando o tamanho em
disco das imagens.
Neste caso, uma das técnicas mais simples de esteganálise estrutural consiste em comprimir as imagens para o formato ZIP, que como é de se esperar também utiliza compressão sem perdas, e comparar o tamanho dos arquivos comprimidos, seguindo o mesmo princípio de análise das imagens PNG (os formatos ZIP e PNG empregam o mesmo algoritmo de compressão, conhecido como
DEFLATE).
O algoritmo a seguir implementa uma rotina para determinar o nível de alteração entre duas imagens analisando a razão dos tamanhos da imagem original e da imagem suspeita, após uma compressão sem perdas nas mesmas. Se o valor retornado for 1, não há indícios de esteganografia. Quanto mais este valor se afastar de 1, maior a quantidade de informações embutidas na imagem suspeita.
A compressão é realizada utilizando o módulo zipfile da biblioteca padrão da linguagem Python.
# coding: utf-8
import os
import zipfile
def ataque_estrutural(img1, img2):
# Armazena o tamanho das imagens comprimidas;
tam = []
for img in (img1, img2):
# Comprime a imagem
zip = zipfile.ZipFile('imagem.zip', 'w')
zip.write(img, img, zipfile.ZIP_DEFLATED)
# Obtém o tamanho da imagem comprimida;
tam.append(float(zip.infolist()[0].compress_size))
# Fecha o arquivo e o remove
zip.close()
os.remove('imagem.zip')
# Retorna a proporção entre os tamanhos;
return tam[1] / tam[0]