daily pastebin goal
63%
SHARE
TWEET

Untitled

a guest Feb 19th, 2019 61 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #!/usr/bin/env python
  2. #-*- coding: utf-8 -*-
  3.  
  4. '''
  5. Usage Example -
  6. python steganography.py -f X.bmp -o Y.bmp -m "Hidden message!"
  7. '''
  8.  
  9.  
  10.  
  11. from optparse import OptionParser
  12.  
  13.  
  14. __author__ = "ITC"
  15. __license__ = "GPLv3"
  16.  
  17. from PIL import Image
  18.  
  19. try:
  20.    input = raw_input
  21. except NameError:
  22.    pass
  23.  
  24.  
  25. def set_bit(v, index, x):
  26.   """Set the index:th bit of v to 1 if x is truthy, else to 0, and return the new value."""
  27.   mask = 1 << index
  28.   v &= ~mask
  29.   if x:
  30.     v |= mask
  31.   return v
  32.  
  33. def setlsb(component, bit):
  34.     """
  35.     Set Least Significant Bit of a colour component.
  36.     """
  37.     return component & ~1 | int(bit)
  38.  
  39. def a2bits_list(chars):
  40.     """
  41.     Convert a string to its bits representation as a list of 0's and 1's.
  42.     """
  43.     return [bin(ord(x))[2:].rjust(8,"0") for x in chars]
  44.  
  45. def fib():
  46.     a, b = 0, 1
  47.     while 1:
  48.         yield a
  49.         a, b = b, a + b
  50.  
  51. def hide(input_image_file, message, auto_convert_rgb=False, order_func = fib):
  52.     """
  53.     Hide a message (string) in an image with a  (Least Significant Bit) technique.
  54.     """
  55.  
  56.  
  57.     message_length = len(message)
  58.     assert message_length != 0, "message length is zero"
  59.  
  60.     img = Image.open(input_image_file)
  61.  
  62.  
  63.     if img.mode not in ['RGB', 'RGBA']:
  64.         if not auto_convert_rgb:
  65.             print('The mode of the image is not RGB. Mode is {}'.\
  66.                                                             format(img.mode))
  67.             answer = input('Convert the image to RGB ? [Y / n]\n') or 'Y'
  68.             if answer.lower() == 'n':
  69.                 raise Exception('Not a RGB image.')
  70.         img = img.convert('RGB')
  71.  
  72.     hidden_bits_order = order_func()
  73.     encoded = img.copy()
  74.     width, height = img.size
  75.     index = 0
  76.  
  77.     message = str(message_length) + ":" + str(message)
  78.     message_bits = "".join(a2bits_list(message))
  79.     message_bits += '0' * ((3 - (len(message_bits) % 3)) % 3)
  80.    
  81.     npixels = width * height
  82.     len_message_bits = len(message_bits)
  83.     if len_message_bits > npixels * 3:
  84.         raise Exception("The message you want to hide is too long: {}". \
  85.                                                         format(message_length))
  86.     for row in range(height):
  87.         for col in range(width):
  88.             if index + 3 <= len_message_bits :
  89.  
  90.                 # Get the colour component.
  91.                 pixel = img.getpixel((col, row))
  92.                 r = pixel[0]
  93.                 g = pixel[1]
  94.                 b = pixel[2]
  95.  
  96.                 # Change the Least Significant Bit of each colour component.
  97.                 # Get next bit to hide.
  98.                 bit = hidden_bits_order.next() % 8
  99.                 r = set_bit(r, bit, ('1' == message_bits[index]))
  100.                 g = set_bit(g, bit, ('1' == message_bits[index+1]))
  101.                 b = set_bit(b, bit, ('1' == message_bits[index+2]))
  102.  
  103.                 # Save the new pixel
  104.                 if img.mode == 'RGBA':
  105.                     updated_pixel = (r, g, b, pixel[3])
  106.                 else:
  107.                     updated_pixel = (r, g, b)
  108.  
  109.                 encoded.putpixel((col, row), updated_pixel)
  110.  
  111.                 index += 3
  112.             else:
  113.                 img.close()
  114.                 return encoded
  115.  
  116.     img.close()
  117.     return encoded
  118.  
  119.  
  120. def write(image, output_image_file):
  121.     """
  122.     Writes the output image file to disk, handles exceptions.
  123.     """
  124.     try:
  125.         image.save(output_image_file)
  126.     except Exception as e:
  127.         # If hide() returns an error (Too long message).
  128.         print(e)
  129.     finally:
  130.         image.close()
  131.  
  132. def main():
  133.  
  134.     # Read the imahe from disk
  135.     encoded = hide(options.input_file, options.message, True)
  136.     write(encoded, options.output_file)
  137.  
  138.  
  139. if __name__ == "__main__" :
  140.     parser = OptionParser()
  141.     parser.add_option("-f", "--input-file", dest="input_file",
  142.                       help="input image file", action="store", type="string")
  143.  
  144.     parser.add_option("-o", "--output-file", dest="output_file",
  145.                       help="output image file", action="store", type="string")
  146.  
  147.     parser.add_option("-m", "--message", dest="message",
  148.                       help="message to encode", action="store", type="string")
  149.  
  150.     (options, args) = parser.parse_args()
  151.  
  152.     if None in (options.input_file, options.output_file, options.message):  # if filename is not given
  153.         parser.error('Aall parameters are required')
  154.  
  155.     main()
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top