Skip to content

Instantly share code, notes, and snippets.

@jlsajfj
Last active May 7, 2021 17:19
Show Gist options
  • Save jlsajfj/1d35180872f336fb65a9b10f7b3dd843 to your computer and use it in GitHub Desktop.
Save jlsajfj/1d35180872f336fb65a9b10f7b3dd843 to your computer and use it in GitHub Desktop.
Simple program to encrypt and decrypt images, through image manipulation. Seems secure enough.
from PIL import Image
import sys
import hashlib
from getpass import getpass
import random
swap = ((1, 2, 3, 0), (3, 2, 1, 0), (1, 3, 0, 2), (0, 3, 1, 2), (1, 2, 0, 3), (2, 0, 3, 1), (2, 1, 0, 3), (3, 1, 2, 0), (0, 1, 3, 2), (2, 3, 1, 0), (0, 3, 2, 1), (3, 1, 0, 2), (3, 0, 2, 1), (3, 2, 0, 1), (2, 1, 3, 0), (0, 2, 3, 1), (3, 0, 1, 2), (2, 3, 0, 1), (0, 2, 1, 3), (1, 3, 2, 0), (2, 0, 1, 3), (0, 1, 2, 3), (1, 0, 2, 3), (1, 0, 3, 2))
def encrypt(file, pword):
img = Image.open(file)
img = img.convert('RGBA')
pixels = img.load()
width, height = img.size
i_cnt, j_cnt = 0, 0
hashed = hashlib.md5(pword.encode()).hexdigest()
random.seed(hashed)
for ii in range(width):
for jj in range(height):
cur = list(pixels[ii, jj])
for kk in range(4):
cur[kk] = cur[kk]^((ord(hashed[j_cnt]) + int(random.random() * 255)) % 256)
j_cnt += 1
j_cnt = j_cnt % len(hashed)
num = (ord(pword[i_cnt]) + int(random.random()*24)) % 24
cur = [cur[swap[num][0]], cur[swap[num][1]], cur[swap[num][2]], cur[swap[num][3]]]
i_cnt += 1
i_cnt = i_cnt % len(pword)
pixels[ii, jj] = tuple(cur)
img.save('encrypted-' + file)
def decrypt(file, pword):
img = Image.open(file)
pixels = img.load()
width, height = img.size
i_cnt, j_cnt = 0, 0
hashed = hashlib.md5(pword.encode()).hexdigest()
random.seed(hashed)
for ii in range(width):
for jj in range(height):
cur = list(pixels[ii, jj])
rr = [random.random(), random.random(), random.random(), random.random()]
r2 = random.random()
num = (ord(pword[i_cnt]) + int(r2*24))%24
cur[swap[num][0]], cur[swap[num][1]], cur[swap[num][2]], cur[swap[num][3]] = cur
for kk in range(4):
cur[kk] = cur[kk]^((ord(hashed[j_cnt]) + int(rr[kk] * 255)) % 256)
j_cnt += 1
j_cnt = j_cnt % len(hashed)
i_cnt += 1
i_cnt = i_cnt % len(pword)
pixels[ii, jj] = tuple(cur)
img.save('decrypted-'+file)
dec = False
infile = ""
if not len(sys.argv) > 1:
infile = input("File: ")
else:
import argparse
parser = argparse.ArgumentParser()
paa = parser.add_argument
paa('input_file')
paa('-d', action='store_true', dest='decrypt')
res = parser.parse_args()
dec = res.decrypt
infile = res.input_file
password = getpass()
if dec:
decrypt(infile, password)
else:
encrypt(infile, password)
@jlsajfj
Copy link
Author

jlsajfj commented Apr 30, 2021

Ohhh thanks, I'll rewrite it in a bit

@JasonL84
Copy link

Nevermind, the correctness of your system relies on the ability to seed your PRNG. You can't do that with secrets since it reads from /dev/random. So it looks like you'll have to use the random library.

@jlsajfj
Copy link
Author

jlsajfj commented Apr 30, 2021

Guess I'm sticking to it haha

@jlsajfj
Copy link
Author

jlsajfj commented May 7, 2021

Just made it non-destructive on encryption, decryption was already fine. This way if you do the wrong operation, you can basically just undo it by deleting the new file

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment