0

I'm currently making an encryption program for an assignment however I cannot decrypt. The cause of this is that the key is a string made from a randomly generated bitstring however when turning the key back into a bitstring I get a different bitstring. I realized this after checking and finding out that the bitstring after turning the key back to binary is shorter than the bitstring used to make the key.

##imports##################################################
from socket import *
import random

##functions################################################
def CCipher(message, k):
    output = ""
    for x in message:
        i = ord(x)
        i = (i+k)%128
        output += chr(i)
    return output

def toBinary(message):
    output = ""
    for x in message:
        i = bin(ord(x))[2:]
        output += i
    return output

def XOR(bitstring1, bitstring2):
    output = ""
    if(len(bitstring1) != len(bitstring2)):
        print("Use bitstrings of the same length")
        return None
    for x in range(len(bitstring1)):
        if(bitstring1[x] == "1" and bitstring2[x] == "0"):
            output += "1"
        elif(bitstring1[x] == "0" and bitstring2[x] == "1"):
            output += "1"
        else:
            output += "0"
    return output

def randomBinary(k):
    output = ""
    for x in range(k):
        i = random.randint(0,1)
        output = output + str(i)
    return output

def toString(message):
    output = ""
    i = ""
    n = 0
    for x in message:
        n += 1
        i += x
        if(n == 7):
            output += chr(int(i,2))
            n = 0
            i = ""
    return output

##server stuff#########################################
serverName = "OmariPC"
serverPort = 12347
clientSocket = socket(AF_INET,SOCK_STREAM)
clientSocket.connect((serverName,serverPort))

##files################################################
nowar = open("NoWar.dat",'r')
trump = open("Trump.dat","w")

##encryption###########################################
message = nowar.read()
mesBin = toBinary(message)
bkey = randomBinary(len(mesBin))
encrypted = XOR(mesBin, bkey)
encrypted = toString(encrypted)
key = toString(bkey)
trump.write(encrypted)
trump.close()
enKey = CCipher(key, 4)

##sending###############################################
clientSocket.send(enKey.encode())
print(len(enKey))
clientSocket.send(encrypted.encode())
print(len(encrypted))

##testing###############################################
if key == toString(bkey):
    print(True)
else:
    print(False)
if len(toBinary(key)) == len(bkey):
    print(True)
else:
    print(False)

output: 168 168 True False

  • The `key == toString(bkey)` test does not appear to be useful since `key` was initialized to `toString(bkey)` in the first place. Of course they'll be equal. You should start to debug this by unit-testing your functions: does `toString()` produce the strings you expect for given inputs? Does `toBinary()`? – jamesdlin Feb 25 '19 at 01:29
  • Your `toString()` implementation generates characters after collecting 7 bits, but shouldn't you be collecting 8? – jamesdlin Feb 25 '19 at 01:35
  • Yes in a previous program i had used these exact functions (though the message being converted was much smaller) and they had provided me with the results i had expected. Also thank you now that you mentioned it there is no need for the key == toString(bkey) test – Omari Lawrence Feb 25 '19 at 01:41
  • The `toString()` function works as it is supposed to because the binary codes being generated are also 7 bits long. It was originally supposed to be 8 but sir said to use 7 since thats what was being generated and others didnt know how to add the extra 0 to the front of the bitstring – Omari Lawrence Feb 25 '19 at 01:46

1 Answers1

1
def toBinary(message):
    output = ""
    for x in message:
        i = bin(ord(x))[2:]
        output += i
    return output

bin(ord(x)) generates strings of variable length. For example:

>>> bin(ord(' '))
0b100000
>>> bin(ord('a'))
0b1100001

You concatenate all of the results of bin() together, so there's no way to separate them later. Meanwhile, your toString() function reads exactly 7 "bits" at a time.

You could make bin() append chunks of a fixed-size instead:

# Pad the left with 0s to always generate a string of length 7.
# (Assumes that all input characters are ASCII.)
assert(ord(x) < 128)
bin(ord(x))[2:].rjust(7, '0')
jamesdlin
  • 81,374
  • 13
  • 159
  • 204