I have created a program that encrypts a file using caesar cipher, the only problem is that it does not include upper case letters, as they are not included in my list. Is it possible to include upper case letters in this somehow, or do i need to make all characters lowercase?
My current code:
encrypt = str.maketrans('abcdefghijklmnopqrstuvwxyz0123456789', 'ghijklmnopqrstuvwxyz0123456789abcdef')
decrypt = str.maketrans('ghijklmnopqrstuvwxyz0123456789abcdef', 'abcdefghijklmnopqrstuvwxyz0123456789')
filename = "abc_abd.txt"
with open(filename, "r") as readfile:
with open(filename+'-encrypted.txt', 'w+') as writefile:
for line in readfile:
print(line.translate(encrypt), file=writefile)
I'd like for the program to include upper case letters in the shift, but they are not included.
>>> import string
>>> charset = ''.join(string.ascii_lowercase + string.ascii_uppercase + ''.join([str(i) for i in range(0, 10)]))
>>> charset
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
>>> delta = 6
>>> encrypt = str.maketrans(charset, charset[delta:] + charset[:delta])
>>> decrypt = str.maketrans(charset[delta:] + charset[:delta], charset)
>>> with open(r'C:/Users/Kevin/Desktop/abc_abd.txt') as f1:
... for line in f1:
... print(f'Original: {line}')
... encrypted_line = line.translate(encrypt)
... print(f'Encrypted: {encrypted_line}')
... decrypted_line = encrypted_line.translate(decrypt)
... print(f'Unencrypted: {decrypted_line}')
...
Original: this is a test
Encrypted: znoy oy g zkyz
Unencrypted: this is a test
Original: number 9 in here
Encrypted: tAshkx f ot nkxk
Unencrypted: number 9 in here
Note that I'm assuming you're starting from scratch here, to implement including upper case letters. Also, I hope you're not storing anything important in this, it's not true encryption by any means. I would not consider this safe for storing anything.
Related
I am trying to implement Caesar cipher in Python where my program would take input from a text file i.e. input_file.txt, and write the encrypted text as an output to another text file named output_file.txt. The input file contains:
Attack On Titans
4
where "Attack On Titan" is the string to be encrypted and 4 is the key to the encryption algorithm. The correct output for this string should be
Exxego Sr Xmxerw
but my program gives me
Exxego Sr Xmxerwv
i.e an extra character v. Here is my code for review:
data = open("input_file.txt", "r")
text = data.readline()
print(text)
key = int(data.readline())
def encrypt(text,key):
result = ""
for i in range(len(text)):
char = text[i]
if char == ' ':
result += ' '
elif char.isupper():
result += chr((ord(char) + key-65) % 26 + 65)
else:
result += chr((ord(char) + key - 97) % 26 + 97)
return result
ex= open("output_file.txt","w")
ex.write(encrypt(text,key))
print(encrypt(text , key))
I just wanted to know why am I getting this incorrect output although I know I can make it correct if I change the for statement by doing this:
for i in range(len(text)-1)
Please don't mind this amateurish coding since I am not good at it and want to improve it. Thanks.
data.readline() will give you the trailing newline character \n. You need to call text.strip() before passing to the encrypt function to get arid of it.
It look like you have a trailing newline character in the file you are reading in.
Testing it in the python interpreter:
>>> a = '\n'
>>> (ord(a)+4-97) % 26 + 97
118
>>> chr(118)
'v'
Remove trailing and beginning whitespace by calling test.strip() before passing it to your encrypt function.
As an aside, you should either explicitly close your files, e.g. ex.close() or wrap in in a block like this, to prevent file corruption.
with open('', 'r') as ex:
ex.write('bar')
data.readline() keeps the '\n' (newline) character at the end of the line. It's the reason why you have an extra character in your output.
To remove it you can replace
text = data.readline()
by
text = data.readline().rstrip('\n')
which will remove the '\n' at the end.
text.strip() (see other answers) will remove all whitespace characters from both end of the string. So if it's not the behaviour expected, use .rstrip('\n') which removes only '\n' at the end of the string.
You should also add
ex.close()
after
ex.write(encrypt(text,key))
to commit the change to the file.
I can't seem to get this program I'm supposed to do for a project to output the correct output, even though I have tried getting it to work multiple times. The project is:
Your program needs to decode an encrypted text file called "encrypted. txt". The person who wrote it used a cipher specified in "key. txt". This key file would look similar to the following:
A B
B C
C D
D E
E F
F G
G H
H I
I J
J K
K L
L M
M N
N O
O P
P Q
Q R
R S
S T
T U
U V
V W
W X
X Y
Y Z
Z A
The left column represents the plaintext letter, and the right column represents the corresponding ciphertext.
Your program should decode the "encrypted.txt" file using "key.txt" and write the plaintext to "decrypted.txt".
Your program should handle both upper and lower case letters in the encrypted without having two key files (or duplicating keys). You may have the decrypted text in all caps.
You should be able to handle characters in the encrypted text that are not in your key file. In that case, just have the decryption repeat the character. This will allow you to have spaces in your encrypted text that remain spaces when decrypted.
While you may write a program to create the key file - do NOT include that in the submission. You may manually create the encrypted and key text files. Use either the "new file" option in Python Shell (don't forget to save as txt) or an editor such as notepad. Do not use word.
Here is my code:
keyFile = open("key.txt", "r")
keylist1= []
keylist2 = []
for line in keyFile:
keylist1.append(line.split()[0])
keylist2.append(line.split()[1])
keyFile.close()
encryptedfile = open("encrypted.txt", "r")
lines = encryptedfile.readlines()
currentline = ""
decrypt = ""
for line in lines:
currentline = line
letter = list(currentline)
for i in range(len(letter)):
currentletter = letter[i]
if not letter[i].isalpha():
decrypt += letter[i]
else:
for o in range(len(keylist1)):
if currentletter == keylist1[o]:
decrypt += keylist2[o]
print(decrypt)
The only output I get is:
, ?
which is incorrect.
You forgot to handle lowercase letters. Use upper() to convert everything to a common case.
It would also be better to use a dictionary instead of a pair of lists.
mapping = {}
with open("key.txt", "r") as keyFile:
for line in keyFile:
l1, l2 = line.split()
mapping[upper(l1)] = upper(l2)
decrypt = ""
with open("encrypted.txt", "r") as encryptedFile:
for line in encryptedFile:
for char in line:
char = upper(char)
if char in mapping:
decrypt += mapping[char]
else:
decrypt += char
print(decrypt)
I want to determine which type of ROT encoding is used and based off that, do the correct decode.
Also, I have found the following code which will indeed decode rot13 "sbbone" to "foobart" correctly:
import codecs
codecs.decode('sbbone', 'rot_13')
The thing is I'd like to run this python file against an existing file which has rot13 encoding. (for example rot13.py encoded.txt).
Thank you!
To answer the second part of your first question, decode something in ROT-x, you can use the following code:
def encode(s, ROT_number=13):
"""Encodes a string (s) using ROT (ROT_number) encoding."""
ROT_number %= 26 # To avoid IndexErrors
alpha = "abcdefghijklmnopqrstuvwxyz" * 2
alpha += alpha.upper()
def get_i():
for i in range(26):
yield i # indexes of the lowercase letters
for i in range(53, 78):
yield i # indexes of the uppercase letters
ROT = {alpha[i]: alpha[i + ROT_number] for i in get_i()}
return "".join(ROT.get(i, i) for i in s)
def decode(s, ROT_number=13):
"""Decodes a string (s) using ROT (ROT_number) encoding."""
return encrypt(s, abs(ROT_number % 26 - 26))
To answer the first part of your first question, find the rot encoding of an arbitrarily encoded string, you probably want to brute-force. Uses all rot-encodings, and check which one makes the most sense. A quick(-ish) way to do this is to get a space-delimited (e.g. cat\ndog\nmouse\nsheep\nsay\nsaid\nquick\n... where \n is a newline) file containing most common words in the English language, and then check which encoding has the most words in it.
with open("words.txt") as f:
words = frozenset(f.read().lower().split("\n"))
# frozenset for speed
def get_most_likely_encoding(s, delimiter=" "):
alpha = "abcdefghijklmnopqrstuvwxyz" + delimiter
for punctuation in "\n\t,:; .()":
s.replace(punctuation, delimiter)
s = "".join(c for c in s if c.lower() in alpha)
word_count = [sum(w.lower() in words for w in encode(
s, enc).split(delimiter)) for enc in range(26)]
return word_count.index(max(word_count))
A file on Unix machines that you could use is /usr/dict/words, which can also be found here
Well, you can read the file line by line and decode it.
The output should go to an output file:
import codecs
import sys
def main(filename):
output_file = open('output_file.txt', 'w')
with open(filename) as f:
for line in f:
output_file.write(codecs.decode(line, 'rot_13'))
output_file.close()
if __name__ == "__main__":
_filename = sys.argv[1]
main(_filename)
For my class assignment we need to decrypt a message that used RSA Encryption. We were given code that should help us with the decryption, but its not helping.
def block_decode(x):
output = ""
i = BLOCK_SIZE+1
while i > 0:
b1 = int(pow(95,i-1))
y = int(x/b1)
i = i - 1
x = x - y*b1
output = output + chr(y+32)
return output
I'm not great with python yet but it looks like it is doing something one character at a time. What really has me stuck is the data we were given. Can't figure out where or how to store it or if it is really decrypted data using RSA. below are just 3 lines of 38 lines some lines have ' or " or even multiple.
FWfk ?0oQ!#|eO Wgny 1>a^ 80*^!(l{4! 3lL qj'b!.9#'!/s2_
!BH+V YFKq _#:X &?A8 j_p< 7\[0 la.[ a%}b E`3# d3N? ;%FW
KyYM!"4Tz yuok J;b^!,V4) \JkT .E[i i-y* O~$? o*1u d3N?
How do I get this into a string list?
You are looking for the function ord which is a built-in function that
Returns the integer ordinal of a one-character string.
So for instance, you can do:
my_file = open("file_containing_encrypted_message")
data = my_file.read()
to read in the encrypted contents.
Then, you can iterate over each character doing
char_val = ord(each_character)
block_decode(char_val)
I'm trying to write a program that opens a text file, and shifts each of the characters in the file 5 characters to the right. It should only do this for alphanumeric characters, and leave nonalphanumerics as they are. (ex: C becomes H) I'm supposed to be using the ASCII table to do this, and I'm having an issue when the characters wrap around. ex: w should become b, but my program gives me a character that's in the ASCII table. Another issue I'm having is that all the characters are printing on separate lines and I'd like them all to print on the same line.
I can't use lists or dictionaries.
This is what I have, I'm not sure how to do the final if statement
def main():
fileName= input('Please enter the file name: ')
encryptFile(fileName)
def encryptFile(fileName):
f= open(fileName, 'r')
line=1
while line:
line=f.readline()
for char in line:
if char.isalnum():
a=ord(char)
b= a + 5
#if number wraps around, how to correct it
if
print(chr(c))
else:
print(chr(b))
else:
print(char)
Using str.translate:
In [24]: import string
In [25]: string.uppercase
Out[25]: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
In [26]: string.uppercase[5:]+string.uppercase[:5]
Out[26]: 'FGHIJKLMNOPQRSTUVWXYZABCDE'
In [27]: table = string.maketrans(string.uppercase, string.uppercase[5:]+string.uppercase[:5])
In [28]: 'CAR'.translate(table)
Out[28]: 'HFW'
In [29]: 'HELLO'.translate(table)
Out[29]: 'MJQQT'
First, it matters if it is lower or upper case. I am going to assume here that all the characters are lower case (if they aren't, it would be easy enough to make them)
if b>122:
b=122-b #z=122
c=b+96 #a=97
w=119 in ASCII and z=122 (decimal in ASCII) so 119+5=124 and 124-122=2 which is our new b, then we add that to a-1 (this takes care of if we get a 1 back, 2+96=98 and 98 is b.
For the printing on the same line, instead of printing when you have them, I would write them to a list, then create a string from that list.
e.g instead of
print(chr(c))
else:
print(chr(b))
I would do
someList.append(chr(c))
else:
somList.append(chr(b))
then join each element of the list together into one string.
You could create a dictionary to handle it:
import string
s = string.lowercase + string.uppercase + string.digits + string.lowercase[:5]
encryptionKey = {s[i]:s[i+5] for i in range(len(s)-5)}
The final addend to s (+ string.lowercase[:5]) adds the first 5 letters into the key. Then, we use a simple dictionary comprehension to create a key for the encryption.
Put into your code (I also changed it so you iterate through the lines rather than using f.readline():
import string
def main():
fileName= input('Please enter the file name: ')
encryptFile(fileName)
def encryptFile(fileName):
s = string.lowercase + string.uppercase + string.digits + string.lowercase[:5]
encryptionKey = {s[i]:s[i+5] for i in range(len(s)-5)}
f= open(fileName, 'r')
line=1
for line in f:
for char in line:
if char.isalnum():
print(encryptionKey[char])
else:
print(char)