Skip to main content
[Edit removed during grace period]
Source Link
Tweeted twitter.com/StackCodeReview/status/1385111154100473859
added 1 character in body
Source Link

I'mI've been working on this for a while, and now that I've got a working program I thought I'd see what other people think about it.

I'm been working on this for a while, and now that I've got a working program I thought I'd see what other people think about it.

I've been working on this for a while, and now that I've got a working program I thought I'd see what other people think about it.

Source Link

Encryption/Decryption algorithm

I'm been working on this for a while, and now that I've got a working program I thought I'd see what other people think about it.

Basically if there is anything you think would make it faster or make it simpler, or make it better in general, please share your thoughts. As for actual strength, I have no idea how to test that. And yes, I know I should just use AES, but this is just for practice/fun more than anything.

Anyway, here's the code. (255 lines, sorry)

import base64
import os
import random
# from datetime import datetime


def add_padding(s, i=128):
    padding = len(s) % i

    for j in range(i - padding):
        s += '='
    
    s = ascii_to_bin(s)
    
    # make last byte equal to number of padding bytes
    s = s[:len(s) - 8] + decimal_to_binary([i - padding])
    
    return s 


def xor_string(k, s):
    xored_secret = ''
    
    for i in range(len(s) // len(k)):
        if i > 0:
            k = round_key(k)
        
        xored_secret += decimal_to_binary([bin_to_decimal(k, len(k))[0] ^ bin_to_decimal(s[i * len(k):len(k) + (i * len(k))], len(k))[0]], len(k))
    
    return xored_secret


def generate_key(k):
    if len(k) == 128:
        k = ascii_to_bin(k)
        return k
    elif len(k) < 128:
        
        k = ascii_to_decimal(k)
        
        for i in range(128 - len(k)):
            b = decimal_to_binary([k[i]])
            b = xor_string(decimal_to_binary([int(sum(k) / len(k))]), b[::-1])
            
            k.append(int(b, 2))
        
        s = ''
        for i in k:
            s += str(i)
        
        j = str(s[:len(s) // 2])
        y = str(s[len(s) // 2:])
        s = decimal_to_binary([int(y + j)])
        s = s[:1024]
        return s


def bin_to_base64(binary):
    return base64.b64encode(bytes([int(binary[i * 8:8 + i * 8], 2) for i in range(len(binary) // 8)])).decode()


def ascii_to_bin(string):
    return decimal_to_binary(ascii_to_decimal(string))


def bin_to_decimal(binary, length=8):
    b = [binary[i * length:length + (i * length)] for i in range(len(binary) // length)]

    decimal = [int(i, 2) for i in b]

    # returns an list of ints
    return decimal


def decimal_to_binary(decimal, length=8):
    output = ''
    for i in range(len(decimal)):
        output += str(bin(decimal[i])[2:].zfill(length))
        
    # returns a string
    return output


def ascii_to_decimal(string):
    # returns a list of ints
    return [ord(i) for i in string]


def bin_to_ascii(binary):
    x = bin_to_decimal(binary)
    s = ''
    for i in x:
        s += chr(i)
    
    # returns a string
    return s


def base64_to_bin(base):
    decoded = ''
    for letter in base64.b64decode(base):
        # print(letter)
        decoded += bin(letter)[2:].zfill(8)

    return decoded

def matrix_to_str(m):
    s = ''
    for i in range(32):
        for j in range(32):
            s += str(m[i][j])
    
    return s


def obfuscate(binary, k, x, xd):
    b = ''
    d = k  # donkey kong

    for i in range(len(binary) // 1024):
        if i > 0:
            d = round_key(d)
        
        # m = [list(binary[j * 32 + i * 1024:j * 32 + i * 1024 + 32]) for j in range(32)]
        
        if x:
            m = [list(binary[j * 32 + i * 1024:j * 32 + i * 1024 + 32]) for j in range(32)]
            m = shuffle(m, bin_to_decimal(d, 1024)[0], xd)
            b += xor_string(d, matrix_to_str(m))
        elif not x:
            xor = xor_string(d, binary[i * 1024:i * 1024 + 1024])
            m = [list(xor[j * 32:j * 32 + 32]) for j in range(32)]
            m = reverse_shuffle(m, bin_to_decimal(d, 1024)[0], xd)
            b += matrix_to_str(m)
        
    return xor_string(k, b)


def shuffle(m, d, xd):
    for j in range(xd):
        # move columns to the right
        m = [row[-1:] + row[:-1] for row in m]
    
        # move rows down
        m = m[-1:] + m[:-1]
        
        shuffled_m = [[0] * 32 for _ in range(32)]

        for idx, sidx in enumerate(test(d)):
            shuffled_m[idx // 32][idx % 32] = m[sidx // 32][sidx % 32]

        m = shuffled_m

        # cut in half and flip halves
        m = m[len(m) // 2:] + m[:len(m) // 2]

        # test
        m = list(map(list, zip(*m)))
    
    return m


def reverse_shuffle(m, d, xd):
    for j in range(xd):
        # test
        m = list(map(list, zip(*m)))
        
        # cut in half and flip halves
        m = m[len(m) // 2:] + m[:len(m) // 2]
        
        shuffled_m = [[0] * 32 for _ in range(32)]
        
        for idx, sidx in enumerate(test(d)):
            shuffled_m[sidx // 32][sidx % 32] = m[idx // 32][idx % 32]
        
        m = shuffled_m
        
        # move rows up
        m = m[1:] + m[:1]
        
        # move columns to the left
        m = [row[1:] + row[:1] for row in m]
    
    return m


def test(d):
    random.seed(d)
    lst = list(range(1024))
    random.shuffle(lst)
    
    return lst


def round_key(k):
    k = [[k[(j * 32 + n)] for n in range(32)] for j in range(32)]
    # get the last column
    col = [i[-1] for i in k]
    # interweave
    col = [x for i in range(len(col) // 2) for x in (col[-i - 1], col[i])]
    new_key = ''
    for i in range(32):
        cols = ''
        for row in k:
            cols += row[i]
        
        cols = cols[16:] + cols[:16]
        new_key += xor_string(''.join(str(ele) for ele in col), cols)
    
    return new_key


def encrypt(p, s, xd):
    k = generate_key(p)
    s = add_padding(s)
    s = xor_string(k, s)
    s = obfuscate(s, k, True, xd)
    s = bin_to_base64(s)
    return s


def decrypt(p, b, xd):
    k = generate_key(p)
    b = base64_to_bin(b)
    b = xor_string(k, b)
    b = obfuscate(b, k, False, xd)
    pad = b[len(b) - 8:]
    b = bin_to_ascii(b)
    b = b[:len(b) - bin_to_decimal(pad)[0]]
    return b


if __name__ == '__main__':
    while True:
        os.system('cls')
        com = input('1)Encrypt Text \n2)Decrypt Text\n3)Exit\n')

        if com == '1':
            os.system('cls')
            secret = input('Enter the text you wish to encrypt: ')
            os.system('cls')
            key = input('Enter your key: ')
            os.system('cls')
            print(f'Encrypted text: {encrypt(key, secret, 1)}') # the 1 is the number of loops, I'm not sure how many I should do :/
            input()
        elif com == '2':
            os.system('cls')
            b64 = input('Enter the text you wish to decrypt: ')
            os.system('cls')
            key = input('Enter your key: ')
            os.system('cls')
            print(f'Decrypted text: {decrypt(key, b64, 1)}')
            input()
        elif com == '3':
            break

If you need clarification on anything, just ask. Thanks!