===== Sažetak ===== Kako bi olakšali generiranje forenzičkog materijala za laboratorijske vježbe i ispite napravili smo skripte koje je potrebno iz vršiti samo jednom. Automatizacija generiranja je zahtjevala korištenje liste jmbag-a studenta koji polažu kolegij Forenzika digitalnih dokumenata. Kako izgledaju navedene skirpte moguće je vidjeti [[https://github.com/MarinoRabuzin/ForenzikaSeminar.git|ovdje]]. Također kako se koriste skripte i što je sve potrebno za pokretanje moguće je pročitati u predanom pdf dokumentu. ===== Automatsko generiranje mape i kodova ===== Kako bi svaki student prilikom provjere imao različit primjer zadatka potrebno je generirati kodove za svakog od studenata. To je napravljeno na sljedeći način: ''def generate_codes(jmbags):'' jmbag_code_dir = {} for jmbag in jmbags: jmbag = jmbag.strip() jmbag_int = int(jmbag) random.seed(jmbag_int) code = random.randint(0, jmbag_int * 65537) % 1000 code = str(code) while len(code) < 3: code += str(random.randint(0,9)) jmbag_code_dir[jmbag] = "answer" + str(code) return jmbag_code_dir Unutar funkcije potrebno je poslati listu svih jmbag-a studenata za koje je potrebno kreirati forenzicki materijal. Kako bi se dobila nasumičnost za svakog studenta je potrebno postaviti seed na njegov jmbag jer svaki jmbag je jedinstven i pripada točno jednom studentu pa ga i preko njega možemo identificirati. ''random.seed(jmbag_int)'' ''code = random.randint(0, jmbag_int * 65537) % 1000'' Prva od gore navedenih linija postavlja novi seed za svakog studenta te nakon toga kako bi se dobila još veća nasumičnost dodan je broj **65537** koji se koristi kao javni eksponent RSA enkripcije i na kraju je potrebno uzeti samo zadnje tri znamenke generiranog broja. Sada dolazimo do prvog problema generiranja koda za svakog studenta, a to je što se događa ako su zadnje tri znamenke **007** automatski se brišu vodeće nule. Sljedeće dvije linije koda se brinu o tome da kod uvijek ima tri znamenke: ''while len(code) < 3:'' code += str(random.randint(0,9)) Također za svakog studenta je potrebno napraviti mapu gdje će mu biti pohranjene slike i audio materijal. ''def generate_folder(dir):'' os.mkdir("JMBAGS") file_answers = "" for key in dir.keys(): os.mkdir(os.path.join("JMBAGS/" + key)) generate_watermarks(key, dir.get(key)) file_answers += key + "->" + dir.get(key) + "\n" os.mkdir("ANSWERS") with open("ANSWERS/answers.txt", "w") as f: f.write(file_answers) Nakon ovog koraka svaki student ima kreiranu mapu s njegovim jmbag-om te unutar mape se nalazi modificirana slika na kojoj je potrebno naći watermark, te se naknadno u taj folder mogu dodati i audio materijali tj. modifcirani audio materijal koji će generiratni kod iz gore navedene funkcije "zamutit" kako ne bi bez filtracije bio razumljiv korisniku. Kako se točno automatski generiraju forenzički materijali audio sadržaja objašnjeno je u poglavlju **Automatsko generiranje zvučnih forenzičkih materijala**, a kako se automatski generiraju forenzički materijali slikovnog sadržaja moguće je pročitati u **Automatsko generiranje slikovnih forenzičkih materijala** ===== Automatsko generiranje zvučnih forenzičkih materijala ===== Postupak stvaranja zvučnih forenzičkih materijala se može razdvojiti na dva glavna dijela: - Generiranje glasa s odgovorom u obliku zvučnog zapisa - Modifikacija zvučnog zapisa tako da postane ne razumljiv Budući da je cilj potpuno automatsko generiranje svih zapisa, potrebno je izbijeći snimanje ljudske osobe kako izgovara željeni tekst. Time se treba koristiti tehnologija računalnog stvaranja glasa iz proizvoljnog teksta, koja se naziva Text-To-Speech. Text-To-Speech tehnologija je danas iznimno razvijena te je gotovo nemoguće raspoznati razliku između stvarnog govornika i generiranog glasa. Za uporabu Text-To-Speech tehnologije u Python programskom jeziku, je danas u širokoj primijeni programska biblioteka gTTS. Google Text-To-Speech biblioteka koristi API od Google Translate online alata za generiranje glasa. Ostale biblioteke koje su korištene su numpy, soundfile i pydub. Zatim je za određene funkcionalnosti nekih Python biblioteka potrebno postaviti ffmpeg na računalu. ffmpeg je svojevrsni švicarski nožić za audio-video modifikaciju. ''from gtts import gTTS'' ''text = **generirani kod**'' ''language = "en"'' ''audio = gTTS(text=text, lang=language, slow=False)'' ''audio.save("audio.mp3")'' Navedeni isječak generira proizvolja tekst na engleskome. Tekst koji se izgovara se postavalja kao text parametar, jezik kao lang parametar i slow se postavlja na False jer pre sporo čita inače. ''sound = AudioSegment.from_mp3("audio.mp3")'' ''sound.export("audio.wav", format="wav")'' Navedenim linijama se generirana datoteka formata mp3 pretvara u format wav. Naime, gTTS može stvarati samo mp3 datoteke dok je wav pogodonija za uređivanje te ju je zato potrebno pretvoriti u drugi oblik. ''signal, sr = sf.read("audio.wav")'' ''RMS = math.sqrt(np.mean(signal**2))'' ''noise = np.random.normal(0, RMS*8, signal.shape[0])'' Zatim ponovno pročitatmo daototeku u wav formatu kako bi je mogli uređivati u potpunosti. U RMS varijablu računamo prosječnu glasnoću govora te time dobivamo dobru referentnu vrijednost za određivanje intenziteta manipulacije. Primjer tome je zadnja linija koja generira šum po normalnoj razdiobi. Zadnja dva parametra su jedini koji su bitni za ispravno generiranje šuma. Drugi parametar je standardna devijacija razdiobe te ona određuje raspon glasnoće šuma, dok zadnji parametar govori o duljini šuma. Time dobivamo šum određene glasnoće koji odgovara duljini glasa. ''signal_noise = signal + noise'' Budući da su svi zvučni signali u Pythonu prikazani kao numpy polja, moguće je dodavanjem zbrojiti signale te dobiti potpuni zapis. Time smo sada dobili audio zapis koji sadržava šum dovoljno glasan da nije moguće razlikovati govor. Naime nailazimo na jedan problem a to je da šum potencijalno nije moguće ukloniti ako se frekvencije suvišno preklapaju sa stvarnim govorom. Zato je potrebno istražiti druge metode generiranja šuma koje ne uništavaju integritet glasa. ===== Automatsko generiranje slikovnih forenzičkih materijala ===== Kod automatskog generiranja slikovnog forenzičkog materijala konkretno se misli na stavljanje //watermarka// unutar slike. Kako bi //watermark// što skriveniji potrebno je za početnu sliku uzeti sliku sa jakim tamnim bojama kao što su: smeđa, crna, ljubičasta ... Jer kod takvih boja //watermark// neće biti uočljiv golim okom i preko alata za analizu dodavanja elementa u sliku neće odmah biti uočljiv //watermark// nego će osoba morati malo korigirati parametre kako bi //watermark// bio vidljiv i razumljiv. Početna slika: {{ :racfor_wiki:fdd:slika.jpg?nolink&400 |}} Za umetanje //watermarka// unutar slike korišten je //python library Pillow//. Dokumentaciju //library-a// moguće je vidjeti [[https://pillow.readthedocs.io/en/stable/|ovdje]]. Na početku je potrebno učitati sliku. //Pillow library// omogućuje otvaranje bilo koje ekstenzije slike, ali je zato radi modifikacije potrebno napraviti konverziju u RGBA model boja. RGBA je zapravo model boja isti kao i RGB samo je moguće mjenjati koliko će koja boja biti izražena (A - alfa faktor). Nakon učitanjavanja slike potrebno je napraviti novi sloj na kojem će se pisati generairani //watermark//. Sljedeće dvije linije rade opisani postupak: ''img = Image.open('slika.jpg').convert("RGBA")'' ''txt = Image.new('RGBA', img.size, (255,255,255,0))'' Nakon što je slika učitana i kreiran je sloj na kojem će se pisati potrebno je postaviti font s kojim će se pisati i sami tekst koji će biti napisan. Kada su svi ti parametri određeni moguće je "spojiti" dva sloja tj. sliku i tekst funckijom .Draw(), ali još uvijek ništa nije ubačeno u sliku. ''text = generirani kod'' ''font = ImageFont.truetype("arial.ttf", 82)'' ''d = ImageDraw.Draw(txt)'' Sada je potrebno odrediti poziciju na kojoj će se nalaziti //watermark//. Na početnoj slici je to najbolje postaviti na neko tamno područje kao što je npr. voda ispred grada u ovom slučaju. Ovih nekoliko linija računa poziciju gdje će se nalaziti //watermark//: ''width, height = img.size'' ''textwidth, textheight = d.textsize(text, font)'' ''x=width/2-textwidth/2'' ''y=height-textheight-300'' Nakon što je određena pozicija slike potrebno je konačno ubaciti //watermark// u sliku. Za to je zadužena operacija d.text() koja na gore kreiranom zajedničkom sloju ubacuje tekst s atributima koji su gore postavljeni i postavlja boju teksta u crnu s vidljivosti (alpha faktorom) od 6% kako bi bio što neprimjetniji. Zašto je ovdje alpha faktor baš 6%, jer kod analize ubacivanja teksta u sliku //watermark// neće biti vidljiv ako se alpha faktor smanji preblizu nule. Funckija alpha_composite() spaja dva sloja do kraja te ih pretvara u jednu sliku u kojoj je umetnut //watermark//. Na kraju postupka slika se pohranjuje u točno određenu mapu studenta ovisno o njegovom jmbag-u. ''d.text((x,y+100), text, fill=(0,0,0,6), font=font)'' ''watermarked = Image.alpha_composite(img, txt)'' ''watermarked.save(f'./JMBAGS/{key}/watermarked.png')'' Usporedba slika prije i poslije umetanja //watermarka// (lijeva je početna): {{ :racfor_wiki:fdd:slika.jpg?nolink&300|}} {{:racfor_wiki:fdd:watermarked.png?nolink&300 |}} Kako izgleda //watermark// kada se napravi adekvatna analiza za pretragu (answer518): {{ :racfor_wiki:fdd:nakon_analize.png?nolink&600 |}} ===== Zaključak ===== Automatsko generiranje forenzičkog materijala je uspiješno izvedena. Kvaliteta samog generiranog sadržaja je vrlo kvalitetna u smislu nije na prvi pogleda vidljiva razlika kod modificirane slike, a niti kod zvučnog sadržaja od originala. Također kodovi su različiti za svakog studenta tako da se dane skripte mogu koristi za kreiranje laboratorijskih vježbi i samog ispita. Skripte koje su napravljene za automatsko generiranje forenzičkog materijala su iznimno lake za pokretanje tj. nije potrebna nikakva modifikacija nego samo pokretanje skripte prateći upute koje su predane u pdf dokumentu. ===== Literatura ===== [1] [[https://github.com/jiaaro/pydub/blob/master/API.markdown]] [2] [[https://gtts.readthedocs.io/en/latest/]] [3] [[https://pysoundfile.readthedocs.io/en/latest/]] [4] [[https://pillow.readthedocs.io/en/stable/]] [5] [[https://29a.ch/photo-forensics/#forensic-magnifier]] ~~DISCUSSION~~