python encryption and decryption using list of stings [duplicate] - python

This question already has answers here:
Conversion of string to upper case without inbuilt methods
(7 answers)
Closed 4 years ago.
I am writing a code that will encrypt a list of String entered by user. these lists will be encrypted and then it will be decrypted.
But once it will reach the part of encryption it gives me this error.
Traceback (most recent call last): File "C:/Users/dana/Desktop/q2.py", line 16, in
x = ord(c) TypeError: ord() expected a character, but string of length 4 found
I am sure that it will give the same error even in the decryption part.
This is my code:
# Encryption
list1=[]
list2=[]
i = 0
while not(False):
plain_text = input ("Enter any string ")
if (plain_text !='q'):
list1.append(plain_text)
i=i+1
else:
break
encrypted_text = ""
for c in list1:
x = ord(c)
x = x + 1
c2 = chr(x)
encrypted_text = encrypted_text + c2
print(encrypted_text)
#Decryption
encrypted_text = "Uijt!jt!b!uftu/!BCD!bcd"
plain_text = ""
for c in encrypted_text:
x = ord(c)
x = x - 1
c2 = chr(x)
plain_text = plain_text + c2
print(plain_text)
list2=[encrypted_text]
print(plain_text)
print("the original msgs are :" , list1)
print("the encrypted msgs are :" ,list2)

list1 contains whatever strings the user enters in response to the input prompt.
Then your first for loop iterates over list1. c takes on values which are the elements of list1. Then you use ord on c. Your intent, I expect, is to use ord on the elements of c, instead. Try adding an additional loop somewhere.
Also, consider organizing your code into functions.

ord() takes single character
for c in list1:
x = ord(c)
but above loop return string as C that's why you are getting error
Corrected Code
list1=[]
list2=[]
i = 0
while not(False):
plain_text = input ("Enter any string ")
if (plain_text !='q'):
list1.append(plain_text)
i=i+1
else:
break
encrypted_text = ""
for c in list1: #Changed Code
for c1 in c:
x = ord(c1)
x = x + 1
c2 = chr(x)
encrypted_text = encrypted_text + c2
print(encrypted_text)
#Decryption
encrypted_text = "Uijt!jt!b!uftu/!BCD!bcd"
plain_text = ""
for c in encrypted_text:
x = ord(c)
x = x - 1
c2 = chr(x)
plain_text = plain_text + c2
print(plain_text)
list2=[encrypted_text]
print(plain_text)
print("the original msgs are :" , list1)
print("the encrypted msgs are :" ,list2)

Related

The while loop doesn't end but the condition is met

I'm trying to code vigenere cypher so I need to have two lists of the same length. I thought everything will be okay with my solution but the while loop doesn't despite of the fact than condition is met. Because of that I got two list with different numbers of letters. Why this works like that and how to improve that. I am new programmer who learnt from books, so I haven't ever seen that while loop doesn't work properly. My code:
plaintext = "This is secret message"
plaintext = plaintext.upper()
key = "secret"
key = key.upper()
def encrypt_vigenere2( key, plaintext ):
a = []
b= []
i = 0
for letter in (plaintext):
if letter != " ":
a.append(letter)
while i<len(a):
for element in key:
if element != " ":
b.append(element)
i +=1
return a,b
print(encrypt_vigenere2(key,plaintext))
The while loop does as expected, for you now you join the key until you reach the size of a,
b: ['S','E','C','R','E','T','S','E','C','R','E','T','S','E','C','R','E','T','S','E','C','R','E','T']
That will be useful for the next part : encryption
def encrypt_vigenere2(key, plaintext):
...
result = ""
for l, k in zip(a, b):
result += chr(((ord(l) - 65 + ord(k) - 65) % 26) + 65)
return result
You can just use replace(" ", "") to remove the spaces, and to repeat the key, use itertools.cycle
from itertools import cycle
def encrypt_vigenere2(key, plaintext):
result = ""
for l, k in zip(plaintext.replace(" ", ""), cycle(key)):
result += chr(((ord(l) - 65 + ord(k) - 65) % 26) + 65)
return result
The idea for a vigenere encrypter program sounded nice to me so I did some coding and here is my result:
def encrypt_vigenere(plaintext, key):
letter_matrix = [[chr(65 + i) for i in range(26)] for j in range(26)]
for index, column in enumerate(letter_matrix):
for i in range(index):
letter_matrix[index].append(column[0])
del letter_matrix[index][0]
plaintext = plaintext.upper()
key = key.upper()
keystream = ""
ciphertext = ""
current_letter = 0
for letter in plaintext:
if current_letter == len(key):
current_letter = 0
keystream += key[current_letter]
current_letter += 1
for letter_plaintext, letter_keystream in zip(plaintext.replace(" ", ""), keystream):
ciphertext += letter_matrix[ord(letter_plaintext)-65][ord(letter_keystream)-65]
return ciphertext
You said that you were new to coding, so here are the things you might not now:
like previous said, list comprehension
chr() -> takes a number and assigns it to it corresponding ascii value
ord() -> the opposite of chr(). Takes letter and transforms it to ascii number
zip() -> goes trough two lists simultaneously
I am not sure if I understood your code right, but seems for me like you did not try to encrypt something. It looks like you tried to get the keystream, and correct me if I am wrong. But here is the code how to get the keystream:
def encrypt_vigenere3(key, plaintext):
# variables
a = [letter for letter in plaintext.upper() if letter != " "]
b = [element for element in key.upper() if element != " "]
keystream = []
# creating the keystream
i = 0
current_num = 0
while i <= len(a):
if current_num == len(key):
current_num = 0
keystream.append(b[current_num])
current_num += 1
i += 1
return keystream
I created the variables by "list comprehension". You should go look that term up, it makes your code way cleaner.

Decrypting a Caesar Cipher with ord() and chr()?

I have an assignment for a lab that asks me to decrypt an input file that has been encrypted with a ceasar cipher. As background, my instructor has already let everyone know that the cipher has a shift distance of three.
I was able to get my to write to an output file, but my output.txt is completely unreadable, and not close at all to what the expected output should be. I remember my instructor mentioning that we could use ord() and chr() combined with arithmetic to transform the encoded characters to plaintext.
decode = inpf.readlines()
for line in decode:
output = ""
c = str()
for c in line:
if c >= "a" and c <= "z":
x = ord(c)
x += 23
x %= 26
y = chr(x)
output = output + y
if c >= "A" and c <= "Z":
x = ord(c)
x += 23
x %= 26
y = chr(x)
output = output + y
else:
output = output + c
outf.write(output + "\n")
I appreciate any help or advice you can offer! Thanks!!
EDIT:
Sample Input: "Wkh Orug Ri Wkh Ulqjv:"
Output: " :"
Expected Output: "The Lord Of The Rings:"
The ord() method in Python converts a character into its Unicode code value. Capital 'A' starts from unicode 65 and small 'a' from 97. Also you should use 'elif' instead of second 'if' statement. Otherwise, in case of a small letter, the letter will repeat. You need to get the letters position in alphabet, apply the shift and convert it back to unicode. A working example of your code is given below:
inpf = open("input.txt",'r')
outf = open("output.txt",'w')
decode = inpf.readlines()
for line in decode:
output = ""
c = str()
for c in line:
if c >= "a" and c <= "z":
x = ord(c) - 97 #small a
x -= 3
x = (x+26)%26 #For handling negative numbers
y = chr(x + 97)
output = output + y
elif c >= "A" and c <= "Z":
x = ord(c) - 65 #Capital A
x -= 3
x = (x+26)%26 #For handling negative numbers
y = chr(x + 65)
output = output + y
else:
output = output + c
outf.write(output + "\n")

how do i make a ceaser cipher where the letter "z" becomes "a" on +1 shift in python

How do I shift the end of the alphabet so "z" becomes "a"?
i was thinking a if statement
plaintext = input("please type message:")
def split(plaintext):
return list(plaintext)
print(split(plaintext))
for s in plaintext:
a = ord(s)
print (a)
list1=[]
for t in plaintext:
b = ord(t)
c = b+1
print (c)
list1.append(c)
print (list1)
aa =""
for ab in list1:
aa = aa + chr(ab)
print (str(aa))
print(split(aa))
if you just want to increase the character by one you could do this:
def inc_chr(c):
return chr((ord(c) + 1 - ord("a")) % 26 + ord("a"))
test:
for char in "abcxyz":
print(f"{char} {inc_chr(char)}")
outputs:
a b
b c
c d
x y
y z
z a
basically you do calculations modulo 26 with an offset of ord("a") = 97.
You can use a look up dict and convert the characters.
import string
alphabets = string.ascii_lowercase
look_up = {alphabets[i]: alphabets[i-1] for i in range(len(alphabets))}
You can then use this lookup for cypher
test = "This will be encoded"
out = = "".join([look_up.get(char, char) for char in test])
print(out)

when i try to decrypt my message in python it says 'string index out of range' in line 8

my code just rearranges the string so that every odd index is moved to the front then the even indexes are moved to the back. now I want to know how do I decrypt this
s = input('please enter a string: ')
for i in range(1,len(s),2):
s = s[ : :2] + s[1: :2]
print('encrypted:',s)
c = input('type your encrypted message to decrypt: ')
for i in range(0,round(len(c)//2,0)+1,2):
c = c[ :i] + c[len(c)//2 +1 + i] + c[i+1: ]
print(c)
Give this a try and see if it's what your looking for.
s = input ('Please enter a string : ')
# incrypt
s = s[::2] + s[1::2]
print (s)
# decrypt
s += ' '
d = ''
half = int (len (s) /2)
for i in range (half) : d += s [i] + s [i + half]
print (d)

Convert a number into its respective letter in the alphabet - Python 2.7

I am currently working on a python project to take a string of text, encrypt the text by adding a keyword to it and then outputting the result. I currently have all the features of this program operational except converting the numerical value back into text.
For example, the raw text will be converted into a numerical value, for instance [a, b, c] will become [1, 2, 3].
Currently I have no ideas of how to correct this issue and would welcome any help, my current code is as follows:
def encryption():
print("You have chosen Encryption")
outputkeyword = []
output = []
input = raw_input('Enter Text: ')
input = input.lower()
for character in input:
number = ord(character) - 96
output.append(number)
input = raw_input('Enter Keyword: ')
input = input.lower()
for characterkeyword in input:
numberkeyword = ord(characterkeyword) - 96
outputkeyword.append(numberkeyword)
first = output
second = outputkeyword
print("The following is for debugging only")
print output
print outputkeyword
outputfinal = [x + y for x, y in zip(first, second)]
print outputfinal
def decryption():
print("You have chosen Decryption")
outputkeyword = []
output = []
input = raw_input('Enter Text: ')
input = input.lower()
for character in input:
number = ord(character) - 96
output.append(number)
input = raw_input('Enter Keyword: ')
input = input.lower()
for characterkeyword in input:
numberkeyword = ord(characterkeyword) - 96
outputkeyword.append(numberkeyword)
first = output
second = outputkeyword
print("The following is for debuging only")
print output
print outputkeyword
outputfinal = [y - x for x, y in zip(second, first)]
print outputfinal
mode = raw_input("Encrypt 'e' or Decrypt 'd' ")
if mode == "e":
encryption()
elif mode == "d":
decryption()
else:
print("Enter a valid option")
mode = raw_input("Encrypt 'e' or Decrypt 'd' ")
if mode == "e":
encryption()
elif mode == "d":
decryption()
Although Your Question is not quite clear I wrote a script which do encryption using Dictionary
plaintext = list('ABCDEFGHIJKLMNOPQRSTUVWXYZ') #Alphabet String for Input
Etext = list('1A2B3C4D5E6F7G8H90IJKLMNOP') """Here is string combination of numbers and alphabets you can replace it with any kinda format and your dictionary will be build with respect to the alphabet sting"""
def messageEnc(text,plain, encryp):
dictionary = dict(zip(plain, encryp))
newmessage = ''
for char in text:
try:
newmessage = newmessage + dictionary[char.upper()]
except:
newmessage += ''
print(text,'has been encryptd to:',newmessage)
def messageDec(text,encryp, plain):
dictionary = dict(zip(encryp,plain))
newmessage = ''
for char in text:
try:
newmessage = newmessage + dictionary[char.upper()]
except:
newmessage += ''
print(text,'has been Decrypted to:',newmessage)
while True:
print("""
Simple Dictionary Encryption :
Press 1 to Encrypt
Press 2 to Decrypt
""")
try:
choose = int(input())
except:
print("Press Either 1 or 2")
continue
if choose == 1:
text = str(input("enter something: "))
messageEnc(text,plaintext,Etext)
continue
else:
text = str(input("enter something: "))
messageDec(text,Etext,plaintext)
Suppose you've got a list of numbers like a = [1, 2, 3] and an alphabet: alpha = "abcdef". Then you convert this as follows:
def NumToStr(numbers, alpha):
ret = ""
for num in numbers:
try:
ret += alpha[num-1]
except:
# handle error
pass
return ret
Going by your question , you want to convert number back to text.
You can have two list declared for both the number and alphabet, such as:
num=[1,2,3....26]
alpa=['a','b','c'....'z']
and after that find the index/position from the num list and find the alphabet for that index in alpa list.
A couple of things. The first is to convert the coded values back to characters you can use the chr(i) command. Just remember to ad the 96 back on.
for code in outputfinal:
print chr(code + 96),
I tried 'aaa' as my plaintext and 'bbb' as my keyword and this printed 'ccc' which is what I think you are trying to do.
Another thing. The zip command iterates over two lists but (in my playing) only until one of the lists runs out of members. If your plaintext is 10 characters and your keyword is only 5 then only the first 5 characters of your plaintext get encrypted. You will need to expand or inflate your key to the length of your plaintext message. I played with something like this:
plaintext = ['h','e','l','l','o',' ','w','o','r','l','d']
keyword = ['f','r','e','d']
index = len(keyword) # point to the end of the key word
keyLength = len(keyword)
while index < len(plaintext): # while there are still letters in the plain text
keyword.append(keyword[index - keyLength]) # expand the key
index += 1
print keyword
for a,b in zip(plaintext, keyword):
print a, b
I hope this helps. Please let me know if I have misunderstood.

Categories