Python how to convert character to string - python

array = "qwertyuiopasdfghjklzxcvbnm"
m = len(array)
user_input= input("Enter plaintext: ")
a= int(input("choose a: "))
b= int(input("choose b: "))
encryption = ""
for n in array:
if n in user_input :
inin=array.find(n)
result =array.index(user_input) * a+b
enc= result % m
encryption = encryption + array[enc]
print("Encrypted message is :"+encryption)
as you can see from the code above my code worked fine but the only problem that I am facing is
I need to encrypt the message as string like I want to use " hello world" not only a character "s" and its encrypted to " d" i want "hello word"

I tried to correct your code:
array = "qwertyuiopasdfghjklzxcvbnm"
m = len(array)
user_input= input("Enter plaintext: ")
a= int(input("choose a: "))
b= int(input("choose b: "))
encryption = ""
for char in user_input:
if char in array :
index = (array.find(char) * a + b) % m
encryption += array[index]
else:
encryption += char
print("Encrypted message is :", encryption)
From what I understood, you are trying to encrypt your message by shifting the index using an affine function (and applying a modulo so it "loops" if the index is bigger than your alphabet size). Since your input can contain multiple times the same char, you need to iterate through the input and then check for the index of every char in your alphabet (array). Then you can apply your formula to the index and get the new char. I also added a code to add the unciphered char if it doesn't exist in your array. This will prevent you to lose informations when ciphering.
e.g.: hello world will be ciphered in xirrm tmars instead of xirrmtmars which couldn't be unciphered to get the original.

Related

Rc4 decrypt ValueError: Unknown format code 'x' for object of type 'str'

When I get to the following line in my code, I receive the following error:
inputString = "{:02x}".format(inputNumber)
ValueError: Unknown format code 'x' for object of type 'str'
How can I avoid this?
# Global variables
state = [None] * 256
p = q = None
def setKey(key):
##RC4 Key Scheduling Algorithm
global p, q, state
state = [n for n in range(256)]
p = q = j = 0
for i in range(256):
if len(key) > 0:
j = (j + state[i] + key[i % len(key)]) % 256
else:
j = (j + state[i]) % 256
state[i], state[j] = state[j], state[i]
def byteGenerator():
##RC4 Pseudo-Random Generation Algorithm
global p, q, state
p = (p + 1) % 256
q = (q + state[p]) % 256
state[p], state[q] = state[q], state[p]
return state[(state[p] + state[q]) % 256]
def encrypt(key,inputString):
##Encrypt input string returning a byte list
setKey(string_to_list(key))
return [ord(p) ^ byteGenerator() for p in inputString]
def decrypt(inputByteList):
##Decrypt input byte list returning a string
return "".join([chr(c ^ byteGenerator()) for c in inputByteList])
def intToList(inputNumber):
##Convert a number into a byte list
inputString = "{:02x}".format(inputNumber)
return [(inputString[i:i + 2], 16) for i in range(0, len(inputString), 2)]
def string_to_list(inputString):
##Convert a string into a byte list
return [ord(c) for c in inputString]
loop = 1
while loop == 1: #simple loop to always bring the user back to the menu
print("RC4 Encryptor/Decryptor")
print
print("Please choose an option from the below menu")
print
print("1) Encrypt")
print("2) Decrypt")
print
choice = input("Choose your option: ")
choice = int(choice)
if choice == 1:
key = input("Enter Key: ")
inputstring = input("enter plaintext: ")
print(encrypt(key, inputstring))
elif choice == 2:
key = input("Enter Key: ")
ciphertext = input("enter plaintext: ")
print(decrypt(intToList(ciphertext)))
elif choice == 3:
#returns the user to the previous menu by ending the loop and clearing the screen.
loop = 0
else:
print ("please enter a valid option") #if any NUMBER other than 1, 2 or 3 is entered.
The format string code x converts an integer to its hexadecimal representation as a string. For example:
>>> "{:02x}".format(54563)
'd523'
The error you are getting occurs when you pass a string as inputNumber. Arguments passed to your intToList function should be integers. Consider using intToList(int(your_argument_here)).
It looks like you’re trying to convert a string to hex. Unfortunately that’s not the way to do it: "{:02x}".format is for formatting a single integer, so it doesn’t work for a whole string.
Python 3 includes the method bytes.hex() which performs this transformation for you, but you’ll need a byte string rather than a normal string. You can use string encoding to convert from str to bytes.
If you wanted to do the transformation yourself, you could call "{:02x}".format on the character codes of each character in your string, and concatenate the individual hex values together. Be careful with Unicode in this case; you might be better off working with a byte string.

Entering more than 1 shift amount in a program

Hi I'm having a tough time trying to incorporate more than 1 shift in my program. The goal is to assign a shift amount to each character like:
statement = input("Enter string: ")
shift = input("Enter shift amounts: ")
For example, if
statement = "Hello"
shift = 5 6 7
How do I assign that 5 number to H, 6 to E, 7 to l, then again 5 to l, and 7 to o
I think that I need to make it into a list so this is what I have thus far:
for char in statement:
char[0] = shift[0]
Try this:
#!/usr/bin/python
statement = raw_input("Enter string: ")
shift = raw_input("Enter shift amounts: ").split()
for index, char in enumerate(statement):
if index < len(shift):
print chr(ord(char) + int(shift[index])),
else:
print char,
Written for Python 2, and doesn't do error checking on user input, but should work.
Edit: And a Python3 version, since it looks like that's what you're using:
#!/usr/bin/python
statement = input("Enter string: ")
shift = input("Enter shift amounts: ").split()
for index, char in enumerate(statement):
if index < len(shift):
print(chr(ord(char) + int(shift[index])), end='')
else:
print(char, end='')
print()
In both versions, if the number of integers provided by the user for shift is less than the size of the string, a shift value of 0 is assumed.
If you wanted to, you could do a test to see if the number of shift integers provided by the user is less than the length of the string, and error out, or ask the user for input again.
Edit 2: As requested in comments, this code makes the shift restart instead of assuming it is 0:
#!/usr/bin/python
statement = input("Enter string: ")
shift = input("Enter shift amounts: ").split()
for index, char in enumerate(statement):
index = index % len(shift)
print(chr(ord(char) + int(shift[index])), end='')
print()
Edit 3: As requested in comments, this code makes sure user input is only a-z or A-Z, and is in a function.
#!/usr/bin/python
import sys
from string import ascii_letters as alphabet
def enc_string(statement, shift):
# Make sure user entered valid shift values
try:
shift = [ int(val) for val in shift.split() ]
except ValueError:
print("Error: All shift values must be integers")
sys.exit(1)
# Make sure all chars in statement are valid
for char in statement:
if char not in alphabet:
print("Error: all characters in string must be a-z or A-Z")
sys.exit(1)
# Start putting together result
res = "Result: "
# Convert statement
for index, char in enumerate(statement):
shift_to_use = shift[index % len(shift)]
index_of_char = alphabet.index(char)
index_of_new_char = (index_of_char + shift_to_use) % len(alphabet)
res += alphabet[index_of_new_char]
return res
statement = input("Enter string: ")
shift = input("Enter shift amounts: ")
print(enc_string(statement, shift))

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.

Error I can't fix while converting text to number in RSA algorithm using Python

I was tasked an assignment by my teacher to make a python program that can encrypt messages using the RSA algorithm. So to do that I had to create functions which convert text to numbers and then be able to manipulate those numbers and encrypt it. However to test if i have encrypted it correctly i also designed a decryption function which I also made at the bottom. All the functions between the encryption functions and Ascii functions are there to be used in other functions(At this point you would realize i like dividing my code into functions). The problem with my code is that i keep getting this error when i run it
Traceback (most recent call last):
File "D:/Applications/Python/Ziad/RSA algotrithim V2.py", line 127, in <module>
print(decrypt(Phi_N, e, encrypted))
File "D:/Applications/Python/Ziad/RSA algotrithim V2.py", line 115, in decrypt
return Num2Text(message)
File "D:/Applications/Python/Ziad/RSA algotrithim V2.py", line 58, in Num2Text
return Ascii2Text(Num2Ascii(message))
File "D:/Applications/Python/Ziad/RSA algotrithim V2.py", line 17, in Ascii2Text
text = text + chr(int(char))
ValueError: invalid literal for int() with base 10: '1.0'
>>> ================================ RESTART =================
I tested all the functions individually to see if they work and they do. I rechecked my encryption and decryption functions and they should work. For some reason i think my problem is with my decryption function as i think it is giving me the decimal number however i searched the internet on the algorithm and all the sites i looked uses the same algorithm. Please help me with finding the problem, I usually dont ask other people for help (This is my first ever question on StackOverFlow) and I've been hurting my head on this for 3 weeks.
import math
def Text2Ascii(message):
Ascii = ""
for count in range(len(message)):
if len(str(ord(message[count]))) <= 2:
Ascii = Ascii + "0" +str(ord(message[count])) + " "
else:
Ascii = Ascii + str(ord(message[count])) + " "
return Ascii
def Ascii2Text(message):
text = ""
char = ""
for count in range(len(message)):
if message[count] == " ":
text = text + chr(int(char))
char = ""
else:
char = char + message[count]
text = text + chr(int(char))
return text
def Ascii2Num(message):
Num = ""
for count in range(len(message)):
if message[count] != " ":
Num = Num + message[count]
return int(Num)
def Num2Ascii(message):
Ascii = ""
char = ""
message = str(message)
if len(message)%3 == 0:
for count in range(len(message)):
if (count+1)%3 == 0:
char = char + message[count]
Ascii = Ascii + char + " "
char = ""
else:
char = char + message[count]
else:
Ascii = "0"
for count in range(len(message)):
if (count+2)%3 == 0:
char = char + message[count]
Ascii = Ascii + char + " "
char = ""
else:
char = char + message[count]
return Ascii
def Text2Num(message):
return Ascii2Num(Text2Ascii(message))
def Num2Text(message):
return Ascii2Text(Num2Ascii(message))
def exponent(number, power):
answer = 1
for count in range(power):
answer = number*answer
return answer
def primeCheck(number):
if number == 2:
prime = True
elif number <= 1:
prime = False
else:
n = math.sqrt(number)
n = math.ceil(n)
for count in range(2,n+1):
if number%count == 0:
prime = False
break
else:
prime = True
return prime
def factors(number):
answer = []
if primeCheck(number)== True:
answer = [number,1]
else:
for count in range(1,number+1):
if number%count == 0:
answer.append(count)
return answer
def phi(number):
answer = number
if primeCheck(number) == True:
answer = number - 1
else:
factor = factors(number)
for count in factor:
for count2 in factors(count):
if count2 == count:
answer = answer -1
break
return answer
def encrypt(N,e):
message = input("What is the message you need encrypted?\n")
message = Text2Num(message)
encrypted = (message ** e)%N
return encrypted
def decrypt(Phi_N, e,encrypted):
k = 3
d = (Phi_N*k + 1)/e
message = encrypted ** d
return Num2Text(message)
p = int(input("Give me a prime number: "))
while primeCheck(p) == False:
p = int(input("Give me a prime number: "))
q = int(input("Give me a prime number: "))
while primeCheck(q) == False:
q = int(input("Give me a prime number: "))
N = q*p
Phi_N = (q-1)*(p-1)
e = int(input("Enter your encryption key: "))
encrypted = encrypt(N,e)
print(decrypt(Phi_N, e, encrypted))
That specific error that you're getting is due to combination of two factors:
The first, and probably easiest to address, is the way you are breaking up the string in Ascii2Text:
def Ascii2Text(message):
text = ""
char = ""
for count in range(len(message)):
**if message[count] == " ":** #<-- This line is not robust
text = text + chr(int(char))
char = ""
else:
char = char + message[count]
text = text + chr(int(char))
return text
The problem is that, with the way Num2Ascii is implemented, you are ending up with both a trailing space that causes you to try to cast empty string to an int at the end of the loop, and non-space characters earlier in your ascii-fied message. I would recommend either loudly choking on invalid characters, or at the very least not trying to append them to the "char" string that you try to cast to an int on the next line.
This brings us to the next problem: that you even have non-numeral characters in the first place. The decimal point causing the failure you see is coming from an incorrect calculation for d. d is supposed to be the modular multiplicative inverse of e, and it will always be an integer when calculated correctly. Yours, however, was coming up as a decimal more often than not when I ran this code. This is one of the bits of RSA that people choke on most often, since it involves manipulating the modulo operator in ways that people without a math background aren't typically taught. One of the more common, efficient ways to calculate this value is to use the Extended Euclidean algorithm.
A few more notes on things you will probably run into after addressing the two issues above:
e should be co-prime with and less than Phi_N, which you are not currently validating. Failure to do this can make it impossible to correctly calculate d (only few pairs of numbers have a modular multiplicative inverse). The easiest (though not strictly correct) way to do this would be to use a while loop beneath e like you did for the prime numbers, which checks that False == primeCheck(e) or e >= Phi_N. To be more correct, you'd have to write a coprime check that takes in both Phi_N and e, and asserts that they do not share a common factor besides 1.
The padded version of your message, m, must be less than N. Failure to do this may result in some messages being unrecoverable when you attempt to reverse the exponentiation during decryption. To more easily verify this, you may want to capture the message from the user before they select P and Q (they're more likely to change their numbers than the message they want to send), then add an additional gate after the two primes are provided which checks that N > m.

Decrypting Input?

This is my assignment:
Write a program which DECRYPTS secret messages.
It should first prompt the user for the scrambled alphabet. It then should ask for the secret message. Finally, it outputs the unscrambled version.
Note that there are exactly 26 characters input for the scrambled alphabet. All alphabetic characters are translated into their decoded equivalents (which will take a WHILE loop), and all other, non-alphabetic characters should be output exactly as they were without translation.
This is my code so far:
decrypt = ["*"] * 26
scram_alphabet = input("Please input the scrambled alphabet in order: ")
while len(scram_alphabet) != 26:
scram_alphabet = input("Please input the scrambled alphabet in order. The alphabet must have 26 characters: ")
num = 0
for each_letter in scram_alphabet:
decrypt[num] = ord(each_letter)
num = num + 1
print()
print("Your scrambled alphabet is: ", end = "")
for num in range (26):
print(chr(decrypt[num]), end = "")
print()
print()
msg = input("Now input your scrambled message: ")
print()
print()
alphabet = 65
for s in range (26):
decrypt[s] = (alphabet)
alphabet = alphabet + 1
print("The unscrambled alphabet is: ", end = "")
for num in range (26):
print(chr(decrypt[num]), end = "")
print()
print()
print("Your unscrambled message reads: ")
for alpha in msg.upper():
if alpha < "A" or alpha > "Z":
print(alpha, end="")
else:
ord_alpha = ord(alpha)
print (chr(decrypt[ord_alpha - 65]), end = "")
Ex: Scrambled Alphabet = XQHAJDENKLTCBZGUYFWVMIPSOR , Scrambled Message = VNKW KW BO 1WV WJHFJV BJWWXEJ!
Everything works fine until I get to the last print statement, where it says that the unscrambled message is the same as the scrambled message. I know that the instructions call for a while loop but I couldn't figure out how to use one to decode the alphabet.
Any helpers?
Well, as has already been noted, you are clobbering your decrypt variable.
However, you are also not building the mapping from the 'scrambled' alphabet to the regular one properly / at all.
Decrypting without using anything more than basic iteration over lists and simple list functions (index()) might look something like this:
cleartext = ""
for c in msg:
if c in alphabet:
pos = alphabet.index(c)
cleartext += string.ascii_uppercase[pos]
else:
cleartext += c
Rather than just patching your code, it could benefit from some improvement. I gather this is probably homework and you are probably not expected to go this far, but IMO there is nothing wrong with learning it anyway.
You are not checking that the input alphabet only contains whatever you consider to be legal values (e.g. probably A-Z in this case), nor are you checking for duplicates. The user could input any old rubbish and break your program otherwise.
Your printing and looping is not very idiomatic.
Functions are good for breaking up your code into more easily readable and maintainable pieces.
This may come across as old school or pedantic, but lines longer than 80 characters are not recommended style for Python. Adjacent string literals (e.g "one""two") will be joined (even across newlines).
If I had to do what you're doing without translate (see below), I might do something like this (just a quick example, could probably be improved with a bit of work):
import string
def validate(alpha):
# Is it exactly 26 characters long?
if len(alpha) != 26: return False
for c in alpha:
# Is every character in [A-Z]?
if c not in string.ascii_uppercase: return False
# Is this character duplicated?
if alpha.count(c) > 1: return False
return True
alphabet = ""
while not validate(alphabet):
alphabet = input("Please input the encryption alphabet in order (only A-Z"
" allowed, with no duplicates): ")
msg = input("Now input your encrypted message: ")
print("Your encrypted alphabet is:", alphabet)
print("Your encrypted message is:", msg)
# Create a mapping from one alphabet to the other using a dictionary
table = dict(zip(alphabet, string.ascii_uppercase))
cleartext = "".join([table[c] if c in table else c for c in msg])
print("Your decrypted message reads:", cleartext)
Lastly, you could also do this using Python's builtin string translation, like so:
import string
# read and validate alphabet
# read message
print(str.translate(message, str.maketrans(alphabet, string.ascii_uppercase)))
You are clobbering decrypt after you wrote all the scrambled letters into it:
crypt = ["*"] * 26
for s in range (26):
val = decrypt[s] - 65
crypt[val] = (s + 65)

Categories