Lang geleden schreef ik mijn . En die post was gewijd aan een zeer interessant probleem, namelijk steganografie. Natuurlijk kan de oplossing die in dat oude topic werd voorgesteld niet als steganografie in de ware zin van het woord worden beschouwd. Het is slechts een spel met bestandsformaten, maar desondanks een vrij interessant spel.
Vandaag zullen we iets dieper graven en het LSB-algoritme bekijken. Als je geïnteresseerd bent, nodig ik je uit om verder te lezen. (Onder de leeslink is het dataverkeer: ongeveer een megabyte.)
Allereerst is het nodig om een kleine inleiding te geven. Iedereen weet dat de bedoeling van cryptografie is om het lezen van geheime informatie onmogelijk te maken. Natuurlijk heeft cryptografie zijn toepassingsgebieden, maar er is ook een andere benadering van gegevensbescherming. Informatie hoeft niet versleuteld te worden; we kunnen doen alsof we het niet hebben. Steganografie is precies daarvoor bedacht. Wikipedia verzekert ons dat "steganografie (van het Griekse στεγανοσ — verborgen en het Griekse γραφω — schrijven, letterlijk 'geheimschrift') de wetenschap is van het verborgen overbrengen van informatie door het feit van de overdracht zelf geheim te houden.
Natuurlijk is het niemand verboden om cryptografische en steganografische methoden te combineren. Sterker nog, in de praktijk gebeurt dit vaak, maar onze taak is om de basisprincipes te begrijpen. Als je het Wikipedia-artikel aandachtig bestudeert, kun je leren dat in steganografie-algoritmen de termen container en bericht worden gebruikt. De container is elke informatie die helpt ons geheime bericht te verbergen.
In ons geval zal de container een afbeelding in BMP-formaat zijn. Laten we beginnen met de structuur van dit bestand te bekijken. Het bestand kan ruwweg worden opgesplitst in 4 delen: de bestandskop, het afbeeldingskop, de palette en de eigenlijke afbeelding. Voor onze doeleinden is het belangrijk genoeg om te weten wat er in de koptekst is opgeslagen.
De eerste twee bytes van de koptekst zijn de handtekening BM, vervolgens staat in een dubbele woord de bestandsgrootte in bytes, de volgende 4 bytes zijn gereserveerd en moeten nullen bevatten en tenslotte staat in nog een dubbele woord het offset van het begin van het bestand tot de eigenlijke afbeeldingsbytes. In een 24-bits bmp-bestand wordt elke pixel gecodeerd met drie bytes BGR.
Nu weten we hoe we bij de afbeelding kunnen komen, is het tijd om te begrijpen hoe we de benodigde informatie daarin kunnen opslaan. Hiervoor zullen we de LSB-methode gebruiken. Het principe van de methode is als volgt: we vervangen de minst significante bits in de bytes die verantwoordelijk zijn voor de kleurcodering. Stel dat een byte van ons geheime bericht – 11001011 is, en de bytes in de afbeelding zijn …11101100 01001110 01111100 0101100111…, dan ziet de codering er als volgt uit. We splitsen de byte van het geheime bericht in 4 delen van twee bits: 11, 00, 10, 11, en vervangen de minst significante bits van de afbeelding: …11101111 01001100 01111110 0101100111…. Deze vervangingen zijn over het algemeen niet waarneembaar voor het menselijk oog. Bovendien kunnen veel oude uitvoerapparaten zulke onbeduidende veranderingen zelfs niet weergeven.
Het is duidelijk dat we niet alleen de 2 minst significante bits kunnen wijzigen, maar ook elk ander aantal. Hier is de volgende regel: hoe meer bits we wijzigen, hoe meer informatie we kunnen verbergen en hoe groter de verstoringen in de oorspronkelijke afbeelding zullen zijn. Ter illustratie hier zijn twee afbeeldingen:


Ondanks mijn inspanningen kon ik het verschil tussen de twee niet zien, en toch is in de tweede afbeelding met de beschreven methode het gedicht 'The Hunting of the Snark' van Lewis Carroll verborgen. Als je tot dit punt bent gekomen, ben je vast ook benieuwd naar de implementatie. Die is vrij eenvoudig, maar ik waarschuw je vooraf dat alles in Delphi is gemaakt. Hiervoor zijn twee redenen: 1. Ik beschouw Delphi als een goede, bruikbare taal; 2. Dit programma is ontstaan tijdens de voorbereiding van een cursus over de basisprincipes van machine vision, en de jongens aan wie ik deze cursus geef, weten vooralsnog niets anders dan Delphi. Voor degenen die niet vertrouwd zijn met de syntaxis, moet ik één ding verduidelijken: shl x – bitverschuiving naar links met x, shr x – bitverschuiving naar rechts met x.
Laten we aannemen dat we de tekst in de container opslaan, opgeslagen in een string en de minst significante twee bytes vervangen:
Code voor schrijven:
for i:=1 to length(str) do
begin
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.Position:=f.Position-1;
tmp:=((tmp shr 2) shl 2)+l1;
f.WriteBuffer(tmp,1);
f.ReadBuffer(tmp,1);
f.Position:=f.Position-1;
tmp:=((tmp shr 2) shl 2)+l2;
f.WriteBuffer(tmp,1);
f.ReadBuffer(tmp,1);
f.Position:=f.Position-1;
tmp:=((tmp shr 2) shl 2)+l3;
f.WriteBuffer(tmp,1);
f.ReadBuffer(tmp,1);
f.Position:=f.Position-1;
tmp:=((tmp shr 2) shl 2)+l4;
f.WriteBuffer(tmp,1);
end;
code voor lezen:
for i:=1 to MsgSize do
begin
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;
En voor de echt luie – .
We wachten op je in onze
Bron: habr.com
