Here is code for the steganalysis lab. import os,os.path,zlib import struct from pylab import * from PIL import Image ### LSB steganography ### ### We're only embedding in grayscale images here. def iread(file): """Read an image file as an integer array, then pick the G channel if it is a color image.""" image = array(Image.open(file)) if image.ndim==3: image = image[:,:,1] return image def bitunpack(data): """Unpack an 8bit byte array into an array into an array of binary values.""" data = array(bytearray(data),'B') n = len(data) bits = zeros(8*n,'B') index = arange(n) for i in range(8): bits[8*index+i] = (data&(1<<i)!=0) return bits def bitpack(bits): """Pack an array of binary values into an 8bit byte array.""" n = int(len(bits)/8) data = zeros(n,'B') index = arange(n) for i in range(8): data += (bits[8*index+i]!=0)*(1<<i) return bytearray(data) def lsb_encode(cover,data): """Encode the given data into the LSB of the cover image. Also encodes the data length.""" assert cover.ndim==2 data = struct.pack("I",len(data))+bytearray(data) result = cover.copy() bits = bitunpack(data) assert len(bits)>=len(data),"too many bits for the given image size" seq = result.ravel()[:len(bits)] assert seq.size>=bits.size print seq.shape,bits.shape seq[:] = ((seq&0xfffffffe) | (bits!=0)) return result def lsb_decode(image): """Decode the LSB data from the image into a byte array.""" assert image.ndim==2 bits = (array(image,'B').ravel()&1) data = bitpack(bits) l = struct.unpack_from("I",str(data[:4]))[0] return data[4:4+l] ### RS steganalysis ### ### This is a simple implementation; among other things, ### it only allows for 1D bit patterns in the analysis. def rs_discriminant(image,g=3): """Compute the RS discriminant function. g is the group size.""" image = array(image.ravel(),'f') deltas = abs(image[:-1]-image[1:]) n = len(deltas) ng = (n+g-1)/g global groups groups = array(arange(n)/g,'i') totals = zeros(ng) totals[groups] += deltas return totals def rs_vals(image_,ntrials=10,mask=array([0,1,1,0])): """Compute the R and S values of RS steganalysis for the given mask.""" assert image_.ndim==2 image = array(image_.ravel(),'i') # imshow(image.reshape(image_.shape)) bits = array(tile(mask,1+image.size/mask.size)[:image.size],'i') before = rs_discriminant(image) steg = (image^bits) after = rs_discriminant(steg) steg1 = ((image+1)^bits)-1 after1 = rs_discriminant(steg1) R = sum(before<after)*1.0/before.size R1 = sum(before<after1)*1.0/before.size S = sum(before>after)*1.0/before.size S1 = sum(before>after1)*1.0/before.size return (R,R1,S,S1) def rs_plot(image): """Plot the RS values for a given image, embedding different fractions of random bits in the image.""" assert image.ndim==2 clf() data = [] ps = linspace(0.0,1.0,41) for p in ps: bits = 1*(uniform(size=image.shape)<p) steg = image^bits data.append(rs_vals(steg)) data = array(data) plot(ps,data[:,0],'r',ps,data[:,1],'b',ps,data[:,2],'g',ps,data[:,3],'y') masks = [array(uniform(size=11)>0.5,'i') for i in range(10)] def rs_plot1(image,masks=masks): """Plot the RS values for a given image, embedding different fractions of random bits in the image. Averages the values using multiple masks to achieve a smoother plot.""" assert image.ndim==2 clf() data = [] ps = linspace(0.0,1.0,41) for p in ps: v = zeros(4) for mask in masks: bits = 1*(uniform(size=image.shape)<p) steg = image^bits v += array(rs_vals(steg,mask=mask)) data.append(v/len(masks)) data = array(data) plot(ps,data[:,0],'r',ps,data[:,1],'b',ps,data[:,2],'g',ps,data[:,3],'y') ### compression-based steganalysis def zlib_size(image): """Return the size of the zlib compressed LSB bitplane.""" return len(zlib.compress(str(bytearray((image&1).ravel())))) def png_size(image): """Return the size of the PNG compressed image.""" Image.fromarray(image).save("/tmp/_test.png") return os.path.getsize("/tmp/_test.png") def lsb_fft_show(image): """Display the log spectrum of the LSB of (part of the image); useful for showing differences in spatial frequencies in LSB patterns of images containing hidden data.""" assert image.ndim==2 q = fft(1.0*(image[:256,:256]&1)) ion() imshow(log(abs(q)+1)) draw() |
Course Info >