├── .gitignore ├── Paper.pdf ├── large.mp4 ├── small.mp4 ├── message.png ├── r_message.png ├── images ├── steganography.png ├── r_message_large.png ├── r_message_small.png ├── hamming_decoding.png ├── hamming_encoding.png ├── steganography_decoding.png └── steganography_encoding.png ├── yuv2rgb.m ├── rgb2yuv.m ├── psnr.m ├── combine_frames.m ├── main.m ├── construct_frames.m ├── Design.md ├── frames_to_video.m ├── embed_message.m ├── Introduction.md ├── receiver_retrieve.m ├── README.md ├── unscramble.m └── scramble.m /.gitignore: -------------------------------------------------------------------------------- 1 | frames 2 | em_small.avi 3 | em_video.avi 4 | r_message.png -------------------------------------------------------------------------------- /Paper.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CSE-Projects/Secure-Video-Steganography/HEAD/Paper.pdf -------------------------------------------------------------------------------- /large.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CSE-Projects/Secure-Video-Steganography/HEAD/large.mp4 -------------------------------------------------------------------------------- /small.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CSE-Projects/Secure-Video-Steganography/HEAD/small.mp4 -------------------------------------------------------------------------------- /message.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CSE-Projects/Secure-Video-Steganography/HEAD/message.png -------------------------------------------------------------------------------- /r_message.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CSE-Projects/Secure-Video-Steganography/HEAD/r_message.png -------------------------------------------------------------------------------- /images/steganography.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CSE-Projects/Secure-Video-Steganography/HEAD/images/steganography.png -------------------------------------------------------------------------------- /images/r_message_large.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CSE-Projects/Secure-Video-Steganography/HEAD/images/r_message_large.png -------------------------------------------------------------------------------- /images/r_message_small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CSE-Projects/Secure-Video-Steganography/HEAD/images/r_message_small.png -------------------------------------------------------------------------------- /images/hamming_decoding.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CSE-Projects/Secure-Video-Steganography/HEAD/images/hamming_decoding.png -------------------------------------------------------------------------------- /images/hamming_encoding.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CSE-Projects/Secure-Video-Steganography/HEAD/images/hamming_encoding.png -------------------------------------------------------------------------------- /images/steganography_decoding.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CSE-Projects/Secure-Video-Steganography/HEAD/images/steganography_decoding.png -------------------------------------------------------------------------------- /images/steganography_encoding.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CSE-Projects/Secure-Video-Steganography/HEAD/images/steganography_encoding.png -------------------------------------------------------------------------------- /yuv2rgb.m: -------------------------------------------------------------------------------- 1 | %yuv2rgb Convert Y, U, V components of a frame to a RGB frame 2 | function [RGB] = yuv2rgb( Y, U, V ) 3 | % Conversion formula YUV to RGB 4 | R = Y + 1.139834576 * V; 5 | G = Y -.3946460533 * U -.58060 * V; 6 | B = Y + 2.032111938 * U; 7 | 8 | % combine components 9 | RGB = cat(3,R,G,B); 10 | imshow(RGB); 11 | end -------------------------------------------------------------------------------- /rgb2yuv.m: -------------------------------------------------------------------------------- 1 | %rgb2yuv Convert RBG frame to separate Y, U, V components 2 | function [Y, U, V] = rgb2yuv( RGB ) 3 | % Get R, G, B components of the frame 4 | R = RGB(:,:,1); 5 | G = RGB(:,:,2); 6 | B = RGB(:,:,3); 7 | % Conversion formula RGB to YUV 8 | Y = 0.299 * R + 0.587 * G + 0.114 * B; 9 | U = (-0.14713 * R )- (0.28886 * G) + (0.436 * B); 10 | V = 0.615 * R - 0.51499 * G - 0.10001 * B; 11 | % imshow(Y); 12 | % imshow(U); 13 | % imshow(V); 14 | end -------------------------------------------------------------------------------- /psnr.m: -------------------------------------------------------------------------------- 1 | %=== Get both messages ===% 2 | r_message = logical(imread('r_message.png')); 3 | message = imread('message.png'); 4 | 5 | %=== Calculate squared error ===% 6 | squared_error = 0; 7 | for i = 1:140 8 | for j = 1:200 9 | % difference in pixel squared 10 | squared_error = squared_error + (message(i, j) - r_message(i, j))^2; 11 | end 12 | end 13 | 14 | % calculate mean squared error 15 | mean_squared_error = squared_error / (140*200); 16 | 17 | % Get PSNR value 18 | psnr_val = -10*(log10(mean_squared_error)) -------------------------------------------------------------------------------- /combine_frames.m: -------------------------------------------------------------------------------- 1 | %=== Set directory of frames ===% 2 | workingDir = 'frames'; 3 | mkdir(workingDir,'embeddedFramesRGB'); 4 | 5 | % Unscramble each of the frames Y, U, V 6 | unscramble(key, height, width, noOfFrames, workingDir, 'framesY', 'framesU', 'framesV'); 7 | 8 | % read Y, U, V frames, convert and combine them into single RGB frame 9 | for i = 1:noOfFrames 10 | % Get Y component 11 | filename = [sprintf('%d',i) '.bmp']; 12 | fullname = fullfile(workingDir,'framesY',filename); 13 | Y = imread(fullname); 14 | % Get U component 15 | filename = [sprintf('%d',i) '.bmp']; 16 | fullname = fullfile(workingDir,'framesU',filename); 17 | U = imread(fullname); 18 | % Get V component 19 | filename = [sprintf('%d',i) '.bmp']; 20 | fullname = fullfile(workingDir,'framesV',filename); 21 | V = imread(fullname); 22 | 23 | % convert and combine Y, U, V components into RGB frame 24 | % YCbCr = cat(3, Y, U, V); 25 | % RGB = ycbcr2rgb(YCbCr); 26 | RGB = yuv2rgb(Y, U, V); 27 | 28 | % store the RGB frame 29 | filename = [sprintf('%d',i) '.bmp']; 30 | fullname = fullfile(workingDir, 'embeddedFramesRGB', filename); 31 | imwrite(RGB,fullname); 32 | end -------------------------------------------------------------------------------- /main.m: -------------------------------------------------------------------------------- 1 | %=== Set directories to store video frames ===% 2 | workingDir = 'frames'; 3 | %=== exist with two arguments is better than single argument as it searches for all categories (file, dir, var, func, buitlin etc) ===% 4 | %=== when a single argument is given. So, its better to provide specific category as second argument to search for... ===% 5 | if( exist(workingDir, 'dir') ) 6 | rmdir(workingDir, 's'); 7 | end 8 | mkdir(workingDir); 9 | mkdir(workingDir,'framesRGB'); 10 | mkdir(workingDir,'framesY'); 11 | mkdir(workingDir,'framesU'); 12 | mkdir(workingDir,'framesV'); 13 | 14 | %=== Get video reader obj for the video ===% 15 | video = VideoReader('small.mp4'); 16 | 17 | %=== construct frames and get their dimentions from the video reader object ===% 18 | %=== store them in these directories ===% 19 | [height, width] = construct_frames(video, workingDir, 'framesRGB', 'framesY', 'framesU', 'framesV'); 20 | 21 | %=== Get no of frames of the video ===% 22 | noOfFrames = floor(video.FrameRate*video.Duration) - 1; 23 | disp(noOfFrames); 24 | 25 | %=== Fix a key ===% 26 | key = 5; 27 | 28 | %=== scamble the video frames ===% 29 | scramble(key, height, width, noOfFrames, workingDir, 'framesY', 'framesU', 'framesV'); 30 | -------------------------------------------------------------------------------- /construct_frames.m: -------------------------------------------------------------------------------- 1 | % Construct frames from video and store in respective directories 2 | function [height, width] = construct_frames(video, workingDir, frameLocationRGB, frameLocationY, frameLocationU, frameLocationV) 3 | 4 | i = 1; 5 | %=== Convert each video frame into different formats and store them ===% 6 | while hasFrame(video) 7 | % read frame from the video % 8 | img = readFrame(video); 9 | height = size(img,1); 10 | width = size(img,2); 11 | % get YUV format from function defined in rgb2yuv.m % 12 | % each frame's Y, U, V component to be stored separately % 13 | [Y, U, V] = rgb2yuv(img); 14 | 15 | % maming for each frame % 16 | filename = [sprintf('%d',i) '.bmp']; 17 | 18 | %=== Store the frames in their respective directories ===% 19 | fullname = fullfile(workingDir,frameLocationRGB,filename); 20 | imwrite(img,fullname); 21 | fullname = fullfile(workingDir,frameLocationY,filename); 22 | imwrite(Y,fullname); 23 | fullname = fullfile(workingDir,frameLocationU,filename); 24 | imwrite(U,fullname); 25 | fullname = fullfile(workingDir,frameLocationV,filename); 26 | imwrite(V,fullname); 27 | i = i+1; 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /Design.md: -------------------------------------------------------------------------------- 1 | ## Design Details 2 | 3 | The folowing points will be implemented in MATLAB 4 | 5 | ### Sender's Side: 6 | 7 | * Convert the video stream into frames. 8 | 9 | * Separate each frame into Y, U and V components. 10 | 11 | * Change the position of all pixels in three components Y, U and V by a special key. 12 | 13 | * Convert the message which is to be sent to a one dimension array, and then change the position of the whole message by a key. 14 | 15 | * Encode each 4 bits of the message using Hamming (7, 4) encoder. 16 | 17 | * The result of the encoded data, which consists of 7 bits (4 bits of message + 3 bits of parity) is XORed with the 18 | 7 bits of random value using a key. 19 | 20 | * The pixels are then repositioned to the original locations and the video is rebuilt. 21 | 22 | 23 | 24 | 25 | ### Receivers's Side: 26 | 27 | * Convert the video stream into frames. 28 | 29 | * Separate each frame into Y, U and V components. 30 | 31 | * Change the position of all pixel values in the three Y, U, and V components by the special key that was used in the embedding process. 32 | 33 | * Obtain the encoded data from the YUV components and XOR with the random number using the same key that was used in the sender side. 34 | 35 | * Decode 4 bits of the message by the Hamming decoder. 36 | 37 | * Reposition the whole message again into the original order. 38 | 39 | * Convert the message array to two dimensions. 40 | 41 | 42 | -------------------------------------------------------------------------------- /frames_to_video.m: -------------------------------------------------------------------------------- 1 | %=== Set directory of frames ===% 2 | workingDir = 'frames'; 3 | mkdir(workingDir,'receiver_embeddedFramesRGB'); 4 | 5 | %=== Get embedded RGB frames ===% 6 | imageNames = dir(fullfile(workingDir,'embeddedFramesRGB','*.bmp')); 7 | imageNames = {imageNames.name}'; 8 | % for ii = 1:length(imageNames) 9 | % disp(imageNames{ii}); 10 | % end 11 | 12 | % original video 13 | video1 = VideoReader('small.mp4'); 14 | 15 | %=== Set output video writer object ===% 16 | outputVideo = VideoWriter('em_video.avi', 'Uncompressed AVI'); 17 | % set lossless compression 18 | ouputVideo.LosslessCompression = true; 19 | % Set same frame rate as original video 20 | outputVideo.FrameRate = video1.FrameRate 21 | open(outputVideo); 22 | 23 | %=== Frames to Video ===% 24 | for ii = 1:length(imageNames) 25 | % read a RGB frame 26 | img = imread(fullfile(workingDir,'embeddedFramesRGB',[sprintf('%d',ii) '.bmp'])); 27 | % put the frame in the video writer object 28 | writeVideo(outputVideo,img) 29 | end 30 | close(outputVideo); 31 | 32 | 33 | %=== Check if the frames after video formation ===% 34 | %=== are same as the frames before =====% 35 | 36 | video = VideoReader('em_video.avi'); 37 | i = 1; 38 | 39 | count = 0; 40 | %=== Convert each video frame into different formats and store them ===% 41 | while hasFrame(video) 42 | 43 | % Read frame from the video % 44 | img = readFrame(video); 45 | %=== Store the frames in their respective directories ===% 46 | filename = [sprintf('%d',i) '.bmp']; 47 | fullname = fullfile(workingDir,'receiver_embeddedFramesRGB',filename); 48 | imwrite(img,fullname); 49 | img1 = imread(fullfile(workingDir,'receiver_embeddedFramesRGB',filename)); 50 | img2 = imread(fullfile(workingDir,'embeddedFramesRGB',filename)); 51 | if img1 == img2 52 | count = count + 1; 53 | end 54 | i = i+1; 55 | end 56 | 57 | disp(count); 58 | 59 | -------------------------------------------------------------------------------- /embed_message.m: -------------------------------------------------------------------------------- 1 | filename = 'message.png'; 2 | 3 | % Read message 4 | message = imread(filename); 5 | figure, imshow(message); 6 | message_transpose = message'; 7 | 8 | % Converting the 2-D image into 1-D matrix 9 | one_d = message_transpose(:); 10 | 11 | count=1; 12 | 13 | % key = 5; 14 | 15 | % Cyclic shift for the message matrix using the key 16 | temp = one_d(1:key,1); 17 | 18 | for i = key+1:28000 19 | one_d (i-key,1) = one_d (i, 1); 20 | end 21 | 22 | for i = 28000-key+1:28000 23 | one_d (i,1) = temp (i-28000+key,1); 24 | end 25 | 26 | % Using G for calculating Hamming code 27 | G = [1 1 0 1 0 0 0; 0 1 1 0 1 0 0; 1 1 1 0 0 1 0; 1 0 1 0 0 0 1]; 28 | % Using xor_key for xoring the bits of the message matrix 29 | xor_key = 8; 30 | % Using embed_key for determining the row where the message should be embedded 31 | embed_key = 3; 32 | % image_count keeps track of which image is being modified 33 | image_count = 1; 34 | % position keeps track of where the message pixels are to be embedded 35 | position = 1; 36 | workingDir = 'frames'; 37 | 38 | fullnameV = ''; 39 | fullnameU = ''; 40 | fullnameY = ''; 41 | 42 | frameV = zeros(height,width); 43 | frameU = zeros(height,width); 44 | frameY = zeros(height,width); 45 | 46 | for i = 1:4:28000 47 | if i+3>28000 48 | break; 49 | end 50 | temp = one_d(i:i+3,1); 51 | % Applying Hamming code 52 | temp = temp'*G; 53 | % Calculating the xor and taking mod 2 54 | for j = 1:7 55 | temp(1,j) = mod(temp(1,j),2); 56 | temp(1,j) = xor(temp(1,j),xor_key); 57 | end 58 | 59 | %temp(1,1)+temp(1,4)+temp(1,6)+temp(1,7)+temp(1,1) 60 | 61 | % Shifting the image_count for message embedding 62 | if position == 181 63 | position = 1; 64 | image_count = image_count + 1; 65 | end 66 | if position == 1 67 | filename = [sprintf('%d',image_count) '.bmp']; 68 | fullnameV = fullfile(workingDir,'framesV',filename); 69 | frameV = imread(fullnameV); 70 | 71 | filename = [sprintf('%d',image_count) '.bmp']; 72 | fullnameU = fullfile(workingDir,'framesU',filename); 73 | frameU = imread(fullnameU); 74 | 75 | filename = [sprintf('%d',image_count) '.bmp']; 76 | fullnameY = fullfile(workingDir,'framesY',filename); 77 | frameY = imread(fullnameY); 78 | end 79 | 80 | % Embedding the message 81 | frameY(embed_key,(position-1)*3+1) = temp(1,1); 82 | frameY(embed_key,(position-1)*3+2) = temp(1,2); 83 | frameY(embed_key,(position-1)*3+3) = temp(1,3); 84 | 85 | frameU(embed_key,(position-1)*2+1) = temp(1,4); 86 | frameU(embed_key,(position-1)*2+2) = temp(1,5); 87 | 88 | frameV(embed_key,(position-1)*2+1) = temp(1,6); 89 | frameV(embed_key,(position-1)*2+2) = temp(1,7); 90 | 91 | imwrite(frameU,fullnameU); 92 | imwrite(frameV,fullnameV); 93 | imwrite(frameY,fullnameY); 94 | 95 | % Shifting the position for message embedding 96 | position = position + 1; 97 | end 98 | -------------------------------------------------------------------------------- /Introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | Due to connected nature of world because of the Internet many computer systems and other devices have become prone to attacks. Preventing unauthorized access, use, disclosure or destruction of data is gaining importance in the Digital world. Steganography and data hiding have become necessary for information security. 3 | 4 | 5 | ## Steganography 6 | Steganography is the art and science of writing covert messages such that the presence of the message is only known to the sender and the receipient. It involves concealing a file, message, image, or video within another file, message, image, or video. If cover is video file then it is called Video Steganography. 7 | 8 | 9 | 10 | There are two important factors that every successful steganography system should take into consideration, which are embedding efficiency and embedding payload. 11 | 12 | * First, the steganography scheme that has a high embedding efficiency means good quality of stego data and less amount of host (carrier) data are going to be changed. 13 | 14 | * Second, the high embedding payload means the capacity of secret 15 | information to be hidden inside host data is large. 16 | 17 | ### Some implementations fo video steganography 18 | * In 2012, Rongyue et al proposed an efficient BCH coding 19 | for steganography which is embedding the secret information 20 | inside a block of cover data by changing some coefficients. 21 | Authors have improved the computational time of the system 22 | and the complexity becomes low because of the system’s 23 | linearity. 24 | 25 | * In 2013, Liu et al proposed a robust data hiding scheme in 26 | H.264 compressed video stream, where they have prevented a 27 | drift of intra-frame distortion. To give the system more 28 | robustness, authors have encoded the message using BCH 29 | code before making the embedding process. The host data is 30 | the DCT coefficients of the luminance I-frame component. 31 | The obtained results have a high quality and robustness. 32 | 33 | 34 | ## (7, 4) Hamming Code 35 | 36 | The Hamming code is one of the most well-known block code methods that can do both error detection and correction on a block of data. In the Hamming code technique, the original information will be coded by adding some extra data 37 | with the minimum amount of redundancy, which is called the codeword, of length n bits. The added part consists of parity information of length (n-k) bits where k is the length of message that is expected to be coded. 38 | 39 | The Hamming codes are linear codes so they have two matrices: parity-check matrix H and generator matrix G, which they need for both encoding and decoding. 40 | 41 | On the encoding side, each message M, which consists of 4-bits, will be multiplied by the generator matrix and then have modulo of 2 applied; the result is the codeword X of 7-bits ready to be sent through a noisy channel. 42 | 43 | 44 | 45 | On the decoding side, for the purpose of checking the encoded message of 7-bits R (data + parity) will be received, 46 | then will be multiplied by the transpose of the parity-check matrix, and taking modulo of 2 again. 47 | 48 | 49 | 50 | The result is a syndrome vector Z (z1, z2, z3) of three bits, which has to be all zeroes (000) if it’s an error-free message. Otherwise, any change in the message during transmission will lead to flipping one or more bits of the message; then it needs an error correction process. 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /receiver_retrieve.m: -------------------------------------------------------------------------------- 1 | workingDir = 'frames'; 2 | 3 | % Read video 4 | video = VideoReader('em_video.avi'); 5 | 6 | % Constructing frames 7 | construct_frames(video, workingDir, 'receiver_embeddedFramesRGB', 'framesY', 'framesU', 'framesV'); 8 | 9 | % Fix the same key 10 | key = 5; 11 | 12 | % Scrambling frames 13 | scramble(key, height, width, noOfFrames, workingDir, 'framesY', 'framesU', 'framesV'); 14 | read_message = zeros(28000,1); 15 | 16 | % Initializing matrices for hamming correction 17 | r = zeros(1,7); 18 | ht = [1 0 0; 0 1 0; 0 0 1; 1 1 0; 0 1 1; 1 1 1; 1 0 1]; 19 | count = 1; 20 | position = 1; 21 | 22 | % Used to keep image count 23 | image_count = 1; 24 | 25 | % Key to xor 26 | xor_key = 8; 27 | 28 | % intializations 29 | count_diff = 1; 30 | 31 | frameY = zeros(height,width); 32 | frameV = zeros(height,width); 33 | frameU = zeros(height,width); 34 | 35 | 36 | % Iterating over each pixel 37 | for i= 1:28000 38 | if count>=28001 39 | break 40 | end 41 | 42 | % Going to next image once we are done with the current one 43 | if position == 181 44 | position = 1; 45 | image_count = image_count + 1; 46 | end 47 | 48 | % Opening a new image 49 | if position == 1 50 | % Get Y component 51 | filename = [sprintf('%d',image_count) '.bmp']; 52 | fullnameY = fullfile(workingDir,'framesY',filename); 53 | frameY = imread(fullnameY); 54 | % Get V component 55 | filename = [sprintf('%d',image_count) '.bmp']; 56 | fullnameV = fullfile(workingDir,'framesV',filename); 57 | frameV = imread(fullnameV); 58 | % Get U component 59 | filename = [sprintf('%d',image_count) '.bmp']; 60 | fullnameU = fullfile(workingDir,'framesU',filename); 61 | frameU = imread(fullnameU); 62 | end 63 | 64 | % Assigning values to read matrix 65 | r(1,1)=xor(xor_key,frameY(3,(position-1)*3+1)); 66 | % r(1,1)=mod(r(1,1),2); 67 | r(1,2)=xor(xor_key,frameY(3,(position-1)*3+2)); 68 | % r(1,2)=mod(r(1,2),2); 69 | r(1,3)=xor(xor_key,frameY(3,(position-1)*3+3)); 70 | % r(1,3)=mod(r(1,3),2); 71 | r(1,4)=xor(xor_key,frameU(3,(position-1)*2+1)); 72 | % r(1,4)=mod(r(1,4),2); 73 | r(1,5)=xor(xor_key,frameU(3,(position-1)*2+2)); 74 | % r(1,5)=mod(r(1,5),2); 75 | r(1,6)=xor(xor_key,frameV(3,(position-1)*2+1)); 76 | % r(1,6)=mod(r(1,6),2); 77 | r(1,7)=xor(xor_key,frameV(3,(position-1)*2+2)); 78 | % r(1,7)=mod(r(1,7),2); 79 | 80 | 81 | % Calculating syndrome 82 | z = r * ht; 83 | 84 | z(1,1)=mod(z(1,1),2); 85 | z(1,2)=mod(z(1,2),2); 86 | z(1,3)=mod(z(1,3),2); 87 | z 88 | 89 | %=== Hamming (7, 4) correction ===% 90 | % Making corrections using syndrome 91 | if (z(1,1)==0) && (z(1,2)==0) && (z(1,3)==0) 92 | % No error 93 | count_diff = count_diff + 1; 94 | read_message(count) =r(1,4); 95 | read_message(count+1)=r(1,5); 96 | read_message(count+2)=r(1,6); 97 | read_message(count+3)=r(1,7); 98 | 99 | % Making corrections using syndrome 100 | elseif (z(1,1)==1) && (z(1,2)==1) && (z(1,3)==0) 101 | % Error in 1st bit 102 | read_message(count) =~r(1,4); 103 | read_message(count+1)=r(1,5); 104 | read_message(count+2)=r(1,6); 105 | read_message(count+3)=r(1,7); 106 | 107 | % Making corrections 108 | elseif (z(1,1)==0) && (z(1,2)==1) && (z(1,3)==1) 109 | % Error in 2nd bit 110 | read_message(count) =r(1,4); 111 | read_message(count+1)=~r(1,5); 112 | read_message(count+2)=r(1,6); 113 | read_message(count+3)=r(1,7); 114 | 115 | % Making corrections 116 | elseif (z(1,1)==1) && (z(1,2)==1) && (z(1,3)==1) 117 | % Error in 3rd bit 118 | read_message(count) =r(1,4); 119 | read_message(count+1)=r(1,5); 120 | read_message(count+2)=~r(1,6); 121 | read_message(count+3)=r(1,7); 122 | 123 | % Making corrections 124 | elseif (z(1,1)==1) && (z(1,2)==0) && (z(1,3)==1) 125 | % Error in 4th bit 126 | read_message(count) =r(1,4); 127 | read_message(count+1)=r(1,5); 128 | read_message(count+2)=r(1,6); 129 | read_message(count+3)=~r(1,7); 130 | 131 | % Making corrections 132 | else 133 | % Error in the redundant bits 134 | read_message(count) =r(1,4); 135 | read_message(count+1)=r(1,5); 136 | read_message(count+2)=r(1,6); 137 | read_message(count+3)=r(1,7); 138 | 139 | end 140 | count = count + 4; 141 | position = position + 1; 142 | 143 | end 144 | 145 | 146 | % Performing cyclic shift of image pixels using key 147 | temp = read_message(27996:28000,1); 148 | for i= 27995:-1:1 149 | read_message(i+5,1)=read_message(i,1); 150 | end 151 | read_message(1,1)=temp(1,1); 152 | read_message(2,1)=temp(2,1); 153 | read_message(3,1)=temp(3,1); 154 | read_message(4,1)=temp(4,1); 155 | read_message(5,1)=temp(5,1); 156 | 157 | 158 | % Constructing the image 159 | xe = zeros(140,200); 160 | count=1; 161 | 162 | for i = 1:140 163 | for j = 1:200 164 | xe(i,j) = read_message(count,1); 165 | count = count + 1; 166 | end 167 | end 168 | figure, imshow(xe) 169 | imwrite(xe, 'r_message.png'); 170 | % xe - message -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Data Communications (CO250): Mini-Project 2 | 3 | **Title:** 4 | 5 | A Highly Secure Video Steganography using Hamming Code (7, 4) 6 | 7 | **Members:** 8 | 9 | Dibyadarshan Hota (16C0154) - 10 | 11 | Omkar Prabhu (16C0233) - 12 | 13 | **Abstract:** 14 | 15 | Preventing unauthorized access, use, disclosure or destruction of data is gaining importance in the Digital world. Steganography and data hiding have become necessary for information security. Steganography is the practice of concealing a file, message, image, or video within another file, message, image, or video. 16 | 17 | The paper referenced has proposed a secure video steganography algorithm using linear block code. The algorithm requires a video to be converted into frames and changing the pixel positions. The message which is to be transmitted must be converted into one-dimension, XOR and Hamming code are applied to this message. Then this encoded message is embedded in the scrambled video frames. These frames are reconstructed and sent to the receiver. The receiver can extract information using the same key as the sender side. The receiver has to disassemble the video, use XOR and hamming code to reconstruct the correct intended message. 18 | 19 | 20 | **Objectives:** 21 | * Implement the following in MATLAB: 22 | 23 | At sender's side: 24 | 25 | * Conversion of video frames into a YUV format. 26 | 27 | * Applying (7, 4) Hamming code to 1D structure of message which is a image to obtain the codeword. 28 | 29 | * Embedding the message codeword into the video frames. 30 | 31 | * Recontruct the video from the frames. 32 | 33 | At receiver's side: 34 | 35 | * Split the received video into frames and convert them to YUV format. 36 | 37 | * Retrieve back the message codeword from the frames. 38 | 39 | * Retrieve back original message from the message codeword by using decoding for hamming code. 40 | 41 | 42 | **References:** 43 | 44 | Ramadhan J. Mstafa, Khaled M. Elleithy, "A highly secure video steganography using Hamming code (7, 4)," presented at Systems, Applications and Technology Conference (LISAT), 2014 IEEE Long Island, Farmingdale, NY, USA, May 2-2, 2014. 45 | 46 | [View Paper](http://ieeexplore.ieee.org/document/6845191/) 47 | 48 | 49 | ## Usage 50 | 51 | * Specify the video to be used in the files: `main.m`, `frames_to_video.m` and `receiver_retrieve.m` 52 | 53 | * Specify the key to be used in the file `main.m` 54 | 55 | * Run the following files in order 56 | 57 | 1. `main.m` : In the `frames` directory the following would be present 58 | * `framesRGB` : RGB frames of the video `small.mp4` or `large.mp4` 59 | * `framesY` : srambled Y components for RGB frames 60 | * `framesU` : srambled U components for RGB frames 61 | * `framesV` : srambled V components for RGB frames 62 | 63 | 2. `embed_message.m` : The binary image `message.png` will be embedded into the scrambled Y, U, V components. 64 | 65 | 3. `combine_frames.m` : In the directory `frames\embeddedFramesRGB`, the embedded RGB frames will be created. 66 | 67 | 4. `frames_to_video.m` : Video named `em_small.avi` will be created from the embedded RGB frames. 68 | 69 | 5. `receiver_retrieve.m` : From the video `em_small.avi` the message will be constructed back and displayed. 70 | 71 | 6. `psnr.m` : Displays the PSNR value comparing the original and retrieved image message. 72 | 73 | 74 | ## Results 75 | 76 | Original message: 77 | 78 |

79 | 80 | * Using `large.mp4` the retrieved message and PSNR is: infintiy 81 | 82 |

83 | 84 | * Using `small.mp4` the retrieved message and PSNR is: 13.9140 85 | 86 |
87 | 88 | 89 | ## File Structure 90 | 91 | * `Introduction.md` - Explains theoretical aspects of the mini project. 92 | 93 | * `Design.md` - Explains design aspects of the mini project. 94 | 95 | * `main.m` - Main module of the implementation. 96 | 97 | * `construct_frames.m` - Construct RGB frames from the video and get their Y, U, V components. Save them in the mentioned location. 98 | 99 | * `embed_message.m` - Applying (7, 4) Hamming Code to the message and embed the same into the scrambled Y, U, V frames. 100 | 101 | * `combine_frames.m` - Combine the embedded Y, U, V frames into their embedded RGB frame. 102 | 103 | * `frames_to_video.m` - Construct the video from the embedded RGB frames. 104 | 105 | * `receiver_retrieve.m` - From the constructed video after embedding, it will retrieve the message back after applying Hamming correction. 106 | 107 | * `psnr.m` - Calculate Peak signal-to-noise ratio. 108 | 109 | * `scramble.m` - Scrambles all the Y, U, V frames given their directory based on a key. 110 | 111 | * `unscramble.m` - Unscrambles all the Y, U, V frames given their directory based on a key. 112 | 113 | * `yuv2rgb.m` - Converts Y, U, V components into a single RGB frame. 114 | 115 | * `rgb2yuv.m` - Converts a RGB frame to its Y, U, V components. 116 | 117 | * `small.mp4` - Video used to embed message into. 118 | 119 | * `large.mp4` - Video used to embed message into. 120 | 121 | * `message.png` - Binary image to be sent after embedding it into small.mp4 video and retreived at the other end. 122 | 123 | 124 | -------------------------------------------------------------------------------- /unscramble.m: -------------------------------------------------------------------------------- 1 | % Unscrambles a frame based on the key 2 | function unscramble(key, height, width, noOfFrames, workingDir, frameLocationY, frameLocationU, frameLocationV) 3 | % Following the reverse procedure of scrambling 4 | 5 | % Determine number of slots 6 | cycle = floor(width/key); 7 | 8 | % Making number of cycles even 9 | if mod(cycle,2) == 1 10 | cycle = cycle - 1; 11 | end 12 | 13 | for i = 1:noOfFrames 14 | % Read images from 1 to noOfFrames 15 | filename = [sprintf('%d',i) '.bmp']; 16 | fullname = fullfile(workingDir,frameLocationV,filename); 17 | frame = imread(fullname); 18 | for j = 1:cycle/2 19 | endpart1 = cycle - j; 20 | endpart = (endpart1*key)+1; 21 | 22 | % Skipping odd slots 23 | if mod(j,2) == 1 24 | continue; 25 | end 26 | 27 | % Swapping of slots 28 | temp = frame(:,(j-1)*key+1:j*key); 29 | frame(:,(j-1)*key+1:j*key) = frame(:,endpart:endpart+key-1); 30 | frame(:,endpart:endpart+key-1) = temp; 31 | end 32 | %figure, imshow(frame); 33 | imwrite(frame,fullname); 34 | 35 | end 36 | 37 | % Determine number of slots 38 | 39 | cycle = floor(height/key); 40 | 41 | % Making number of cycles even 42 | if mod(cycle,2) == 1 43 | cycle = cycle - 1; 44 | end 45 | 46 | for i = 1:noOfFrames 47 | % Read images from 1 to noOfFrames 48 | 49 | filename = [sprintf('%d',i) '.bmp']; 50 | fullname = fullfile(workingDir,frameLocationV,filename); 51 | frame = imread(fullname); 52 | abc = frame; 53 | for j = 1:cycle/2 54 | endpart1 = cycle - j; 55 | endpart = (endpart1*key)+1; 56 | % Skipping odd slots 57 | 58 | if mod(j,2) == 1 59 | continue; 60 | end 61 | % Swapping of slots 62 | 63 | temp = frame((j-1)*key+1:j*key,:); 64 | frame((j-1)*key+1:j*key,:) = frame(endpart:endpart+key-1,:); 65 | frame(endpart:endpart+key-1,:) = temp; 66 | end 67 | imwrite(frame,fullname); 68 | end 69 | 70 | % Determine number of slots 71 | 72 | cycle = floor(width/key); 73 | 74 | % Making number of cycles even 75 | if mod(cycle,2) == 1 76 | cycle = cycle - 1; 77 | end 78 | 79 | for i = 1:noOfFrames 80 | % Read images from 1 to noOfFrames 81 | 82 | filename = [sprintf('%d',i) '.bmp']; 83 | fullname = fullfile(workingDir,frameLocationU,filename); 84 | frame = imread(fullname); 85 | for j = 1:cycle/2 86 | endpart1 = cycle - j; 87 | endpart = (endpart1*key)+1; 88 | % Skipping odd slots 89 | 90 | if mod(j,2) == 1 91 | continue; 92 | end 93 | % Swapping of slots 94 | 95 | temp = frame(:,(j-1)*key+1:j*key); 96 | frame(:,(j-1)*key+1:j*key) = frame(:,endpart:endpart+key-1); 97 | frame(:,endpart:endpart+key-1) = temp; 98 | end 99 | %figure, imshow(frame); 100 | imwrite(frame,fullname); 101 | 102 | end 103 | 104 | % Determine number of slots 105 | 106 | cycle = floor(height/key); 107 | 108 | % Making number of cycles even 109 | if mod(cycle,2) == 1 110 | cycle = cycle - 1; 111 | end 112 | 113 | for i = 1:noOfFrames 114 | % Read images from 1 to noOfFrames 115 | 116 | filename = [sprintf('%d',i) '.bmp']; 117 | fullname = fullfile(workingDir,frameLocationU,filename); 118 | frame = imread(fullname); 119 | abc = frame; 120 | for j = 1:cycle/2 121 | endpart1 = cycle - j; 122 | endpart = (endpart1*key)+1; 123 | % Skipping odd slots 124 | 125 | if mod(j,2) == 1 126 | continue; 127 | end 128 | % Swapping of slots 129 | 130 | temp = frame((j-1)*key+1:j*key,:); 131 | frame((j-1)*key+1:j*key,:) = frame(endpart:endpart+key-1,:); 132 | frame(endpart:endpart+key-1,:) = temp; 133 | end 134 | imwrite(frame,fullname); 135 | end 136 | 137 | % Determine number of slots 138 | 139 | cycle = floor(width/key); 140 | 141 | % Making number of cycles even 142 | if mod(cycle,2) == 1 143 | cycle = cycle - 1; 144 | end 145 | 146 | for i = 1:noOfFrames 147 | % Read images from 1 to noOfFrames 148 | 149 | filename = [sprintf('%d',i) '.bmp']; 150 | fullname = fullfile(workingDir,frameLocationY,filename); 151 | frame = imread(fullname); 152 | for j = 1:cycle/2 153 | endpart1 = cycle - j; 154 | endpart = (endpart1*key)+1; 155 | % Skipping odd slots 156 | 157 | if mod(j,2) == 1 158 | continue; 159 | end 160 | % Swapping of slots 161 | 162 | temp = frame(:,(j-1)*key+1:j*key); 163 | frame(:,(j-1)*key+1:j*key) = frame(:,endpart:endpart+key-1); 164 | frame(:,endpart:endpart+key-1) = temp; 165 | end 166 | %figure, imshow(frame); 167 | imwrite(frame,fullname); 168 | 169 | end 170 | 171 | % Determine number of slots 172 | 173 | cycle = floor(height/key); 174 | 175 | % Making number of cycles even 176 | if mod(cycle,2) == 1 177 | cycle = cycle - 1; 178 | end 179 | 180 | for i = 1:noOfFrames 181 | % Read images from 1 to noOfFrames 182 | 183 | filename = [sprintf('%d',i) '.bmp']; 184 | fullname = fullfile(workingDir,frameLocationY,filename); 185 | frame = imread(fullname); 186 | abc = frame; 187 | for j = 1:cycle/2 188 | endpart1 = cycle - j; 189 | endpart = (endpart1*key)+1; 190 | % Skipping odd slots 191 | 192 | if mod(j,2) == 1 193 | continue; 194 | end 195 | % Swapping of slots 196 | 197 | temp = frame((j-1)*key+1:j*key,:); 198 | frame((j-1)*key+1:j*key,:) = frame(endpart:endpart+key-1,:); 199 | frame(endpart:endpart+key-1,:) = temp; 200 | end 201 | imwrite(frame,fullname); 202 | end 203 | end 204 | -------------------------------------------------------------------------------- /scramble.m: -------------------------------------------------------------------------------- 1 | % Scrambles a frame based on the key 2 | function scramble(key, height, width , noOfFrames, workingDir, frameLocationY, frameLocationU, frameLocationV) 3 | % Determining the number of slots based on key 4 | cycle = floor(height/key); 5 | 6 | % Making sure that there are even slots 7 | if mod(cycle,2) == 1 8 | cycle = cycle - 1; 9 | end 10 | 11 | for i = 1:noOfFrames 12 | % Reading images from 1 to noOfFrames 13 | filename = [sprintf('%d',i) '.bmp']; 14 | fullname = fullfile(workingDir, frameLocationV, filename); 15 | frame = imread(fullname); 16 | abc = frame; 17 | 18 | % Iterating from 1st to cycle/2 slots 19 | for j = 1:cycle/2 20 | endpart1 = cycle - j; 21 | endpart = (endpart1*key)+1; 22 | 23 | % Skipping odd slots 24 | if mod(j,2) == 1 25 | continue; 26 | end 27 | 28 | % Swapping xth slot with cycle-x th slot 29 | temp = frame((j-1)*key+1:j*key,:); 30 | frame((j-1)*key+1:j*key,:) = frame(endpart:endpart+key-1,:); 31 | frame(endpart:endpart+key-1,:) = temp; 32 | end 33 | imwrite(frame,fullname); 34 | end 35 | 36 | % Repeating the swapping procedure column wise 37 | 38 | % Determining the number of slots based on key 39 | 40 | cycle = floor(width/key); 41 | 42 | % Making sure that there are even slots 43 | 44 | if mod(cycle,2) == 1 45 | cycle = cycle - 1; 46 | end 47 | 48 | for i = 1:noOfFrames 49 | % Reading images from 1 to noOfFrames 50 | 51 | filename = [sprintf('%d',i) '.bmp']; 52 | fullname = fullfile(workingDir,frameLocationV,filename); 53 | frame = imread(fullname); 54 | % Iterating from 1st to cycle/2 slots 55 | 56 | for j = 1:cycle/2 57 | endpart1 = cycle - j; 58 | endpart = (endpart1*key)+1; 59 | if mod(j,2) == 1 60 | continue; 61 | end 62 | % Swapping xth slot with cycle-x th slot 63 | 64 | temp = frame(:,(j-1)*key+1:j*key); 65 | frame(:,(j-1)*key+1:j*key) = frame(:,endpart:endpart+key-1); 66 | frame(:,endpart:endpart+key-1) = temp; 67 | end 68 | %figure, imshow(frame); 69 | imwrite(frame,fullname); 70 | 71 | end 72 | 73 | % Repeating the scrambling procedure for Y and U as well 74 | 75 | % Determining the number of slots based on key 76 | 77 | cycle = floor(height/key); 78 | 79 | % Making sure that there are even slots 80 | 81 | if mod(cycle,2) == 1 82 | cycle = cycle - 1; 83 | end 84 | 85 | for i = 1:noOfFrames 86 | % Reading images from 1 to noOfFrames 87 | 88 | filename = [sprintf('%d',i) '.bmp']; 89 | fullname = fullfile(workingDir,frameLocationU,filename); 90 | frame = imread(fullname); 91 | abc = frame; 92 | % Iterating from 1st to cycle/2 slots 93 | 94 | for j = 1:cycle/2 95 | endpart1 = cycle - j; 96 | endpart = (endpart1*key)+1; 97 | if mod(j,2) == 1 98 | continue; 99 | end 100 | % Swapping xth slot with cycle-x th slot 101 | 102 | temp = frame((j-1)*key+1:j*key,:); 103 | frame((j-1)*key+1:j*key,:) = frame(endpart:endpart+key-1,:); 104 | frame(endpart:endpart+key-1,:) = temp; 105 | end 106 | imwrite(frame,fullname); 107 | end 108 | 109 | % Determining the number of slots based on key 110 | 111 | cycle = floor(width/key); 112 | 113 | % Making sure that there are even slots 114 | 115 | if mod(cycle,2) == 1 116 | cycle = cycle - 1; 117 | end 118 | 119 | for i = 1:noOfFrames 120 | % Reading images from 1 to noOfFrames 121 | 122 | filename = [sprintf('%d',i) '.bmp']; 123 | fullname = fullfile(workingDir,frameLocationU,filename); 124 | frame = imread(fullname); 125 | % Iterating from 1st to cycle/2 slots 126 | 127 | for j = 1:cycle/2 128 | endpart1 = cycle - j; 129 | endpart = (endpart1*key)+1; 130 | if mod(j,2) == 1 131 | continue; 132 | end 133 | % Swapping xth slot with cycle-x th slot 134 | 135 | temp = frame(:,(j-1)*key+1:j*key); 136 | frame(:,(j-1)*key+1:j*key) = frame(:,endpart:endpart+key-1); 137 | frame(:,endpart:endpart+key-1) = temp; 138 | end 139 | %figure, imshow(frame); 140 | imwrite(frame,fullname); 141 | 142 | end 143 | 144 | % Determining the number of slots based on key 145 | 146 | cycle = floor(height/key); 147 | 148 | % Making sure that there are even slots 149 | 150 | if mod(cycle,2) == 1 151 | cycle = cycle - 1; 152 | end 153 | 154 | for i = 1:noOfFrames 155 | % Reading images from 1 to noOfFrames 156 | 157 | filename = [sprintf('%d',i) '.bmp']; 158 | fullname = fullfile(workingDir,frameLocationY,filename); 159 | frame = imread(fullname); 160 | abc = frame; 161 | % Iterating from 1st to cycle/2 slots 162 | 163 | for j = 1:cycle/2 164 | endpart1 = cycle - j; 165 | endpart = (endpart1*key)+1; 166 | if mod(j,2) == 1 167 | continue; 168 | end 169 | % Swapping xth slot with cycle-x th slot 170 | 171 | temp = frame((j-1)*key+1:j*key,:); 172 | frame((j-1)*key+1:j*key,:) = frame(endpart:endpart+key-1,:); 173 | frame(endpart:endpart+key-1,:) = temp; 174 | end 175 | imwrite(frame,fullname); 176 | end 177 | 178 | % Determining the number of slots based on key 179 | 180 | cycle = floor(width/key); 181 | 182 | % Making sure that there are even slots 183 | 184 | if mod(cycle,2) == 1 185 | cycle = cycle - 1; 186 | end 187 | 188 | for i = 1:noOfFrames 189 | % Reading images from 1 to noOfFrames 190 | 191 | filename = [sprintf('%d',i) '.bmp']; 192 | fullname = fullfile(workingDir,frameLocationY,filename); 193 | frame = imread(fullname); 194 | % Iterating from 1st to cycle/2 slots 195 | 196 | for j = 1:cycle/2 197 | endpart1 = cycle - j; 198 | endpart = (endpart1*key)+1; 199 | if mod(j,2) == 1 200 | continue; 201 | end 202 | % Swapping xth slot with cycle-x th slot 203 | 204 | temp = frame(:,(j-1)*key+1:j*key); 205 | frame(:,(j-1)*key+1:j*key) = frame(:,endpart:endpart+key-1); 206 | frame(:,endpart:endpart+key-1) = temp; 207 | end 208 | %figure, imshow(frame); 209 | imwrite(frame,fullname); 210 | end 211 | end 212 | --------------------------------------------------------------------------------