I'm currently seeking someone to review the source code for an image encryption program in Python 2.7. The code is complete and should run provided you have installed the correct packages. For this project I used Anaconda 2 as it had scipy which was convenient for its write access.
I've spent some time on cryptography stack exchange and they have specific rules preventing the analysis of cryptographic functions on that site. I'm well aware that my programming abilities are elementary, but I enjoy cryptography! I know that you're not supposed to roll your own cryptography, but that is why I'm here! I would like some security advice regarding the actual implementation. Like what aspects of my code would make it vulnerable to side channel attacks (ex differential power analysis)? Or is there information that is leaked and embedded in the actual photo? (Yikes!) Any help is appreciated!
About the code:
I know that it's slow, but it's not an issue for me. Any comments that show how to increase the speed WITHOUT the addition of the
^
operator would be appreciated. I personally like my home brewed XOR function.The particular encryption style uses cryptographic block chaining. And no, for the love of all things intelligent, I'm not talking about bit coin. This is the particular mode of operation that I used, where by SHA-512 is initially seeded with a password of the users choice the SHA-512 output is recursively passed back into SHA-512 while simultaneously being stored in the actual key_string. This is repeated until the key_string reaches the length of the image to be encrypted, and is then is trimmed if necessary. The key trimming could be an issue from a cryptographic perspective so any comments on that would be appreciated. Everything is converted to bit_strings and XOR'd and then packed back into an image to be transferred.
The commented code is below! Rip it apart!
#Precooked packages
#Running Anaconda2
from PIL import Image
import numpy as np
import hashlib
import scipy.misc
def L_P(SET,n):
#Splits an iterable object into n len chunks
to_return=[]
j=0
k=n
while k<len(SET)+1:
to_return.append(SET[j:k])
j=k
k+=n
return(to_return)
def xo(bit_string_1,bit_string_2):
#This is the exclusive or function I used, I know there is
#the ^ function that will execute the same for 0b and 0x
#encoded values, but I don't things I can't "see".
xor_str=''
for i in range(len(bit_string_1)):
if bit_string_1[i]=='0' and bit_string_2[i]=='0':
xor_str+='0'
if bit_string_1[i]=='1' and bit_string_2[i]=='1':
xor_str+='0'
if bit_string_1[i]=='0' and bit_string_2[i]=='1':
xor_str+='1'
if bit_string_1[i]=='1' and bit_string_2[i]=='0':
xor_str+='1'
return(xor_str)
def bin_n_bit(dec,n):
#Used for encoding int values to a binary string.
return(str(format(dec,'0'+n+'b')))
def list_concat(list_of_lists):
#As in the name will concatinated a list of lists
to_return=[]
for i in range(len(list_of_lists)):
to_return+=list_of_lists[i]
return(to_return)
def str_concat(list_of_strings):
#As in name it will concatinated a list of strings to a single string
to_return=''
for i in range(len(list_of_strings)):
to_return+=list_of_strings[i]
return(to_return)
def array_to_list(a_array):
#Function will take a nested numpy array and return and convert
#each element of the numpy array to a python list type
to_return=[]
for i in range(len(a_array)):
to_return.append(a_array[i].tolist())
return(to_return)
def image_mount(file_string_name):
return(Image.open(file_string_name + '.png').convert('L'))
def itl(file_string_name):
#From the file directory will convert image to list, black and white.
return(list(np.array(Image.open(file_string_name + '.png').convert('L'))))
def lti(a_list):
#In python shell will convert list to an image, black and white only.
return(Image.fromarray(np.array(a_list)))
def image_dim(image_list):
#Function will take and image and return the dimensions of the photo
#in pixel locations.
return(len(image_list),len(image_list[0]))
def int_list(a_image_str_name):
#Function will take a .png image and convert the image to a set
#of pixel integers.
to_return=[]
to_iter=list_concat(array_to_list(itl(a_image_str_name)))
for i in range(len(to_iter)):
to_return.append(to_iter[i])
return(to_return)
def int_list_bin(int_list):
#Function will take an int list and convert each list value to its
#binary representaion.
for i in range(len(int_list)):
int_list[i]=bin_n_bit(int_list[i],'8')
return(int_list)
def image_encryption(password_str,image_str_name):
#Images must be png files types, type is a string without the .png handle
#Password is any string, no length restrictions
key_to_build=''
int_pic_list=int_list_bin(int_list(image_str_name))
split_len=image_dim(array_to_list(itl(image_str_name)))[-1]
while len(key_to_build) < (len(int_pic_list))*2:
insert=hashlib.sha512(password_str.encode('utf-8')).hexdigest()
#password_str.encode('utf-8')
#MUST HAVE .encode('utf-8') can have silent failure FUCK!
key_to_build+=insert
password_str=insert
to_xor=L_P(key_to_build,2)
for i in range(len(int_pic_list)):
int_pic_list[i]=int(xo(int_pic_list[i],bin_n_bit(int(to_xor[i],16),'8')),2)
int_pic_list.append(split_len)
image_list_split=L_P(int_pic_list,int_pic_list[-1])
list_of_arrays=[]
for i in range(len(image_list_split)):
list_of_arrays.append(np.asarray(image_list_split[i]))
array_main=np.asarray(list_of_arrays)
scipy.misc.toimage(array_main).save(image_str_name + '_encryption' + '.png')
def image_decryption(password_str,image_str_name):
#Images must be png files types, type is a string without the .png handle
#Password is any string, no length restrictions
key_to_build=''
encryption_list=int_list_bin(int_list(image_str_name))
split_len=image_dim(array_to_list(itl(image_str_name)))[-1]
while len(key_to_build) < len(encryption_list)*2:
insert=hashlib.sha512(password_str.encode('utf-8')).hexdigest()
#password_str.encode('utf-8')
#MUST HAVE .encode('utf-8') can have silent failure FUCK!
key_to_build+=insert
password_str=insert
to_xor=L_P(key_to_build,2)
for i in range(len(encryption_list)):
encryption_list[i]=int(xo(encryption_list[i],bin_n_bit(int(to_xor[i],16),'8')),2)
encryption_list.append(split_len)
image_list_split=L_P(encryption_list,encryption_list[-1])
list_of_arrays=[]
for i in range(len(image_list_split)):
list_of_arrays.append(np.asarray(image_list_split[i]))
array_main=np.asarray(list_of_arrays)
scipy.misc.toimage(array_main).save(image_str_name + '_decryption' + '.png')