Era uma vez eu escrevi meu
Hoje tentaremos nos aprofundar um pouco mais e examinar o algoritmo LSB. Se você estiver interessado, será bem-vindo no gato. (Sob o corte está o tráfego: cerca de um megabyte.)
Antes de mais nada é necessário fazer uma breve introdução. Todo mundo sabe que o objetivo da criptografia é impossibilitar a leitura de informações secretas. É claro que a criptografia tem suas aplicações, mas existe outra abordagem para a proteção de dados. Não precisamos criptografar as informações, mas fingir que não as temos. É precisamente por isso que a esteganografia foi inventada. A Wikipedia nos garante que “a esteganografia (do grego στεγανοσ - oculto e do grego γραφω - escrevo, literalmente “escrita secreta”) é a ciência da transmissão oculta de informações, mantendo em segredo o próprio fato da transmissão.
É claro que ninguém proíbe combinar métodos criptográficos e esteganográficos. Além disso, na prática eles fazem isso, mas nossa tarefa é entender o básico. Se você estudar cuidadosamente o artigo da Wikipedia, descobrirá que os algoritmos de esteganografia incluem os chamados. contêiner e mensagem. Um contêiner é qualquer informação que ajude a ocultar nossa mensagem secreta.
No nosso caso, o container será uma imagem em formato BMP. Primeiro, vamos dar uma olhada na estrutura deste arquivo. O arquivo pode ser dividido em 4 partes: cabeçalho do arquivo, cabeçalho da imagem, paleta e a própria imagem. Para nossos propósitos, só precisamos saber o que está escrito no cabeçalho.
Os dois primeiros bytes do cabeçalho são a assinatura BM, depois o tamanho do arquivo em bytes é escrito em uma palavra dupla, os próximos 4 bytes são reservados e devem conter zeros e, por fim, outra palavra dupla contém o deslocamento do início do arquivo para os bytes reais da imagem. Em um arquivo bmp de 24 bits, cada pixel é codificado com três bytes BGR.
Agora que sabemos como chegar à imagem, só falta entender como podemos escrever ali as informações que precisamos. Para isso precisaremos do método LSB. A essência do método é a seguinte: substituímos os bits menos significativos nos bytes responsáveis pela codificação de cores. Digamos que se o próximo byte da nossa mensagem secreta for 11001011, e os bytes na imagem forem...11101100 01001110 01111100 0101100111..., então a codificação ficará assim. Dividiremos o byte da mensagem secreta em 4 partes de dois bits: 11, 00, 10, 11 e substituiremos os bits de ordem inferior da imagem pelos fragmentos resultantes: ...11101111 01001100 01111110 0101100111…. Tal substituição geralmente não é perceptível ao olho humano. Além disso, muitos dispositivos de saída mais antigos nem serão capazes de exibir essas pequenas alterações.
É claro que você pode alterar não apenas os 2 bits menos significativos, mas qualquer número deles. Existe o seguinte padrão: quanto mais bits alterarmos, mais informações poderemos ocultar e mais interferência isso causará na imagem original. Por exemplo, aqui estão duas imagens:
Apesar dos meus melhores esforços, não consegui ver a diferença entre eles, mas mesmo assim, na segunda imagem, usando o método descrito, o poema de Lewis Carroll “The Hunting of the Snark” está escondido. Se você leu até aqui, provavelmente está interessado em aprender sobre a implementação. É bem simples, mas já aviso que tudo é feito em Delphi. Há duas razões para isso: 1. Acho Delphi uma boa linguagem; 2. Este programa nasceu no processo de preparação de um curso sobre noções básicas de visão computacional, e os caras para quem estou ministrando este curso ainda não sabem nada além de Delphi. Para aqueles que não estão familiarizados com a sintaxe, uma coisa precisa ser explicada: shl x é um deslocamento bit a bit para a esquerda por x, shr x é um deslocamento bit a bit para a direita por x.
Assumimos que estamos escrevendo o texto armazenado em uma string no contêiner e substituindo os dois bytes inferiores:
Código de gravação:
para i:=1 para comprimento(str) faça
começar
l1:=byte(str[i]) shr 6;
l2:=byte(str[i]) shl 2; l2:=l2 shr 6;
l3:=byte(str[i]) shl 4; l3:=l3 shr 6;
l4:=byte(str[i]) shl 6; l4:=l4 shr 6;
f.ReadBuffer(tmp,1);
f.Posição:=f.Posição-1;
tmp:=((tmp shr 2) shl 2)+l1;
f.WriteBuffer(tmp,1);
f.ReadBuffer(tmp,1);
f.Posição:=f.Posição-1;
tmp:=((tmp shr 2) shl 2)+l2;
f.WriteBuffer(tmp,1);
f.ReadBuffer(tmp,1);
f.Posição:=f.Posição-1;
tmp:=((tmp shr 2) shl 2)+l3;
f.WriteBuffer(tmp,1);
f.ReadBuffer(tmp,1);
f.Posição:=f.Posição-1;
tmp:=((tmp shr 2) shl 2)+l4;
f.WriteBuffer(tmp,1);
end;
código para ler:
para i:=1 para MsgSize faça
começar
f.ReadBuffer(tmp,1);
l1:=tmp shl 6;
f.ReadBuffer(tmp,1);
l2:=tmp shl 6; l2:=l2 shr 2;
f.ReadBuffer(tmp,1);
l3:=tmp shl 6; l3:=l3 shr 4;
f.ReadBuffer(tmp,1);
l4:=tmp shl 6; l4:=l4 shr 6;
str:=str+char(l1+l2+l3+l4);
end;
Bem, para os realmente preguiçosos -
Obrigado.
Fonte: habr.com