Reorganization of all modules.

This commit is contained in:
Cédric Bonhomme 2016-05-19 21:32:15 +02:00
parent e0bed8ba52
commit 872a5546fc
No known key found for this signature in database
GPG key ID: A1CB94DE57B7A70D
23 changed files with 77 additions and 43 deletions

View file

@ -0,0 +1,4 @@
#!/usr/bin/env python
#-*- coding: utf-8 -*-
from .lsbset import *

View file

@ -0,0 +1,156 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Stéganô - Stéganô is a basic Python Steganography module.
# Copyright (C) 2010-2016 Cédric Bonhomme - https://www.cedricbonhomme.org
#
# For more information : https://github.com/cedricbonhomme/Stegano
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>
__author__ = "Cedric Bonhomme"
__version__ = "$Revision: 0.2 $"
__date__ = "$Date: 2011/12/28 $"
__revision__ = "$Date: 2012/12/14 $"
__license__ = "GPLv3"
import math
import itertools
def identity():
"""
f(x) = x
"""
n = 0
while True:
yield n
n += 1
def Dead_Man_Walking():
n = 0
while True:
yield n + 7
n += 2
def OEIS_A000217():
"""
http://oeis.org/A000217
Triangular numbers: a(n) = C(n+1,2) = n(n+1)/2 = 0+1+2+...+n.
"""
n = 0
while True:
yield (n*(n+1))//2
n += 1
def fermat():
"""
Generate the n-th Fermat Number.
"""
y = 5
while True:
yield y
y = pow(y-1,2)+1
def mersenne():
"""
Generate 2^n-1.
"""
y = 1
while True:
yield y
y = 2*y + 1
def eratosthenes():
"""
Generate the prime numbers with the sieve of Eratosthenes.
"""
d = {}
for i in itertools.count(2):
if i in d:
for j in d[i]:
d[i + j] = d.get(i + j, []) + [j]
del d[i]
else:
d[i * i] = [i]
yield i
def eratosthenes_composite():
"""
Generate the composite numbers with the sieve of Eratosthenes.
"""
p1 = 3
for p2 in eratosthenes():
for n in range(p1 + 1, p2):
yield n
p1 = p2
def carmichael():
for m in eratosthenes_composite():
for a in range(2, m):
if pow(a,m,m) != a:
break
else:
yield m
def ackermann(m, n):
"""
Ackermann number.
"""
if m == 0:
return n + 1
elif n == 0:
return ackermann(m - 1, 1)
else:
return ackermann(m - 1, ackermann(m, n - 1))
def fibonacci():
"""
A generator for Fibonacci numbers, goes to next number in series on each call.
This generator start at 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, ...
See: http://oeis.org/A000045
"""
a, b = 1, 2
while True:
yield a
a, b = b, a + b
def syracuse(l=15):
"""
Generate the sequence of Syracuse.
"""
y = l
while True:
yield y
q,r = divmod(y,2)
if r == 0:
y = q
else:
y = 3*y + 1
def log_gen():
"""
Logarithmic generator.
"""
y = 1
while True:
adder = max(1, math.pow(10, int(math.log10(y))))
yield int(y)
y = y + adder
if __name__ == "__main__":
# Point of entry in execution mode.
f = fibonacci()
for x in range(13):
#print(next(f), end=' ') # 0 1 1 2 3 5 8 13 21 34 55 89 144
pass

199
stegano/lsbset/lsbset.py Normal file
View file

@ -0,0 +1,199 @@
#!/usr/bin/env python
#-*- coding: utf-8 -*-
# Stéganô - Stéganô is a basic Python Steganography module.
# Copyright (C) 2010-2016 Cédric Bonhomme - https://www.cedricbonhomme.org
#
# For more information : https://github.com/cedricbonhomme/Stegano
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>
__author__ = "Cedric Bonhomme"
__version__ = "$Revision: 0.4.1 $"
__date__ = "$Date: 2016/03/13 $"
__license__ = "GPLv3"
import sys
from PIL import Image
from stegano import tools
from . import generators
try:
input = raw_input
except NameError:
pass
def hide(input_image_file, message, generator_function, auto_convert_rgb=False):
"""
Hide a message (string) in an image with the
LSB (Least Significant Bit) technique.
"""
img = Image.open(input_image_file)
if img.mode != 'RGB':
print('The mode of the image is not RGB. Mode is {}'.format(img.mode))
if not auto_convert_rgb:
answer = input('Convert the image to RGB ? [Y / n]\n') or 'Y'
if answer.lower() == 'n':
raise Exception('Not a RGB image.')
img = img.convert('RGB')
img_list = list(img.getdata())
width, height = img.size
index = 0
message = str(len(message)) + ":" + str(message)
#message_bits = tools.a2bits(message)
message_bits = "".join(tools.a2bits_list(message))
message_bits += '0' * ((3 - (len(message_bits) % 3)) % 3)
npixels = width * height
if len(message_bits) > npixels * 3:
raise Exception("""The message you want to hide is too long (%s > %s).""" % (len(message_bits), npixels * 3))
generator = getattr(generators, generator_function)()
while index + 3 <= len(message_bits) :
generated_number = next(generator)
(r, g, b) = img_list[generated_number]
# Change the Least Significant Bit of each colour component.
r = tools.setlsb(r, message_bits[index])
g = tools.setlsb(g, message_bits[index+1])
b = tools.setlsb(b, message_bits[index+2])
# Save the new pixel
img_list[generated_number] = (r, g , b)
index += 3
# create empty new image of appropriate format
encoded = Image.new('RGB', (img.size))
# insert saved data into the image
encoded.putdata(img_list)
return encoded
def reveal(input_image_file, generator_function):
"""
Find a message in an image
(with the LSB technique).
"""
img = Image.open(input_image_file)
img_list = list(img.getdata())
width, height = img.size
buff, count = 0, 0
bitab = []
limit = None
generator = getattr(generators, generator_function)()
while True:
generated_number = next(generator)
# color = [r, g, b]
for color in img_list[generated_number]:
buff += (color&1)<<(7-count)
count += 1
if count == 8:
bitab.append(chr(buff))
buff, count = 0, 0
if bitab[-1] == ":" and limit == None:
try:
limit = int("".join(bitab[:-1]))
except:
pass
if len(bitab)-len(str(limit))-1 == limit :
return "".join(bitab)[len(str(limit))+1:]
return ""
def write(image, output_image_file):
"""
"""
try:
image.save(output_image_file)
except Exception as e:
# If hide() returns an error (Too long message).
print(e)
if __name__ == '__main__':
# Point of entry in execution mode.
from optparse import OptionParser
parser = OptionParser(version=__version__)
parser.add_option('--hide', action='store_true', default=False,
help="Hides a message in an image.")
parser.add_option('--reveal', action='store_true', default=False,
help="Reveals the message hided in an image.")
# Original image
parser.add_option("-i", "--input", dest="input_image_file",
help="Input image file.")
# Generator
parser.add_option("-g", "--generator", dest="generator_function",
help="Generator")
# Image containing the secret
parser.add_option("-o", "--output", dest="output_image_file",
help="Output image containing the secret.")
# Non binary secret message to hide
parser.add_option("-m", "--secret-message", dest="secret_message",
help="Your secret message to hide (non binary).")
# Binary secret to hide (OGG, executable, etc.)
parser.add_option("-f", "--secret-file", dest="secret_file",
help="Your secret to hide (Text or any binary file).")
# Output for the binary binary secret.
parser.add_option("-b", "--binary", dest="secret_binary",
help="Output for the binary secret (Text or any binary file).")
parser.set_defaults(input_image_file = './pictures/Lenna.png',
generator_function = 'fermat',
output_image_file = './pictures/Lenna_enc.png',
secret_message = '', secret_file = '', secret_binary = "")
(options, args) = parser.parse_args()
if options.hide:
if options.secret_message != "" and options.secret_file == "":
secret = options.secret_message
elif options.secret_message == "" and options.secret_file != "":
secret = tools.binary2base64(options.secret_file)
img_encoded = hide(options.input_image_file, secret, options.generator_function)
try:
img_encoded.save(options.output_image_file)
except Exception as e:
# If hide() returns an error (Too long message).
print(e)
elif options.reveal:
try:
secret = reveal(options.input_image_file, options.generator_function)
except IndexError:
print("Impossible to detect message.")
exit(0)
if options.secret_binary != "":
data = tools.base642binary(secret)
with open(options.secret_binary, "w") as f:
f.write(data)
else:
print(secret)