#!/usr/bin/env murgaLua -- GUI for steghide -- function is limited to embedding data into jpg -- 2010 mikshaw -- version 0.1 function apply_img(img) image=img -- global image filename local imgdata=fltk:Fl_JPEG_Image(img) local w=imgdata:w() local h=imgdata:h() if w>0 and h>0 then imgbox:image(imgdata) end local outname=string.gsub(image,"(.*)%..*","%1_stego.jpg") outpoot:value(outname) -- display image info/capacity in menu bar local my_cmd=io.popen("steghide info "..image.." -p nothing") local my_result=my_cmd:read("*a") my_cmd:close() local cap_str=string.gsub(my_result,".*capacity:%s*([%d%.]*%s*%a+).*","%1") local cap_num=string.gsub(cap_str,"([%d%.]*).*","%1") local cap_fmt=string.gsub(cap_str,"[%d%.%s]*(%a+)","%1") if cap_fmt=="Byte" then cap_num=math.floor(cap_num); mult=1 elseif cap_fmt=="KB" then mult=1024 end local chars=math.floor(cap_num*mult) imgbar:menu(0):label(fltk.fl_filename_name(img).. " | "..w.."x"..h.." | embed capacity: "..cap_str) textfield:label("Your message ("..chars.." character limit for this image):") textfield:redraw_label() imgbox:size(w,h) imgscr:position(0,0) imgscr:redraw() imgbar:redraw() end function choose_img() local img=fltk.fl_file_chooser("Choose a JPEG","*.jp{e,}g",nil,0) if img then apply_img(img) end end function choose_target() local target=fltk.fl_file_chooser("Save As...","*.jp{e,}g",nil,0) if target then outpoot:value(target) end end function write_file() if not image then tabs:value(t1) fltk.fl_alert("You must choose an image file.") return end if outpoot:value()=="" then fltk.fl_alert("You must supply an output filename.") return end if embpass:value()=="" then fltk.fl_alert("You must set a password.") return end local tmp=os.tmpname()..".txt" local out=io.open(tmp,"w") if out then out:write(textfield:value()) out:close() else fltk.fl_alert("Can't read "..tmp.." for some reason") end if overw:value()==1 then ow=" -f " else ow="" end os.execute("steghide embed -ef "..tmp.." -cf "..image.." -sf "..outpoot:value().. " -p "..embpass:value()..ow.." -e "..enc_menu:text(enc_menu:value()).." "..mod_menu:text(mod_menu:value())) os.remove(tmp) end function extract(cmd) if not image then tabs:value(t1) fltk.fl_alert("You must choose an image file.") return end if extpass:value()=="" then fltk.fl_alert("You must supply a password.") return end local my_cmd=io.popen("steghide "..cmd..image.." -p "..extpass:value()) local my_result=my_cmd:read("*a") my_cmd:close() extbuff:append(my_result.."\n") end bh=30; ww=500; wh=bh*20 w=fltk:Fl_Double_Window(ww,wh,"Steghide") tabs=fltk:Fl_Tabs(0,0,ww,wh) -- IMAGE TAB -- t1=fltk:Fl_Group(0,bh,ww,wh-bh,"image file") t1:selection_color(46) imgbar=fltk:Fl_Menu_Bar(0,bh,ww,bh) imgbar:add("click here to choose an image") imgbar:menu(0):callback(choose_img) imgscr=fltk:Fl_Scroll(0,bh*2,ww,wh-bh*2) imgbox=fltk:Fl_Box(0,bh*2,ww,wh-bh*2) fltk:Fl_End() --imgscr imgbox:align(85) fltk:Fl_End() --t1 -- EMBED TAB -- t2=fltk:Fl_Group(0,bh,ww,wh-bh,"embed") t2:selection_color(46) embpass=fltk:Fl_Secret_Input(10,bh*2,ww-20,bh,"password:") textfield=fltk:Fl_Multiline_Input(10,bh*4,ww-20,bh*10) textfield:align(5) textfield:label("Type your secret message here") enc_menu=fltk:Fl_Choice(10,bh*15+10,ww/2-10,bh,"encryption:") mod_menu=fltk:Fl_Choice(ww/2,bh*15+10,ww/2-10,bh,"mode:") enc_menu:align(5); mod_menu:align(5) enc_menu:add("none") -- get encinfo enc_info=io.popen("steghide encinfo") enc_data=enc_info:read("*a") enc_info:close() -- first 2 lines are useless enc_data=string.gsub(enc_data,".*%.%.%.%s*(.*)%s*\n","%1") count=0 -- create table for encryption modes enc_tab={} for line in string.gmatch(enc_data,".-\n") do count=count+1 e=string.gsub(line,"(.-):(.*)","%1") m=string.gsub(line,".-:(.*)","%1") enc_tab[count]={} for i in string.gmatch(m,"%w+") do table.insert(enc_tab[count],i) end if e == "rijndael-128" then enc_def=count end enc_menu:add(e) end -- select the default encoding enc_menu:value(enc_def) outpoot=fltk:Fl_File_Input(10,bh*17,ww-20-bh,bh,"save as:") ch_target=fltk:Fl_Button(ww-bh-10,bh*17,bh,bh,"@>") ch_target:callback(choose_target) outpoot:align(5); embpass:align(5) save=fltk:Fl_Button(10,bh*18,bh*3,bh,"save") save:callback(write_file) overw=fltk:Fl_Round_Button(bh*4,bh*18,bh*4,bh,"overwrite an existing file?") enc_menu:callback(function() mod_menu:clear() mod_menu:add(" ") if enc_menu:value()==0 then mod_menu:value(0) else for k,v in pairs(enc_tab[enc_menu:value()]) do mod_menu:add(v) end mod_menu:value(1) end end) enc_menu:do_callback() fltk:Fl_End() --t2 -- EXTRACT TAB -- t3=fltk:Fl_Group(0,bh,ww,wh-bh,"extract") t3:selection_color(46) exttext=fltk:Fl_Text_Display(10,bh*4,ww-20,bh*15) extbuff=fltk:Fl_Text_Buffer() exttext:buffer(extbuff) extpass=fltk:Fl_Secret_Input(10,bh*2,ww-20,bh,"password:") extpass:align(5) infobutt=fltk:Fl_Button(10,bh*3,bh*3,bh,"get info") infobutt:callback(function() extract("info ") end) astext=fltk:Fl_Button(10+bh*3,bh*3,bh*3,bh,"extract text") astext:callback(function() extract("extract -f -xf - -sf ") end) -- The asfile feature doesn't work well with lua --asfile=fltk:Fl_Button(10+bh*6,bh*3,bh*3,bh,"extract file") --asfile:callback(function() extract("extract -sf ") end) fltk:Fl_End() --t3 fltk:Fl_End() --tabs if arg[1] then apply_img(arg[1]) end w:resizable(tabs) tabs:resizable(t1) tabs:resizable(t2) tabs:resizable(t3) t1:resizable(imgscr) t2:resizable(textfield) t3:resizable(exttext) w:show() Fl:run()