I'm trying to write a vigenere app in Python. Here is the way the app is supposed to run:
The cypher key is a string of alpha-numeric chars
that are then converted to an int
and that number is used to rotate the plain-text to cypher-text. For example: A
or a
rotate one letter to the right to encrypt or one letter to the left to decrypt.
Almost everything works fine. If I enter a plain-text file in English, encrypt it and then decrypt that file it using the same key, the output file should look EXACTLY like the plain-text file with which I started... and it does except for the newlines. Some of the original newlines are gone and a few new ones are thrown in for good measure.
I've spent a LONG time trying to understand what I'm doing wrong. I will appreciate any help. Here's the entire code:
# ask user if he/she wishes to encrypt or decrypt a message
pmode = 0
while True:
try:
pmode = int(input("Enter 1 to encrypt or 2 to decrypt a message: "))
while pmode not in {1, 2}:
int(input("Oops! Please enter 1 or 2: "))
break
break
except (ValueError, NameError):
print("Oops! That entry is not supported, try again...")
# ask user for a cypher keyword
key = input("Enter codeword: ")
# create list to store converted key
keylength = len(key)
realkey = [] * keylength
# convert "key" from string of chars to string of ints
for i in key:
if i.isalpha():
if i.isupper():
realkey.append(ord(i) % ord('A') + 1)
elif i.islower():
realkey.append(ord(i) % ord('a') + 1)
elif ord(i) >= 48 and ord(i) <=57:
realkey.append(int(i))
else:
realkey.append(0)
# prompt user for input file and open it
infile_name = input("Enter input file name: ")
infile = open(infile_name, 'r')
# prompt user for output file and open it
outfiler_name = input("Enter output file name: ")
outfile = open(outfiler_name, "w")
# if on encryption mode, encrypt
if pmode == 1:
# iterate over inmessage and rotate (within ASCII chars 32 - 126) using realkey
indx = -1
# loop over infile, encrypt and write to outfile
while True:
# temp variable to store current char
char = infile.read(1)
indx += 1
# stop when EOF is reached
if not char:
break
else:
if ord(char) + realkey[indx % keylength] > 126:
outfile.write(chr((ord(char) - 126 + realkey[indx % keylength])))
else:
outfile.write(chr((ord(char) + realkey[indx % keylength])))
else:
# iterate over inmessage and rotate (within ASCII chars 32 - 126) using realkey
indx = -1
# loop over infile, encrypt and write to outfile
while True:
# temp variable to store current char
char = infile.read(1)
indx += 1
# stop when EOF is reached
if not char:
break
else:
if ord(char) + realkey[indx % keylength] < 32:
outfile.write(chr((ord(char) + 126 - realkey[indx % keylength])))
else:
outfile.write(chr((ord(char) - realkey[indx % keylength])))
# close files
infile.close()
outfile.close()
Thanks.
because \n
(a newline) is ascii 10 so remember ord('\n') == 10
you have 2 possibilities at this point
ord(char) + realkey[indx % keylength] < 32:
ord(key_letter)-ord('a') >= 22
1
) then 10+126+1 = 137 (or '\x89'
)ord(char) + realkey[indx % keylength] < 32:
is false89 - 1
, well that definately does not get us back to 10, and so this has decoded the string wrongI guess the answer is your algorithm will break under many many cases ... and should be entirely refactored .... I will give you some pointers on refactoring it that will help make it more testable for you
key="Yellow55"
my_string="Hello\nTest\t\rString\r\n"
... really it would be smart to just use string.printable
as that should include all the ascii letters as a test case...def decrypt(string_to_decrypt,key):
#do your stuff
def encrypt(string_to_encrypt,key):
#do your stuff
Instead of while True: i+=1 ...
you should use for i,value in enumerate(my_list):
if you cannot print everything for somereason then at least use a debugger