RC4 Encryption in Python - python

i've had a look through several python scripts for using an RC4 block cipher... i'm having issues completing the program so that it outputs properly...
Program currently asks for a "key" and "plaintext" (text to encrypt with key).
and outputs a encoded string... i think. so if i enter the word "Plaintext" to encrypt i get the following. however i think this is incomplete...
[187, 243, 22, 232, 217, 64, 175, 10, 211]
i want to have my encrypted output in hex
BB F3 16 E8 D9 40 AF 0A D3
my program is incomplete at the moment, but would just like some direction on how to
finish off the encryption part so it outputs as Hexadecimal (i think i have to convert bytes to hex?)
EDIT: The above has been resolved by Ebrahim. just need help with the decryption
i'm lost on where to begin with the decryption... i want to be able to have an input that will take a key and a ciphertext both in hexadecimal; and decrypt the ciphertext to plaintext.
I understand the logic in the encryption process, but i'm having trouble grasping the decryption process even though it is quite similar.
# 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 [int(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 = raw_input("Enter Key: ")
inputstring = raw_input("enter plaintext: ")
encrypt(key, inputstring)
elif choice == 2:
key = raw_input("Enter Key: ")
ciphertext = raw_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.

To convert your decimal output to hex output:
>>> arr = [187, 243, 22, 232, 217, 64, 175, 10, 211]
>>> ' '.join('%02x'%i for i in arr)
'bb f3 16 e8 d9 40 af 0a d3'
>>>

I know this is very old question, but here are some insigths just in case:
First RC4 is not a block cipher, is a stream cipher
Second, the decryption is exact the same as the encryption, as the algorithm generates the ciphertext by XORing the plaintext with some stream obtained using the key, and XOR is reversible, meaning: to decypher just need to XOR the ciphertext with the same generated stream.

Related

How would I fix my Vigenere Cipher Decryption

I'm having an issue with Vigenere Cipher Decryption, When an encrypted message is decrypted, the decrypted message is not printed, but the encrypted is?
I cant seem to see why this dose not work. But its probably a simple issue.
I think the issue is in the main decrypt function.
Help would be much appreciated
Encryption works fine
def encrypt_key(message, key):
i = 0
empty_key = '' # empty key to append to
# turn characters into index
for characters in message:
if characters.isalpha(): # checks if character is in the alphabet
empty_key = empty_key + key[i % len(key)] # append characters to empty key
i = i + 1 # increase integer value by 1
else:
empty_key = empty_key + ' ' # if character is a space or punctuation then add empty space
return empty_key
def encrypt_decrypt(message_char, key_char, choice='encrypt'):
if message_char.isalpha():
first_alphabet_letter = 'a' # assume character is lowercase
if message_char.isupper():
first_alphabet_letter = 'A' # assume character is upper, then replace with A
original_char_position = ord(message_char) - ord(first_alphabet_letter) # difference results in position of char in alphabet
key_char_position = ord(key_char.lower()) - ord('a')
if choice == 'encrypt':
new_char_position = (original_char_position + key_char_position) % 26 # encrypts & loops back around with % 26
else: # if choice == 'decrypt':
new_char_position = (original_char_position - key_char_position + 26) % 26 # decrypts & loops back around
return chr(new_char_position + ord(first_alphabet_letter))
return message_char
def encrypt(message, key):
cipher = ''
empty_key = encrypt_key(message, key)
for message_char, key_char in zip(message, empty_key):
cipher = cipher + encrypt_decrypt(message_char, key_char)
return cipher
def decrypt(cipher, key):
message = ''
empty_key = encrypt_key(cipher, key)
for cipher_char, key_char in zip(cipher, empty_key):
message = message + encrypt_decrypt(cipher_char, key_char, 'decrypt')
return message
message = input('Enter your message to encrypt here: ')
key = input('Enter your key: ')
cipher = encrypt(message, key) # inputs message and key to encrypt function
decrypt_message = decrypt(cipher, key)# inputs message and key to decrypt function
print(f'Cipher: {cipher}')
print(f'Decrypted: {decrypt_message}')
def choice():
user_choice = int(input('''
Enter your choice (1 or 2):
1. Encrypt
2. Decrypt
> '''))
if user_choice == 1:
print(f'Cipher: {cipher}')
print('')
elif user_choice == 2:
print('')
print(f'Decrypted: {decrypt_message}')
choice()

How can I make this Python code more efficient

I would greatly appreciate your feedback on my first ever Python project! :D
Basically I am coding a Caesar Cipher and I think its pretty terribly 'optimised / efficient' if you know what I mean, this is because I copied and pasted the encrypt() method for the decrypt() method and the only thing I changes was instead of rotating the numbers more, I rotated them less. This is what I'm talking about:
newPosition = (abc.find(letter) - key) % 26
^^ Instead of having a + (plus) I made it a - (minus) ^^
Is there a way I can sort of call the encrypt() method at just the newPosition line? Or what I did was correct and it doesn't need fixing (which I highly doubt)
** Please do take in mind that I do not have much knowledge in Python (if any at all) since I just started today so don't blow my brain up with some super complex code. THANK YOU!!! **
abc = 'abcdefghijklmnopqrstuvwxyz'
def main():
message = input("Would you like to encrypt or decrypt a word?")
if message.lower() == "encrypt":
encrypt()
elif message.lower() == "decrypt":
decrypt()
else:
print("You must enter either 'encrypt' or 'decrypt'.")
main()
def encrypt():
message = input("Enter a message to encrypt: ")
message = message.lower()
key = int(input("What number would you like for your key value?"))
cipherText = ""
for letter in message:
if letter in abc:
newPosition = (abc.find(letter) + key) % 26
cipherText += abc[newPosition]
else:
cipherText += letter
print(cipherText)
return cipherText
def decrypt():
message = input("Enter a message to decrypt: ")
message = message.lower()
key = int(input("What number would you like for your key value?"))
cipherText = ""
for letter in message:
if letter in abc:
newPosition = (abc.find(letter) - key) % 26
cipherText += abc[newPosition]
else:
cipherText += letter
print(cipherText)
return cipherText
main()
In general, str.find is bad performance-wise. It's O(n) complexity, which isn't awful, but you rarely actually need it. In this case you can use ord to convert each letter to its ordinal, then subtract ord('a') to get 0-25 instead of 97-122.
This is particularly useful, because you can then use chr to convert back without needing a lookup.
for letter in message:
if letter in string.ascii_lowercase: # same as "abcdef..z"
new_position = ((ord(letter) - ord('a') + key) % 26) + ord('a')
new_ch = chr(new_position)
ciphertext += new_ch
Note also that concatenating strings with += isn't as fast as something like str.join.
new_letters = [chr(((ord(letter) - ord('a') + key) % 26) + ord('a')) if letter in ascii_lowercase else letter for letter in message]
ciphertext = "".join(new_letters)
And since that chr(((ord(letter) - ord('a') + key) % 26) + ord('a')) is so ugly, I'd refactor that into a function.
def rotate(letter, key=0):
c_pos = ord(letter) - ord('a')
rotated = c_pos + key
modded = rotated % 26
final_pos = modded + ord('a')
return chr(final_pos)
new_letters = [rotate(c, key) if c in string.ascii_lowercase else c for c in letters]
ciphertext = "".join(new_letters)
A point of maintainability: it's easier to write testably good code if you separate your inputs from your results. Right now you'd have to do some monkey patching of stdin to write unit tests for any of your functions, but if you move your requests for user input into main and out of their respective function, that gets much easier.
def main():
message = input("What's the message to encrypt/decrypt? ")
key = int(input("What number would you like for your key value? "))
choice = input("Choose: encrypt or decrypt. ")
if choice == "encrypt":
result = encrypt(message, key)
elif choice == "decrypt":
result = decrypt(message, key)
else:
# something here about a bad user input.
In fact, when you consider the Caesar Cipher is reversible by flipping the sign of the key, you can simply do:
if choice == "encrypt":
result = encrypt(message, key)
elif choice == "decrypt":
result = encrypt(message, key * (-1))
and not write a decrypt function at all!

Encoding / Decoding Caesar cipher Python 3 ASCII

I am learning to code through the introduction to computer science book written by John Zelle. I am stuck on exercise 5.8. I need to somehow modify this solution where the next character after "z" is "a" in order to make it circular. Any help would be great :)
def main():
print("This program can encode and decode Caesar Ciphers") #e.g. if key value is 2 --> word shifted 2 up e.g. a would be c
#input from user
inputText = input("Please enter a string of plaintext:").lower()
inputValue = eval(input("Please enter the value of the key:"))
inputEorD = input("Please enter e (to encrypt) or d (to decrypt) ")
#initate empty list
codedMessage = ""
#for character in the string
if inputEorD == "e":
for ch in inputText:
codedMessage += chr(ord(ch) + inputValue) #encode hence plus
elif inputEorD =="d":
codedMessage += chr(ord(ch) - inputValue) #decode hence minus
else:
print("You did not enter E/D! Try again!!")
print("The text inputed:", inputText, ".Is:", inputEorD, ".By the key of",inputValue, ".To make the message", codedMessage)
main()
Since you're dealing with .lower()-case letters, it's fair to know that their ASCII range is [97-122].
A good way to make the shifting circular would be to represent each letter with the range [0-25], which is done by ord(ch) - 97, and then add the key, then modulo the result with 26 so it becomes (ord(ch) - 97 + key)%26, we'll then have a result in range [0-25], adding 97 will then get it's ASCII code:
def main():
print("This program can encode and decode Caesar Ciphers")
inputText = input("Please enter a string of plaintext:").lower()
inputValue = int(input("Please enter the value of the key:")) # use int(), don't eval unless you read more about it
inputEorD = input("Please enter e (to encrypt) or d (to decrypt) ")
codedMessage = ""
if inputEorD == "e":
for ch in inputText:
codedMessage += chr((ord(ch) - 97 + inputValue)%26 + 97)
elif inputEorD =="d":
codedMessage += chr((ord(ch) - 97 - inputValue)%26 + 97)
else:
print("You did not enter E/D! Try again!!")
print("The text inputed:", inputText, ".Is:", inputEorD, ".By the key of",inputValue, ".To make the message", codedMessage)
main()

Python shift with alphabet

Locked. There are disputes about this question’s content being resolved at this time. It is not currently accepting new answers or interactions.
def menu():
choice = input("Press 1 to encode, 2 to decode, 9 to exit ")
return choice
def makeKeycode(message):
key = input("What is the key? ").upper()
length = len(message)
keycode = ""
counter = 0
while length >0:
if counter == len(key):
counter = 0
keycode = keycode + key[counter]
counter = counter + 1
length = length - 1
print(keycode)
return keycode
def enterMessage():
message = input("What is the message ").upper()
return message
def encodeMessage(message, keycode):
ciphertext =""
alphabet= "ABCDEFGHIJKLMNOPQRTUVWXYZ"
for i in range (len(message)):
character = message[i]
charCode = alphabet.find(character)
keycodeChar =keycode[i]
keyLetter = alphabet.find(keycodeChar)
position = (charCode + keyLetter)%25
cipherLetter = alphabet[position]
ciphertext =ciphertext + cipherLetter
return ciphertext
def decodeMessage(ciphertext,keycode):
ciphertext =""
alphabet= "ABCDEFGHIJKLMNOPQRTUVWXYZ"
for i in range (len(ciphertext)):
character = ciphertext[i]
charCode = alphabet.find(character)
keycodeChar =keycode[i]
keyLetter = alphabet.find(keycodeChar)
position = (charCode - keyLetter)%25
cipherLetter = alphabet[position]
ciphertext =ciphertext - cipherLetter
return message
def enterCipher ():
ciphertext = input("Enter the text to be decoded")
return ciphertext
def encode():
message = enterMessage()
keycode = makeKeycode(message)
ciphertext = encodeMessage(message,keycode)
print(ciphertext)
def decode():
keycode = makeKeycode(ciphertext)
message = decodeMessage(ciphertext, keycode)
print (message)
def main():
MyDictionary=("A:1","B:2","C:3","D:4","E:5","F:6","G:7","H:8","I:9","J:10","K:11","L:12","M:13","N:14","O:15","P:16","Q:17","R:18","S:19","T:20","U:21","V:22","W:23","X:24","Y:25","X:26")
print (MyDictionary)
choice = 0
while choice !=9:
choice = int(menu())
if choice == 1:
encode()
elif choice == 2:
decode()
if __name__ == "__main__":
main()
Hi, I cant get my code to work, my encode function works but i am struggling to fix my decode function. I dont understand where i am going wrong. I want to be able to decode the message i will have encoded, but this doesn't work as the decode function stops the program. Have I made an error in the coding? Thanks for all the help
Regards
def decodeMessage(ciphertext,keycode):
ciphertext =""
It appears that you are resetting ciphertext to a null string. as a result, your len(ciphertext) is 0 which means you ae not doing anything.
python 2.75
sig = 'abcd'
def test(sig):
sig = ""
print 'sig = ', sig
>>> test(sig)
sig = ''
>>> print sig
'abcd'
I am finding two problems with your decode message function:
def decodeMessage(ciphertext,keycode):
ciphertext =""
alphabet= "ABCDEFGHIJKLMNOPQRTUVWXYZ"
for i in range (len(ciphertext)):
character = ciphertext[i]
charCode = alphabet.find(character)
keycodeChar =keycode[i]
keyLetter = alphabet.find(keycodeChar)
position = (charCode - keyLetter)%25
cipherLetter = alphabet[position]
ciphertext =ciphertext - cipherLetter
return message
The first issue that I found was the fact that you pass in ciphertext to decodeMessage as a mandatory parameter and then you change the value of ciphertext to "" (an empty string). I would recommend changing the ciphertext in the parameters to something like "ct" to prevent that overlap.
The second issue I found was the fact you return message, but you don't perform any action on message. When running this program, you'll get a global error because message is not global yet you're calling message in the local scope without having defined it locally.
Now, onto another matter: Your encode method doesn't encode anything correctly. Look at the following output:
Press 1 to encode, 2 to decode, 9 to exit 1
What is the message some
What is the key? 18
YNLD
Press 1 to encode, 2 to decode, 9 to exit 1
What is the message some
What is the key? 5
YNLD
Press 1 to encode, 2 to decode, 9 to exit 1
What is the message some
What is the key? 1
YNLD
All 'some's get encoded to 'YNLD' regardless of the key. To cipher something using a Caesar Cypher, you're going to want to use ords and chrs. Ord makes the character numerical, Chr makes the number into a letter. Consider the following function made in Python 3, for example:
from string import ascii_letters
def cypher_letter(letter, key):
if letter not in ascii_letters: #commas, question marks, etc
return letter
if letter.islower(): #lowercase and uppercase have differing ord values
lower, upper = ord('a'), ord('z') # values: 97 to 122
elif letter.isupper():
lower, upper = ord('A'), ord('Z') # values: 65 to 90
else:
print("Something went wrong.") #probably didn't enter valid letters
cypher = ord(letter) + key #if key is "1" and letter is 'a', 97 + 1
if cypher < lower: cypher += 26 #26 letters in alphabet, this is for looping
if cypher > upper: cypher -= 26 #back around if it exceeds upper,lower limits
return chr(cypher) #chr(98) = 'b'
The following code:
cyphered_words = []
keys = [18, 5, 1]
for key in keys:
encoded = ""
for letter in 'some':
encoded += (cypher_letter(letter, key)) #to cypher we pass the key
print(encoded)
cyphered_word.append(encoded)
Outputs this:
Kgewlzafy hjwllq dgfy, oalz ugehdwp dwllwjk!
Xtrjymnsl uwjyyd qtsl, bnym htruqjc qjyyjwx!
Tpnfuijoh qsfuuz mpoh, xjui dpnqmfy mfuufst!
Cyphering and decyphering is almost the same thing. It's like they're yin and yang or something, so the decypher function would look like:
def decrypt_message(message, key):
decyphered_text = ""
for letter in message:
decyphered_text += cypher_letter(letter, (key*-1)) #to decypher we pass the negative key
return decyphered_text
And a loop to decrypt our 3 'some's:
for count, word in enumerate(cyphered_words):
print(decrypt_message_k(word, keys[count]))
And the output:
Something pretty long, with complex letters!
Something pretty long, with complex letters!
Something pretty long, with complex letters!
I hope this helps you get on the right track.

Caesar Cipher Function in Python

I'm trying to create a simple Caesar Cipher function in Python that shifts letters based on input from the user and creates a final, new string at the end. The only problem is that the final cipher text shows only the last shifted character, not an entire string with all the shifted characters.
Here's my code:
plainText = raw_input("What is your plaintext? ")
shift = int(raw_input("What is your shift? "))
def caesar(plainText, shift):
for ch in plainText:
if ch.isalpha():
stayInAlphabet = ord(ch) + shift
if stayInAlphabet > ord('z'):
stayInAlphabet -= 26
finalLetter = chr(stayInAlphabet)
cipherText = ""
cipherText += finalLetter
print "Your ciphertext is: ", cipherText
return cipherText
caesar(plainText, shift)
I realize that this answer doesn't really answer your question, but I think it's helpful anyway. Here's an alternative way to implementing the caesar cipher with string methods:
def caesar(plaintext, shift):
alphabet = string.ascii_lowercase
shifted_alphabet = alphabet[shift:] + alphabet[:shift]
table = string.maketrans(alphabet, shifted_alphabet)
return plaintext.translate(table)
In fact, since string methods are implemented in C, we will see an increase in performance with this version. This is what I would consider the 'pythonic' way of doing this.
You need to move cipherText = "" before the start of the for loop. You're resetting it each time through the loop.
def caesar(plainText, shift):
cipherText = ""
for ch in plainText:
if ch.isalpha():
stayInAlphabet = ord(ch) + shift
if stayInAlphabet > ord('z'):
stayInAlphabet -= 26
finalLetter = chr(stayInAlphabet)
cipherText += finalLetter
print "Your ciphertext is: ", cipherText
return cipherText
This is an improved version of the code in the answer of #amillerrhodes that works with different alphabets, not just lowercase:
def caesar(text, step, alphabets):
def shift(alphabet):
return alphabet[step:] + alphabet[:step]
shifted_alphabets = tuple(map(shift, alphabets))
joined_aphabets = ''.join(alphabets)
joined_shifted_alphabets = ''.join(shifted_alphabets)
table = str.maketrans(joined_aphabets, joined_shifted_alphabets)
return text.translate(table)
Example of usage:
>>> import string
>>> alphabets = (string.ascii_lowercase, string.ascii_uppercase, string.digits)
>>> caesar('Abc-xyZ.012:789?жñç', step=4, alphabets=alphabets)
'Efg-bcD.456:123?жñç'
References:
Docs on str.maketrans.
Docs on str.translate.
Docs on the string library
Using some ascii number tricks:
# See http://ascii.cl/
upper = {ascii:chr(ascii) for ascii in range(65,91)}
lower = {ascii:chr(ascii) for ascii in range(97,123)}
digit = {ascii:chr(ascii) for ascii in range(48,58)}
def ceasar(s, k):
for c in s:
o = ord(c)
# Do not change symbols and digits
if (o not in upper and o not in lower) or o in digit:
yield o
else:
# If it's in the upper case and
# that the rotation is within the uppercase
if o in upper and o + k % 26 in upper:
yield o + k % 26
# If it's in the lower case and
# that the rotation is within the lowercase
elif o in lower and o + k % 26 in lower:
yield o + k % 26
# Otherwise move back 26 spaces after rotation.
else: # alphabet.
yield o + k % 26 -26
x = (''.join(map(chr, ceasar(s, k))))
print (x)
Batteries included
while 1:
phrase = raw_input("Could you please give me a phrase to encrypt?\n")
if phrase == "" : break
print "Here it is your phrase, encrypted:"
print phrase.encode("rot_13")
print "Have a nice afternoon!"
https://docs.python.org/2/library/codecs.html#python-specific-encodings
Python 3 update
The fine docs say
[Now the rot_13] codec provides a text transform: a str to str mapping. It is not supported by str.encode() (which only produces bytes output).
Or, in other words, you have to import encode from the codecs module and use it with the string to be encoded as its first argument
from codecs import decode
...
print(encode(phrase, 'rot13'))
The problem is that you set cipherText to empty string at every cycle iteration, the line
cipherText = ""
must be moved before the loop.
As pointed by others, you were resetting the cipherText in the iteration of the for loop. Placing cipherText before the start of the for loop will solve your problem.
Additionally, there is an alternate approach to solving this problem using Python's Standard library. The Python Standard Library defines a function maketrans() and a method translate that operates on strings.
The function maketrans() creates translation tables that can be used with the translate method to change one set of characters to another more efficiently. (Quoted from The Python Standard Library by Example).
import string
def caesar(plaintext, shift):
shift %= 26 # Values greater than 26 will wrap around
alphabet_lower = string.ascii_lowercase
alphabet_upper = string.ascii_uppercase
shifted_alphabet_lower = alphabet_lower[shift:] + alphabet_lower[:shift]
shifted_alphabet_upper = alphabet_upper[shift:] + alphabet_upper[:shift]
alphabet = alphabet_lower + alphabet_upper
shifted_alphabet = shifted_alphabet_lower + shifted_alphabet_upper
table = string.maketrans(alphabet, shifted_alphabet)
return plaintext.translate(table)
Here, a more functional way:
(if you use shift i to encode, then use -i to decode)
def ceasar(story, shift):
return ''.join([ # concentrate list to string
(lambda c, is_upper: c.upper() if is_upper else c) # if original char is upper case than convert result to upper case too
(
("abcdefghijklmnopqrstuvwxyz"*2)[ord(char.lower()) - ord('a') + shift % 26], # rotate char, this is extra easy since Python accepts list indexs below 0
char.isupper()
)
if char.isalpha() else char # if not in alphabet then don't change it
for char in story
])
plainText = raw_input("What is your plaintext? ")
shift = int(raw_input("What is your shift? "))
def caesar(plainText, shift):
for ch in plainText:
if ch.isalpha():
stayInAlphabet = ord(ch) + shift
if stayInAlphabet > ord('z'):
stayInAlphabet -= 26
finalLetter = chr(stayInAlphabet)
#####HERE YOU RESET CIPHERTEXT IN EACH ITERATION#####
cipherText = ""
cipherText += finalLetter
print "Your ciphertext is: ", cipherText
return cipherText
caesar(plainText, shift)
As an else to if ch.isalpha() you can put finalLetter=ch.
You should remove the line: cipherText = ""
Cheers.
As #I82much said, you need to take cipherText = "" outside of your for loop. Place it at the beginning of the function. Also, your program has a bug which will cause it to generate encryption errors when you get capital letters as input. Try:
if ch.isalpha():
finalLetter = chr((ord(ch.lower()) - 97 + shift) % 26 + 97)
>>> def rotate(txt, key):
... def cipher(i, low=range(97,123), upper=range(65,91)):
... if i in low or i in upper:
... s = 65 if i in upper else 97
... i = (i - s + key) % 26 + s
... return chr(i)
... return ''.join([cipher(ord(s)) for s in txt])
# test
>>> rotate('abc', 2)
'cde'
>>> rotate('xyz', 2)
'zab'
>>> rotate('ab', 26)
'ab'
>>> rotate('Hello, World!', 7)
'Olssv, Dvysk!'
I have a hard time remember the char to int conversions so this could be optimized
def decryptCaesar(encrypted, shift):
minRange = ord('a')
decrypted = ""
for char in encrypted:
decrypted += chr(((ord(char) - minRange + shift) % 26) + minRange)
return decrypted
def encrypt():
plainText = input("What is your plaintext? ")
shift = int(input("What is your shift? "))
cipherText = ""
for ch in plainText:
if ch.isalpha():
stayInAlphabet = ord(ch) + shift
if stayInAlphabet > ord('z'):
stayInAlphabet -= 26
finalLetter = chr(stayInAlphabet)
cipherText += finalLetter
print ("Your ciphertext is: ", cipherText,"with a shift of",shift)
def decrypte():
encryption=input("enter in your encrypted code")
encryption_shift=int(input("enter in your encryption shift"))
cipherText1 = ""
for c in encryption:
if c.isalpha():
stayInAlphabet1 = ord(c) - encryption_shift
if stayInAlphabet1 > ord('z'):
stayInAlphabet1 += 26
finalLetter1 = chr(stayInAlphabet1)
cipherText1 += finalLetter1
print ("Your ciphertext is: ", cipherText1,"with negative shift of",encryption_shift)
from tkinter import *
menu=Tk()
menu.title("menu")
menu.geometry("300x300")
button1= Button(menu,text="encrypt",command=encrypt)
button1.pack()
button2= Button(menu,text="decrypt",command=decrypte)
button2.pack()
button3= Button(menu,text="exit",command=exit)
button3.pack()
menu.mainloop()
message = 'The quick brown fox jumped over the lazy dog. 1234567890 !##$%^&*()_+-'
encrypted = ''.join(chr(ord(char)+3) for char in message)
decrypted = ''.join(chr(ord(char)-3) for char in encrypted)
print(encrypted)
print(decrypted)
# Wkh#txlfn#eurzq#ir{#mxpshg#ryhu#wkh#od}|#grj1#456789:;<3#$C&'(a)-+,b.0
# The quick brown fox jumped over the lazy dog. 1234567890 !##$%^&*()_+-
def encrypt(text,shift):
'''
INPUT: text as a string and an integer for the shift value.
OUTPUT: The shifted text after being run through the Caeser cipher.
'''
# Create a placeholder list
encrypted_text = list(range(len(text)))
alphabet = string.ascii_lowercase
# Create shifted alphabet
first_half = alphabet[:shift]
second_half = alphabet[shift:]
shifted_alphabet = second_half+first_half
for i,letter in enumerate(text.lower()):
# Check for spaces or punctuation
if letter in alphabet:
# Find the original index position
original_index = alphabet.index(letter)
# Shifted letter
new_letter = shifted_alphabet[original_index]
encrypted_text[i] = new_letter
# Punctuation or space
else:
encrypted_text[i] = letter
return ''.join(encrypted_text)
For example, decod string:
"uo jxuhu! jxyi yi qd unqcfbu ev q squiqh syfxuh. muhu oek qrbu je tusetu yj? y xefu ie! iudt cu q cuiiqwu rqsa myjx jxu iqcu evviuj!".
This message has an offset of 10.
Code below:
import string
alphabet = list(string.ascii_lowercase)
print(alphabet, len(alphabet))
messege = "xuo jxuhu! jxyi yi qd unqcfbu ev q squiqh syfxuh. muhu oek qrbu je tusetu yj? y xefu ie! iudt cu q cuiiqwu rqsa myjx jxu iqcu evviuj!"
messege_split = messege.split()
print(messege_split)
encrypted_messege = ""
position = 0
for i in messege_split:
for j in i:
if ord(j) < 65:
encrypted_messege += j
else:
for k in alphabet:
if j == k:
position = alphabet.index(k)
if (position + 10) >= len(alphabet):
encrypted_messege += alphabet[abs((position + 10) - len(alphabet))]
else:
encrypted_messege += alphabet[position + 10]
encrypted_messege += " "
print(encrypted_messege)
Decoded string:
"hey there! this is an example of a caesar cipher. were you able to decode it? i hope so! send me a message back with the same offset!"
TRY IT!
Using cyclic generator:
import string
from itertools import cycle
def caesarCipherEncryptor(s, key):
def generate_letters():
yield from cycle(string.ascii_lowercase)
def find_next(v, g, c):
# Eat up characters until we arrive at the plaintext character
while True:
if v == next(g):
break
# Increment the plaintext character by the count using the generator
try:
for _ in range(c):
item = next(g)
return item
except UnboundLocalError:
return v
return "".join([find_next(i, generate_letters(), key) for i in s])
# Outputs
>>> caesarCipherEncryptor("xyz", 3)
>>> 'abc'
from string import ascii_lowercase as alphabet
class CaesarCypher:
alpha_len = len(alphabet)
min_guess_rate = 0.2
Encryption and decryption is a same stuff. when you want to decrypt for example with shift 10 that means that you can encrypt it with shift 26 - 10. In this case cycle will repeat at if you going to shift whole alphabet it will be the same. Also here i've proceed upper case and non chars
def __call__(self, text, offset, encrypt=True):
if not encrypt:
offset = self.alpha_len - offset
result = []
for letter in text:
if not letter.isalpha():
result.append(letter)
continue
letter_to_process = letter.lower()
processed_letter = self._encrypt_letter(letter_to_process, offset)
if letter.isupper():
processed_letter = processed_letter.upper()
result.append(processed_letter)
return ''.join(result)
all encryption goes here at most.
def _encrypt_letter(self, letter, offset=0):
position = (alphabet.find(letter) + offset) % self.alpha_len
return alphabet[position]
this part is for broot force and guess throug dictionary frequency.
#staticmethod
def __how_many_do_i_know(text):
clean_words = filter(lambda x: x.isalpha(), text.split())
clean_words = ['\'{}\''.format(x) for x in clean_words]
cursor = conn.cursor()
query = 'SELECT COUNT(*) FROM mydictionary WHERE word IN ({})'.format(",".join(clean_words))
cursor.execute(query)
response = cursor.fetchone()[0]
return response / len(clean_words)
def guess_encode(self, text):
options = [self(text, offset, encrypt=False) for offset in range(self.alpha_len)]
best_option = [self.__how_many_do_i_know(option) for option in options]
best_key, guess_rate = max(enumerate(best_option), key=lambda x: x[-1])
guess_text = options[best_key]
return best_key, guess_rate, guess_text
import string
wrd=raw_input("Enter word").lower()
fwrd=""
for let in wrd:
fwrd+=string.ascii_lowercase[(string.ascii_lowercase).index(let)+3]
print"Original word",wrd
print"New word",fwrd
according to me this answer is useful for you:
def casear(a,key):
str=""
if key>26:
key%=26
for i in range(0,len(a)):
if a[i].isalpha():
b=ord(a[i])
b+=key
#if b>90: #if upper case letter ppear in your string
# c=b-90 #if upper case letter ppear in your string
# str+=chr(64+c) #if upper case letter ppear in your string
if b>122:
c=b-122
str+=chr(96+c)
else:
str+=chr(b)
else:
str+=a[i]
print str
a=raw_input()
key=int(input())
casear(a,key)
This function shifts all letter to right according to given key.
Why not use the function reverse on the shift input, and and join the plain_text with the shift, and input it as the cipher text:
Plain = int(input("enter a number "))
Rev = plain[::-1]
Cipher = " ".join(for cipher_text in Rev)
The code is very large, but easy to understand. I think it fits your situation.
alphabet = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
class CaesarCipher(object):
def __init__(self, shift):
self.shift = shift
def encode(self, str):
encode = ''
str = str.lower()
for i in str:
if i in alphabet:
encode += alphabet[alphabet.index(i) + self.shift]
else:
encode += i
return encode.upper()
def decode(self, str):
decode = ''
str = str.lower()
for i in str:
if i in alphabet:
decode += alphabet[alphabet.index(i) - self.shift]
else:
decode += i
return decode.upper()
Using map:
def caesar(text, key):
return ''.join(map(lambda c:
chr((ord(c.lower()) - ord('a') + key) % 26 + ord('a')) if c.isalpha() else ''
, text))
This solution is more intuitively without the use of ord function:
def caesar_cipher(raw_text, key):
alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
shifted_alphabet = alphabet[26-key:]+alphabet[0:(26-key)]
cipher_text = ""
for i in range(len(raw_text)):
char = raw_text[i]
idx = alphabet.find(char.upper())
if idx == -1:
cipher_text = cipher_text + char
elif char.islower():
cipher_text = cipher_text + shifted_alphabet[idx].lower()
else:
cipher_text = cipher_text + shifted_alphabet[idx]
return(cipher_text)
And an example:
plain_text = "The quick brown fox jumps over the lazy dog!"
caesar_cipher(plain_text,3)
And we get:
'Qeb nrfzh yoltk clu grjmp lsbo qeb ixwv ald!'
If we want to decrypt it:
caesar_cipher(caesar_cipher(plain_text,3),26-3)
and we get:
'The quick brown fox jumps over the lazy dog!'
More details here:https://predictivehacks.com/caesar-cipher-in-python/
caesar-cipher
message = str(input("Enter you message:"))
shift = int(input("Enter a number:"))
# encode
stringValue = [ord(message) - 96 for message in message]
print(stringValue)
encode_msg_val = []
[encode_msg_val.append(int(stringValue[i])+shift) for i in
range(len(stringValue))]
encode_msg_array = []
for i in range(len(encode_msg_val)):
encode_val = encode_msg_val[i] + 96
encode_msg_array.append(chr(encode_val))
print(encode_msg_array)
encode_msg = ''.join(encode_msg_array)
# dedcode
[deocde_msg_val = [ord(encode_msg) - 96 for encode_msg in encode_msg]
decode_val = []
[decode_val.append(deocde_msg_val[i] - shift) for i in
range(len(deocde_msg_val))]
decode_msg_array = []
[decode_msg_array.append(decode_val[i] + 96) for i in range(len(decode_val))]
decode_msg_list = []
[decode_msg_list.append(chr(decode_msg_array[i])) for i in
range(len(decode_msg_array))]
decode_msg = ''.join(decode_msg_list)
print(decode_msg)
alph = 'abcdefghijklmnopqrstuvwxyz'
# shift = int(input("Please enter the number of places to shift:"))
shift = 15
text = "python is fun!"
alph_len = len(alph)
if shift >=0 and shift <= alph_len:
# text = input("Please enter a sentence:")
shifted_alph = alph[shift:] + alph[:shift] # rotate
text = text.lower()
crypted_text = ""
for letter in text:
if letter in alph:
ind = alph.index(letter)
crypted_letter = shifted_alph[ind]
else:
crypted_letter = letter
crypted_text += crypted_letter
print(crypted_text)
else:
print(f"You need to enter a number between 0 and {alph_len}!")
# eniwdc xh ujc! # output
key = 3
def wub():
def choice():
choice = input("Do you wish to Encrypt of Decrypt?")
choice = choice.lower()
if choice == "e" or "encrypt":
return choice
elif choice == "d" or "decrypt":
return choice
else:
print("Invalid response, please try again.")
choice()
def message():
user = input("Enter your message: ")
return user
def waffle(choice, message, key):
translated = ""
if choice == "e" or "encrypt":
for character in message:
num = ord(character)
num += key
translated += chr(num)
derek = open('Encrypted.txt', 'w')
derek.write(translated)
derek.close()
return translated
else:
for character in message:
num = ord(character)
num -= key
translated += chr(num)
return translated
choice = choice() #Runs function for encrypt/decrypt selection. Saves choice made.
message = message() #Run function for user to enter message. Saves message.
final = waffle(choice, message, key) #Runs function to translate message, using the choice, message and key variables)
print("\n Operation complete!")
print(final)
wub()

Categories

Resources