Hello i have an encrypted message i have opened the file in python created a list from the text document of all the individual characters, I then want to add a key to each letter in the list.
print (chr((ord(Z+key)))) # takes the ASCII value of the letter adds the key then changes back into a character
My issue is how do i made Z+1 Equal A instead of [
Use congruent addition!
key = 5
for i in range(26):
print (chr((i + key) % 26 + ord('A')))
Like the comment says. if result > Z. Then you count up more number to result so that is becomes a.
result = chr(ord(Z+key))
if result > ord(Z):
result = chr(ord(Z+102))
i am not sure of it is 102 or 103.
An easy way out is to view both the message and the keys as bytes.
Then you can just perform an exclusive-or (^) for both encryption and decryption.
If you need readable output, use base64 encoding on the key and ciphertext before writing them to disk. You can use my onepad program as an example of this approach.
Related
Caesar Cipher is a simple way of encryption that shifts a character a number of places in front of it. For example, ABC with a Rotation of 1 would be BCD. In this program, however, the list of all characters include special characters in a random order, i.e.
1234567890-=qwertyuiopasdfghjklzxcvbnm,./~!##$%^&*()_+|\\{}[]:;\'"QWERTYUIOPASDFGHJKLZXCVBNM
Thus, it is more of a custom cipher but following the principle of Caesar Cipher, the code can be tested by using the 2 functions I have made (encode() and decode()) on the same text, and if the output given is the same as the input, it means that it works. I get an output for some rotation numbers, but some numbers, like 70, give me an error. The code I have written is:
characters = '`1234567890-=qwertyuiopasdfghjklzxcvbnm,./~!##$%^&*()_+|\\{}[]:;\'"QWERTYUIOPASDFGHJKLZXCVBNM' # All characters in a string, no specific order
key_raw = 70 # One of the keys that gives me an error.
def encode(text, key): # Function that takes in two inputs: Text and key, which is the number of characters to shift forward
output, text = '', str(text)
limit = len(characters)
while key > limit:
key -= limit # This is my attempt to simplify the key
for i in text:
if i in characters:
output += characters[characters.index(i)+key] # If i is in characters, the rotated character is concatenated to the output
else:
output += i # Otherwise, it directly adds the text
return output
def decode(text, key): # Same thing, except key is subtracted from the index of i in key, as to decrypt it
output, text = '', str(text)
limit = len(characters)
while key > limit:
key -= limit
for i in text:
if i in characters:
output += characters[characters.index(i)-key]
else:
output += i
return output
print(encode('Why do I get String_Index_Out_Of_Range?', key_raw))
Please let me know where I made an error.
Consider what happens when you receive characters.index(i)+key where index is the last symbol in characters.
Simply put, your Caesar cipher is missing modulo operations.
But, to make this more useful, we can still try to improve your code further.
Lets start with the way you build strings. What you are currently using is slower when it comes to large strings. Instead, you should try using .join().
def encrypt(text, key): # Function that takes in two inputs: Text and key, which is the number of characters to shift forward
output, text = [], str(text)
limit = len(characters)
while key > limit:
key -= limit # This is my attempt to simplify the key
for i in text:
if i in characters:
output.append(characters[characters.index(i)+key]) # If i is in characters, the rotated character is concatenated to the output
else:
output.append(i) # Otherwise, it directly adds the text
return output.join()
Now your key optimization is basically just a modulo operation, so lets replace it with `key = key % len(characters).
def encrypt(text:str, key:int): # Function that takes in two inputs: Text and key, which is the number of characters to shift forward
output, text = [], str(text)
key = key % len(characters)
for i in text:
if i in characters:
output.append(characters[characters.index(i)+key]) # If i is in characters, the rotated character is concatenated to the output
else:
output.append(i) # Otherwise, it directly adds the text
return output.join()
Now comes your lookup method. It hopes for O(n) complexity, and has O(nm) complexity. Considering you might encrypt large texts, you may want to trade some space to save time. Lets use mapping structure instead.
And then add some finishing touches to make this prettier.
def encrypt(text:str, key:int, characters:str=characters):
'''
Function that shifts input by the number of buckets specified in key.
Unknown characters are retained.
:param text: text to be encrypted
:param key: number to shift by
:param characters: string specifying character ordering, None for default.
:return: encrypted string
'''
if not isinstance(text, str) or not isinstance(key, int):
raise ValueError('Incorrect param type')
output= []
l = len(characters)
key = key % l
char_map = { characters[i]:((i+key) % l) for i in characters}
for i in text:
ch = char_map.get(i)
if ch is None:
ch = i
output.append(ch)
return output.join()
output += characters[characters.index(i)+key]
output += characters[characters.index(i)-key]
The above lines are missing modulo operations.
characters.index(i)+key must be taken under modulo division with length of characters, which is limit in your code.
So, it should be,
output += characters[(characters.index(i)+key) % limit]
output += characters[(characters.index(i)-key) % limit]
This should work for you.
I'm trying to code another encrypter, I'm having problems with the decoding process.
I've read a lot of StackOverflow's questions about this argument, I alredy know that someone is going to mark this question as a duplicate but I'm writing this because I can't find a solution to my problem.
The encode function gives me this string
4697625275273471234347364527724769
That is the encoded message (it says 'Hello world!') and I have the 'Key' (randomly generated every time I start the program), that cointains the combiantions of numbers needed to decode the message.
Here is the key
12040512030417060213060413030716060915090216080313040713060215090916020217020419040215050918070812050414030615020715020512061602071404091407041805160407170516030919090718050315070618020719070218050812030317020918060815070817020816040318080414060914060414050419030818030513020419030517040912040218020918030616050313050413040319070618020617060518060314090616070612080615060613020912040413070619070918050217040512070813020816020513090812090218080715020317050217050313070419020717090712060814020816030518040317030616050915020215030516050518080314040619060815030816020613040518080817060913070312080316050717020714070212090915090812090517030916060218091905051608071904041303021209031606081707051209081908041302051808021602081202041508031708041204031608041504031708051307051908081405091809051207091408061805061806021306061902021805041706081902061303031606051803091309061202031504061702021206091402091604041906041709091609061506081908091707021604061604081309051508091905041903031903071202021705061409091205091803071409041505071204061709041909091209061409051309041707031207041709061704021804051907071703031707091605081907051506041308051305071407031708031607021902051802051705041209071909081709051804041804091403021503031507071208051307021507041806051404031904031903061208041607031204071609091904091809031807031206041308091907041908031809071704031807071909021209041509071304041804071309071707061603081305051606031304021208071908021407081803021807021406071808051602041502061903091205051508051206031803081802021503061602031403081403091909061409081703021606071504051609041409031504021308021509051905031206071605021206051507021408021402061907031502041705091504081308081207051902091704061603071503041202061605061303091507091408041906091608061609081504041706071205021405021603041303041305031607081403051703041406061304081306071308061307081602091207061203091403071503091202051607041308071506021407071803031305021309031805091203061906051406031304061704071207071706031508061206021709021404051403041508071704041203071403031306081705051709081708061706041207031909031309091507031708021404041704081702031404071307071203051409071
it's a bit long.
And now that I have the parameters you need to put them in the decoder
input_text = input('Encrypted MSG\n> ')
key = input('Key\n> ')
alphabet = list(" qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890èéòç#à°#ù§[]+*,;.:-_<>£$₽%&()=?ì^/|!ėëęēêĖËĘĒÉÈÊūûüúŪÛÜÚÙīïįíìîĪÏĮÍÌκōøõœöôóŌØÕŒÖÓÒãåāáâäæÃÅĀªÀÁÂÄÆßẞÇñÑ¥¢∆¶×÷π√•`~©®™✓йцукенгшщзхфывапролджэячсмитьбюЙЦУКЕНГШЩЗХФЫВАПРОЛДЖЭЯЧСМИТЬБЮ⌂☻‼‰╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤▬╥╙╘╒╓╫╪┘┌¤█▄▌▐▀αΣσ░▒▓│┤╡╢╖╕╣║╗╝¿þ¼½¾ⁿ⌠⌡≤≥±≡∩∞ΘΩð«»⌐¬¨↨↑↓→←↔₧☼♥♦♣♠♂♀♪◘○◙►◄▲▼Þ‘’“”„☭卐")
key = key.replace('0', '')
key = key.replace('1', ' ')
key = key.split()
key.insert(0,'1')
charmap = zip(key, alphabet)
_map = dict(charmap)
output_text = ''.join(str(_map.get(c)) for c in input_text)
print(f'Output\n> {output_text}')
The output [ACTUAL]
Encrypted MSG
> 4697625275273471234347364527724769
Key
> 12040512030417060213060413030716060915090216080313040713060215090916020217020419040215050918070812050414030615020715020512061602071404091407041805160407170516030919090718050315070618020719070218050812030317020918060815070817020816040318080414060914060414050419030818030513020419030517040912040218020918030616050313050413040319070618020617060518060314090616070612080615060613020912040413070619070918050217040512070813020816020513090812090218080715020317050217050313070419020717090712060814020816030518040317030616050915020215030516050518080314040619060815030816020613040518080817060913070312080316050717020714070212090915090812090517030916060218091905051608071904041303021209031606081707051209081908041302051808021602081202041508031708041204031608041504031708051307051908081405091809051207091408061805061806021306061902021805041706081902061303031606051803091309061202031504061702021206091402091604041906041709091609061506081908091707021604061604081309051508091905041903031903071202021705061409091205091803071409041505071204061709041909091209061409051309041707031207041709061704021804051907071703031707091605081907051506041308051305071407031708031607021902051802051705041209071909081709051804041804091403021503031507071208051307021507041806051404031904031903061208041607031204071609091904091809031807031206041308091907041908031809071704031807071909021209041509071304041804071309071707061603081305051606031304021208071908021407081803021807021406071808051602041502061903091205051508051206031803081802021503061602031403081403091909061409081703021606071504051609041409031504021308021509051905031206071605021206051507021408021402061907031502041705091504081308081207051902091704061603071503041202061605061303091507091408041906091608061609081504041706071205021405021603041303041305031607081403051703041406061304081306071308061307081602091207061203091403071503091202051607041308071506021407071803031305021309031805091203061906051406031304061704071207071706031508061206021709021404051403041508071704041203071403031306081705051709081708061706041207031909031309091507031708021404041704081702031404071307071203051409071
Output
> NoneNoneNoneNoneNoneNoneNoneNoneNoneNoneNoneNoneNoneNoneNone NoneNoneNoneNoneNoneNoneNoneNoneNoneNoneNoneNoneNoneNoneNoneNoneNoneNone
The output [EXPECTED]
Encrypted MSG
> 4697625275273471234347364527724769
Key
> 12040512030417060213060413030716060915090216080313040713060215090916020217020419040215050918070812050414030615020715020512061602071404091407041805160407170516030919090718050315070618020719070218050812030317020918060815070817020816040318080414060914060414050419030818030513020419030517040912040218020918030616050313050413040319070618020617060518060314090616070612080615060613020912040413070619070918050217040512070813020816020513090812090218080715020317050217050313070419020717090712060814020816030518040317030616050915020215030516050518080314040619060815030816020613040518080817060913070312080316050717020714070212090915090812090517030916060218091905051608071904041303021209031606081707051209081908041302051808021602081202041508031708041204031608041504031708051307051908081405091809051207091408061805061806021306061902021805041706081902061303031606051803091309061202031504061702021206091402091604041906041709091609061506081908091707021604061604081309051508091905041903031903071202021705061409091205091803071409041505071204061709041909091209061409051309041707031207041709061704021804051907071703031707091605081907051506041308051305071407031708031607021902051802051705041209071909081709051804041804091403021503031507071208051307021507041806051404031904031903061208041607031204071609091904091809031807031206041308091907041908031809071704031807071909021209041509071304041804071309071707061603081305051606031304021208071908021407081803021807021406071808051602041502061903091205051508051206031803081802021503061602031403081403091909061409081703021606071504051609041409031504021308021509051905031206071605021206051507021408021402061907031502041705091504081308081207051902091704061603071503041202061605061303091507091408041906091608061609081504041706071205021405021603041303041305031607081403051703041406061304081306071308061307081602091207061203091403071503091202051607041308071506021407071803031305021309031805091203061906051406031304061704071207071706031508061206021709021404051403041508071704041203071403031306081705051709081708061706041207031909031309091507031708021404041704081702031404071307071203051409071
Output
> Hello world!
The debug that I made with Visual Studio Code show that the problem is the map function
Can you help me please?
Thanks
You read one by one digit on the Encrypted message.
So if you have a 4 on your encrypted message to find 4 on the map you need to have 141 on your key due to the processing you do on your key.
In your exemple you dont have 141 on your generated key thats why you get None.
I change the key to use
12141512030417060213060413030716060915090216080313040713060215090916020217020419040215050918070812050414030615020715020512061602071404091407041805160407170516030919090718050315070618020719070218050812030317020918060815070817020816040318080414060914060414050419030818030513020419030517040912040218020918030616050313050413040319070618020617060518060314090616070612080615060613020912040413070619070918050217040512070813020816020513090812090218080715020317050217050313070419020717090712060814020816030518040317030616050915020215030516050518080314040619060815030816020613040518080817060913070312080316050717020714070212090915090812090517030916060218091905051608071904041303021209031606081707051209081908041302051808021602081202041508031708041204031608041504031708051307051908081405091809051207091408061805061806021306061902021805041706081902061303031606051803091309061202031504061702021206091402091604041906041709091609061506081908091707021604061604081309051508091905041903031903071202021705061409091205091803071409041505071204061709041909091209061409051309041707031207041709061704021804051907071703031707091605081907051506041308051305071407031708031607021902051802051705041209071909081709051804041804091403021503031507071208051307021507041806051404031904031903061208041607031204071609091904091809031807031206041308091907041908031809071704031807071909021209041509071304041804071309071707061603081305051606031304021208071908021407081803021807021406071808051602041502061903091205051508051206031803081802021503061602031403081403091909061409081703021606071504051609041409031504021308021509051905031206071605021206051507021408021402061907031502041705091504081308081207051902091704061603071503041202061605061303091507091408041906091608061609081504041706071205021405021603041303041305031607081403051703041406061304081306071308061307081602091207061203091403071503091202051607041308071506021407071803031305021309031805091203061906051406031304061704071207071706031508061206021709021404051403041508071704041203071403031306081705051709081708061706041207031909031309091507031708021404041704081702031404071307071203051409071
It finds w for 4 which is the result intended.
Best regards
I've been coding this for almost 2 days now but cant get it. I've coded two different bits trying to find it.
Code #1
So this one will list the letters but wont change it to the numbers (a->1, b->2, ect)
import re
text = input('Write Something- ')
word = '{}'.format(text)
for letter in word:
print(letter)
#lists down
Outcome-
Write something- test
t
e
s
t
Then I have this code that changes the letters into numbers, but I haven't been able to convert it back into letters.
Code #2
u = input('Write Something')
a = ord(u[-1])
print(a)
#converts to number and prints ^^
enter code here
print('')
print(????)
#need to convert from numbers back to letters.
Outcome:
Write Something- test
116
How can I send a text through (test) and make it convert it to either set numbers (a->1, b->2) or random numbers, save it to a .txt file and be able to go back and read it at any time?
What youre trying to achieve here is called "caesar encryption".
You for example say normally you would have: A=1, a=2, B=3, B=4, etc...
then you would have a "key" which "shifts" the letters. Lets say the key is "3", so you would shift all letters 3 numbers up and you would end up with: A=4, a=5, B=6, b=7, etc...
This is of course only ONE way of doing a caesar encryption. This is the most basic example. You could also say your key is "G", which would give you:
A=G, a=g, B=H, b=h, etc.. or
A=G, a=H, B=I, b=J, etc...
Hope you understand what im talking about. Again, this is only one very simple example way.
Now, for your program/script you need to define this key. And if the key should be variable, you need to save it somewhere (write it down). Put your words in a string, and check and convert each letter and write it into a new string.
You then could say (pseudo code!):
var key = READKEYFROMFILE;
string old = READKEYFROMFILE_OR_JUST_A_NORMAL_STRING_:)
string new = "";
for (int i=0, i<old.length, i++){
get the string at i;
compare with your "key";
shift it;
write it in new;
}
Hope i could help you.
edit:
You could also use a dictionary (like the other answer says), but this is a very static (but easy) way.
Also, maybe watch some guides/tutorials on programming. You dont seem to be that experienced. And also, google "Caesar encryption" to understand this topic better (its very interesting).
edit2:
Ok, so basically:
You have a variable, called "key" in this variable, you store your key (you understood what i wrote above with the key and stuff?)
You then have a string variable, called "old". And another one called "new".
In old, you write your string that you want to convert.
New will be empty for now.
You then do a "for loop", which goes as long as the ".length" of your "old" string. (that means if your sentence has 15 letters, the loop will go through itself 15 times and always count the little "i" variable (from the for loop) up).
You then need to try and get the letter from "old" (and save it for short in another vairable, for example char temp = "" ).
After this, you need to compare your current letter and decide how to shift it.
If thats done, just add your converted letter to the "new" string.
Here is some more precise pseudo code (its not python code, i dont know python well), btw char stands for "character" (letter):
var key = g;
string old = "teststring";
string new = "";
char oldchar = "";
char newchar = "";
for (int i=0; i<old.length; i++){
oldchar = old.charAt[i];
newchar = oldchar //shift here!!!
new.addChar(newchar);
}
Hope i could help you ;)
edit3:
maybe also take a look at this:
https://inventwithpython.com/chapter14.html
Caesar Cipher Function in Python
https://www.youtube.com/watch?v=WXIHuQU6Vrs
Just use dictionary:
letters = {'a': 1, 'b': 2, ... }
And in the loop:
for letter in word:
print(letters[letter])
To convert to symbol codes and back to characters:
text = input('Write Something')
for t in text:
d = ord(t)
n = chr(d)
print(t,d,n)
To write into file:
f = open("a.txt", "w")
f.write("someline\n")
f.close()
To read lines from file:
f = open("a.txt", "r")
lines = f.readlines()
for line in lines:
print(line, end='') # all lines have newline character at the end
f.close()
Please see documentation for Python 3: https://docs.python.org/3/
Here are a couple of examples. My method involves mapping the character to the string representation of an integer padded with zeros so it's 3 characters long using str.zfill.
Eg 0 -> '000', 42 -> '042', 125 -> '125'
This makes it much easier to convert a string of numbers back to characters since it will be in lots of 3
Examples
from string import printable
#'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?#[\\]^_`{|}~ \t\n\r\x0b\x0c'
from random import sample
# Option 1
char_to_num_dict = {key : str(val).zfill(3) for key, val in zip(printable, sample(range(1000), len(printable))) }
# Option 2
char_to_num_dict = {key : str(val).zfill(3) for key, val in zip(printable, range(len(printable))) }
# Reverse mapping - applies to both options
num_to_char_dict = {char_to_num_dict[key] : key for key in char_to_num_dict }
Here are two sets of dictionaries to map a character to a number. The first option uses random numbers eg 'a' = '042', 'b' = '756', 'c' = '000' the problem with this is you can use it one time, close the program and then the next time the mapping will most definitely not match. If you want to use random values then you will need to save the dictionary to a file so you can open to get the key.
The second option creates a dictionary mapping a character to a number and maintains order. So it will follow the sequence eg 'a' = '010', 'b' = '011', 'c' = '012' everytime.
Now I've explained the mapping choices here are the function to convert between
def text_to_num(s):
return ''.join( char_to_num_dict.get(char, '') for char in s )
def num_to_text(s):
slices = [ s[ i : i + 3 ] for i in range(0, len(s), 3) ]
return ''.join( num_to_char_dict.get(char, '') for char in slices )
Example of use ( with option 2 dictionary )
>>> text_to_num('Hello World!')
'043014021021024094058024027021013062'
>>> num_to_text('043014021021024094058024027021013062')
'Hello World!'
And finally if you don't want to use a dictionary then you can use ord and chr still keeping with padding out the number with zeros method
def text_to_num2(s):
return ''.join( str(ord(char)).zfill(3) for char in s )
def num_to_text2(s):
slices = [ s[ i : i + 3] for i in range(0, len(s), 3) ]
return ''.join( chr(int(val)) for val in slices )
Example of use
>>> text_to_num2('Hello World!')
'072101108108111032087111114108100033'
>>> num_to_text2('072101108108111032087111114108100033')
'Hello World!'
I am going through old exams, my final is in a few days. I want to decrypt a ciphertext, it was first encrypted by vigenere and then encrypted by columna transposition. How do I decrypt to get original message?
message -> rgyqhbmnwaazxcajittuzqyagkx
vigenere key -> final
columnar transposition key -> exam
I have spent hours on this, but am not getting anything out. I first want to decrypt by columnar then Vigenere. I think output should look English, but am just getting junk. My vigenere code is below, I guess the problem is with the columnar, all the codes I have come across take numbers as key, but I have a letter key.
def decrypt(message, password):
decrypted = ''
for i in range(0, len(message)):
letter = ord(message[i]) - ord(password[i%len(password)]) + 65
if letter < 65:
letter += 26
decrypted += chr(letter)
return decrypted
thanks
The columnar transposition does take a word as key, not a number. If "exam" is the key, then you write out the message from left to write in rows of four and read off the cipher text from top to bottom starting with column 3, then column 1, then column 4 then column 2. The order comes form the alphabetical order of the letters "e","x","a","m": "2nd", "4th", "1st", "3rd".
For example, to encrypt "THIS IS THE MESSAGE":
E X A M
----------
T H I S
I S T H
E M E S
S A G E
--> ITEG TIES SHSE HSMA
I.e., "ITEGTIESSHSEHSMA".
To decrypt do the reverse. I don't want to solve your homework for you, but I will say that, when you properly decrypt via the columnar transposition with "exam" you will find a string starting with "nzrawq..."
When you then further decrypt that string with the vigenere cipher you will indeed find English words, in particular a string starting with "ireallywant..."
Hey guys so I 'm trying to make a cipher following these sets of instructions:
Print a header.
Prompt the user to enter the name of the file with the encrypted message, the decode
key (the shift number), and the name of the file to store the decrypted message.
Read the encrypted message from the file.
Use the decode key to shift each character in the encrypted message by the
appropriate number to generate the new string corresponding to the decrypted message.
Save the decrypted message in the second file.
Print the encypted and decrypted messages on the screen.
I'm not allowed to use the ord() or chr() functions.
What really confuses me is the encrypted and decrypted files part. I don't really know how to code for this.
I'm pretty new to this so any help would be greatly appreciated.
Thanks in advance.
Note: It sounds like you're probably doing this as a school assignment. I highly recommend that you use the code below only as an example and not as a full solution. I would hate for there to be plagiarism issues surrounding your assignment and I'm sure your professor/teacher is knowledgeable at Googling for prior work. Good luck on your assignment!
I wrote a quick example of how I might try and tackle your problem. The example has a few known issues:
It doesn't deal with capital letters. (Other than to convert them to their lowercase counterparts.)
It doesn't deal with punctuation or non alphanumeric characters. (Numbers, spaces or line endings.)
There is no error checking.
If you try to convert a number < -25 it will throw up on you.
Probably the biggest problem that needed to be solved was the limitation of not using ord() and chr(). I bypassed that limitation by creating my own conversion list of letters to numbers and vice versa. A tricky corner case to make sure you deal with is what happens if the shift moves a letter outside of the conversion range [0,25].
As a side note if you want to decrypt a file you can simply open it up as the plaintext and use a negative offset whose absolute value is equal to the encrypting offset. Or in plain English, if you use the parameters:
infile = clear.txt, offset = 1, outfile = encrypted.txt
To decrypt you can use:
infile = encrypted.txt, offset = -1, outfile = decrypted.txt
caesarcipher.py
import itertools
letters = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
'r','s','t','u','v','w','x','y','z']
numbers = range(26) # Numbers 0 - 25
lettersToNumbers = dict(zip(letters, numbers))
numbersToLetters = dict(zip(numbers, letters))
def printHeader():
""" Print the program informational header """
print """=======================================
Welcome to CaesarCipher - The unbreakable
Roman cipher.
======================================="""
def convertToNumber(letter):
""" Convert a letter to a number using our predefined conversion table
#param letter: The letter to convert to an integer value
#type letter: str
#rtype: int
"""
return lettersToNumbers[letter]
def convertToLetter(number):
""" Convert a number to a letter using our predefined conversion table
#param number: The number to convert to a letter
#type number: int
#rtype: str
"""
# If we shift outside of our range make sure to wrap
if number > 25:
return numbersToLetters[number%25]
elif number < 0:
return numbersToLetters[number+25]
else:
return numbersToLetters[number]
def shiftUp(letter, shift):
""" Shift letter up a given number of positions
#param letter: The letter we're shifting
#param shift: The number of positions to shift up
#type letter: str
#type shift: int
#note: For simplicity we encode both capital and lowercase letters
to the same values
"""
number = convertToNumber(letter.lower())
number += shift
return convertToLetter(number)
def prompt():
""" Prompt for user input
#rtype: tuple of str, int, str
"""
infile = raw_input("File to encrypt: ")
offset = int(raw_input("Encoding number: "))
outfile = raw_input("Encrypted file destination: ")
return (infile, offset, outfile)
def encrypt(infile, offset, outfile):
""" Encrypt the file using the given offset """
print "=== Plaintext input ==="
printFile(infile)
with open(infile) as red_file:
with open(outfile, 'w') as black_file:
for line in red_file:
for letter in line:
# Only convert alphabetic characters
if letter.isalpha():
black_file.write(shiftUp(letter, offset))
else:
black_file.write(letter)
print "=== Ciphertext output ==="
printFile(outfile)
def printFile(path):
""" Print the data in the given file """
with open(path) as print_file:
for line in print_file:
print line
printHeader()
encrypt(*prompt()) # `*` unpacks the tuple returned by `prompt()` into
# three separate arguments.
test.txt
abcdef
ABCDEF
This is some text I want to try and encrypt.
Example run:
mike#test:~$ python caesarcipher.py
=======================================
Welcome to CaesarCipher - The unbreakable
Roman cipher.
=======================================
File to encrypt: test.txt
Encoding number: 1
Encrypted file destination: test.out
=== Plaintext input ===
abcdef
ABCDEF
This is some text I want to try and encrypt.
=== Ciphertext output ===
bcdefg
bcdefg
uijt jt tpnf ufyu j xbou up usz boe fodszqu.
Since you say the file bits is your biggest problem, I assume function like:
def decaesar(message, shift):
pass
that does the decyphering for you on a string basis - that is, it takes the encrypted message as a string and gives you back the decrypted message as a string. If you haven't written that already, do that first, and test it with hard-coded strings. Ignore the "encrypted and decrypted files" bit at this stage - programming is all about solving one problem at a time.
Once you have that function and you're happy that it works, extending your program to deal with files instead of strings is as simple as asking:
Can I get a string with the contents of a file, given the file's name? , and conversely,
Can I write a string into a file with a given name?
If you can answer both of those with 'yes', then you can extend your program in this way without changing your decaesar function - your logic looks like this:
# Print header
encrypted_filename, decrypted_filename, shift = # get from user input
encrypted_message = # get the contents of encrypted_filename as a string
decrypted_message = decaesar(encrypted_message, shift)
# write decrypted_message to decrypted_filename
# print encrypted_message and decrypted_message
Usefully, Python's file IO works on exactly this principle of converting between strings and files. If you have a file open for reading:
in_file = open(filename)
, then the return value of:
in_file.read()
is exactly the string to answer the first point. Likewise, if you have a file open for writing:
out_file = open(filename, 'w')
. then:
out_file.write(my_string)
will put my_string into that file.
So that means that if you do already have your decaeser function, then you can slip this code into the pseudocode above at the appropriate places, and you will have a mostly working solution.