0

I am writing a script that can encrypt and decrypt an image using the RSA algorithm. My public key is (7, 187) and the private key is (23,187) now the calculation for the encryption is correct like for an entry in the matrix of the image, 41 the encrypted value is 46. But when the decryption is happening it is not giving the appropriate result like for 46 it is giving 136 and for every entry of 46 in the encrypt matrix the result I am getting is 136 in the decrypt matrix. And I don't know why this is happening. When I am doing the same calculation in the python prompt(or shell) it is giving the correct answer.

In the script, I am first converting the RGB image into grayscale and then converting it to a 2d numpy array, then for each element, I am applying the RSA algo(the keys) and then saving it as an image. Then I am applying the decryption key in the encrypted matrix and then the problem is occurring. Heres the code:

from PIL import Image
import numpy as np
from pylab import * 
#encryption

img1 = (Image.open('image.jpeg').convert('L')) 
img1.show()

img = array((Image.open('image.jpeg').convert('L')))
a,b = img.shape #saving the no of rows and col in a tuple
print('\n\nOriginal image: ')
print(img)
print((a,b))
tup = a,b

for i in range (0, tup[0]):
    for j in range (0, tup[1]):
        img[i][j]= (pow(img[i][j],7)%187)


print('\n\nEncrypted image: ')
print(img)
imgOut = Image.fromarray(img)
imgOut.show()
imgOut.save('img.bmp')

#decryption

img2 = (Image.open('img.bmp'))
img2.show()
img3 = array(Image.open('img.bmp'))
print('\n\nEncrypted image: ')
print(img3)
a1,b1 = img3.shape
print((a1,b1))
tup1 = a1,b1

for i1 in range (0, tup1[0]):
    for j1 in range (0, tup1[1]):
        img3[i1][j1]= ((pow(img3[i1][j1], 23))%187) 
print('\n\nDecrypted image: ')
print(img3)
imgOut1 = Image.fromarray(img3)
imgOut1.show()
print(type(img))  

The values of the matrices:

Original image:

[[41 42 45 ... 47 41 33]

[41 43 45 ... 44 38 30]

[41 42 46 ... 41 36 30] ...

[43 43 44 ... 56 56 55]

[45 44 45 ... 55 55 54]

[46 46 46 ... 53 54 54]]

Encrypted image:

[[ 46 15 122 ... 174 46 33]

[ 46 87 122 ... 22 47 123]

[ 46 15 7 ... 46 9 123] ...

[ 87 87 22 ... 78 78 132]

[122 22 122 ... 132 132 164]

[ 7 7 7 ... 26 164 164]]

Decrypted image:

[[136 70 24 ... 178 136 164]

[136 111 24 ... 146 141 88]

[136 70 96 ... 136 100 88] ...

[111 111 146 ... 140 140 1]

[ 24 146 24 ... 1 1 81]

[ 96 96 96 ... 52 81 81]]

Any help will be greatly appreciated. Thank You.

Dutta
  • 326
  • 1
  • 3
  • 10

1 Answers1

0

I think you will get on better using the 3rd parameter to the pow() function which does the modulus internally for you.

Here is a little example without the complexity of loading images - just imagine it is a greyscale gradient from black to white.

# Make single row greyscale gradient from 0..255
img = [ x for x in range(256) ]

# Create encrypted version
enc = [ pow(x,7,187) for x in img ]

# Decrypt back to plaintext
dec = [ pow(x,23,187) for x in enc ]

It seems to decrypt back into the original values from 0..187, where it goes wrong - presumably because of overflow? Maybe someone cleverer than me will be able to explain that - please add comment for me if you know!

Mark Setchell
  • 191,897
  • 31
  • 273
  • 432
  • This will not work in this script as the `img[i][j]` is a `numpy.ndarray` and to use the 3rd parameter of the `pow()` i need to have all the parameter as `int` – Dutta Mar 21 '19 at 11:21
  • For this to work i need to take each and every value of `img` into a `int` data type like `temp` then only i can use this. – Dutta Mar 21 '19 at 11:23
  • You can make a Numpy array into a list easily with `img.tolist()` However, my point is to use the 3rd parameter to `pow()` not to make you use a list. – Mark Setchell Mar 21 '19 at 11:24