Why does this inverse matrix encryption, decryption not work with more than 1 digit matrix as a key?

40 Views Asked by At

This is a program that aims to encrypt text by: turning them into alphabetical order first, checking if its even or not, then splitting it into two numbers that represent those alpha in one list to make it possible to multiply by the key matrix to then get the resultant numbers. The decrypt works by paring them into two items per list Calculate using multiplication of inverse of the key matrix with the encryped numbers u get from the function above, Afterwards it convert those numbers back to alphabet via the dictionary I think this is called hill cypher The code:

import pyperclip
Alphabet_Dictionary = {chr(i): i - ord('A') + 1 if i >= ord('A') and i <= ord('Z') else i - ord('a') + 1 for i in range(ord('A'), ord('Z') + 1)}

Alphabet_Dictionary[' '] = 27

def text2num(message):
    text2numresult = []
    for letter in message:
        text2numresult.append(Alphabet_Dictionary[letter.upper()])
    return text2numresult
def num2text(numlist):
    num2textresult = ""
    for num in numlist:
        for letter,value in Alphabet_Dictionary.items():
            if num == value:
                num2textresult += letter
    return num2textresult
def splittingNums(messagenum):
    splittingNumsresult = []
    for i in range(len(messagenum)):
        if i % 2 == 0:
            splittingNumsresult.append([messagenum[i], messagenum[i+1]])
    return splittingNumsresult
def matrixmultiplication2x2and2x1(keymatrix, textmatrix):
    return [keymatrix[0][0]*textmatrix[0] + keymatrix[0][1]*textmatrix[1], keymatrix[1][0]*textmatrix[0] + keymatrix[1][1]*textmatrix[1]]



def encryption(message, keymatrix):
    messagenum = text2num(message)
    messagenumsplit = splittingNums(messagenum)
    resultantmatrix = []
    resultantnumber = ""
    for i in messagenumsplit:
        resultantmatrix.append(matrixmultiplication2x2and2x1(keymatrix, i))
    for x in resultantmatrix:
        for y in x:
            resultantnumber += str(y) + " "
    return resultantnumber[0:-1]

def decryption(messagenum, keymatrix):
    messagenumsplit = splittingNums(messagenum)
    resultantmatrix = []
    det = keymatrix[0][0]*keymatrix[1][1] - keymatrix[1][0]*keymatrix[0][1]
    invkeymatrix = [
        [keymatrix[1][1]/float(det), -keymatrix[0][1]/float(det)],
        [-keymatrix[1][0]/float(det), keymatrix[0][0]/float(det)]
    ]
    for i in messagenumsplit:
        resultantmatrix.extend(matrixmultiplication2x2and2x1(invkeymatrix, i))
    textresult = num2text(resultantmatrix)
    return textresult
    


while True:
    choice = input("I want to: decrypt(d) | encrypt(e):")
    key = input("Please enter your keymatrix(2x2) as each number serperated by a space:")
    key = list(map(int, key.split(" ")))
    keymatrix = [
        [key[0], key[1]],
        [key[2], key[3]]
    ]
    if choice.lower() == "e":
        message = input("Message:").strip()
        if len(message) % 2 != 0:
            message += " "
        result = encryption(message, keymatrix)
        pyperclip.copy(result)
    elif choice.lower() == "d":
        messagenum = input("Enter your numbers, with space in between:").strip()
        messagenum = list(map(int, messagenum.split(" ")))
        result = decryption(messagenum, keymatrix)
    print(result)




# This program can only handle 1 degit inverse matrix for some reason idk why

The above code work if my key is 1 digit like this:

Case1(1 digit keys)

I want to: decrypt(d) | encrypt(e):e Please enter your keymatrix(2x2) as each number serperated by a space:1 2 1 3 Message:attack 41 61 22 23 25 36 I want to: decrypt(d) | encrypt(e):d Please enter your keymatrix(2x2) as each number serperated by a space:1 2 1 3 Enter your numbers, with space in between:41 61 22 23 25 36 ATTACK

Why does this inverse matrix encryption, decryption not work with more than 1 digit matrix as a key? if I use key that is large, like this: ** Case2(multiple digis keys)**

I want to: decrypt(d) | encrypt(e):e Please enter your keymatrix(2x2) as each number serperated by a space:421 7842 10312 85983 Message:attack now 157261 1729972 16262 292223 87525 976749 121155 1482186 186681 2132289 I want to: decrypt(d) | encrypt(e):d Please enter your keymatrix(2x2) as each number serperated by a space:421 7842 10312 85983 Enter your numbers, with space in between:157261 1729972 16262 292223 87525 976749 121155 1482186 186681 2132289 AACO

The answer would be AACO compared to ATTACK NOW, which is completely wrong. I can't figure out why this is.

Asked AI and it doesn't seems to know how to fix it either, all attempts failed. First change i made was to use float in the inv matrix. Second change tried to make was using decrypt like this:

def decryption(messagenum, keymatrix):
    messagenumsplit = splittingNums(messagenum)
    resultantmatrix = []
    det = keymatrix[0][0]*keymatrix[1][1] - keymatrix[1][0]*keymatrix[0][1]
    invkeymatrix = [
        [keymatrix[1][1]/float(det), -keymatrix[0][1]/float(det)],
        [-keymatrix[1][0]/float(det), keymatrix[0][0]/float(det)]
    ]
    for i in messagenumsplit:
        decrypted_pair = matrixmultiplication2x2and2x1(invkeymatrix, i)
        resultantmatrix.append(decrypted_pair)
    textresult = num2text([num for pair in resultantmatrix for num in pair])
    return textresult

But it didn't seems to fix anything. so i reverted back Third, thought i did use a weird method of adding space to odd letters, it seems to function fine.

Now I am not sure if it the problem with encrypt or decrpyt that gives me the wrong text.

0

There are 0 best solutions below