Python Caesar cipher code flaws - python

I'm new to Python. This is my 3rd project and I'm facing to some obstacles. Here I have a Caesar cipher project. It seems to do everything I needed it to do that accepts only capital letters, no special characters, no lower case letters, no spaces.
However, I have two issues:
It MUST only accept numbers that range from 1 to 26. Unfortunately, it's also accepting numbers that are even higher than 26.
Regardless of a key size it only shifts letters by 1 digit. Ideally, it must shift the letters according to entered key size:
this is where problem(s) occurring
It would be tremendous help if anyone could provide a solution or give suggestions to fix above issues. Thank you so much for your time and attention!
Here is my code:
MAX_NUMBER_KEY = 26
def getMode():
while True:
print('Please make your selection from the following "E" for encryption or "D" for decryption:')
mode = raw_input()
if mode in 'E D'.split():
return mode
else:
print('Error! Please try again and make sure to choose only "E" or "D"!')
def getText():
while True:
print('Enter your text that you would like to encrypt or decrypt:')
text = raw_input()
if text.isalpha() and text.isupper():
return text
else:
print('Error! No spaces, no special characters or numbers! Please only use letters!')
def getKey():
key = 0
while True:
print('Enter your number key for "K" (1-%s)' % (MAX_NUMBER_KEY))
key = int(raw_input().isdigit())
if (key >= 1 and key <= MAX_NUMBER_KEY):
return key
else:
print('Error! Please try again and choose only numbers between (1-26)!')
def getEncryptedMessage(mode, text, key):
if mode[0] == 'D':
key = -key
encrypted = ''
for each in text:
if each.isalpha():
num = ord(each)
num += key
if each.isupper():
if num > ord('Z'):
num -= 26
elif num < ord('A'):
num += 26
encrypted += chr(num)
else:
encrypted += each
return encrypted
mode = getMode()
message = getText()
key = getKey()
print('Your encrypted message is:')
print(getEncryptedMessage(mode, message, key))

In getKey(), raw_input().isdigit() returns a boolean, so by casting it to an int, you are going to be doing int(True) or int(False) which is 1 and 0 respectively.

Related

Need Guidance with some Python code (Substitute Cypher Python)

I have some code already but I got feedback on how to pass the rest of the criteria but I have no idea how to do it.
Assignment brief:
You are working in a Newspaper office that handles the reports from their journalists. You have been asked to design a program that will be used to help them send confidential reports in that others cannot read as email is not secure, we need to generate an encryption key that they can encode their scoops and documents when sent by email.
The program will need to generate the key. Encode the message, export the key, import a key from another person and decode a message. It will be a simple substitution cipher. The key needs to be made up out of all Alphanumeric Characters and some Special Characters. It will be a single key per session so you will need to save the key if you close the program otherwise you won’t be able to decode those messages used to encode them.
All projects start with planning it is the most important part that can make or break a project so ensure this is carried out correctly
Pass, Merit and Distinction Requirements
What the feedback says to do:
You were asked to import a key and export a key your program doesn't allow this so you would need to resubmit to get Pass4 and Pass6
Code I have done so far below
def run():
x=input("code or decode? ")
if x == "code":
a=list("")
import string
alpha = str("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")
message=input("What is your message to encode? ")
x=len(message)
y=0
z=0
for counter in range(x):
y=y+1
letter = alpha.find(message[z:y])
z=z+1
letter=letter+13
if letter > 24:
letter=letter-24
letter=alpha[letter:letter+1]
if counter != x-1:
print(letter,end="")
else:
print(letter)
x=input("type yes to go again? ")
if x == "yes":
run()
else:
input()
else:
a=list("")
import string
alpha = str("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")
message=input("What is your message to decode? ")
x=len(message)
y=0
z=0
for counter in range(x):
y=y+1
letter = alpha.find(message[z:y])
z=z+1
letter=letter-13
if letter < 0:
letter=24+letter
letter=alpha[letter:letter+1]
if counter != x-1:
print(letter,end="")
else:
print(letter)
x=input("again? ")
if x == "yes":
run()
else:
input()
run()
I did some research and come up with this.
You can use it as it is or edit it to meet your needs. Hope it helps.
Update.1: The longer the message, the bigger the encryption key will be. One solution for this is to use zlib.compress method in order to shrink the key, and then decompress it when needed.
Update.2: Added the export/import functionality of the encryption key using a Json file (you can of course choose other way of storing data) along with a title assigned to it, so you have the choice to either enter the title or enter the encryption key of the message for decryption. The title is just optional and for simplicity purposes, you can get rid of it if you want to. You'll also notice the code contains lots of if/else statements, that's just so you know where you currently are and what choices you have.
A GUI based would be better.
import string
import json
import os
# A list containing all characters
alpha = string.ascii_letters
def code(title, message, key = 6):
temp_dict = {}
cipher=[]
for i in range(len(alpha)):
temp_dict[alpha [i]] = alpha [(i+key)%len(alpha )]
# Generating the encryption key
for char in message:
if char in alpha :
temp = temp_dict[char]
cipher.append(temp)
else:
temp =char
cipher.append(temp)
# This code is needed to decode the expected message so make sure to save it by any method you want,
# otherwhise it'll generate a random text.
cipher= "".join(cipher)
main_data = {title : cipher}
file_name = "encryption_key.json"
if os.path.exists(file_name):
with open(file_name, "r+") as file:
data = json.load(file)
data[0].update(main_data)
file.seek(0)
json.dump(data, file)
else:
with open(file_name, "w") as file:
json.dump([main_data], file)
print("Encryption code :",cipher)
def decode(cipher, key = 6):
temp_dict = {}
for i in range(len(alpha)):
temp_dict[alpha [i]] = alpha [(i-key)%(len(alpha ))]
# Decoding the message
decoded_text = []
for char in cipher:
if char in alpha :
temp = temp_dict[char]
decoded_text.append(temp)
else:
temp = char
decoded_text.append(temp)
decoded_text = "".join(decoded_text)
return decoded_text
while True:
# There is an optional parameter (key) within the function which you can change according to your preference.
# The default value is 5 and it needs to be the same in both encode and decodefunctions.
x=input('[E]ncode or [D]ecode? answer with "e/d:" ')
if x.lower() == "e":
title = input("Enter the title of the message: ")
message = input("What is your message to encode? ")
code(title, message)
break
elif x.lower() == "d":
file_name = "encryption_key.json"
if os.path.exists(file_name):
with open(file_name, "r+") as file:
data = json.load(file)[0]
else:
print("There is no related file for decryption.")
continue
choice = input('Enter the [T]itle or the [K]ey of the message for decryption. [A]ll to decrypt everything on the file. answer with "t/k/a:" ')
if choice.lower() == 't':
title = input("Enter the title: ")
if title in data.keys():
encryption_key = data[title]
print(decode(encryption_key))
break
else:
print("There is no such title.")
elif choice.lower() == "k":
encryption_key = input("Enter the encryption code related to the message? ")
if encryption_key in data.values():
print(decode(encryption_key))
break
else:
print("There is no such encryption key.")
elif choice.lower() == "a":
decrypt_dict = {}
for k, v in data.items():
decrypt_dict[k] = decode(v)
print(decrypt_dict)
break
else:
print("There is no related file for decryption.")
else:
print("Enter a valid answer.")

Vigenere Cipher Python giving foreign characters instead of English

This code is meant to encrypt and decrypt using the Vigenere Cipher technique and when I choose encryption and enter my key word and text the outcome is a bunch of foreign characters printed one at a time on individual lines like this:
L
Lo
lou and so on. And additionally when I choose decryption the printed result is an error stating the 'print index is out of range'. Both of these errors I do not know how to solve, any help I would be greatly appreciative for.
#encryption
def encrypt():
crypt = ''
key_phrase = raw_input("Please enter a key phrase to encrypt by: ")
key_text = raw_input("Please enter a piece of text to encrypt: ")
if len(key_text) == 0:
print("Key must be of length 1 or more."); exit()
if not key_text.isalpha() or not key_phrase.isalpha():
print("Both text and key must be composed of letters only."); exit()
for letters in range(0, len(key_text)):
new = ord(key_text[letters]) + ord(key_text[letters%len(key_text)]) - 65
if new > 90:
new -= 26
crypt += chr(new)
print crypt
#decryption
def decrypt():
decrypt = ''
_key_phrase = raw_input("Please enter a key phrase to decrypt by: ")
_key_text = raw_input("Please enter a piece of text to include: ")
if len(_key_text) == 0:
print("Key must be of length 1 or more."); exit()
if not _key_text.isalpha() or not _key_phrase.isalpha():
print("Both text and key must be composed of letters only."); exit()
for letters in range(0, len(_key_text)):
new = ord(_key_phrase[letters]) - ord(_key_text[letters%len(_key_text)]) + 65
if new < 65:
new += 26
decrypt == chr(new)
print decrypt
#asking the user to enter a or b for en/decryption
choice = raw_input("Please enter either 'a' for encryption or 'b' for decryption: ")
if choice == 'a':
print encrypt()
else:
print decrypt()
You use ASCII codes for upper case but your key and text are in lower case.
Possible solutions:
Use upper case for key and text during input.
Set key and text to upper case by key_phrase = key_phrase.upper()
Use ASCII code for lower case not for upper case. e.g. range from 97 to 122, not 65 to 90.
This will work (though it is not the best solution):
in encrypt:
key_phrase = raw_input("Please enter a key phrase to encrypt by: ")
key_phrase = key_phrase.upper()
key_text = raw_input("Please enter a piece of text to encrypt: ")
key_text = key_text.upper()
in decrypt:
_key_phrase = raw_input("Please enter a key phrase to decrypt by: ")
_key_phrase = _key_phrase.upper()
_key_text = raw_input("Please enter a piece of text to include: ")
_key_text = _key_text.upper()

My program runs but it doesn't output an Encrypted Message

The code I wrote is a Vignere Cipher encryption program that uses a keyword to encrypt a message. I wrote this code and when I finished it I ran it and it did all it was supposed to but output the encrypted message. See my code below, any help is gratefully received:
ans = False
print(""" *****Hello. Welcome to the Vignère Cipher Encryption Program*****
***This program uses a keyword that is repeated until it
matches the same lenght of the message and then adds its
numerical value to the numerical value of the message and
outputs the encrypted message in alpha.
Please press:
E to Encrypt
D to Decrypt
or double tap enter to quit.
""")
ans=input("What would you like to do now???")
if ans == "E":
plaintext = input("Please enter a message to be encrypted: ").upper()
keyword = input("Please enter a keyword to be used to encrypt a message (alpha only): ").upper()
ciphered = " "
for i in range (len(plaintext)):
char = plaintext[i]
alphakeywordvalue = ord(keyword[i%len(keyword)]) - ord("A")+1
if char.isupper():
if ans == "E" :
value = ord(char) + alphakeywordvalue
if value > ord("Z"):
value -= 26
print ("Your encrypted text is:", ciphered)
elif ans == "D":
plaintext = input("Please enter a message to be dencrypted: ").upper()
keyword = input("Please enter a keyword to be used to dencrypt a message (alpha only(make sure that it is the same keyword used to encrypt the message)): ").upper()
ciphered = " "
for i in range (len(plaintext)):
char = plaintext[i]
alphakeywordvalue = ord(keyword[i%len(keyword)]) - ord("A")+1
if char.isupper():
if ans == "D" :
value = ord(char) - alphakeywordvalue
if value <ord("A"):
value += 26
ciphered += chr(value)
print ("Your decrypted text is:", ciphered)
This is not a good style of writing code. Very shabby and hard to read. You should make methods for individual parts and create a separate main() like section to interact with the user, if required. Engine should be hidden, car body should be polished. Keep them separate. And yes, DO NOT REPEAT YOURSELF
Well, here's my re-written code. Important parts contain the comments. Errors are explained after it..
def encrypt(message, key, direction='E'):
# Look here. There are three arguments. Third one takes 'E' to encrypt
# and anything else to decrypt. You can modify to handle more cases
ciphered = "" # Initialize. You did it almost well
for i in range (len(message)):
char = message[i]
alphakeywordvalue = ord(key[i%len(key)]) - ord("A")+1 # Perfect. We took the key
if direction=='E': # To encrypt
value = ord(char) + alphakeywordvalue
else: # To decrypt
value = ord(char) - alphakeywordvalue
ciphered += chr(value) # chr is the inverse of ord. It gets the character back
# You missed this line
return ciphered
That's it. Now you can write the code to interact with user or other modules. Here's a sample test:-
message = "Hello World"
key = "abc"
print "ORIGINAL : "+message
encoded_message = encrypt(message, key, 'E')
print "ENCRYPTED : "+encoded_message
plain_message = encrypt(encoded_message, key, 'D')
print "DECRYPTED : "+plain_message
Here's the output:
Now you can edit this method to handle more cases like out of ascii range characters etc.
How could it print the encrypted message, the encryption routine never changes ciphered from an empty string.
if ans == "E":
plaintext = input("Please enter a message to be encrypted: ").upper()
keyword = input("Please enter a keyword to be used to encrypt a message (alpha only): ").upper()
1)-> ciphered = " "
for i in range (len(plaintext)):
char = plaintext[i]
alphakeywordvalue = ord(keyword[i%len(keyword)]) - ord("A")+1
2)-> if char.isupper():
3)-> if ans == "E" :
value = ord(char) + alphakeywordvalue
if value > ord("Z"):
value -= 26
4)-> print ("Your encrypted text is:", ciphered)
ciphered set to empty string, is never changed.
You always know char is upper, because you made all the plaintext upper()
You know ans == "E" because you tested it earlier
This print() is so far indented it tries to print every time through the loop

Python issue when reading from a file [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 7 years ago.
Improve this question
Hello so i was doing a school project and I wrote this out I got it all working so my next task was to make it to read the message from an file so i changed the definition where it asked for the message which is UserMessage() so i run the code it works it prints out whats in the text file but when i do the last bit where it gets the final answer it shows this error
Traceback (most recent call last):
File "C:\Users\christian\Desktop\Python\2 keywor with cypher code.py", line 138, in <module>
Restart()
File "C:\Users\christian\Desktop\Python\2 keywor with cypher code.py", line 127, in Restart
Text = TranslateMessage2(Key2, Message2, Option)
File "C:\Users\christian\Desktop\Python\2 keywor with cypher code.py", line 107, in TranslateMessage2
Translated.append(symbol) # The symbol was not in LETTERS, so add it to translated as is.
NameError: name 'Translated' is not defined
import pyperclip
Valid_Letters = 'ZABCDEFGHIJKLMNOPQRSTUVWXY' # This is where it stores the Letters witch are being used in the program
def Linespacer():
print('================================================================')
def GetOption(): # This is the first queston in the program witch is asking if they want to encrypt decrypt
while True:
print('Do you wish to encrypt or decrypt a message?')
Option = input().lower()
if Option in 'encrypt e decrypt d'.split():
return Option # This is where if the user does not enter the right ifomation it goes back tot he top and ask the question
else:
print('Enter either "encrypt" or "e" or "decrypt" or "d".') # If the user doers not enter the right thing for example if they enter an 'l' it prints that message
def UserMessage():
mes = str(input('would you like to encrypt or decrypt from a file or type your own message?(file/f or message/m): '))
if mes == 'f' or mes == 'file':
name = str(input("What is the document you want to read called?: "))
with open(name, "rt") as in_file:
text = in_file.read()
print(text)
return text
if mes == 'm' or mes == 'message':
text = str(input('Enter your message: '))
def UserKeyword(): # This def is what ask the user for the Message and gathers the infomation
print('Enter your First keyword:') # Prints out the message asking for the keyword
return input()
def UserKeyword2(): # This def is what ask the user for the Message and gathers the infomation
print('Enter your Second keyword:') # Prints out the message asking for the keyword
return input()
def TranslateMessage(Key, Message, Option): # This is the main def and where it does all of the maths when you call the def it reqires 3 Variables
Translated = [] # stores the encrypted/decrypted message string
keyIndex = 0 # This is the defult keyIndex when the program is started
Key = Key.upper() # This is allowing the user to have Upper case letters or lowercase letters
for symbol in Message: # loop through each character in message
num = Valid_Letters.find(symbol.upper()) #
if num != -1: # -1 means symbol.upper() was not found in LETTERS
if Option == 'encrypt' or Option == 'e':
num += Valid_Letters.find(Key[keyIndex]) #This makes it so if they are encrypting it adds
elif Option == 'decrypt' or Option == 'd':
num -= Valid_Letters.find(Key[keyIndex]) # This makes it so if they are decrypting it subtract
num %= len(Valid_Letters)
if symbol.isupper():
Translated.append(Valid_Letters[num])
elif symbol.islower():
Translated.append(Valid_Letters[num].lower())
keyIndex += 1 # move to the next letter in the key
if keyIndex == len(Key):
keyIndex = 0
else:
Translated.append(symbol) # The symbol was not in LETTERS, so add it to translated as is.
return ''.join(Translated) # It joins all of the functions together so the user can have all of the text together
def TranslateMessage2(Key2, Message2, Option): # This is the main def and where it does all of the maths when you call the def it reqires 3 Variables
Translated2 = [] # stores the encrypted/decrypted message string
keyIndex = 0 # This is the defult keyIndex when the program is started
Key2 = Key2.upper() # This is allowing the user to have Upper case letters or lowercase letters
for symbol in Message2: # loop through each character in message
num = Valid_Letters.find(symbol.upper()) #
if num != -1: # -1 means symbol.upper() was not found in LETTERS
if Option == 'encrypt' or Option == 'e':
num += Valid_Letters.find(Key2[keyIndex]) #This makes it so if they are encrypting it adds
elif Option == 'decrypt' or Option == 'd':
num -= Valid_Letters.find(Key2[keyIndex]) # This makes it so if they are decrypting it subtract
num %= len(Valid_Letters)
if symbol.isupper():
Translated2.append(Valid_Letters[num])
elif symbol.islower():
Translated2.append(Valid_Letters[num].lower())
keyIndex += 1 # move to the next letter in the key
if keyIndex == len(Key2):
keyIndex = 0
else:
Translated.append(symbol) # The symbol was not in LETTERS, so add it to translated as is.
return ''.join(Translated2) # It joins all of the functions together so the user can have all of the text together
def PlayAgainMessage():
again = str(input("Would you like to restart Y or N: "));
Linespacer()
if again == "Y" or again == "y": # This is an if statment it is saying that if the user types "Y" it runs the code to restart the program
Restart(); # If the user types "N" it Exits the program
elif again == "N" or again == "n":
exit()
def Restart(): # This is the def which allows the user to restart the prgram once they have done it
Option = GetOption()
Message = UserMessage()
Key = UserKeyword()
Key2 = UserKeyword2()
Message2 = TranslateMessage(Key, Message, Option)
Text = TranslateMessage2(Key2, Message2, Option)
Linespacer()
print('Your translated text is: %s' % Text) # Prints the message and get the text which has been encrypt or decrypt
pyperclip.copy(Text)
Linespacer()
name = str(input("What would you like to name the File: "))
name1 = str;
file = open(name+".txt", "w")
file.write(Text)
file.close()
PlayAgainMessage()
Restart()
You left a Translated in your TranslateMessage2 when you probably meant to change it to Translated2.
In TranslateMessage2:
Translated.append(symbol)
Should be:
Translated2.append(symbol)
You defined Translated in TranslateMessage but not in TranslateMessage2
As a result Translated does not exist within the global namespace, nor the namespace of TranslateMessage2.
Assuming you intentionally wanted to append to Translated and not Translated2 you either need to make Translated global variable or assign it to a variable through your TranslateMessage function.
To make Translated global you simply need to initialise it outside of the function.

Python Vigenere Code repeating error

We have to do a vigenere cipher for a project, and my code just keeps repeating itself. Like it wont run the encrypt or decrypt.
here is my code.
like this is what it does for an example..
"Hey There user!
whats your message??hi
How many letters are in the message?2
Do you want to decrypt or encrypt?decrypt
Lets decrypt your message!!
Do you want to decrypt or encrypt?"
print "Hey There user!"
def vig():
dore = raw_input("Do you want to decrypt or encrypt?")
if "decrypt" in dore:
print "Lets decrypt your message!!"
else:
print "lets encrypt your message!!"
def dore(message):
encrypt = ''
decrypt = ''
if "encrypt" in vig():
for i in range(0, len(message)):
e = ord(message[i]) + ord(key[i%len(key)]) - 65
if e > 90:
e -= 26
encrypt += chr(e)
print encrypt
if "decrypt" in vig():
e = ord(message[i]) - ord(key[i%len(key)]) + 65
if e < 65:
e += 26
decrypt += chr(e)
print decrypt
####################################
###########################################:)#####
message = raw_input("whats your message??")
key = raw_input("How many letters are in the message?")
vig()
dore(message)
message = message
encrypt = ''
decrypt = ''
One of the first things you do in dore is call vig again:
if "encrypt" in vig():
Try separating encryption and decryption into two functions and calling them accordingly:
def vig(message):
ui = raw_input("Encrypt or decrypt? ").lower()
if "decrypt" in ui:
return decrypt(message)
else:
return encrypt(message)
Also, the user doesn't need to enter the length of the message, just do:
key = len(message)

Categories

Resources