Last active
May 7, 2021 17:19
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
Small nitpick but using python's random library is not secure. You should be using the secrets module. (See: warning in the random library doc)
Ohhh thanks, I'll rewrite it in a bit
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.
Guess I'm sticking to it haha
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
big nerd ❤️