Cyfarchion.
Ddim mor bell yn ôl, pan oeddwn yn astudio yn y brifysgol, roedd yna waith cwrs yn y ddisgyblaeth “Meddalwedd dulliau diogelwch gwybodaeth.” Roedd yr aseiniad yn gofyn i ni greu rhaglen sy'n mewnosod neges mewn ffeiliau GIF. Penderfynais ei wneud yn Java.
Yn yr erthygl hon byddaf yn disgrifio rhai pwyntiau damcaniaethol, yn ogystal â sut y cafodd y rhaglen fach hon ei chreu.
Rhan ddamcaniaethol
Fformat GIF
Mae GIF (Fformat Cyfnewid Graffeg - fformat ar gyfer cyfnewid delweddau) yn fformat ar gyfer storio delweddau graffig, sy'n gallu storio data cywasgedig heb golli ansawdd mewn fformat hyd at 256 o liwiau. Datblygwyd y fformat hwn ym 1987 (GIF87a) gan CompuServe ar gyfer trosglwyddo delweddau raster dros rwydweithiau. Ym 1989, addaswyd y fformat (GIF89a), ychwanegwyd cefnogaeth ar gyfer tryloywder ac animeiddio.
Mae gan ffeiliau GIF strwythur bloc. Mae gan y blociau hyn hyd sefydlog bob amser (neu mae'n dibynnu ar rai baneri), felly mae bron yn amhosibl gwneud camgymeriad ynghylch lleoliad pob bloc. Strwythur y ddelwedd GIF symlaf heb ei hanimeiddio mewn fformat GIF89a:
O'r holl flociau o'r strwythur, yn yr achos hwn bydd gennym ddiddordeb yn y bloc palet byd-eang a'r paramedrau sy'n gyfrifol am y palet:
CT — presenoldeb palet byd-eang. Os gosodir y faner hon, rhaid i'r palet byd-eang ddechrau yn syth ar ôl handlen y sgrin resymegol.
Size — maint palet a nifer y lliwiau yn y llun. Gwerthoedd ar gyfer y paramedr hwn:
Maint
Nifer o liwiau
Maint palet, beit
7
256
768
6
128
384
5
64
192
4
32
96
3
16
48
2
8
24
1
4
12
0
2
6
Dulliau amgryptio
Defnyddir y dulliau canlynol i amgryptio negeseuon mewn ffeiliau delwedd:
Dull LSB (Y Rhan Lleiaf Arwyddocaol).
Dull ychwanegu palet
dull LSB - dull cyffredin o steganograffeg. Mae'n cynnwys disodli'r darnau arwyddocaol olaf yn y cynhwysydd (yn ein hachos ni, y bytes palet byd-eang) gyda darnau'r neges gudd.
Bydd y rhaglen yn defnyddio'r ddau ddarn olaf yn y palet beit byd-eang fel rhan o'r dull hwn. Mae hyn yn golygu, ar gyfer delwedd 24-did, lle mae'r palet lliw yn dri beit ar gyfer coch, glas a gwyrdd, ar ôl ymgorffori neges ynddo, bydd pob cydran lliw yn newid o uchafswm o 3/255 graddiad. Bydd newid o'r fath, yn gyntaf, yn anweledig neu'n anodd sylwi arno i'r llygad dynol, ac yn ail, ni fydd yn weladwy ar ddyfeisiau allbwn gwybodaeth o ansawdd isel.
Bydd faint o wybodaeth yn dibynnu'n uniongyrchol ar faint y palet delwedd. Gan mai maint mwyaf y palet yw 256 o liwiau, ac os yw dau ddarn neges wedi'u hysgrifennu i gydran pob lliw, yna uchafswm hyd y neges (gyda'r palet mwyaf yn y ddelwedd) yw 192 beit. Unwaith y bydd y neges wedi'i hymgorffori yn y ddelwedd, nid yw maint y ffeil yn newid.
Dull ehangu palet, sydd ond yn gweithio ar gyfer y strwythur GIF. Bydd yn fwyaf effeithiol ar ddelweddau gyda phalet bach. Ei hanfod yw ei fod yn cynyddu maint y palet, a thrwy hynny ddarparu gofod ychwanegol ar gyfer ysgrifennu'r bytes angenrheidiol yn lle'r beit lliw. Os ydym yn ystyried mai lleiafswm maint y palet yw 2 liw (6 beit), yna gall maint mwyaf y neges fewnosod fod yn 256 × 3–6 = 762 beit. Yr anfantais yw diogelwch cryptograffig isel; gellir darllen y neges wreiddiedig gan ddefnyddio unrhyw olygydd testun os nad yw'r neges wedi'i hamgryptio ychwanegol.
Rhan ymarferol
Dyluniad rhaglen
Bydd yr holl offer angenrheidiol ar gyfer gweithredu algorithmau amgryptio a dadgryptio yn cael eu cynnwys yn y pecyn com.tsarik.steganography. Mae'r pecyn hwn yn cynnwys y rhyngwyneb Encryptor gyda dulliau encrypt и decrypt, Dosbarth Binary, sy'n darparu'r gallu i weithio gydag araeau didau, yn ogystal â dosbarthiadau eithriad UnableToEncryptException и UnableToDecryptException, y dylid ei ddefnyddio mewn dulliau rhyngwyneb Encryptor rhag ofn y bydd gwallau amgodio a dadgodio yn y drefn honno.
Prif becyn rhaglen com.tsarik.programs.gifed yn cynnwys dosbarth rhaglen rhedadwy gyda dull statig main, sy'n eich galluogi i redeg y rhaglen; dosbarth sy'n storio paramedrau rhaglen; a phecynnau gyda dosbarthiadau eraill.
Bydd gweithrediad yr algorithmau eu hunain yn cael eu cyflwyno yn y pecyn com.tsarik.programs.gifed.gif dosbarthiadau GIFEncryptorByLSBMethod и GIFEncryptorByPaletteExtensionMethod. Bydd y ddau ddosbarth hyn yn gweithredu'r rhyngwyneb Encryptor.
Yn seiliedig ar strwythur y fformat GIF, gallwch greu algorithm cyffredinol ar gyfer cyflwyno neges i'r palet delwedd:
Er mwyn pennu presenoldeb neges mewn delwedd, mae angen ychwanegu dilyniant penodol o ddarnau i ddechrau'r neges, y mae'r datgodiwr yn ei ddarllen yn gyntaf ac yn gwirio cywirdeb. Os nad yw'n cyfateb, yna ystyrir nad oes neges gudd yn y ddelwedd. Nesaf mae angen i chi nodi hyd y neges. Yna testun y neges ei hun.
Diagram dosbarth o'r cais cyfan:
Gweithredu'r rhaglen
Gellir rhannu gweithrediad y rhaglen gyfan yn ddwy gydran: gweithredu dulliau amgryptio rhyngwyneb a dadgryptio Encryptor, mewn dosbarthiadau GIFEncryptorByLSBMethod и GIFEncryptorByPaletteExtensionMethod, a gweithredu'r rhyngwyneb defnyddiwr.
Ystyriwch y dosbarth GIFEncryptorByLSBMethod.
Maes firstLSBit и secondLSBit cynnwys nifer y darnau o bob beit o'r ddelwedd y dylid mewnbynnu'r neges iddo ac o ble y dylid darllen y neges. Maes checkSequence yn storio dilyniant did siec i sicrhau adnabyddiaeth o'r neges wedi'i fewnosod. Dull statig getEncryptingFileParameters yn dychwelyd paramedrau'r ffeil penodedig a nodweddion y neges bosibl.
@Override
public void encrypt(File in, File out, String text) throws UnableToEncodeException, NullPointerException, IOException {
if (in == null) {
throw new NullPointerException("Input file is null");
}
if (out == null) {
throw new NullPointerException("Output file is null");
}
if (text == null) {
throw new NullPointerException("Text is null");
}
// read bytes from input file
byte[] bytes = new byte[(int)in.length()];
InputStream is = new FileInputStream(in);
is.read(bytes);
is.close();
// check format
if (!(new String(bytes, 0, 6)).equals("GIF89a")) {
throw new UnableToEncodeException("Input file has wrong GIF format");
}
// read palette size property from first three bits in the 10-th byte from the file
byte[] b10 = Binary.toBitArray(bytes[10]);
byte bsize = Binary.toByte(new byte[] {b10[0], b10[1], b10[2]});
// calculate color count and possible message length
int bOrigColorCount = (int)Math.pow(2, bsize+1);
int possibleMessageLength = bOrigColorCount*3/4;
int possibleTextLength = possibleMessageLength-2;// one byte for check and one byte for message length
if (possibleTextLength < text.length()) {
throw new UnableToEncodeException("Text is too big");
}
int n = 13;
// write check sequence
for (int i = 0; i < checkSequence.length/2; i++) {
byte[] ba = Binary.toBitArray(bytes[n]);
ba[firstLSBit] = checkSequence[2*i];
ba[secondLSBit] = checkSequence[2*i+1];
bytes[n] = Binary.toByte(ba);
n++;
}
// write text length
byte[] cl = Binary.toBitArray((byte)text.length());
for (int i = 0; i < cl.length/2; i++) {
byte[] ba = Binary.toBitArray(bytes[n]);
ba[firstLSBit] = cl[2*i];
ba[secondLSBit] = cl[2*i+1];
bytes[n] = Binary.toByte(ba);
n++;
}
// write message
byte[] textBytes = text.getBytes();
for (int i = 0; i < textBytes.length; i++) {
byte[] c = Binary.toBitArray(textBytes[i]);
for (int ci = 0; ci < c.length/2; ci++) {
byte[] ba = Binary.toBitArray(bytes[n]);
ba[firstLSBit] = c[2*ci];
ba[secondLSBit] = c[2*ci+1];
bytes[n] = Binary.toByte(ba);
n++;
}
}
// write output file
OutputStream os = new FileOutputStream(out);
os.write(bytes);
os.close();
}
Algorithm a chod ffynhonnell y dull decrypt dosbarth GIFEncryptorByLSBMethod:
@Override
public String decrypt(File in) throws UnableToDecodeException, NullPointerException, IOException {
if (in == null) {
throw new NullPointerException("Input file is null");
}
// read bytes from input file
byte[] bytes = new byte[(int)in.length()];
InputStream is = new FileInputStream(in);
is.read(bytes);
is.close();
// check format
if (!(new String(bytes, 0, 6)).equals("GIF89a")) {
throw new UnableToDecodeException("Input file has wrong GIF format");
}
// read palette size property from first three bits in the 10-th byte from the file
byte[] b10 = Binary.toBitArray(bytes[10]);
byte bsize = Binary.toByte(new byte[] {b10[0], b10[1], b10[2]});
// calculate color count and possible message length
int bOrigColorCount = (int)Math.pow(2, bsize+1);
int possibleMessageLength = bOrigColorCount*3/4;
int possibleTextLength = possibleMessageLength-2; // one byte for check and one byte for message length
int n = 13;
// read check sequence
byte[] csBits = new byte[checkSequence.length];
for (int i = 0; i < 4; i++) {
byte[] ba = Binary.toBitArray(bytes[n]);
csBits[2*i] = ba[firstLSBit];
csBits[2*i+1] = ba[secondLSBit];
n++;
}
byte cs = Binary.toByte(csBits);
if (cs != Binary.toByte(checkSequence)) {
throw new UnableToDecodeException("There is no encrypted message in the image (Check sequence is incorrect)");
}
// read text length
byte[] cl = new byte[8];
for (int i = 0; i < 4; i++) {
byte[] ba = Binary.toBitArray(bytes[n]);
cl[2*i] = ba[firstLSBit];
cl[2*i+1] = ba[secondLSBit];
n++;
}
byte textLength = Binary.toByte(cl);
if (textLength < 0) {
throw new UnableToDecodeException("Decoded text length is less than 0");
}
if (possibleTextLength < textLength) {
throw new UnableToDecodeException("There is no messages (Decoded message length (" + textLength + ") is less than Possible message length (" + possibleTextLength + "))");
}
// read text bits and make text bytes
byte[] bt = new byte[textLength];
for (int i = 0; i < bt.length; i++) {
byte[] bc = new byte[8];
for (int bci = 0; bci < bc.length/2; bci++) {
byte[] ba = Binary.toBitArray(bytes[n]);
bc[2*bci] = ba[firstLSBit];
bc[2*bci+1] = ba[secondLSBit];
n++;
}
bt[i] = Binary.toByte(bc);
}
return new String(bt);
}
Gweithrediad y dosbarth GIFEncryptorByPaletteExtensionMethod yn debyg, dim ond y dull o gadw/darllen gwybodaeth sy'n wahanol.
Yn y dosbarth MainFrame Disgrifir dulliau lapio: encryptImage(Encryptor encryptor) и decryptImage(Encryptor encryptor), prosesu canlyniadau dulliau rhyngwyneb Encryptor a rhyngweithio â'r defnyddiwr, h.y. agor deialog dewis ffeil, dangos negeseuon gwall, ac ati; yn ogystal â dulliau eraill: openImage(), gan ganiatáu i'r defnyddiwr ddewis delwedd, exit(), sy'n gadael y cais. Gelwir y dulliau hyn o Actioneitemau dewislen cyfatebol. Mae'r dosbarth hwn hefyd yn gweithredu dulliau ategol: createComponents() - creu cydrannau ffurf, loadImageFile(File f) — llwytho delwedd i gydran arbennig o ffeil. Gweithrediad y dosbarth GIFEncryptorByPaletteExtensionMethod debyg i weithrediad y dosbarth GIFEncryptorByLSBMethod, Y prif wahaniaeth yw'r ffordd y mae neges beit yn cael ei ysgrifennu a'i ddarllen o'r palet.
Gweithrediad rhaglen
dull LBS
Gadewch i ni ddweud bod delwedd fel hyn:
Yn y ddelwedd hon, mae'r palet yn cynnwys 256 o liwiau (fel y mae Paint yn ei arbed). Y pedwar lliw cyntaf yw: gwyn, du, coch, gwyrdd. Mae lliwiau eraill yn ddu. Bydd y dilyniant didau palet byd-eang fel a ganlyn:
Unwaith y bydd y neges wedi'i mewnosod, bydd y darnau sydd wedi'u tanlinellu yn cael eu disodli gan y darnau o'r neges. Nid yw'r ddelwedd sy'n deillio o hyn bron yn wahanol i'r gwreiddiol.
Gwreiddiol
Delwedd gyda neges wedi'i hymgorffori
Dull ehangu palet
Pan fyddwch chi'n agor delwedd sy'n cynnwys neges gan ddefnyddio'r dull hwn, fe welwch y llun canlynol:
Mae'n amlwg na fydd y dull hwn yn gweithio ar gyfer gweithgareddau ysbïo llawn, ac efallai y bydd angen amgryptio ychwanegol o'r neges.
Mae amgryptio/dadgryptio mewn delweddau animeiddiedig yn gweithio yn union fel mewn delweddau sefydlog rheolaidd, ond nid yw'r animeiddiad wedi'i dorri.